3 * Copyright (C) 2010 - 2013 UNISYS CORPORATION
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.
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
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>
27 #include "vbushelper.h"
28 #include <linux/uuid.h>
29 #include <linux/skbuff.h>
30 #include <linux/uuid.h>
32 #include <linux/highmem.h>
35 /* this is shorter than using __FILE__ (full path name) in
36 * debug/info/error messages
38 #define CURRENT_FILE_PC UISLIB_PC_uisutils_c
39 #define __MYFILE__ "uisutils.c"
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() */
48 /*****************************************************/
49 /* Utility functions */
50 /*****************************************************/
53 uisutil_add_proc_line_ex(int *total
, char **buffer
, int *buffer_remaining
,
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");
69 *buffer_remaining
-= len
;
74 EXPORT_SYMBOL_GPL(uisutil_add_proc_line_ex
);
77 uisctrl_register_req_handler(int type
, void *fptr
,
78 ULTRA_VBUS_DEVICEINFO
*chipset_driver_info
)
80 LOGINF("type = %d, fptr = 0x%p.\n", type
, fptr
);
85 if (!virt_control_chan_func
)
86 atomic_inc(&uisutils_registered_services
);
87 virt_control_chan_func
= fptr
;
89 if (virt_control_chan_func
)
90 atomic_dec(&uisutils_registered_services
);
91 virt_control_chan_func
= NULL
;
96 LOGERR("invalid type %d.\n", type
);
99 if (chipset_driver_info
)
100 bus_device_info_init(chipset_driver_info
, "chipset", "uislib",
105 EXPORT_SYMBOL_GPL(uisctrl_register_req_handler
);
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
114 int (*Server_Channel_Init
)
115 (void *x
, unsigned char *clientStr
,
116 u32 clientStrLen
, u64 bytes
),
117 ULTRA_VBUS_DEVICEINFO
*chipset_DriverInfo
)
119 struct req_handler_info
*pReqHandlerInfo
;
120 int rc
= 0; /* assume failure */
122 LOGINF("type=%pUL, controlfunc=0x%p.\n",
123 &switchTypeGuid
, controlfunc
);
125 LOGERR("%pUL: controlfunc must be supplied\n", &switchTypeGuid
);
128 if (!Server_Channel_Ok
) {
129 LOGERR("%pUL: Server_Channel_Ok must be supplied\n",
133 if (!Server_Channel_Init
) {
134 LOGERR("%pUL: Server_Channel_Init must be supplied\n",
138 pReqHandlerInfo
= ReqHandlerAdd(switchTypeGuid
,
142 Server_Channel_Ok
, Server_Channel_Init
);
143 if (!pReqHandlerInfo
) {
144 LOGERR("failed to add %pUL to server list\n", &switchTypeGuid
);
148 atomic_inc(&uisutils_registered_services
);
149 rc
= 1; /* success */
152 if (chipset_DriverInfo
)
153 bus_device_info_init(chipset_DriverInfo
, "chipset",
154 "uislib", VERSION
, NULL
);
156 LOGERR("failed to register type %pUL.\n", &switchTypeGuid
);
160 EXPORT_SYMBOL_GPL(uisctrl_register_req_handler_ex
);
163 uisctrl_unregister_req_handler_ex(uuid_le switchTypeGuid
)
165 int rc
= 0; /* assume failure */
167 LOGINF("type=%pUL.\n", &switchTypeGuid
);
168 if (ReqHandlerDel(switchTypeGuid
) < 0) {
169 LOGERR("failed to remove %pUL from server list\n",
173 atomic_dec(&uisutils_registered_services
);
174 rc
= 1; /* success */
177 LOGERR("failed to unregister type %pUL.\n", &switchTypeGuid
);
180 EXPORT_SYMBOL_GPL(uisctrl_unregister_req_handler_ex
);
183 * unsigned int uisutil_copy_fragsinfo_from_skb(unsigned char *calling_ctx,
185 * unsigned int firstfraglen,
186 * unsigned int frags_max,
187 * struct phys_info frags[])
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
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
[])
206 unsigned int count
= 0, ii
, size
, offset
= 0, numfrags
;
207 struct sk_buff
*skb
= skb_in
;
209 numfrags
= skb_shinfo(skb
)->nr_frags
;
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 */
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
;
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
227 frags
[count
].pi_len
= size
;
228 firstfraglen
-= size
;
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 */
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
].
246 skb_shinfo(skb
)->frags
[ii
].
247 size
, count
, frags_max
,
250 LOGERR("**** FAILED to add physinfo entries\n");
251 return -1; /* failure */
255 dolist
: if (skb_shinfo(skb
)->frag_list
) {
256 struct sk_buff
*skbinlist
;
259 for (skbinlist
= skb_shinfo(skb
)->frag_list
; skbinlist
;
260 skbinlist
= skbinlist
->next
) {
262 c
= uisutil_copy_fragsinfo_from_skb("recursive",
264 skbinlist
->len
- skbinlist
->data_len
,
268 LOGERR("**** FAILED recursive call failed\n");
276 EXPORT_SYMBOL_GPL(uisutil_copy_fragsinfo_from_skb
);
278 static LIST_HEAD(ReqHandlerInfo_list
); /* list of struct req_handler_info */
279 static DEFINE_SPINLOCK(ReqHandlerInfo_list_lock
);
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
))
290 struct req_handler_info
*rc
= NULL
;
292 rc
= kzalloc(sizeof(*rc
), GFP_ATOMIC
);
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
);
310 struct req_handler_info
*
311 ReqHandlerFind(uuid_le switchTypeGuid
)
313 struct list_head
*lelt
, *tmp
;
314 struct req_handler_info
*entry
= NULL
;
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
);
324 spin_unlock(&ReqHandlerInfo_list_lock
);
329 ReqHandlerDel(uuid_le switchTypeGuid
)
331 struct list_head
*lelt
, *tmp
;
332 struct req_handler_info
*entry
= NULL
;
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) {
344 spin_unlock(&ReqHandlerInfo_list_lock
);