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