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