]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/staging/silicom/bypasslib/bypass.c
Staging: silicom: fix sparse non static symbol warnings
[karo-tx-linux.git] / drivers / staging / silicom / bypasslib / bypass.c
1 /******************************************************************************/
2 /*                                                                            */
3 /* bypass library, Copyright (c) 2004-2007 Silicom, Ltd                       */
4 /*                                                                            */
5 /* This program is free software; you can redistribute it and/or modify       */
6 /* it under the terms of the GNU General Public License as published by       */
7 /* the Free Software Foundation, located in the file LICENSE.                 */
8 /*                                                                            */
9 /*                                                                            */
10 /* bypass.c                                                                   */
11 /*                                                                            */
12 /******************************************************************************/
13
14 #if defined(CONFIG_SMP) && !defined(__SMP__)
15 #define __SMP__
16 #endif
17
18 #include <linux/module.h>
19 #include <linux/kernel.h>
20 #include <asm/unistd.h>
21
22 #include <linux/sched.h>
23 #include <linux/wait.h>
24
25 #include <linux/netdevice.h>    /* struct device, and other headers */
26 #include <linux/kernel_stat.h>
27 #include <linux/pci.h>
28 #include <linux/rtnetlink.h>
29 #include <linux/ethtool.h>
30
31 #include <net/net_namespace.h>
32
33 #include "bplibk.h"
34
35 #define MOD_NAME "bypass"
36
37 #define VERSION "\n"MOD_NAME" version 9.0.4\n"
38
39 MODULE_AUTHOR("www.silicom.co.il");
40
41 MODULE_LICENSE("GPL");
42
43 static int do_cmd(struct net_device *dev, struct ifreq *ifr, int cmd, int *data)
44 {
45         int ret = -1;
46         struct if_bypass *bypass_cb;
47
48         bypass_cb = (struct if_bypass *)ifr;
49         bypass_cb->cmd = cmd;
50         bypass_cb->data = *data;
51
52         if (dev->netdev_ops && dev->netdev_ops->ndo_do_ioctl) {
53                 ret = dev->netdev_ops->ndo_do_ioctl(dev, ifr, SIOCGIFBYPASS);
54                 *data = bypass_cb->data;
55         }
56
57         return ret;
58 }
59
60 static int doit(int cmd, int if_index, int *data)
61 {
62         struct ifreq ifr;
63         int ret = -1;
64         struct net_device *dev;
65         struct net_device *n;
66
67         for_each_netdev_safe(&init_net, dev, n) {
68                 if (dev->ifindex == if_index) {
69                         ret = do_cmd(dev, &ifr, cmd, data);
70                         if (ret < 0)
71                                 ret = -1;
72                 }
73         }
74
75         return ret;
76 }
77
78 #define bp_symbol_get(fn_name) symbol_get(fn_name)
79 #define bp_symbol_put(fn_name) symbol_put(fn_name)
80
81 #define SET_BPLIB_INT_FN(fn_name, arg_type, arg, ret)   \
82 ({      int (*fn_ex)(arg_type) = NULL;                  \
83         fn_ex = bp_symbol_get(fn_name##_sd);            \
84         if (fn_ex) {                                    \
85                 ret = fn_ex(arg);                       \
86                 bp_symbol_put(fn_name##_sd);            \
87         } else {                                        \
88                 ret = -1;                               \
89         }                                               \
90 })
91
92 #define  SET_BPLIB_INT_FN2(fn_name, arg_type, arg, arg_type1, arg1, ret)\
93 ({      int (*fn_ex)(arg_type, arg_type1) = NULL;                       \
94         fn_ex = bp_symbol_get(fn_name##_sd);                            \
95         if (fn_ex) {                                                    \
96                 ret = fn_ex(arg, arg1);                                 \
97                 bp_symbol_put(fn_name##_sd);                            \
98         } else {                                                        \
99                 ret = -1;                                               \
100         }                                                               \
101 })
102
103 #define SET_BPLIB_INT_FN3(fn_name, arg_type, arg, arg_type1, arg1,      \
104                           arg_type2, arg2, ret)                         \
105 ({      int (*fn_ex)(arg_type, arg_type1, arg_type2) = NULL;            \
106         fn_ex = bp_symbol_get(fn_name##_sd);                            \
107         if (fn_ex) {                                                    \
108                 ret = fn_ex(arg, arg1, arg2);                           \
109                 bp_symbol_put(fn_name##_sd);                            \
110         } else {                                                        \
111                 ret = -1;                                               \
112         }                                                               \
113 })
114
115 #define DO_BPLIB_GET_ARG_FN(fn_name, ioctl_val, if_index)       \
116 ({      int data, ret = 0;                                      \
117         if (is_dev_sd(if_index)) {                              \
118                 SET_BPLIB_INT_FN(fn_name, int, if_index, ret);  \
119                 return ret;                                     \
120         }                                                       \
121         return doit(ioctl_val, if_index, &data);                \
122 })
123
124 #define DO_BPLIB_SET_ARG_FN(fn_name, ioctl_val, if_index, arg)  \
125 ({      int data, ret = 0;                                      \
126         if (is_dev_sd(if_index)) {                              \
127                 SET_BPLIB_INT_FN2(fn_name, int, if_index, int,  \
128                                   arg, ret);                    \
129                 return ret;                                     \
130         }                                                       \
131         data = arg;                                             \
132         return doit(ioctl_val, if_index, &data);                \
133 })
134
135 static int is_dev_sd(int if_index)
136 {
137         int ret = 0;
138         SET_BPLIB_INT_FN(is_bypass, int, if_index, ret);
139         return ret >= 0 ? 1 : 0;
140 }
141
142 static int is_bypass_dev(int if_index)
143 {
144         struct pci_dev *pdev = NULL;
145         struct net_device *dev = NULL;
146         struct ifreq ifr;
147         int ret = 0;
148         int data = 0;
149
150         while ((pdev = pci_get_class(PCI_CLASS_NETWORK_ETHERNET << 8, pdev))) {
151                 dev = pci_get_drvdata(pdev);
152                 if (dev != NULL) {
153                         dev = pci_get_drvdata(pdev);
154                         if ((dev != NULL) && (dev->ifindex == if_index)) {
155                                 if ((pdev->vendor == SILICOM_VID) &&
156                                     (pdev->device >= SILICOM_BP_PID_MIN) &&
157                                     (pdev->device <= SILICOM_BP_PID_MAX)) {
158                                         goto send_cmd;
159                                 }
160 #if defined(BP_VENDOR_SUPPORT) && defined(ETHTOOL_GDRVINFO)
161                                 else {
162                                         struct ethtool_drvinfo info;
163                                         const struct ethtool_ops *ops =
164                                             dev->ethtool_ops;
165                                         int k = 0;
166
167                                         if (ops->get_drvinfo) {
168                                                 memset(&info, 0, sizeof(info));
169                                                 info.cmd = ETHTOOL_GDRVINFO;
170                                                 ops->get_drvinfo(dev, &info);
171                                                 for (; bp_desc_array[k]; k++)
172                                                         if (!
173                                                             (strcmp
174                                                              (bp_desc_array[k],
175                                                               info.driver)))
176                                                                 goto send_cmd;
177
178                                         }
179
180                                 }
181 #endif
182                                 return -1;
183                         }
184                 }
185         }
186  send_cmd:
187         ret = do_cmd(dev, &ifr, IS_BYPASS, &data);
188         return ret < 0 ? -1 : ret;
189 }
190
191 static int is_bypass(int if_index)
192 {
193         int ret = 0;
194         SET_BPLIB_INT_FN(is_bypass, int, if_index, ret);
195
196         if (ret < 0)
197                 return is_bypass_dev(if_index);
198         return ret;
199 }
200 EXPORT_SYMBOL(is_bypass);
201
202 static int get_bypass_slave(int if_index)
203 {
204         DO_BPLIB_GET_ARG_FN(get_bypass_slave, GET_BYPASS_SLAVE, if_index);
205 }
206 EXPORT_SYMBOL(get_bypass_slave);
207
208 static int get_bypass_caps(int if_index)
209 {
210         DO_BPLIB_GET_ARG_FN(get_bypass_caps, GET_BYPASS_CAPS, if_index);
211 }
212 EXPORT_SYMBOL(get_bypass_caps);
213
214 static int get_wd_set_caps(int if_index)
215 {
216         DO_BPLIB_GET_ARG_FN(get_wd_set_caps, GET_WD_SET_CAPS, if_index);
217 }
218 EXPORT_SYMBOL(get_wd_set_caps);
219
220 static int set_bypass(int if_index, int bypass_mode)
221 {
222         DO_BPLIB_SET_ARG_FN(set_bypass, SET_BYPASS, if_index, bypass_mode);
223 }
224 EXPORT_SYMBOL(set_bypass);
225
226 static int get_bypass(int if_index)
227 {
228         DO_BPLIB_GET_ARG_FN(get_bypass, GET_BYPASS, if_index);
229 }
230 EXPORT_SYMBOL(get_bypass);
231
232 static int get_bypass_change(int if_index)
233 {
234         DO_BPLIB_GET_ARG_FN(get_bypass_change, GET_BYPASS_CHANGE, if_index);
235 }
236 EXPORT_SYMBOL(get_bypass_change);
237
238 static int set_dis_bypass(int if_index, int dis_bypass)
239 {
240         DO_BPLIB_SET_ARG_FN(set_dis_bypass, SET_DIS_BYPASS, if_index,
241                             dis_bypass);
242 }
243 EXPORT_SYMBOL(set_dis_bypass);
244
245 static int get_dis_bypass(int if_index)
246 {
247         DO_BPLIB_GET_ARG_FN(get_dis_bypass, GET_DIS_BYPASS, if_index);
248 }
249 EXPORT_SYMBOL(get_dis_bypass);
250
251 static int set_bypass_pwoff(int if_index, int bypass_mode)
252 {
253         DO_BPLIB_SET_ARG_FN(set_bypass_pwoff, SET_BYPASS_PWOFF, if_index,
254                             bypass_mode);
255 }
256 EXPORT_SYMBOL(set_bypass_pwoff);
257
258 static int get_bypass_pwoff(int if_index)
259 {
260         DO_BPLIB_GET_ARG_FN(get_bypass_pwoff, GET_BYPASS_PWOFF, if_index);
261 }
262 EXPORT_SYMBOL(get_bypass_pwoff);
263
264 static int set_bypass_pwup(int if_index, int bypass_mode)
265 {
266         DO_BPLIB_SET_ARG_FN(set_bypass_pwup, SET_BYPASS_PWUP, if_index,
267                             bypass_mode);
268 }
269 EXPORT_SYMBOL(set_bypass_pwup);
270
271 static int get_bypass_pwup(int if_index)
272 {
273         DO_BPLIB_GET_ARG_FN(get_bypass_pwup, GET_BYPASS_PWUP, if_index);
274 }
275 EXPORT_SYMBOL(get_bypass_pwup);
276
277 static int set_bypass_wd(int if_index, int ms_timeout, int *ms_timeout_set)
278 {
279         int data = ms_timeout;
280         int ret = 0;
281
282         if (is_dev_sd(if_index)) {
283                 SET_BPLIB_INT_FN3(set_bypass_wd, int, if_index, int, ms_timeout,
284                                   int *, ms_timeout_set, ret);
285         } else {
286                 ret = doit(SET_BYPASS_WD, if_index, &data);
287                 if (ret > 0) {
288                         *ms_timeout_set = ret;
289                         ret = 0;
290                 }
291         }
292         return ret;
293 }
294 EXPORT_SYMBOL(set_bypass_wd);
295
296 static int get_bypass_wd(int if_index, int *ms_timeout_set)
297 {
298         int *data = ms_timeout_set;
299         int ret = 0;
300
301         if (is_dev_sd(if_index))
302                 SET_BPLIB_INT_FN2(get_bypass_wd, int, if_index, int *,
303                                   ms_timeout_set, ret);
304         else
305                 ret = doit(GET_BYPASS_WD, if_index, data);
306         return ret;
307 }
308 EXPORT_SYMBOL(get_bypass_wd);
309
310 static int get_wd_expire_time(int if_index, int *ms_time_left)
311 {
312         int *data = ms_time_left, ret = 0;
313
314         if (is_dev_sd(if_index)) {
315                 SET_BPLIB_INT_FN2(get_wd_expire_time, int, if_index, int *,
316                                   ms_time_left, ret);
317         } else {
318                 ret = doit(GET_WD_EXPIRE_TIME, if_index, data);
319                 if ((ret == 0) && (*data != 0))
320                         ret = 1;
321         }
322         return ret;
323 }
324 EXPORT_SYMBOL(get_wd_expire_time);
325
326 static int reset_bypass_wd_timer(int if_index)
327 {
328         DO_BPLIB_GET_ARG_FN(reset_bypass_wd_timer, RESET_BYPASS_WD_TIMER,
329                             if_index);
330 }
331 EXPORT_SYMBOL(reset_bypass_wd_timer);
332
333 static int set_std_nic(int if_index, int bypass_mode)
334 {
335         DO_BPLIB_SET_ARG_FN(set_std_nic, SET_STD_NIC, if_index, bypass_mode);
336 }
337 EXPORT_SYMBOL(set_std_nic);
338
339 static int get_std_nic(int if_index)
340 {
341         DO_BPLIB_GET_ARG_FN(get_std_nic, GET_STD_NIC, if_index);
342 }
343 EXPORT_SYMBOL(get_std_nic);
344
345 static int set_tx(int if_index, int tx_state)
346 {
347         DO_BPLIB_SET_ARG_FN(set_tx, SET_TX, if_index, tx_state);
348 }
349 EXPORT_SYMBOL(set_tx);
350
351 static int get_tx(int if_index)
352 {
353         DO_BPLIB_GET_ARG_FN(get_tx, GET_TX, if_index);
354 }
355 EXPORT_SYMBOL(get_tx);
356
357 static int set_tap(int if_index, int tap_mode)
358 {
359         DO_BPLIB_SET_ARG_FN(set_tap, SET_TAP, if_index, tap_mode);
360 }
361 EXPORT_SYMBOL(set_tap);
362
363 static int get_tap(int if_index)
364 {
365         DO_BPLIB_GET_ARG_FN(get_tap, GET_TAP, if_index);
366 }
367 EXPORT_SYMBOL(get_tap);
368
369 static int get_tap_change(int if_index)
370 {
371         DO_BPLIB_GET_ARG_FN(get_tap_change, GET_TAP_CHANGE, if_index);
372 }
373 EXPORT_SYMBOL(get_tap_change);
374
375 static int set_dis_tap(int if_index, int dis_tap)
376 {
377         DO_BPLIB_SET_ARG_FN(set_dis_tap, SET_DIS_TAP, if_index, dis_tap);
378 }
379 EXPORT_SYMBOL(set_dis_tap);
380
381 static int get_dis_tap(int if_index)
382 {
383         DO_BPLIB_GET_ARG_FN(get_dis_tap, GET_DIS_TAP, if_index);
384 }
385 EXPORT_SYMBOL(get_dis_tap);
386
387 static int set_tap_pwup(int if_index, int tap_mode)
388 {
389         DO_BPLIB_SET_ARG_FN(set_tap_pwup, SET_TAP_PWUP, if_index, tap_mode);
390 }
391 EXPORT_SYMBOL(set_tap_pwup);
392
393 static int get_tap_pwup(int if_index)
394 {
395         DO_BPLIB_GET_ARG_FN(get_tap_pwup, GET_TAP_PWUP, if_index);
396 }
397 EXPORT_SYMBOL(get_tap_pwup);
398
399 static int set_bp_disc(int if_index, int disc_mode)
400 {
401         DO_BPLIB_SET_ARG_FN(set_bp_disc, SET_DISC, if_index, disc_mode);
402 }
403 EXPORT_SYMBOL(set_bp_disc);
404
405 static int get_bp_disc(int if_index)
406 {
407         DO_BPLIB_GET_ARG_FN(get_bp_disc, GET_DISC, if_index);
408 }
409 EXPORT_SYMBOL(get_bp_disc);
410
411 static int get_bp_disc_change(int if_index)
412 {
413         DO_BPLIB_GET_ARG_FN(get_bp_disc_change, GET_DISC_CHANGE, if_index);
414 }
415 EXPORT_SYMBOL(get_bp_disc_change);
416
417 static int set_bp_dis_disc(int if_index, int dis_disc)
418 {
419         DO_BPLIB_SET_ARG_FN(set_bp_dis_disc, SET_DIS_DISC, if_index, dis_disc);
420 }
421 EXPORT_SYMBOL(set_bp_dis_disc);
422
423 static int get_bp_dis_disc(int if_index)
424 {
425         DO_BPLIB_GET_ARG_FN(get_bp_dis_disc, GET_DIS_DISC, if_index);
426 }
427 EXPORT_SYMBOL(get_bp_dis_disc);
428
429 static int set_bp_disc_pwup(int if_index, int disc_mode)
430 {
431         DO_BPLIB_SET_ARG_FN(set_bp_disc_pwup, SET_DISC_PWUP, if_index,
432                             disc_mode);
433 }
434 EXPORT_SYMBOL(set_bp_disc_pwup);
435
436 static int get_bp_disc_pwup(int if_index)
437 {
438         DO_BPLIB_GET_ARG_FN(get_bp_disc_pwup, GET_DISC_PWUP, if_index);
439 }
440 EXPORT_SYMBOL(get_bp_disc_pwup);
441
442 static int set_wd_exp_mode(int if_index, int mode)
443 {
444         DO_BPLIB_SET_ARG_FN(set_wd_exp_mode, SET_WD_EXP_MODE, if_index, mode);
445 }
446 EXPORT_SYMBOL(set_wd_exp_mode);
447
448 static int get_wd_exp_mode(int if_index)
449 {
450         DO_BPLIB_GET_ARG_FN(get_wd_exp_mode, GET_WD_EXP_MODE, if_index);
451 }
452 EXPORT_SYMBOL(get_wd_exp_mode);
453
454 static int set_wd_autoreset(int if_index, int time)
455 {
456         DO_BPLIB_SET_ARG_FN(set_wd_autoreset, SET_WD_AUTORESET, if_index, time);
457 }
458 EXPORT_SYMBOL(set_wd_autoreset);
459
460 static int get_wd_autoreset(int if_index)
461 {
462         DO_BPLIB_GET_ARG_FN(get_wd_autoreset, GET_WD_AUTORESET, if_index);
463 }
464 EXPORT_SYMBOL(get_wd_autoreset);
465
466 static int set_tpl(int if_index, int tpl_mode)
467 {
468         DO_BPLIB_SET_ARG_FN(set_tpl, SET_TPL, if_index, tpl_mode);
469 }
470 EXPORT_SYMBOL(set_tpl);
471
472 static int get_tpl(int if_index)
473 {
474         DO_BPLIB_GET_ARG_FN(get_tpl, GET_TPL, if_index);
475 }
476 EXPORT_SYMBOL(get_tpl);
477
478 static int set_bp_hw_reset(int if_index, int mode)
479 {
480         DO_BPLIB_SET_ARG_FN(set_tpl, SET_BP_HW_RESET, if_index, mode);
481 }
482 EXPORT_SYMBOL(set_bp_hw_reset);
483
484 static int get_bp_hw_reset(int if_index)
485 {
486         DO_BPLIB_GET_ARG_FN(get_tpl, GET_BP_HW_RESET, if_index);
487 }
488 EXPORT_SYMBOL(get_bp_hw_reset);
489
490 static int get_bypass_info(int if_index, struct bp_info *bp_info)
491 {
492         int ret = 0;
493
494         if (is_dev_sd(if_index)) {
495                 SET_BPLIB_INT_FN2(get_bypass_info, int, if_index,
496                                   struct bp_info *, bp_info, ret);
497         } else {
498                 struct net_device *dev;
499                 struct net_device *n;
500
501                 for_each_netdev_safe(&init_net, dev, n) {
502                         if (dev->ifindex == if_index) {
503                                 struct if_bypass_info *bypass_cb;
504                                 struct ifreq ifr;
505
506                                 memset(&ifr, 0, sizeof(ifr));
507                                 bypass_cb = (struct if_bypass_info *)&ifr;
508                                 bypass_cb->cmd = GET_BYPASS_INFO;
509
510                                 if (dev->netdev_ops &&
511                                         dev->netdev_ops->ndo_do_ioctl)
512                                         ret = dev->netdev_ops->ndo_do_ioctl(dev,
513                                                 &ifr, SIOCGIFBYPASS);
514                                 else
515                                         ret = -1;
516                                 if (ret == 0)
517                                         memcpy(bp_info, &bypass_cb->bp_info,
518                                                sizeof(struct bp_info));
519                                 ret = ret < 0 ? -1 : 0;
520                                 break;
521                         }
522                 }
523         }
524         return ret;
525 }
526 EXPORT_SYMBOL(get_bypass_info);
527
528 static int __init init_lib_module(void)
529 {
530         printk(VERSION);
531         return 0;
532 }
533
534 static void __exit cleanup_lib_module(void)
535 {
536 }
537
538 module_init(init_lib_module);
539 module_exit(cleanup_lib_module);