1 /******************************************************************************/
3 /* bypass library, Copyright (c) 2004-2007 Silicom, Ltd */
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. */
12 /******************************************************************************/
14 #if defined(CONFIG_SMP) && ! defined(__SMP__)
18 #include <linux/module.h>
19 #include <linux/kernel.h>
20 #include <asm/unistd.h>
22 #include <linux/sched.h>
23 #include <linux/wait.h>
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>
31 #include <net/net_namespace.h>
35 #define MOD_NAME "bypass"
37 #define VERSION "\n"MOD_NAME" version 9.0.4\n"
39 MODULE_AUTHOR("www.silicom.co.il");
41 MODULE_LICENSE("GPL");
43 int init_lib_module(void);
44 void cleanup_lib_module(void);
46 static int do_cmd(struct net_device *dev, struct ifreq *ifr, int cmd, int *data)
49 struct if_bypass *bypass_cb;
50 static int (*ioctl) (struct net_device *, struct ifreq *, int);
52 bypass_cb = (struct if_bypass *)ifr;
54 bypass_cb->data = *data;
55 if ((dev->netdev_ops) && (ioctl = dev->netdev_ops->ndo_do_ioctl)) {
56 ret = ioctl(dev, ifr, SIOCGIFBYPASS);
57 *data = bypass_cb->data;
63 static int doit(int cmd, int if_index, int *data)
67 struct net_device *dev;
69 for_each_netdev_safe(&init_net, dev, n) {
71 if (dev->ifindex == if_index) {
72 ret = do_cmd(dev, &ifr, cmd, data);
82 #define bp_symbol_get(fn_name) symbol_get(fn_name)
83 #define bp_symbol_put(fn_name) symbol_put(fn_name)
85 #define SET_BPLIB_INT_FN(fn_name, arg_type, arg, ret) \
86 ({ int (* fn_ex)(arg_type)=NULL; \
87 fn_ex=bp_symbol_get(fn_name##_sd); \
90 bp_symbol_put(fn_name##_sd); \
94 #define SET_BPLIB_INT_FN2(fn_name, arg_type, arg, arg_type1, arg1, ret) \
95 ({ int (* fn_ex)(arg_type,arg_type1)=NULL; \
96 fn_ex=bp_symbol_get(fn_name##_sd); \
98 ret= fn_ex(arg,arg1); \
99 bp_symbol_put(fn_name##_sd); \
102 #define SET_BPLIB_INT_FN3(fn_name, arg_type, arg, arg_type1, arg1,arg_type2, arg2, ret) \
103 ({ int (* fn_ex)(arg_type,arg_type1, arg_type2)=NULL; \
104 fn_ex=bp_symbol_get(fn_name##_sd); \
106 ret= fn_ex(arg,arg1,arg2); \
107 bp_symbol_put(fn_name##_sd); \
111 #define DO_BPLIB_GET_ARG_FN(fn_name,ioctl_val, if_index) \
112 ({ int data, ret=0; \
113 if(is_dev_sd(if_index)){ \
114 SET_BPLIB_INT_FN(fn_name, int, if_index, ret); \
117 return doit(ioctl_val,if_index, &data); \
120 #define DO_BPLIB_SET_ARG_FN(fn_name,ioctl_val,if_index,arg) \
121 ({ int data, ret=0; \
122 if(is_dev_sd(if_index)){ \
123 SET_BPLIB_INT_FN2(fn_name, int, if_index, int, arg, ret); \
127 return doit(ioctl_val,if_index, &data); \
130 static int is_dev_sd(int if_index)
133 SET_BPLIB_INT_FN(is_bypass, int, if_index, ret);
134 return (ret >= 0 ? 1 : 0);
137 static int is_bypass_dev(int if_index)
139 struct pci_dev *pdev = NULL;
140 struct net_device *dev = NULL;
142 int ret = 0, data = 0;
144 while ((pdev = pci_get_class(PCI_CLASS_NETWORK_ETHERNET << 8, pdev))) {
145 if ((dev = pci_get_drvdata(pdev)) != NULL)
146 if (((dev = pci_get_drvdata(pdev)) != NULL) &&
147 (dev->ifindex == if_index)) {
148 if ((pdev->vendor == SILICOM_VID) &&
149 (pdev->device >= SILICOM_BP_PID_MIN) &&
150 (pdev->device <= SILICOM_BP_PID_MAX))
152 #if defined(BP_VENDOR_SUPPORT) && defined(ETHTOOL_GDRVINFO)
154 struct ethtool_drvinfo info;
155 const struct ethtool_ops *ops =
159 if (ops->get_drvinfo) {
160 memset(&info, 0, sizeof(info));
161 info.cmd = ETHTOOL_GDRVINFO;
162 ops->get_drvinfo(dev, &info);
163 for (; bp_desc_array[k]; k++)
178 ret = do_cmd(dev, &ifr, IS_BYPASS, &data);
179 return (ret < 0 ? -1 : ret);
182 static int is_bypass(int if_index)
185 SET_BPLIB_INT_FN(is_bypass, int, if_index, ret);
188 return is_bypass_dev(if_index);
191 EXPORT_SYMBOL(is_bypass);
193 static int get_bypass_slave(int if_index)
195 DO_BPLIB_GET_ARG_FN(get_bypass_slave, GET_BYPASS_SLAVE, if_index);
197 EXPORT_SYMBOL(get_bypass_slave);
199 static int get_bypass_caps(int if_index)
201 DO_BPLIB_GET_ARG_FN(get_bypass_caps, GET_BYPASS_CAPS, if_index);
203 EXPORT_SYMBOL(get_bypass_caps);
205 static int get_wd_set_caps(int if_index)
207 DO_BPLIB_GET_ARG_FN(get_wd_set_caps, GET_WD_SET_CAPS, if_index);
209 EXPORT_SYMBOL(get_wd_set_caps);
211 static int set_bypass(int if_index, int bypass_mode)
213 DO_BPLIB_SET_ARG_FN(set_bypass, SET_BYPASS, if_index, bypass_mode);
215 EXPORT_SYMBOL(set_bypass);
217 static int get_bypass(int if_index)
219 DO_BPLIB_GET_ARG_FN(get_bypass, GET_BYPASS, if_index);
221 EXPORT_SYMBOL(get_bypass);
223 static int get_bypass_change(int if_index)
225 DO_BPLIB_GET_ARG_FN(get_bypass_change, GET_BYPASS_CHANGE, if_index);
227 EXPORT_SYMBOL(get_bypass_change);
229 static int set_dis_bypass(int if_index, int dis_bypass)
231 DO_BPLIB_SET_ARG_FN(set_dis_bypass, SET_DIS_BYPASS, if_index,
234 EXPORT_SYMBOL(set_dis_bypass);
236 static int get_dis_bypass(int if_index)
238 DO_BPLIB_GET_ARG_FN(get_dis_bypass, GET_DIS_BYPASS, if_index);
240 EXPORT_SYMBOL(get_dis_bypass);
242 static int set_bypass_pwoff(int if_index, int bypass_mode)
244 DO_BPLIB_SET_ARG_FN(set_bypass_pwoff, SET_BYPASS_PWOFF, if_index,
247 EXPORT_SYMBOL(set_bypass_pwoff);
249 static int get_bypass_pwoff(int if_index)
251 DO_BPLIB_GET_ARG_FN(get_bypass_pwoff, GET_BYPASS_PWOFF, if_index);
253 EXPORT_SYMBOL(get_bypass_pwoff);
255 static int set_bypass_pwup(int if_index, int bypass_mode)
257 DO_BPLIB_SET_ARG_FN(set_bypass_pwup, SET_BYPASS_PWUP, if_index,
260 EXPORT_SYMBOL(set_bypass_pwup);
262 static int get_bypass_pwup(int if_index)
264 DO_BPLIB_GET_ARG_FN(get_bypass_pwup, GET_BYPASS_PWUP, if_index);
266 EXPORT_SYMBOL(get_bypass_pwup);
268 static int set_bypass_wd(int if_index, int ms_timeout, int *ms_timeout_set)
270 int data = ms_timeout, ret = 0;
271 if (is_dev_sd(if_index))
272 SET_BPLIB_INT_FN3(set_bypass_wd, int, if_index, int, ms_timeout,
273 int *, ms_timeout_set, ret);
275 ret = doit(SET_BYPASS_WD, if_index, &data);
277 *ms_timeout_set = ret;
283 EXPORT_SYMBOL(set_bypass_wd);
285 static int get_bypass_wd(int if_index, int *ms_timeout_set)
287 int *data = ms_timeout_set, ret = 0;
288 if (is_dev_sd(if_index))
289 SET_BPLIB_INT_FN2(get_bypass_wd, int, if_index, int *,
290 ms_timeout_set, ret);
292 ret = doit(GET_BYPASS_WD, if_index, data);
295 EXPORT_SYMBOL(get_bypass_wd);
297 static int get_wd_expire_time(int if_index, int *ms_time_left)
299 int *data = ms_time_left, ret = 0;
300 if (is_dev_sd(if_index))
301 SET_BPLIB_INT_FN2(get_wd_expire_time, int, if_index, int *,
304 ret = doit(GET_WD_EXPIRE_TIME, if_index, data);
305 if ((ret == 0) && (*data != 0))
310 EXPORT_SYMBOL(get_wd_expire_time);
312 static int reset_bypass_wd_timer(int if_index)
314 DO_BPLIB_GET_ARG_FN(reset_bypass_wd_timer, RESET_BYPASS_WD_TIMER,
317 EXPORT_SYMBOL(reset_bypass_wd_timer);
319 static int set_std_nic(int if_index, int bypass_mode)
321 DO_BPLIB_SET_ARG_FN(set_std_nic, SET_STD_NIC, if_index, bypass_mode);
323 EXPORT_SYMBOL(set_std_nic);
325 static int get_std_nic(int if_index)
327 DO_BPLIB_GET_ARG_FN(get_std_nic, GET_STD_NIC, if_index);
329 EXPORT_SYMBOL(get_std_nic);
331 static int set_tx(int if_index, int tx_state)
333 DO_BPLIB_SET_ARG_FN(set_tx, SET_TX, if_index, tx_state);
335 EXPORT_SYMBOL(set_tx);
337 static int get_tx(int if_index)
339 DO_BPLIB_GET_ARG_FN(get_tx, GET_TX, if_index);
341 EXPORT_SYMBOL(get_tx);
343 static int set_tap(int if_index, int tap_mode)
345 DO_BPLIB_SET_ARG_FN(set_tap, SET_TAP, if_index, tap_mode);
347 EXPORT_SYMBOL(set_tap);
349 static int get_tap(int if_index)
351 DO_BPLIB_GET_ARG_FN(get_tap, GET_TAP, if_index);
353 EXPORT_SYMBOL(get_tap);
355 static int get_tap_change(int if_index)
357 DO_BPLIB_GET_ARG_FN(get_tap_change, GET_TAP_CHANGE, if_index);
359 EXPORT_SYMBOL(get_tap_change);
361 static int set_dis_tap(int if_index, int dis_tap)
363 DO_BPLIB_SET_ARG_FN(set_dis_tap, SET_DIS_TAP, if_index, dis_tap);
365 EXPORT_SYMBOL(set_dis_tap);
367 static int get_dis_tap(int if_index)
369 DO_BPLIB_GET_ARG_FN(get_dis_tap, GET_DIS_TAP, if_index);
371 EXPORT_SYMBOL(get_dis_tap);
373 static int set_tap_pwup(int if_index, int tap_mode)
375 DO_BPLIB_SET_ARG_FN(set_tap_pwup, SET_TAP_PWUP, if_index, tap_mode);
377 EXPORT_SYMBOL(set_tap_pwup);
379 static int get_tap_pwup(int if_index)
381 DO_BPLIB_GET_ARG_FN(get_tap_pwup, GET_TAP_PWUP, if_index);
383 EXPORT_SYMBOL(get_tap_pwup);
385 static int set_bp_disc(int if_index, int disc_mode)
387 DO_BPLIB_SET_ARG_FN(set_bp_disc, SET_DISC, if_index, disc_mode);
389 EXPORT_SYMBOL(set_bp_disc);
391 static int get_bp_disc(int if_index)
393 DO_BPLIB_GET_ARG_FN(get_bp_disc, GET_DISC, if_index);
395 EXPORT_SYMBOL(get_bp_disc);
397 static int get_bp_disc_change(int if_index)
399 DO_BPLIB_GET_ARG_FN(get_bp_disc_change, GET_DISC_CHANGE, if_index);
401 EXPORT_SYMBOL(get_bp_disc_change);
403 static int set_bp_dis_disc(int if_index, int dis_disc)
405 DO_BPLIB_SET_ARG_FN(set_bp_dis_disc, SET_DIS_DISC, if_index, dis_disc);
407 EXPORT_SYMBOL(set_bp_dis_disc);
409 static int get_bp_dis_disc(int if_index)
411 DO_BPLIB_GET_ARG_FN(get_bp_dis_disc, GET_DIS_DISC, if_index);
413 EXPORT_SYMBOL(get_bp_dis_disc);
415 static int set_bp_disc_pwup(int if_index, int disc_mode)
417 DO_BPLIB_SET_ARG_FN(set_bp_disc_pwup, SET_DISC_PWUP, if_index,
420 EXPORT_SYMBOL(set_bp_disc_pwup);
422 static int get_bp_disc_pwup(int if_index)
424 DO_BPLIB_GET_ARG_FN(get_bp_disc_pwup, GET_DISC_PWUP, if_index);
426 EXPORT_SYMBOL(get_bp_disc_pwup);
428 static int set_wd_exp_mode(int if_index, int mode)
430 DO_BPLIB_SET_ARG_FN(set_wd_exp_mode, SET_WD_EXP_MODE, if_index, mode);
432 EXPORT_SYMBOL(set_wd_exp_mode);
434 static int get_wd_exp_mode(int if_index)
436 DO_BPLIB_GET_ARG_FN(get_wd_exp_mode, GET_WD_EXP_MODE, if_index);
438 EXPORT_SYMBOL(get_wd_exp_mode);
440 static int set_wd_autoreset(int if_index, int time)
442 DO_BPLIB_SET_ARG_FN(set_wd_autoreset, SET_WD_AUTORESET, if_index, time);
444 EXPORT_SYMBOL(set_wd_autoreset);
446 static int get_wd_autoreset(int if_index)
448 DO_BPLIB_GET_ARG_FN(get_wd_autoreset, GET_WD_AUTORESET, if_index);
450 EXPORT_SYMBOL(get_wd_autoreset);
452 static int set_tpl(int if_index, int tpl_mode)
454 DO_BPLIB_SET_ARG_FN(set_tpl, SET_TPL, if_index, tpl_mode);
456 EXPORT_SYMBOL(set_tpl);
458 static int get_tpl(int if_index)
460 DO_BPLIB_GET_ARG_FN(get_tpl, GET_TPL, if_index);
462 EXPORT_SYMBOL(get_tpl);
464 static int set_bp_hw_reset(int if_index, int mode)
466 DO_BPLIB_SET_ARG_FN(set_tpl, SET_BP_HW_RESET, if_index, mode);
468 EXPORT_SYMBOL(set_bp_hw_reset);
470 static int get_bp_hw_reset(int if_index)
472 DO_BPLIB_GET_ARG_FN(get_tpl, GET_BP_HW_RESET, if_index);
474 EXPORT_SYMBOL(get_bp_hw_reset);
476 static int get_bypass_info(int if_index, struct bp_info *bp_info)
479 if (is_dev_sd(if_index)) {
480 SET_BPLIB_INT_FN2(get_bypass_info, int, if_index,
481 struct bp_info *, bp_info, ret);
483 static int (*ioctl) (struct net_device *, struct ifreq *, int);
484 struct net_device *dev;
486 struct net_device *n;
487 for_each_netdev_safe(&init_net, dev, n) {
488 if (dev->ifindex == if_index) {
489 struct if_bypass_info *bypass_cb;
492 memset(&ifr, 0, sizeof(ifr));
493 bypass_cb = (struct if_bypass_info *)𝔦
494 bypass_cb->cmd = GET_BYPASS_INFO;
496 if ((dev->netdev_ops) &&
497 (ioctl = dev->netdev_ops->ndo_do_ioctl)) {
498 ret = ioctl(dev, &ifr, SIOCGIFBYPASS);
504 memcpy(bp_info, &bypass_cb->bp_info,
505 sizeof(struct bp_info));
506 ret = (ret < 0 ? -1 : 0);
513 EXPORT_SYMBOL(get_bypass_info);
515 int init_lib_module(void)
522 void cleanup_lib_module(void)
526 module_init(init_lib_module);
527 module_exit(cleanup_lib_module);