]>
Commit | Line | Data |
---|---|---|
12e364b9 KC |
1 | /* uisutils.h |
2 | * | |
f6d0c1e6 | 3 | * Copyright (C) 2010 - 2013 UNISYS CORPORATION |
12e364b9 KC |
4 | * All rights reserved. |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License as published by | |
8 | * the Free Software Foundation; either version 2 of the License, or (at | |
9 | * your option) any later version. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, but | |
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | |
14 | * NON INFRINGEMENT. See the GNU General Public License for more | |
15 | * details. | |
16 | */ | |
17 | ||
18 | /* | |
19 | * Unisys Virtual HBA utilities header | |
20 | */ | |
21 | ||
22 | #ifndef __UISUTILS__H__ | |
23 | #define __UISUTILS__H__ | |
24 | #include <linux/string.h> | |
25 | #include <linux/io.h> | |
26 | #include <linux/sched.h> | |
27 | #include <linux/gfp.h> | |
90addb02 | 28 | #include <linux/uuid.h> |
9aee8f97 | 29 | #include <linux/if_ether.h> |
12e364b9 KC |
30 | |
31 | #include "vmcallinterface.h" | |
32 | #include "channel.h" | |
33 | #include "uisthread.h" | |
34 | #include "uisqueue.h" | |
35 | #include "diagnostics/appos_subsystems.h" | |
36 | #include "vbusdeviceinfo.h" | |
37 | #include <linux/atomic.h> | |
38 | ||
39 | /* This is the MAGIC number stuffed by virthba in host->this_id. Used to | |
40 | * identify virtual hbas. | |
41 | */ | |
42 | #define UIS_MAGIC_VHBA 707 | |
43 | ||
44 | /* global function pointers that act as callback functions into | |
45 | * uisnicmod, uissdmod, and virtpcimod | |
46 | */ | |
2df7cc62 BR |
47 | extern int (*uisnic_control_chan_func)(struct io_msgs *); |
48 | extern int (*uissd_control_chan_func)(struct io_msgs *); | |
49 | extern int (*virt_control_chan_func)(struct guest_msgs *); | |
12e364b9 KC |
50 | |
51 | /* Return values of above callback functions: */ | |
52 | #define CCF_ERROR 0 /* completed and failed */ | |
53 | #define CCF_OK 1 /* completed successfully */ | |
54 | #define CCF_PENDING 2 /* operation still pending */ | |
e9b9262a | 55 | extern atomic_t uisutils_registered_services; |
12e364b9 | 56 | |
38ab19b6 | 57 | struct req_handler_info { |
157764e7 | 58 | uuid_le switch_uuid; |
12e364b9 KC |
59 | int (*controlfunc)(struct io_msgs *); |
60 | unsigned long min_channel_bytes; | |
157764e7 | 61 | int (*server_channel_ok)(unsigned long channel_bytes); |
f9dd5dda BR |
62 | int (*server_channel_init)(void *x, unsigned char *client_str, |
63 | u32 client_str_len, u64 bytes); | |
12e364b9 KC |
64 | char switch_type_name[99]; |
65 | struct list_head list_link; /* links into ReqHandlerInfo_list */ | |
38ab19b6 | 66 | }; |
12e364b9 | 67 | |
3636c0da | 68 | struct req_handler_info *req_handler_add(uuid_le switch_uuid, |
12e364b9 KC |
69 | const char *switch_type_name, |
70 | int (*controlfunc)(struct io_msgs *), | |
71 | unsigned long min_channel_bytes, | |
3636c0da BR |
72 | int (*svr_channel_ok)(unsigned long |
73 | channel_bytes), | |
74 | int (*svr_channel_init)(void *x, | |
75 | unsigned char *client_str, | |
76 | u32 client_str_len, u64 bytes)); | |
ea2cfd65 | 77 | struct req_handler_info *req_handler_find(uuid_le switch_uuid); |
7692544d | 78 | int req_handler_del(uuid_le switch_uuid); |
12e364b9 KC |
79 | |
80 | #define uislib_ioremap_cache(addr, size) \ | |
81 | dbg_ioremap_cache(addr, size, __FILE__, __LINE__) | |
82 | ||
8504ff6c | 83 | static inline void __iomem * |
5fc0229a | 84 | dbg_ioremap_cache(u64 addr, unsigned long size, char *file, int line) |
12e364b9 | 85 | { |
8504ff6c | 86 | void __iomem *new; |
613cbd9f | 87 | |
12e364b9 KC |
88 | new = ioremap_cache(addr, size); |
89 | return new; | |
90 | } | |
91 | ||
92 | #define uislib_ioremap(addr, size) dbg_ioremap(addr, size, __FILE__, __LINE__) | |
93 | ||
94 | static inline void * | |
5fc0229a | 95 | dbg_ioremap(u64 addr, unsigned long size, char *file, int line) |
12e364b9 KC |
96 | { |
97 | void *new; | |
613cbd9f | 98 | |
12e364b9 KC |
99 | new = ioremap(addr, size); |
100 | return new; | |
101 | } | |
102 | ||
103 | #define uislib_iounmap(addr) dbg_iounmap(addr, __FILE__, __LINE__) | |
104 | ||
105 | static inline void | |
8504ff6c | 106 | dbg_iounmap(void __iomem *addr, char *file, int line) |
12e364b9 KC |
107 | { |
108 | iounmap(addr); | |
109 | } | |
110 | ||
111 | #define PROC_READ_BUFFER_SIZE 131072 /* size of the buffer to allocate to | |
112 | * hold all of /proc/XXX/info */ | |
927c7927 KC |
113 | int uisutil_add_proc_line_ex(int *total, char **buffer, int *buffer_remaining, |
114 | char *format, ...); | |
12e364b9 KC |
115 | |
116 | int uisctrl_register_req_handler(int type, void *fptr, | |
03ec49dc | 117 | ULTRA_VBUS_DEVICEINFO *chipset_driver_info); |
1032885d | 118 | int uisctrl_register_req_handler_ex(uuid_le switch_guid, |
12e364b9 KC |
119 | const char *switch_type_name, |
120 | int (*fptr)(struct io_msgs *), | |
121 | unsigned long min_channel_bytes, | |
3636c0da | 122 | int (*svr_channel_ok)(unsigned long |
1032885d BR |
123 | channel_bytes), |
124 | int (*svr_channel_init)(void *x, | |
125 | unsigned char *client_str, | |
126 | u32 client_str_len, | |
127 | u64 bytes), | |
128 | ULTRA_VBUS_DEVICEINFO *chipset_driver_info); | |
12e364b9 | 129 | |
d44694af | 130 | int uisctrl_unregister_req_handler_ex(uuid_le switch_uuid); |
12e364b9 KC |
131 | unsigned char *util_map_virt(struct phys_info *sg); |
132 | void util_unmap_virt(struct phys_info *sg); | |
133 | unsigned char *util_map_virt_atomic(struct phys_info *sg); | |
134 | void util_unmap_virt_atomic(void *buf); | |
e1242538 BR |
135 | int uislib_client_inject_add_bus(u32 bus_no, uuid_le inst_uuid, |
136 | u64 channel_addr, ulong n_channel_bytes); | |
ac15ba59 | 137 | int uislib_client_inject_del_bus(u32 bus_no); |
12e364b9 | 138 | |
3d3b7154 | 139 | int uislib_client_inject_add_vhba(u32 bus_no, u32 dev_no, |
5fc0229a | 140 | u64 phys_chan_addr, u32 chan_bytes, |
3d3b7154 | 141 | int is_test_addr, uuid_le inst_uuid, |
4eddbf13 | 142 | struct irq_info *intr); |
062d312d | 143 | int uislib_client_inject_pause_vhba(u32 bus_no, u32 dev_no); |
ae47a51b | 144 | int uislib_client_inject_resume_vhba(u32 bus_no, u32 dev_no); |
6bc962ac | 145 | int uislib_client_inject_del_vhba(u32 bus_no, u32 dev_no); |
94a887da | 146 | int uislib_client_inject_add_vnic(u32 bus_no, u32 dev_no, |
5fc0229a | 147 | u64 phys_chan_addr, u32 chan_bytes, |
94a887da | 148 | int is_test_addr, uuid_le inst_uuid, |
4eddbf13 | 149 | struct irq_info *intr); |
68a4b12c | 150 | int uislib_client_inject_pause_vnic(u32 bus_no, u32 dev_no); |
3fe7cec4 | 151 | int uislib_client_inject_resume_vnic(u32 bus_no, u32 dev_no); |
bdb628d0 | 152 | int uislib_client_inject_del_vnic(u32 bus_no, u32 dev_no); |
12e364b9 | 153 | #ifdef STORAGE_CHANNEL |
5fc0229a | 154 | u64 uislib_storage_channel(int client_id); |
12e364b9 KC |
155 | #endif |
156 | int uislib_get_owned_pdest(struct uisscsi_dest *pdest); | |
157 | ||
158 | int uislib_send_event(CONTROLVM_ID id, CONTROLVM_MESSAGE_PACKET *event); | |
159 | ||
160 | /* structure used by vhba & vnic to keep track of queue & thread info */ | |
161 | struct chaninfo { | |
162 | struct uisqueue_info *queueinfo; | |
163 | /* this specifies the queue structures for a channel */ | |
164 | /* ALLOCATED BY THE OTHER END - WE JUST GET A POINTER TO THE MEMORY */ | |
165 | spinlock_t insertlock; | |
166 | /* currently used only in virtnic when sending data to uisnic */ | |
167 | /* to synchronize the inserts into the signal queue */ | |
168 | struct uisthread_info threadinfo; | |
169 | /* this specifies the thread structures used by the thread that */ | |
170 | /* handles this channel */ | |
171 | }; | |
172 | ||
173 | /* this is the wait code for all the threads - it is used to get | |
174 | * something from a queue choices: wait_for_completion_interruptible, | |
175 | * _timeout, interruptible_timeout | |
176 | */ | |
177 | #define UIS_THREAD_WAIT_MSEC(x) { \ | |
178 | set_current_state(TASK_INTERRUPTIBLE); \ | |
179 | schedule_timeout(msecs_to_jiffies(x)); \ | |
180 | } | |
181 | #define UIS_THREAD_WAIT_USEC(x) { \ | |
182 | set_current_state(TASK_INTERRUPTIBLE); \ | |
183 | schedule_timeout(usecs_to_jiffies(x)); \ | |
184 | } | |
185 | #define UIS_THREAD_WAIT UIS_THREAD_WAIT_MSEC(5) | |
186 | #define UIS_THREAD_WAIT_SEC(x) { \ | |
187 | set_current_state(TASK_INTERRUPTIBLE); \ | |
188 | schedule_timeout((x)*HZ); \ | |
189 | } | |
190 | ||
12e364b9 KC |
191 | /* This is a hack until we fix IOVM to initialize the channel header |
192 | * correctly at DEVICE_CREATE time, INSTEAD OF waiting until | |
193 | * DEVICE_CONFIGURE time. | |
194 | */ | |
e40d1c8a KC |
195 | static inline void |
196 | wait_for_valid_guid(uuid_le __iomem *guid) | |
197 | { | |
198 | uuid_le tmpguid; | |
199 | ||
200 | while (1) { | |
201 | memcpy_fromio((void *)&tmpguid, | |
202 | (void __iomem *)guid, sizeof(uuid_le)); | |
203 | if (uuid_le_cmp(tmpguid, NULL_UUID_LE) != 0) | |
204 | break; | |
205 | LOGERR("Waiting for non-0 GUID (why???)...\n"); | |
206 | UIS_THREAD_WAIT_SEC(5); | |
207 | } | |
208 | LOGERR("OK... GUID is non-0 now\n"); | |
209 | } | |
12e364b9 KC |
210 | |
211 | /* CopyFragsInfoFromSkb returns the number of entries added to frags array | |
212 | * Returns -1 on failure. | |
213 | */ | |
927c7927 KC |
214 | unsigned int uisutil_copy_fragsinfo_from_skb(unsigned char *calling_ctx, |
215 | void *skb_in, | |
216 | unsigned int firstfraglen, | |
217 | unsigned int frags_max, | |
218 | struct phys_info frags[]); | |
12e364b9 KC |
219 | |
220 | static inline unsigned int | |
74658c56 | 221 | issue_vmcall_io_controlvm_addr(u64 *control_addr, u32 *control_bytes) |
12e364b9 KC |
222 | { |
223 | VMCALL_IO_CONTROLVM_ADDR_PARAMS params; | |
224 | int result = VMCALL_SUCCESS; | |
5fc0229a | 225 | u64 physaddr; |
12e364b9 KC |
226 | |
227 | physaddr = virt_to_phys(¶ms); | |
228 | ISSUE_IO_VMCALL(VMCALL_IO_CONTROLVM_ADDR, physaddr, result); | |
229 | if (VMCALL_SUCCESSFUL(result)) { | |
74658c56 BR |
230 | *control_addr = params.ChannelAddress; |
231 | *control_bytes = params.ChannelBytes; | |
12e364b9 KC |
232 | } |
233 | return result; | |
234 | } | |
235 | ||
007ef59b | 236 | static inline unsigned int issue_vmcall_io_diag_addr(u64 *diag_channel_addr) |
12e364b9 KC |
237 | { |
238 | VMCALL_IO_DIAG_ADDR_PARAMS params; | |
239 | int result = VMCALL_SUCCESS; | |
5fc0229a | 240 | u64 physaddr; |
12e364b9 KC |
241 | |
242 | physaddr = virt_to_phys(¶ms); | |
243 | ISSUE_IO_VMCALL(VMCALL_IO_DIAG_ADDR, physaddr, result); | |
244 | if (VMCALL_SUCCESSFUL(result)) | |
007ef59b | 245 | *diag_channel_addr = params.ChannelAddress; |
12e364b9 KC |
246 | return result; |
247 | } | |
248 | ||
8359367e | 249 | static inline unsigned int issue_vmcall_io_visorserial_addr(u64 *channel_addr) |
12e364b9 KC |
250 | { |
251 | VMCALL_IO_VISORSERIAL_ADDR_PARAMS params; | |
252 | int result = VMCALL_SUCCESS; | |
5fc0229a | 253 | u64 physaddr; |
12e364b9 KC |
254 | |
255 | physaddr = virt_to_phys(¶ms); | |
256 | ISSUE_IO_VMCALL(VMCALL_IO_VISORSERIAL_ADDR, physaddr, result); | |
257 | if (VMCALL_SUCCESSFUL(result)) | |
8359367e | 258 | *channel_addr = params.ChannelAddress; |
12e364b9 KC |
259 | return result; |
260 | } | |
261 | ||
e76446ea | 262 | static inline s64 issue_vmcall_query_guest_virtual_time_offset(void) |
12e364b9 | 263 | { |
5fc0229a BR |
264 | u64 result = VMCALL_SUCCESS; |
265 | u64 physaddr = 0; | |
12e364b9 KC |
266 | |
267 | ISSUE_IO_VMCALL(VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET, physaddr, | |
268 | result); | |
269 | return result; | |
270 | } | |
271 | ||
f06ae67c | 272 | static inline s64 issue_vmcall_measurement_do_nothing(void) |
12e364b9 | 273 | { |
5fc0229a BR |
274 | u64 result = VMCALL_SUCCESS; |
275 | u64 physaddr = 0; | |
12e364b9 KC |
276 | |
277 | ISSUE_IO_VMCALL(VMCALL_MEASUREMENT_DO_NOTHING, physaddr, result); | |
278 | return result; | |
279 | } | |
280 | ||
281 | struct log_info_t { | |
282 | volatile unsigned long long last_cycles; | |
283 | unsigned long long delta_sum[64]; | |
284 | unsigned long long delta_cnt[64]; | |
285 | unsigned long long max_delta[64]; | |
286 | unsigned long long min_delta[64]; | |
287 | }; | |
288 | ||
b8fd9902 | 289 | static inline int issue_vmcall_update_physical_time(u64 adjustment) |
12e364b9 KC |
290 | { |
291 | int result = VMCALL_SUCCESS; | |
292 | ||
293 | ISSUE_IO_VMCALL(VMCALL_UPDATE_PHYSICAL_TIME, adjustment, result); | |
294 | return result; | |
295 | } | |
296 | ||
b591ebf2 BR |
297 | static inline unsigned int issue_vmcall_channel_mismatch(const char *chname, |
298 | const char *item_name, u32 line_no, | |
299 | const char *path_n_fn) | |
12e364b9 KC |
300 | { |
301 | VMCALL_CHANNEL_VERSION_MISMATCH_PARAMS params; | |
302 | int result = VMCALL_SUCCESS; | |
5fc0229a | 303 | u64 physaddr; |
12e364b9 KC |
304 | char *last_slash = NULL; |
305 | ||
b591ebf2 | 306 | strlcpy(params.ChannelName, chname, |
12e364b9 | 307 | lengthof(VMCALL_CHANNEL_VERSION_MISMATCH_PARAMS, ChannelName)); |
b591ebf2 | 308 | strlcpy(params.ItemName, item_name, |
12e364b9 | 309 | lengthof(VMCALL_CHANNEL_VERSION_MISMATCH_PARAMS, ItemName)); |
b591ebf2 | 310 | params.SourceLineNumber = line_no; |
12e364b9 KC |
311 | |
312 | last_slash = strrchr(path_n_fn, '/'); | |
313 | if (last_slash != NULL) { | |
314 | last_slash++; | |
4c86db6a | 315 | strlcpy(params.SourceFileName, last_slash, |
12e364b9 KC |
316 | lengthof(VMCALL_CHANNEL_VERSION_MISMATCH_PARAMS, |
317 | SourceFileName)); | |
318 | } else | |
4c86db6a | 319 | strlcpy(params.SourceFileName, |
12e364b9 KC |
320 | "Cannot determine source filename", |
321 | lengthof(VMCALL_CHANNEL_VERSION_MISMATCH_PARAMS, | |
322 | SourceFileName)); | |
323 | ||
324 | physaddr = virt_to_phys(¶ms); | |
325 | ISSUE_IO_VMCALL(VMCALL_CHANNEL_VERSION_MISMATCH, physaddr, result); | |
326 | return result; | |
327 | } | |
328 | ||
8ec85997 | 329 | static inline unsigned int issue_vmcall_fatal(void) |
12e364b9 KC |
330 | { |
331 | int result = VMCALL_SUCCESS; | |
5fc0229a | 332 | u64 physaddr = 0; |
12e364b9 KC |
333 | |
334 | ISSUE_IO_VMCALL(VMCALL_GENERIC_SURRENDER_QUANTUM_FOREVER, physaddr, | |
335 | result); | |
336 | return result; | |
337 | } | |
338 | ||
339 | #define UIS_DAEMONIZE(nam) | |
12e364b9 KC |
340 | void *uislib_cache_alloc(struct kmem_cache *cur_pool, char *fn, int ln); |
341 | #define UISCACHEALLOC(cur_pool) uislib_cache_alloc(cur_pool, __FILE__, __LINE__) | |
342 | void uislib_cache_free(struct kmem_cache *cur_pool, void *p, char *fn, int ln); | |
343 | #define UISCACHEFREE(cur_pool, p) \ | |
344 | uislib_cache_free(cur_pool, p, __FILE__, __LINE__) | |
345 | ||
93d1304f | 346 | void uislib_enable_channel_interrupts(u32 bus_no, u32 dev_no, |
12e364b9 KC |
347 | int (*interrupt)(void *), |
348 | void *interrupt_context); | |
d0dd33f3 | 349 | void uislib_disable_channel_interrupts(u32 bus_no, u32 dev_no); |
f7b33ff4 | 350 | void uislib_force_channel_interrupt(u32 bus_no, u32 dev_no); |
12e364b9 KC |
351 | |
352 | #endif /* __UISUTILS__H__ */ |