]>
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, | |
32b6b291 | 117 | struct ultra_vbus_deviceinfo *chipset_driver_info); |
1032885d | 118 | int uisctrl_register_req_handler_ex(uuid_le switch_guid, |
32b6b291 BR |
119 | const char *switch_type_name, |
120 | int (*fptr)(struct io_msgs *), | |
121 | unsigned long min_channel_bytes, | |
122 | int (*svr_channel_ok)(unsigned long | |
123 | channel_bytes), | |
124 | int (*svr_channel_init)(void *x, | |
125 | unsigned char *client_str, | |
126 | u32 client_str_len, | |
127 | u64 bytes), | |
128 | struct 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 | ||
2ea5117b BR |
158 | int uislib_send_event(enum controlvm_id id, |
159 | struct controlvm_message_packet *event); | |
12e364b9 KC |
160 | |
161 | /* structure used by vhba & vnic to keep track of queue & thread info */ | |
162 | struct chaninfo { | |
163 | struct uisqueue_info *queueinfo; | |
164 | /* this specifies the queue structures for a channel */ | |
165 | /* ALLOCATED BY THE OTHER END - WE JUST GET A POINTER TO THE MEMORY */ | |
166 | spinlock_t insertlock; | |
167 | /* currently used only in virtnic when sending data to uisnic */ | |
168 | /* to synchronize the inserts into the signal queue */ | |
169 | struct uisthread_info threadinfo; | |
170 | /* this specifies the thread structures used by the thread that */ | |
171 | /* handles this channel */ | |
172 | }; | |
173 | ||
174 | /* this is the wait code for all the threads - it is used to get | |
175 | * something from a queue choices: wait_for_completion_interruptible, | |
176 | * _timeout, interruptible_timeout | |
177 | */ | |
178 | #define UIS_THREAD_WAIT_MSEC(x) { \ | |
179 | set_current_state(TASK_INTERRUPTIBLE); \ | |
180 | schedule_timeout(msecs_to_jiffies(x)); \ | |
181 | } | |
2aef999b | 182 | |
12e364b9 KC |
183 | #define UIS_THREAD_WAIT_USEC(x) { \ |
184 | set_current_state(TASK_INTERRUPTIBLE); \ | |
185 | schedule_timeout(usecs_to_jiffies(x)); \ | |
186 | } | |
2aef999b | 187 | |
12e364b9 | 188 | #define UIS_THREAD_WAIT UIS_THREAD_WAIT_MSEC(5) |
2aef999b | 189 | |
12e364b9 KC |
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 | 226 | { |
f42aea3c | 227 | struct vmcall_io_controlvm_addr_params params; |
12e364b9 | 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)) { | |
f42aea3c BR |
234 | *control_addr = params.address; |
235 | *control_bytes = params.channel_bytes; | |
12e364b9 KC |
236 | } |
237 | return result; | |
238 | } | |
239 | ||
007ef59b | 240 | static inline unsigned int issue_vmcall_io_diag_addr(u64 *diag_channel_addr) |
12e364b9 | 241 | { |
3dbf7b73 | 242 | struct vmcall_io_diag_addr_params params; |
12e364b9 | 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)) | |
3dbf7b73 | 249 | *diag_channel_addr = params.address; |
12e364b9 KC |
250 | return result; |
251 | } | |
252 | ||
8359367e | 253 | static inline unsigned int issue_vmcall_io_visorserial_addr(u64 *channel_addr) |
12e364b9 | 254 | { |
0520cfb1 | 255 | struct vmcall_io_visorserial_addr_params params; |
12e364b9 | 256 | int result = VMCALL_SUCCESS; |
5fc0229a | 257 | u64 physaddr; |
12e364b9 KC |
258 | |
259 | physaddr = virt_to_phys(¶ms); | |
260 | ISSUE_IO_VMCALL(VMCALL_IO_VISORSERIAL_ADDR, physaddr, result); | |
261 | if (VMCALL_SUCCESSFUL(result)) | |
0520cfb1 | 262 | *channel_addr = params.address; |
12e364b9 KC |
263 | return result; |
264 | } | |
265 | ||
e76446ea | 266 | static inline s64 issue_vmcall_query_guest_virtual_time_offset(void) |
12e364b9 | 267 | { |
5fc0229a BR |
268 | u64 result = VMCALL_SUCCESS; |
269 | u64 physaddr = 0; | |
12e364b9 KC |
270 | |
271 | ISSUE_IO_VMCALL(VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET, physaddr, | |
272 | result); | |
273 | return result; | |
274 | } | |
275 | ||
12e364b9 | 276 | struct log_info_t { |
3301335f | 277 | unsigned long long last_cycles; |
12e364b9 KC |
278 | unsigned long long delta_sum[64]; |
279 | unsigned long long delta_cnt[64]; | |
280 | unsigned long long max_delta[64]; | |
281 | unsigned long long min_delta[64]; | |
282 | }; | |
283 | ||
b8fd9902 | 284 | static inline int issue_vmcall_update_physical_time(u64 adjustment) |
12e364b9 KC |
285 | { |
286 | int result = VMCALL_SUCCESS; | |
287 | ||
288 | ISSUE_IO_VMCALL(VMCALL_UPDATE_PHYSICAL_TIME, adjustment, result); | |
289 | return result; | |
290 | } | |
291 | ||
b591ebf2 BR |
292 | static inline unsigned int issue_vmcall_channel_mismatch(const char *chname, |
293 | const char *item_name, u32 line_no, | |
294 | const char *path_n_fn) | |
12e364b9 | 295 | { |
a09ad889 | 296 | struct vmcall_channel_version_mismatch_params params; |
12e364b9 | 297 | int result = VMCALL_SUCCESS; |
5fc0229a | 298 | u64 physaddr; |
12e364b9 KC |
299 | char *last_slash = NULL; |
300 | ||
a09ad889 BR |
301 | strlcpy(params.chname, chname, sizeof(params.chname)); |
302 | strlcpy(params.item_name, item_name, sizeof(params.item_name)); | |
303 | params.line_no = line_no; | |
12e364b9 KC |
304 | |
305 | last_slash = strrchr(path_n_fn, '/'); | |
306 | if (last_slash != NULL) { | |
307 | last_slash++; | |
a09ad889 | 308 | strlcpy(params.file_name, last_slash, sizeof(params.file_name)); |
12e364b9 | 309 | } else |
a09ad889 | 310 | strlcpy(params.file_name, |
12e364b9 | 311 | "Cannot determine source filename", |
a09ad889 | 312 | sizeof(params.file_name)); |
12e364b9 KC |
313 | |
314 | physaddr = virt_to_phys(¶ms); | |
315 | ISSUE_IO_VMCALL(VMCALL_CHANNEL_VERSION_MISMATCH, physaddr, result); | |
316 | return result; | |
317 | } | |
318 | ||
12e364b9 | 319 | #define UIS_DAEMONIZE(nam) |
12e364b9 KC |
320 | void *uislib_cache_alloc(struct kmem_cache *cur_pool, char *fn, int ln); |
321 | #define UISCACHEALLOC(cur_pool) uislib_cache_alloc(cur_pool, __FILE__, __LINE__) | |
322 | void uislib_cache_free(struct kmem_cache *cur_pool, void *p, char *fn, int ln); | |
323 | #define UISCACHEFREE(cur_pool, p) \ | |
324 | uislib_cache_free(cur_pool, p, __FILE__, __LINE__) | |
325 | ||
93d1304f | 326 | void uislib_enable_channel_interrupts(u32 bus_no, u32 dev_no, |
12e364b9 KC |
327 | int (*interrupt)(void *), |
328 | void *interrupt_context); | |
d0dd33f3 | 329 | void uislib_disable_channel_interrupts(u32 bus_no, u32 dev_no); |
f7b33ff4 | 330 | void uislib_force_channel_interrupt(u32 bus_no, u32 dev_no); |
12e364b9 KC |
331 | |
332 | #endif /* __UISUTILS__H__ */ |