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> |
12e364b9 KC |
29 | |
30 | #include "vmcallinterface.h" | |
31 | #include "channel.h" | |
32 | #include "uisthread.h" | |
33 | #include "uisqueue.h" | |
34 | #include "diagnostics/appos_subsystems.h" | |
35 | #include "vbusdeviceinfo.h" | |
36 | #include <linux/atomic.h> | |
37 | ||
38 | /* This is the MAGIC number stuffed by virthba in host->this_id. Used to | |
39 | * identify virtual hbas. | |
40 | */ | |
41 | #define UIS_MAGIC_VHBA 707 | |
42 | ||
43 | /* global function pointers that act as callback functions into | |
44 | * uisnicmod, uissdmod, and virtpcimod | |
45 | */ | |
46 | extern int (*UisnicControlChanFunc)(struct io_msgs *); | |
47 | extern int (*UissdControlChanFunc)(struct io_msgs *); | |
48 | extern int (*VirtControlChanFunc)(struct guest_msgs *); | |
49 | ||
50 | /* Return values of above callback functions: */ | |
51 | #define CCF_ERROR 0 /* completed and failed */ | |
52 | #define CCF_OK 1 /* completed successfully */ | |
53 | #define CCF_PENDING 2 /* operation still pending */ | |
54 | extern atomic_t UisUtils_Registered_Services; | |
55 | ||
56 | typedef unsigned int MACARRAY[MAX_MACADDR_LEN]; | |
57 | typedef struct ReqHandlerInfo_struct { | |
90addb02 | 58 | uuid_le switchTypeGuid; |
12e364b9 KC |
59 | int (*controlfunc)(struct io_msgs *); |
60 | unsigned long min_channel_bytes; | |
61 | int (*Server_Channel_Ok)(unsigned long channelBytes); | |
62 | int (*Server_Channel_Init) | |
5fc0229a | 63 | (void *x, unsigned char *clientStr, u32 clientStrLen, u64 bytes); |
12e364b9 KC |
64 | char switch_type_name[99]; |
65 | struct list_head list_link; /* links into ReqHandlerInfo_list */ | |
66 | } ReqHandlerInfo_t; | |
67 | ||
90addb02 | 68 | ReqHandlerInfo_t *ReqHandlerAdd(uuid_le switchTypeGuid, |
12e364b9 KC |
69 | const char *switch_type_name, |
70 | int (*controlfunc)(struct io_msgs *), | |
71 | unsigned long min_channel_bytes, | |
72 | int (*Server_Channel_Ok)(unsigned long | |
73 | channelBytes), | |
74 | int (*Server_Channel_Init) | |
75 | (void *x, unsigned char *clientStr, | |
5fc0229a | 76 | u32 clientStrLen, u64 bytes)); |
90addb02 BR |
77 | ReqHandlerInfo_t *ReqHandlerFind(uuid_le switchTypeGuid); |
78 | int ReqHandlerDel(uuid_le switchTypeGuid); | |
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); |
90addb02 | 118 | int uisctrl_register_req_handler_ex(uuid_le switchTypeGuid, |
12e364b9 KC |
119 | const char *switch_type_name, |
120 | int (*fptr)(struct io_msgs *), | |
121 | unsigned long min_channel_bytes, | |
122 | int (*Server_Channel_Ok)(unsigned long | |
123 | channelBytes), | |
124 | int (*Server_Channel_Init) | |
125 | (void *x, unsigned char *clientStr, | |
5fc0229a | 126 | u32 clientStrLen, u64 bytes), |
12e364b9 KC |
127 | ULTRA_VBUS_DEVICEINFO *chipset_DriverInfo); |
128 | ||
90addb02 | 129 | int uisctrl_unregister_req_handler_ex(uuid_le switchTypeGuid); |
12e364b9 KC |
130 | unsigned char *util_map_virt(struct phys_info *sg); |
131 | void util_unmap_virt(struct phys_info *sg); | |
132 | unsigned char *util_map_virt_atomic(struct phys_info *sg); | |
133 | void util_unmap_virt_atomic(void *buf); | |
b3c55b13 BR |
134 | int uislib_server_inject_add_vnic(u32 switchNo, u32 BusNo, u32 numIntPorts, |
135 | u32 numExtPorts, MACARRAY pmac[], | |
12e364b9 | 136 | pCHANNEL_HEADER **chan); |
b3c55b13 BR |
137 | void uislib_server_inject_del_vnic(u32 switchNo, u32 busNo, u32 numIntPorts, |
138 | u32 numExtPorts); | |
139 | int uislib_client_inject_add_bus(u32 busNo, uuid_le instGuid, | |
5fc0229a | 140 | u64 channelAddr, ulong nChannelBytes); |
b3c55b13 | 141 | int uislib_client_inject_del_bus(u32 busNo); |
12e364b9 | 142 | |
b3c55b13 | 143 | int uislib_client_inject_add_vhba(u32 busNo, u32 devNo, |
5fc0229a | 144 | u64 phys_chan_addr, u32 chan_bytes, |
90addb02 | 145 | int is_test_addr, uuid_le instGuid, |
12e364b9 | 146 | struct InterruptInfo *intr); |
b3c55b13 BR |
147 | int uislib_client_inject_pause_vhba(u32 busNo, u32 devNo); |
148 | int uislib_client_inject_resume_vhba(u32 busNo, u32 devNo); | |
149 | int uislib_client_inject_del_vhba(u32 busNo, u32 devNo); | |
150 | int uislib_client_inject_add_vnic(u32 busNo, u32 devNo, | |
5fc0229a | 151 | u64 phys_chan_addr, u32 chan_bytes, |
90addb02 | 152 | int is_test_addr, uuid_le instGuid, |
12e364b9 | 153 | struct InterruptInfo *intr); |
b3c55b13 BR |
154 | int uislib_client_inject_pause_vnic(u32 busNo, u32 devNo); |
155 | int uislib_client_inject_resume_vnic(u32 busNo, u32 devNo); | |
156 | int uislib_client_inject_del_vnic(u32 busNo, u32 devNo); | |
12e364b9 | 157 | #ifdef STORAGE_CHANNEL |
5fc0229a | 158 | u64 uislib_storage_channel(int client_id); |
12e364b9 KC |
159 | #endif |
160 | int uislib_get_owned_pdest(struct uisscsi_dest *pdest); | |
161 | ||
162 | int uislib_send_event(CONTROLVM_ID id, CONTROLVM_MESSAGE_PACKET *event); | |
163 | ||
164 | /* structure used by vhba & vnic to keep track of queue & thread info */ | |
165 | struct chaninfo { | |
166 | struct uisqueue_info *queueinfo; | |
167 | /* this specifies the queue structures for a channel */ | |
168 | /* ALLOCATED BY THE OTHER END - WE JUST GET A POINTER TO THE MEMORY */ | |
169 | spinlock_t insertlock; | |
170 | /* currently used only in virtnic when sending data to uisnic */ | |
171 | /* to synchronize the inserts into the signal queue */ | |
172 | struct uisthread_info threadinfo; | |
173 | /* this specifies the thread structures used by the thread that */ | |
174 | /* handles this channel */ | |
175 | }; | |
176 | ||
177 | /* this is the wait code for all the threads - it is used to get | |
178 | * something from a queue choices: wait_for_completion_interruptible, | |
179 | * _timeout, interruptible_timeout | |
180 | */ | |
181 | #define UIS_THREAD_WAIT_MSEC(x) { \ | |
182 | set_current_state(TASK_INTERRUPTIBLE); \ | |
183 | schedule_timeout(msecs_to_jiffies(x)); \ | |
184 | } | |
185 | #define UIS_THREAD_WAIT_USEC(x) { \ | |
186 | set_current_state(TASK_INTERRUPTIBLE); \ | |
187 | schedule_timeout(usecs_to_jiffies(x)); \ | |
188 | } | |
189 | #define UIS_THREAD_WAIT UIS_THREAD_WAIT_MSEC(5) | |
190 | #define UIS_THREAD_WAIT_SEC(x) { \ | |
191 | set_current_state(TASK_INTERRUPTIBLE); \ | |
192 | schedule_timeout((x)*HZ); \ | |
193 | } | |
194 | ||
12e364b9 KC |
195 | /* This is a hack until we fix IOVM to initialize the channel header |
196 | * correctly at DEVICE_CREATE time, INSTEAD OF waiting until | |
197 | * DEVICE_CONFIGURE time. | |
198 | */ | |
e40d1c8a KC |
199 | static inline void |
200 | wait_for_valid_guid(uuid_le __iomem *guid) | |
201 | { | |
202 | uuid_le tmpguid; | |
203 | ||
204 | while (1) { | |
205 | memcpy_fromio((void *)&tmpguid, | |
206 | (void __iomem *)guid, sizeof(uuid_le)); | |
207 | if (uuid_le_cmp(tmpguid, NULL_UUID_LE) != 0) | |
208 | break; | |
209 | LOGERR("Waiting for non-0 GUID (why???)...\n"); | |
210 | UIS_THREAD_WAIT_SEC(5); | |
211 | } | |
212 | LOGERR("OK... GUID is non-0 now\n"); | |
213 | } | |
12e364b9 KC |
214 | |
215 | /* CopyFragsInfoFromSkb returns the number of entries added to frags array | |
216 | * Returns -1 on failure. | |
217 | */ | |
927c7927 KC |
218 | unsigned int uisutil_copy_fragsinfo_from_skb(unsigned char *calling_ctx, |
219 | void *skb_in, | |
220 | unsigned int firstfraglen, | |
221 | unsigned int frags_max, | |
222 | struct phys_info frags[]); | |
12e364b9 KC |
223 | |
224 | static inline unsigned int | |
74658c56 | 225 | issue_vmcall_io_controlvm_addr(u64 *control_addr, u32 *control_bytes) |
12e364b9 KC |
226 | { |
227 | VMCALL_IO_CONTROLVM_ADDR_PARAMS params; | |
228 | int result = VMCALL_SUCCESS; | |
5fc0229a | 229 | u64 physaddr; |
12e364b9 KC |
230 | |
231 | physaddr = virt_to_phys(¶ms); | |
232 | ISSUE_IO_VMCALL(VMCALL_IO_CONTROLVM_ADDR, physaddr, result); | |
233 | if (VMCALL_SUCCESSFUL(result)) { | |
74658c56 BR |
234 | *control_addr = params.ChannelAddress; |
235 | *control_bytes = params.ChannelBytes; | |
12e364b9 KC |
236 | } |
237 | return result; | |
238 | } | |
239 | ||
5fc0229a | 240 | static inline unsigned int Issue_VMCALL_IO_DIAG_ADDR(u64 *DiagChannelAddress) |
12e364b9 KC |
241 | { |
242 | VMCALL_IO_DIAG_ADDR_PARAMS params; | |
243 | int result = VMCALL_SUCCESS; | |
5fc0229a | 244 | u64 physaddr; |
12e364b9 KC |
245 | |
246 | physaddr = virt_to_phys(¶ms); | |
247 | ISSUE_IO_VMCALL(VMCALL_IO_DIAG_ADDR, physaddr, result); | |
248 | if (VMCALL_SUCCESSFUL(result)) | |
249 | *DiagChannelAddress = params.ChannelAddress; | |
250 | return result; | |
251 | } | |
252 | ||
253 | static inline unsigned int | |
5fc0229a | 254 | Issue_VMCALL_IO_VISORSERIAL_ADDR(u64 *DiagChannelAddress) |
12e364b9 KC |
255 | { |
256 | VMCALL_IO_VISORSERIAL_ADDR_PARAMS params; | |
257 | int result = VMCALL_SUCCESS; | |
5fc0229a | 258 | u64 physaddr; |
12e364b9 KC |
259 | |
260 | physaddr = virt_to_phys(¶ms); | |
261 | ISSUE_IO_VMCALL(VMCALL_IO_VISORSERIAL_ADDR, physaddr, result); | |
262 | if (VMCALL_SUCCESSFUL(result)) | |
263 | *DiagChannelAddress = params.ChannelAddress; | |
264 | return result; | |
265 | } | |
266 | ||
ec03a7db | 267 | static inline s64 Issue_VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET(void) |
12e364b9 | 268 | { |
5fc0229a BR |
269 | u64 result = VMCALL_SUCCESS; |
270 | u64 physaddr = 0; | |
12e364b9 KC |
271 | |
272 | ISSUE_IO_VMCALL(VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET, physaddr, | |
273 | result); | |
274 | return result; | |
275 | } | |
276 | ||
ec03a7db | 277 | static inline s64 Issue_VMCALL_MEASUREMENT_DO_NOTHING(void) |
12e364b9 | 278 | { |
5fc0229a BR |
279 | u64 result = VMCALL_SUCCESS; |
280 | u64 physaddr = 0; | |
12e364b9 KC |
281 | |
282 | ISSUE_IO_VMCALL(VMCALL_MEASUREMENT_DO_NOTHING, physaddr, result); | |
283 | return result; | |
284 | } | |
285 | ||
286 | struct log_info_t { | |
287 | volatile unsigned long long last_cycles; | |
288 | unsigned long long delta_sum[64]; | |
289 | unsigned long long delta_cnt[64]; | |
290 | unsigned long long max_delta[64]; | |
291 | unsigned long long min_delta[64]; | |
292 | }; | |
293 | ||
5fc0229a | 294 | static inline int Issue_VMCALL_UPDATE_PHYSICAL_TIME(u64 adjustment) |
12e364b9 KC |
295 | { |
296 | int result = VMCALL_SUCCESS; | |
297 | ||
298 | ISSUE_IO_VMCALL(VMCALL_UPDATE_PHYSICAL_TIME, adjustment, result); | |
299 | return result; | |
300 | } | |
301 | ||
302 | static inline unsigned int | |
303 | Issue_VMCALL_CHANNEL_MISMATCH(const char *ChannelName, | |
304 | const char *ItemName, | |
b3c55b13 | 305 | u32 SourceLineNumber, const char *path_n_fn) |
12e364b9 KC |
306 | { |
307 | VMCALL_CHANNEL_VERSION_MISMATCH_PARAMS params; | |
308 | int result = VMCALL_SUCCESS; | |
5fc0229a | 309 | u64 physaddr; |
12e364b9 KC |
310 | char *last_slash = NULL; |
311 | ||
4c86db6a | 312 | strlcpy(params.ChannelName, ChannelName, |
12e364b9 | 313 | lengthof(VMCALL_CHANNEL_VERSION_MISMATCH_PARAMS, ChannelName)); |
4c86db6a | 314 | strlcpy(params.ItemName, ItemName, |
12e364b9 KC |
315 | lengthof(VMCALL_CHANNEL_VERSION_MISMATCH_PARAMS, ItemName)); |
316 | params.SourceLineNumber = SourceLineNumber; | |
317 | ||
318 | last_slash = strrchr(path_n_fn, '/'); | |
319 | if (last_slash != NULL) { | |
320 | last_slash++; | |
4c86db6a | 321 | strlcpy(params.SourceFileName, last_slash, |
12e364b9 KC |
322 | lengthof(VMCALL_CHANNEL_VERSION_MISMATCH_PARAMS, |
323 | SourceFileName)); | |
324 | } else | |
4c86db6a | 325 | strlcpy(params.SourceFileName, |
12e364b9 KC |
326 | "Cannot determine source filename", |
327 | lengthof(VMCALL_CHANNEL_VERSION_MISMATCH_PARAMS, | |
328 | SourceFileName)); | |
329 | ||
330 | physaddr = virt_to_phys(¶ms); | |
331 | ISSUE_IO_VMCALL(VMCALL_CHANNEL_VERSION_MISMATCH, physaddr, result); | |
332 | return result; | |
333 | } | |
334 | ||
335 | static inline unsigned int Issue_VMCALL_FATAL_BYE_BYE(void) | |
336 | { | |
337 | int result = VMCALL_SUCCESS; | |
5fc0229a | 338 | u64 physaddr = 0; |
12e364b9 KC |
339 | |
340 | ISSUE_IO_VMCALL(VMCALL_GENERIC_SURRENDER_QUANTUM_FOREVER, physaddr, | |
341 | result); | |
342 | return result; | |
343 | } | |
344 | ||
345 | #define UIS_DAEMONIZE(nam) | |
12e364b9 KC |
346 | void *uislib_cache_alloc(struct kmem_cache *cur_pool, char *fn, int ln); |
347 | #define UISCACHEALLOC(cur_pool) uislib_cache_alloc(cur_pool, __FILE__, __LINE__) | |
348 | void uislib_cache_free(struct kmem_cache *cur_pool, void *p, char *fn, int ln); | |
349 | #define UISCACHEFREE(cur_pool, p) \ | |
350 | uislib_cache_free(cur_pool, p, __FILE__, __LINE__) | |
351 | ||
b3c55b13 | 352 | void uislib_enable_channel_interrupts(u32 busNo, u32 devNo, |
12e364b9 KC |
353 | int (*interrupt)(void *), |
354 | void *interrupt_context); | |
b3c55b13 BR |
355 | void uislib_disable_channel_interrupts(u32 busNo, u32 devNo); |
356 | void uislib_force_channel_interrupt(u32 busNo, u32 devNo); | |
12e364b9 KC |
357 | |
358 | #endif /* __UISUTILS__H__ */ |