]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blob - drivers/staging/unisys/uislib/uisutils.c
staging: unisys: fix CamelCase in struct req_handler_info
[mirror_ubuntu-zesty-kernel.git] / drivers / staging / unisys / uislib / uisutils.c
1 /* uisutils.c
2 *
3 * Copyright (C) 2010 - 2013 UNISYS CORPORATION
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 #include <linux/string.h>
19 #include <linux/slab.h>
20 #include <linux/types.h>
21 #include <linux/uuid.h>
22 #include <linux/spinlock.h>
23 #include <linux/list.h>
24 #include "uniklog.h"
25 #include "uisutils.h"
26 #include "version.h"
27 #include "vbushelper.h"
28 #include <linux/uuid.h>
29 #include <linux/skbuff.h>
30 #include <linux/uuid.h>
31 #ifdef CONFIG_HIGHMEM
32 #include <linux/highmem.h>
33 #endif
34
35 /* this is shorter than using __FILE__ (full path name) in
36 * debug/info/error messages
37 */
38 #define CURRENT_FILE_PC UISLIB_PC_uisutils_c
39 #define __MYFILE__ "uisutils.c"
40
41 /* exports */
42 atomic_t uisutils_registered_services = ATOMIC_INIT(0);
43 /* num registrations via
44 * uisctrl_register_req_handler() or
45 * uisctrl_register_req_handler_ex() */
46
47
48 /*****************************************************/
49 /* Utility functions */
50 /*****************************************************/
51
52 int
53 uisutil_add_proc_line_ex(int *total, char **buffer, int *buffer_remaining,
54 char *format, ...)
55 {
56 va_list args;
57 int len;
58
59 DBGINF("buffer = 0x%p : *buffer = 0x%p.\n", buffer, *buffer);
60 va_start(args, format);
61 len = vsnprintf(*buffer, *buffer_remaining, format, args);
62 if (len >= *buffer_remaining) {
63 *buffer += *buffer_remaining;
64 *total += *buffer_remaining;
65 *buffer_remaining = 0;
66 LOGERR("bytes remaining is too small!\n");
67 return -1;
68 }
69 *buffer_remaining -= len;
70 *buffer += len;
71 *total += len;
72 return len;
73 }
74 EXPORT_SYMBOL_GPL(uisutil_add_proc_line_ex);
75
76 int
77 uisctrl_register_req_handler(int type, void *fptr,
78 ULTRA_VBUS_DEVICEINFO *chipset_driver_info)
79 {
80 LOGINF("type = %d, fptr = 0x%p.\n", type, fptr);
81
82 switch (type) {
83 case 2:
84 if (fptr) {
85 if (!virt_control_chan_func)
86 atomic_inc(&uisutils_registered_services);
87 virt_control_chan_func = fptr;
88 } else {
89 if (virt_control_chan_func)
90 atomic_dec(&uisutils_registered_services);
91 virt_control_chan_func = NULL;
92 }
93 break;
94
95 default:
96 LOGERR("invalid type %d.\n", type);
97 return 0;
98 }
99 if (chipset_driver_info)
100 bus_device_info_init(chipset_driver_info, "chipset", "uislib",
101 VERSION, NULL);
102
103 return 1;
104 }
105 EXPORT_SYMBOL_GPL(uisctrl_register_req_handler);
106
107 int
108 uisctrl_register_req_handler_ex(uuid_le switchTypeGuid,
109 const char *switch_type_name,
110 int (*controlfunc)(struct io_msgs *),
111 unsigned long min_channel_bytes,
112 int (*Server_Channel_Ok)(unsigned long
113 channelBytes),
114 int (*Server_Channel_Init)
115 (void *x, unsigned char *clientStr,
116 u32 clientStrLen, u64 bytes),
117 ULTRA_VBUS_DEVICEINFO *chipset_DriverInfo)
118 {
119 struct req_handler_info *pReqHandlerInfo;
120 int rc = 0; /* assume failure */
121
122 LOGINF("type=%pUL, controlfunc=0x%p.\n",
123 &switchTypeGuid, controlfunc);
124 if (!controlfunc) {
125 LOGERR("%pUL: controlfunc must be supplied\n", &switchTypeGuid);
126 goto Away;
127 }
128 if (!Server_Channel_Ok) {
129 LOGERR("%pUL: Server_Channel_Ok must be supplied\n",
130 &switchTypeGuid);
131 goto Away;
132 }
133 if (!Server_Channel_Init) {
134 LOGERR("%pUL: Server_Channel_Init must be supplied\n",
135 &switchTypeGuid);
136 goto Away;
137 }
138 pReqHandlerInfo = ReqHandlerAdd(switchTypeGuid,
139 switch_type_name,
140 controlfunc,
141 min_channel_bytes,
142 Server_Channel_Ok, Server_Channel_Init);
143 if (!pReqHandlerInfo) {
144 LOGERR("failed to add %pUL to server list\n", &switchTypeGuid);
145 goto Away;
146 }
147
148 atomic_inc(&uisutils_registered_services);
149 rc = 1; /* success */
150 Away:
151 if (rc) {
152 if (chipset_DriverInfo)
153 bus_device_info_init(chipset_DriverInfo, "chipset",
154 "uislib", VERSION, NULL);
155 } else
156 LOGERR("failed to register type %pUL.\n", &switchTypeGuid);
157
158 return rc;
159 }
160 EXPORT_SYMBOL_GPL(uisctrl_register_req_handler_ex);
161
162 int
163 uisctrl_unregister_req_handler_ex(uuid_le switchTypeGuid)
164 {
165 int rc = 0; /* assume failure */
166
167 LOGINF("type=%pUL.\n", &switchTypeGuid);
168 if (ReqHandlerDel(switchTypeGuid) < 0) {
169 LOGERR("failed to remove %pUL from server list\n",
170 &switchTypeGuid);
171 goto Away;
172 }
173 atomic_dec(&uisutils_registered_services);
174 rc = 1; /* success */
175 Away:
176 if (!rc)
177 LOGERR("failed to unregister type %pUL.\n", &switchTypeGuid);
178 return rc;
179 }
180 EXPORT_SYMBOL_GPL(uisctrl_unregister_req_handler_ex);
181
182 /*
183 * unsigned int uisutil_copy_fragsinfo_from_skb(unsigned char *calling_ctx,
184 * void *skb_in,
185 * unsigned int firstfraglen,
186 * unsigned int frags_max,
187 * struct phys_info frags[])
188 *
189 * calling_ctx - input - a string that is displayed to show
190 * who called * this func
191 * void *skb_in - skb whose frag info we're copying type is hidden so we
192 * don't need to include skbbuff in uisutils.h which is
193 * included in non-networking code.
194 * unsigned int firstfraglen - input - length of first fragment in skb
195 * unsigned int frags_max - input - max len of frags array
196 * struct phys_info frags[] - output - frags array filled in on output
197 * return value indicates number of
198 * entries filled in frags
199 */
200 unsigned int
201 uisutil_copy_fragsinfo_from_skb(unsigned char *calling_ctx, void *skb_in,
202 unsigned int firstfraglen,
203 unsigned int frags_max,
204 struct phys_info frags[])
205 {
206 unsigned int count = 0, ii, size, offset = 0, numfrags;
207 struct sk_buff *skb = skb_in;
208
209 numfrags = skb_shinfo(skb)->nr_frags;
210
211 while (firstfraglen) {
212 if (count == frags_max) {
213 LOGERR("%s frags array too small: max:%d count:%d\n",
214 calling_ctx, frags_max, count);
215 return -1; /* failure */
216 }
217 frags[count].pi_pfn =
218 page_to_pfn(virt_to_page(skb->data + offset));
219 frags[count].pi_off =
220 (unsigned long) (skb->data + offset) & PI_PAGE_MASK;
221 size =
222 min(firstfraglen,
223 (unsigned int) (PI_PAGE_SIZE - frags[count].pi_off));
224 /* can take smallest of firstfraglen(what's left) OR
225 * bytes left in the page
226 */
227 frags[count].pi_len = size;
228 firstfraglen -= size;
229 offset += size;
230 count++;
231 }
232 if (!numfrags)
233 goto dolist;
234
235 if ((count + numfrags) > frags_max) {
236 LOGERR("**** FAILED %s frags array too small: max:%d count+nr_frags:%d\n",
237 calling_ctx, frags_max, count + numfrags);
238 return -1; /* failure */
239 }
240
241 for (ii = 0; ii < numfrags; ii++) {
242 count = add_physinfo_entries(page_to_pfn(
243 skb_frag_page(&skb_shinfo(skb)->frags[ii])),
244 skb_shinfo(skb)->frags[ii].
245 page_offset,
246 skb_shinfo(skb)->frags[ii].
247 size, count, frags_max,
248 frags);
249 if (count == 0) {
250 LOGERR("**** FAILED to add physinfo entries\n");
251 return -1; /* failure */
252 }
253 }
254
255 dolist: if (skb_shinfo(skb)->frag_list) {
256 struct sk_buff *skbinlist;
257 int c;
258
259 for (skbinlist = skb_shinfo(skb)->frag_list; skbinlist;
260 skbinlist = skbinlist->next) {
261
262 c = uisutil_copy_fragsinfo_from_skb("recursive",
263 skbinlist,
264 skbinlist->len - skbinlist->data_len,
265 frags_max - count,
266 &frags[count]);
267 if (c == -1) {
268 LOGERR("**** FAILED recursive call failed\n");
269 return -1;
270 }
271 count += c;
272 }
273 }
274 return count;
275 }
276 EXPORT_SYMBOL_GPL(uisutil_copy_fragsinfo_from_skb);
277
278 static LIST_HEAD(ReqHandlerInfo_list); /* list of struct req_handler_info */
279 static DEFINE_SPINLOCK(ReqHandlerInfo_list_lock);
280
281 struct req_handler_info *
282 ReqHandlerAdd(uuid_le switchTypeGuid,
283 const char *switch_type_name,
284 int (*controlfunc)(struct io_msgs *),
285 unsigned long min_channel_bytes,
286 int (*Server_Channel_Ok)(unsigned long channelBytes),
287 int (*Server_Channel_Init)
288 (void *x, unsigned char *clientStr, u32 clientStrLen, u64 bytes))
289 {
290 struct req_handler_info *rc = NULL;
291
292 rc = kzalloc(sizeof(*rc), GFP_ATOMIC);
293 if (!rc)
294 return NULL;
295 rc->switch_uuid = switchTypeGuid;
296 rc->controlfunc = controlfunc;
297 rc->min_channel_bytes = min_channel_bytes;
298 rc->server_channel_ok = Server_Channel_Ok;
299 rc->server_channel_init = Server_Channel_Init;
300 if (switch_type_name)
301 strncpy(rc->switch_type_name, switch_type_name,
302 sizeof(rc->switch_type_name) - 1);
303 spin_lock(&ReqHandlerInfo_list_lock);
304 list_add_tail(&(rc->list_link), &ReqHandlerInfo_list);
305 spin_unlock(&ReqHandlerInfo_list_lock);
306
307 return rc;
308 }
309
310 struct req_handler_info *
311 ReqHandlerFind(uuid_le switchTypeGuid)
312 {
313 struct list_head *lelt, *tmp;
314 struct req_handler_info *entry = NULL;
315
316 spin_lock(&ReqHandlerInfo_list_lock);
317 list_for_each_safe(lelt, tmp, &ReqHandlerInfo_list) {
318 entry = list_entry(lelt, struct req_handler_info, list_link);
319 if (uuid_le_cmp(entry->switch_uuid, switchTypeGuid) == 0) {
320 spin_unlock(&ReqHandlerInfo_list_lock);
321 return entry;
322 }
323 }
324 spin_unlock(&ReqHandlerInfo_list_lock);
325 return NULL;
326 }
327
328 int
329 ReqHandlerDel(uuid_le switchTypeGuid)
330 {
331 struct list_head *lelt, *tmp;
332 struct req_handler_info *entry = NULL;
333 int rc = -1;
334
335 spin_lock(&ReqHandlerInfo_list_lock);
336 list_for_each_safe(lelt, tmp, &ReqHandlerInfo_list) {
337 entry = list_entry(lelt, struct req_handler_info, list_link);
338 if (uuid_le_cmp(entry->switch_uuid, switchTypeGuid) == 0) {
339 list_del(lelt);
340 kfree(entry);
341 rc++;
342 }
343 }
344 spin_unlock(&ReqHandlerInfo_list_lock);
345 return rc;
346 }