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) | |
63 | (void *x, unsigned char *clientStr, U32 clientStrLen, U64 bytes); | |
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, | |
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 * |
12e364b9 KC |
84 | dbg_ioremap_cache(U64 addr, unsigned long size, char *file, int line) |
85 | { | |
8504ff6c | 86 | void __iomem *new; |
12e364b9 KC |
87 | new = ioremap_cache(addr, size); |
88 | return new; | |
89 | } | |
90 | ||
91 | #define uislib_ioremap(addr, size) dbg_ioremap(addr, size, __FILE__, __LINE__) | |
92 | ||
93 | static inline void * | |
94 | dbg_ioremap(U64 addr, unsigned long size, char *file, int line) | |
95 | { | |
96 | void *new; | |
97 | new = ioremap(addr, size); | |
98 | return new; | |
99 | } | |
100 | ||
101 | #define uislib_iounmap(addr) dbg_iounmap(addr, __FILE__, __LINE__) | |
102 | ||
103 | static inline void | |
8504ff6c | 104 | dbg_iounmap(void __iomem *addr, char *file, int line) |
12e364b9 KC |
105 | { |
106 | iounmap(addr); | |
107 | } | |
108 | ||
109 | #define PROC_READ_BUFFER_SIZE 131072 /* size of the buffer to allocate to | |
110 | * hold all of /proc/XXX/info */ | |
927c7927 KC |
111 | int uisutil_add_proc_line_ex(int *total, char **buffer, int *buffer_remaining, |
112 | char *format, ...); | |
12e364b9 KC |
113 | |
114 | int uisctrl_register_req_handler(int type, void *fptr, | |
115 | ULTRA_VBUS_DEVICEINFO *chipset_DriverInfo); | |
90addb02 | 116 | int uisctrl_register_req_handler_ex(uuid_le switchTypeGuid, |
12e364b9 KC |
117 | const char *switch_type_name, |
118 | int (*fptr)(struct io_msgs *), | |
119 | unsigned long min_channel_bytes, | |
120 | int (*Server_Channel_Ok)(unsigned long | |
121 | channelBytes), | |
122 | int (*Server_Channel_Init) | |
123 | (void *x, unsigned char *clientStr, | |
124 | U32 clientStrLen, U64 bytes), | |
125 | ULTRA_VBUS_DEVICEINFO *chipset_DriverInfo); | |
126 | ||
90addb02 | 127 | int uisctrl_unregister_req_handler_ex(uuid_le switchTypeGuid); |
12e364b9 KC |
128 | unsigned char *util_map_virt(struct phys_info *sg); |
129 | void util_unmap_virt(struct phys_info *sg); | |
130 | unsigned char *util_map_virt_atomic(struct phys_info *sg); | |
131 | void util_unmap_virt_atomic(void *buf); | |
132 | int uislib_server_inject_add_vnic(U32 switchNo, U32 BusNo, U32 numIntPorts, | |
133 | U32 numExtPorts, MACARRAY pmac[], | |
134 | pCHANNEL_HEADER **chan); | |
135 | void uislib_server_inject_del_vnic(U32 switchNo, U32 busNo, U32 numIntPorts, | |
136 | U32 numExtPorts); | |
90addb02 | 137 | int uislib_client_inject_add_bus(U32 busNo, uuid_le instGuid, |
12e364b9 KC |
138 | U64 channelAddr, ulong nChannelBytes); |
139 | int uislib_client_inject_del_bus(U32 busNo); | |
140 | ||
141 | int uislib_client_inject_add_vhba(U32 busNo, U32 devNo, | |
142 | U64 phys_chan_addr, U32 chan_bytes, | |
90addb02 | 143 | int is_test_addr, uuid_le instGuid, |
12e364b9 KC |
144 | struct InterruptInfo *intr); |
145 | int uislib_client_inject_pause_vhba(U32 busNo, U32 devNo); | |
146 | int uislib_client_inject_resume_vhba(U32 busNo, U32 devNo); | |
147 | int uislib_client_inject_del_vhba(U32 busNo, U32 devNo); | |
148 | int uislib_client_inject_add_vnic(U32 busNo, U32 devNo, | |
149 | U64 phys_chan_addr, U32 chan_bytes, | |
90addb02 | 150 | int is_test_addr, uuid_le instGuid, |
12e364b9 KC |
151 | struct InterruptInfo *intr); |
152 | int uislib_client_inject_pause_vnic(U32 busNo, U32 devNo); | |
153 | int uislib_client_inject_resume_vnic(U32 busNo, U32 devNo); | |
154 | int uislib_client_inject_del_vnic(U32 busNo, U32 devNo); | |
155 | #ifdef STORAGE_CHANNEL | |
156 | U64 uislib_storage_channel(int client_id); | |
157 | #endif | |
158 | int uislib_get_owned_pdest(struct uisscsi_dest *pdest); | |
159 | ||
160 | int uislib_send_event(CONTROLVM_ID id, CONTROLVM_MESSAGE_PACKET *event); | |
161 | ||
162 | /* structure used by vhba & vnic to keep track of queue & thread info */ | |
163 | struct chaninfo { | |
164 | struct uisqueue_info *queueinfo; | |
165 | /* this specifies the queue structures for a channel */ | |
166 | /* ALLOCATED BY THE OTHER END - WE JUST GET A POINTER TO THE MEMORY */ | |
167 | spinlock_t insertlock; | |
168 | /* currently used only in virtnic when sending data to uisnic */ | |
169 | /* to synchronize the inserts into the signal queue */ | |
170 | struct uisthread_info threadinfo; | |
171 | /* this specifies the thread structures used by the thread that */ | |
172 | /* handles this channel */ | |
173 | }; | |
174 | ||
175 | /* this is the wait code for all the threads - it is used to get | |
176 | * something from a queue choices: wait_for_completion_interruptible, | |
177 | * _timeout, interruptible_timeout | |
178 | */ | |
179 | #define UIS_THREAD_WAIT_MSEC(x) { \ | |
180 | set_current_state(TASK_INTERRUPTIBLE); \ | |
181 | schedule_timeout(msecs_to_jiffies(x)); \ | |
182 | } | |
183 | #define UIS_THREAD_WAIT_USEC(x) { \ | |
184 | set_current_state(TASK_INTERRUPTIBLE); \ | |
185 | schedule_timeout(usecs_to_jiffies(x)); \ | |
186 | } | |
187 | #define UIS_THREAD_WAIT UIS_THREAD_WAIT_MSEC(5) | |
188 | #define UIS_THREAD_WAIT_SEC(x) { \ | |
189 | set_current_state(TASK_INTERRUPTIBLE); \ | |
190 | schedule_timeout((x)*HZ); \ | |
191 | } | |
192 | ||
12e364b9 KC |
193 | /* This is a hack until we fix IOVM to initialize the channel header |
194 | * correctly at DEVICE_CREATE time, INSTEAD OF waiting until | |
195 | * DEVICE_CONFIGURE time. | |
196 | */ | |
e40d1c8a KC |
197 | static inline void |
198 | wait_for_valid_guid(uuid_le __iomem *guid) | |
199 | { | |
200 | uuid_le tmpguid; | |
201 | ||
202 | while (1) { | |
203 | memcpy_fromio((void *)&tmpguid, | |
204 | (void __iomem *)guid, sizeof(uuid_le)); | |
205 | if (uuid_le_cmp(tmpguid, NULL_UUID_LE) != 0) | |
206 | break; | |
207 | LOGERR("Waiting for non-0 GUID (why???)...\n"); | |
208 | UIS_THREAD_WAIT_SEC(5); | |
209 | } | |
210 | LOGERR("OK... GUID is non-0 now\n"); | |
211 | } | |
12e364b9 KC |
212 | |
213 | /* CopyFragsInfoFromSkb returns the number of entries added to frags array | |
214 | * Returns -1 on failure. | |
215 | */ | |
927c7927 KC |
216 | unsigned int uisutil_copy_fragsinfo_from_skb(unsigned char *calling_ctx, |
217 | void *skb_in, | |
218 | unsigned int firstfraglen, | |
219 | unsigned int frags_max, | |
220 | struct phys_info frags[]); | |
12e364b9 KC |
221 | |
222 | static inline unsigned int | |
223 | Issue_VMCALL_IO_CONTROLVM_ADDR(U64 *ControlAddress, U32 *ControlBytes) | |
224 | { | |
225 | VMCALL_IO_CONTROLVM_ADDR_PARAMS params; | |
226 | int result = VMCALL_SUCCESS; | |
227 | U64 physaddr; | |
228 | ||
229 | physaddr = virt_to_phys(¶ms); | |
230 | ISSUE_IO_VMCALL(VMCALL_IO_CONTROLVM_ADDR, physaddr, result); | |
231 | if (VMCALL_SUCCESSFUL(result)) { | |
232 | *ControlAddress = params.ChannelAddress; | |
233 | *ControlBytes = params.ChannelBytes; | |
234 | } | |
235 | return result; | |
236 | } | |
237 | ||
238 | static inline unsigned int Issue_VMCALL_IO_DIAG_ADDR(U64 *DiagChannelAddress) | |
239 | { | |
240 | VMCALL_IO_DIAG_ADDR_PARAMS params; | |
241 | int result = VMCALL_SUCCESS; | |
242 | U64 physaddr; | |
243 | ||
244 | physaddr = virt_to_phys(¶ms); | |
245 | ISSUE_IO_VMCALL(VMCALL_IO_DIAG_ADDR, physaddr, result); | |
246 | if (VMCALL_SUCCESSFUL(result)) | |
247 | *DiagChannelAddress = params.ChannelAddress; | |
248 | return result; | |
249 | } | |
250 | ||
251 | static inline unsigned int | |
252 | Issue_VMCALL_IO_VISORSERIAL_ADDR(U64 *DiagChannelAddress) | |
253 | { | |
254 | VMCALL_IO_VISORSERIAL_ADDR_PARAMS params; | |
255 | int result = VMCALL_SUCCESS; | |
256 | U64 physaddr; | |
257 | ||
258 | physaddr = virt_to_phys(¶ms); | |
259 | ISSUE_IO_VMCALL(VMCALL_IO_VISORSERIAL_ADDR, physaddr, result); | |
260 | if (VMCALL_SUCCESSFUL(result)) | |
261 | *DiagChannelAddress = params.ChannelAddress; | |
262 | return result; | |
263 | } | |
264 | ||
265 | static inline S64 Issue_VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET(void) | |
266 | { | |
267 | U64 result = VMCALL_SUCCESS; | |
268 | U64 physaddr = 0; | |
269 | ||
270 | ISSUE_IO_VMCALL(VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET, physaddr, | |
271 | result); | |
272 | return result; | |
273 | } | |
274 | ||
275 | static inline S64 Issue_VMCALL_MEASUREMENT_DO_NOTHING(void) | |
276 | { | |
277 | U64 result = VMCALL_SUCCESS; | |
278 | U64 physaddr = 0; | |
279 | ||
280 | ISSUE_IO_VMCALL(VMCALL_MEASUREMENT_DO_NOTHING, physaddr, result); | |
281 | return result; | |
282 | } | |
283 | ||
284 | struct log_info_t { | |
285 | volatile unsigned long long last_cycles; | |
286 | unsigned long long delta_sum[64]; | |
287 | unsigned long long delta_cnt[64]; | |
288 | unsigned long long max_delta[64]; | |
289 | unsigned long long min_delta[64]; | |
290 | }; | |
291 | ||
292 | static inline int Issue_VMCALL_UPDATE_PHYSICAL_TIME(U64 adjustment) | |
293 | { | |
294 | int result = VMCALL_SUCCESS; | |
295 | ||
296 | ISSUE_IO_VMCALL(VMCALL_UPDATE_PHYSICAL_TIME, adjustment, result); | |
297 | return result; | |
298 | } | |
299 | ||
300 | static inline unsigned int | |
301 | Issue_VMCALL_CHANNEL_MISMATCH(const char *ChannelName, | |
302 | const char *ItemName, | |
303 | U32 SourceLineNumber, const char *path_n_fn) | |
304 | { | |
305 | VMCALL_CHANNEL_VERSION_MISMATCH_PARAMS params; | |
306 | int result = VMCALL_SUCCESS; | |
307 | U64 physaddr; | |
308 | char *last_slash = NULL; | |
309 | ||
4c86db6a | 310 | strlcpy(params.ChannelName, ChannelName, |
12e364b9 | 311 | lengthof(VMCALL_CHANNEL_VERSION_MISMATCH_PARAMS, ChannelName)); |
4c86db6a | 312 | strlcpy(params.ItemName, ItemName, |
12e364b9 KC |
313 | lengthof(VMCALL_CHANNEL_VERSION_MISMATCH_PARAMS, ItemName)); |
314 | params.SourceLineNumber = SourceLineNumber; | |
315 | ||
316 | last_slash = strrchr(path_n_fn, '/'); | |
317 | if (last_slash != NULL) { | |
318 | last_slash++; | |
4c86db6a | 319 | strlcpy(params.SourceFileName, last_slash, |
12e364b9 KC |
320 | lengthof(VMCALL_CHANNEL_VERSION_MISMATCH_PARAMS, |
321 | SourceFileName)); | |
322 | } else | |
4c86db6a | 323 | strlcpy(params.SourceFileName, |
12e364b9 KC |
324 | "Cannot determine source filename", |
325 | lengthof(VMCALL_CHANNEL_VERSION_MISMATCH_PARAMS, | |
326 | SourceFileName)); | |
327 | ||
328 | physaddr = virt_to_phys(¶ms); | |
329 | ISSUE_IO_VMCALL(VMCALL_CHANNEL_VERSION_MISMATCH, physaddr, result); | |
330 | return result; | |
331 | } | |
332 | ||
333 | static inline unsigned int Issue_VMCALL_FATAL_BYE_BYE(void) | |
334 | { | |
335 | int result = VMCALL_SUCCESS; | |
336 | U64 physaddr = 0; | |
337 | ||
338 | ISSUE_IO_VMCALL(VMCALL_GENERIC_SURRENDER_QUANTUM_FOREVER, physaddr, | |
339 | result); | |
340 | return result; | |
341 | } | |
342 | ||
343 | #define UIS_DAEMONIZE(nam) | |
12e364b9 KC |
344 | void *uislib_cache_alloc(struct kmem_cache *cur_pool, char *fn, int ln); |
345 | #define UISCACHEALLOC(cur_pool) uislib_cache_alloc(cur_pool, __FILE__, __LINE__) | |
346 | void uislib_cache_free(struct kmem_cache *cur_pool, void *p, char *fn, int ln); | |
347 | #define UISCACHEFREE(cur_pool, p) \ | |
348 | uislib_cache_free(cur_pool, p, __FILE__, __LINE__) | |
349 | ||
350 | void uislib_enable_channel_interrupts(U32 busNo, U32 devNo, | |
351 | int (*interrupt)(void *), | |
352 | void *interrupt_context); | |
353 | void uislib_disable_channel_interrupts(U32 busNo, U32 devNo); | |
354 | void uislib_force_channel_interrupt(U32 busNo, U32 devNo); | |
355 | ||
356 | #endif /* __UISUTILS__H__ */ |