Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
bypass.c
Go to the documentation of this file.
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 #include <linux/version.h>
15 #if defined(CONFIG_SMP) && ! defined(__SMP__)
16 #define __SMP__
17 #endif
18 
19 #include <linux/module.h>
20 #include <linux/kernel.h>
21 #include <asm/unistd.h>
22 
23 #include <linux/sched.h>
24 #include <linux/wait.h>
25 
26 #include <linux/netdevice.h> // struct device, and other headers
27 #include <linux/kernel_stat.h>
28 #include <linux/pci.h>
29 #include <linux/rtnetlink.h>
30 #include <linux/ethtool.h>
31 
32 #include <net/net_namespace.h>
33 
34 #include "bplibk.h"
35 
36 #define MOD_NAME "bypass"
37 
38 #define VERSION "\n"MOD_NAME" version 9.0.4\n"
39 
40 MODULE_AUTHOR("www.silicom.co.il");
41 
42 MODULE_LICENSE("GPL");
43 
44 int init_lib_module(void);
45 void cleanup_lib_module(void);
46 
47 static int do_cmd(struct net_device *dev, struct ifreq *ifr, int cmd, int *data)
48 {
49  int ret = -1;
50  struct if_bypass *bypass_cb;
51  static int (*ioctl) (struct net_device *, struct ifreq *, int);
52 
53  bypass_cb = (struct if_bypass *)ifr;
54  bypass_cb->cmd = cmd;
55  bypass_cb->data = *data;
56  if ((dev->netdev_ops) && (ioctl = dev->netdev_ops->ndo_do_ioctl)) {
57  ret = ioctl(dev, ifr, SIOCGIFBYPASS);
58  *data = bypass_cb->data;
59  }
60 
61  return ret;
62 }
63 
64 static int doit(int cmd, int if_index, int *data)
65 {
66  struct ifreq ifr;
67  int ret = -1;
68  struct net_device *dev;
69  struct net_device *n;
70  for_each_netdev_safe(&init_net, dev, n) {
71 
72  if (dev->ifindex == if_index) {
73  ret = do_cmd(dev, &ifr, cmd, data);
74  if (ret < 0)
75  ret = -1;
76 
77  }
78  }
79 
80  return ret;
81 }
82 
83 #define bp_symbol_get(fn_name) symbol_get(fn_name)
84 #define bp_symbol_put(fn_name) symbol_put(fn_name)
85 
86 #define SET_BPLIB_INT_FN(fn_name, arg_type, arg, ret) \
87  ({ int (* fn_ex)(arg_type)=NULL; \
88  fn_ex=bp_symbol_get(fn_name##_sd); \
89  if(fn_ex) { \
90  ret= fn_ex(arg); \
91  bp_symbol_put(fn_name##_sd); \
92  } else ret=-1; \
93  })
94 
95 #define SET_BPLIB_INT_FN2(fn_name, arg_type, arg, arg_type1, arg1, ret) \
96  ({ int (* fn_ex)(arg_type,arg_type1)=NULL; \
97  fn_ex=bp_symbol_get(fn_name##_sd); \
98  if(fn_ex) { \
99  ret= fn_ex(arg,arg1); \
100  bp_symbol_put(fn_name##_sd); \
101  } else ret=-1; \
102  })
103 #define SET_BPLIB_INT_FN3(fn_name, arg_type, arg, arg_type1, arg1,arg_type2, arg2, ret) \
104  ({ int (* fn_ex)(arg_type,arg_type1, arg_type2)=NULL; \
105  fn_ex=bp_symbol_get(fn_name##_sd); \
106  if(fn_ex) { \
107  ret= fn_ex(arg,arg1,arg2); \
108  bp_symbol_put(fn_name##_sd); \
109  } else ret=-1; \
110  })
111 
112 #define DO_BPLIB_GET_ARG_FN(fn_name,ioctl_val, if_index) \
113  ({ int data, ret=0; \
114  if(is_dev_sd(if_index)){ \
115  SET_BPLIB_INT_FN(fn_name, int, if_index, ret); \
116  return ret; \
117  } \
118  return doit(ioctl_val,if_index, &data); \
119  })
120 
121 #define DO_BPLIB_SET_ARG_FN(fn_name,ioctl_val,if_index,arg) \
122  ({ int data, ret=0; \
123  if(is_dev_sd(if_index)){ \
124  SET_BPLIB_INT_FN2(fn_name, int, if_index, int, arg, ret); \
125  return ret; \
126  } \
127  data=arg; \
128  return doit(ioctl_val,if_index, &data); \
129  })
130 
131 static int is_dev_sd(int if_index)
132 {
133  int ret = 0;
134  SET_BPLIB_INT_FN(is_bypass, int, if_index, ret);
135  return (ret >= 0 ? 1 : 0);
136 }
137 
138 int is_bypass_dev(int if_index)
139 {
140  struct pci_dev *pdev = NULL;
141  struct net_device *dev = NULL;
142  struct ifreq ifr;
143  int ret = 0, data = 0;
144 
145  while ((pdev = pci_get_class(PCI_CLASS_NETWORK_ETHERNET << 8, pdev))) {
146  if ((dev = pci_get_drvdata(pdev)) != NULL)
147  if (((dev = pci_get_drvdata(pdev)) != NULL) &&
148  (dev->ifindex == if_index)) {
149  if ((pdev->vendor == SILICOM_VID) &&
150  (pdev->device >= SILICOM_BP_PID_MIN) &&
151  (pdev->device <= SILICOM_BP_PID_MAX))
152  goto send_cmd;
153 #if defined(BP_VENDOR_SUPPORT) && defined(ETHTOOL_GDRVINFO)
154  else {
155  struct ethtool_drvinfo info;
156  const struct ethtool_ops *ops =
157  dev->ethtool_ops;
158  int k = 0;
159 
160  if (ops->get_drvinfo) {
161  memset(&info, 0, sizeof(info));
162  info.cmd = ETHTOOL_GDRVINFO;
163  ops->get_drvinfo(dev, &info);
164  for (; bp_desc_array[k]; k++)
165  if (!
166  (strcmp
167  (bp_desc_array[k],
168  info.driver)))
169  goto send_cmd;
170 
171  }
172 
173  }
174 #endif
175  return -1;
176  }
177  }
178  send_cmd:
179  ret = do_cmd(dev, &ifr, IS_BYPASS, &data);
180  return (ret < 0 ? -1 : ret);
181 }
182 
183 int is_bypass(int if_index)
184 {
185  int ret = 0;
186  SET_BPLIB_INT_FN(is_bypass, int, if_index, ret);
187 
188  if (ret < 0)
189  return is_bypass_dev(if_index);
190  return ret;
191 }
192 
193 int get_bypass_slave(int if_index)
194 {
196 }
197 
198 int get_bypass_caps(int if_index)
199 {
201 }
202 
203 int get_wd_set_caps(int if_index)
204 {
206 }
207 
208 int set_bypass(int if_index, int bypass_mode)
209 {
210  DO_BPLIB_SET_ARG_FN(set_bypass, SET_BYPASS, if_index, bypass_mode);
211 }
212 
213 int get_bypass(int if_index)
214 {
216 }
217 
218 int get_bypass_change(int if_index)
219 {
221 }
222 
223 int set_dis_bypass(int if_index, int dis_bypass)
224 {
226  dis_bypass);
227 }
228 
229 int get_dis_bypass(int if_index)
230 {
232 }
233 
234 int set_bypass_pwoff(int if_index, int bypass_mode)
235 {
237  bypass_mode);
238 }
239 
240 int get_bypass_pwoff(int if_index)
241 {
243 }
244 
245 int set_bypass_pwup(int if_index, int bypass_mode)
246 {
248  bypass_mode);
249 }
250 
251 int get_bypass_pwup(int if_index)
252 {
254 }
255 
256 int set_bypass_wd(int if_index, int ms_timeout, int *ms_timeout_set)
257 {
258  int data = ms_timeout, ret = 0;
259  if (is_dev_sd(if_index))
260  SET_BPLIB_INT_FN3(set_bypass_wd, int, if_index, int, ms_timeout,
261  int *, ms_timeout_set, ret);
262  else {
263  ret = doit(SET_BYPASS_WD, if_index, &data);
264  if (ret > 0) {
265  *ms_timeout_set = ret;
266  ret = 0;
267  }
268  }
269  return ret;
270 }
271 
272 int get_bypass_wd(int if_index, int *ms_timeout_set)
273 {
274  int *data = ms_timeout_set, ret = 0;
275  if (is_dev_sd(if_index))
276  SET_BPLIB_INT_FN2(get_bypass_wd, int, if_index, int *,
277  ms_timeout_set, ret);
278  else
279  ret = doit(GET_BYPASS_WD, if_index, data);
280  return ret;
281 }
282 
283 int get_wd_expire_time(int if_index, int *ms_time_left)
284 {
285  int *data = ms_time_left, ret = 0;
286  if (is_dev_sd(if_index))
287  SET_BPLIB_INT_FN2(get_wd_expire_time, int, if_index, int *,
288  ms_time_left, ret);
289  else {
290  ret = doit(GET_WD_EXPIRE_TIME, if_index, data);
291  if ((ret == 0) && (*data != 0))
292  ret = 1;
293  }
294  return ret;
295 }
296 
297 int reset_bypass_wd_timer(int if_index)
298 {
300  if_index);
301 }
302 
303 int set_std_nic(int if_index, int bypass_mode)
304 {
305  DO_BPLIB_SET_ARG_FN(set_std_nic, SET_STD_NIC, if_index, bypass_mode);
306 }
307 
308 int get_std_nic(int if_index)
309 {
311 }
312 
313 int set_tx(int if_index, int tx_state)
314 {
315  DO_BPLIB_SET_ARG_FN(set_tx, SET_TX, if_index, tx_state);
316 }
317 
318 int get_tx(int if_index)
319 {
320  DO_BPLIB_GET_ARG_FN(get_tx, GET_TX, if_index);
321 }
322 
323 int set_tap(int if_index, int tap_mode)
324 {
325  DO_BPLIB_SET_ARG_FN(set_tap, SET_TAP, if_index, tap_mode);
326 }
327 
328 int get_tap(int if_index)
329 {
330  DO_BPLIB_GET_ARG_FN(get_tap, GET_TAP, if_index);
331 }
332 
333 int get_tap_change(int if_index)
334 {
336 }
337 
338 int set_dis_tap(int if_index, int dis_tap)
339 {
340  DO_BPLIB_SET_ARG_FN(set_dis_tap, SET_DIS_TAP, if_index, dis_tap);
341 }
342 
343 int get_dis_tap(int if_index)
344 {
346 }
347 
348 int set_tap_pwup(int if_index, int tap_mode)
349 {
350  DO_BPLIB_SET_ARG_FN(set_tap_pwup, SET_TAP_PWUP, if_index, tap_mode);
351 }
352 
353 int get_tap_pwup(int if_index)
354 {
356 }
357 
358 int set_bp_disc(int if_index, int disc_mode)
359 {
360  DO_BPLIB_SET_ARG_FN(set_bp_disc, SET_DISC, if_index, disc_mode);
361 }
362 
363 int get_bp_disc(int if_index)
364 {
366 }
367 
368 int get_bp_disc_change(int if_index)
369 {
371 }
372 
373 int set_bp_dis_disc(int if_index, int dis_disc)
374 {
375  DO_BPLIB_SET_ARG_FN(set_bp_dis_disc, SET_DIS_DISC, if_index, dis_disc);
376 }
377 
378 int get_bp_dis_disc(int if_index)
379 {
381 }
382 
383 int set_bp_disc_pwup(int if_index, int disc_mode)
384 {
386  disc_mode);
387 }
388 
389 int get_bp_disc_pwup(int if_index)
390 {
392 }
393 
394 int set_wd_exp_mode(int if_index, int mode)
395 {
397 }
398 
399 int get_wd_exp_mode(int if_index)
400 {
402 }
403 
404 int set_wd_autoreset(int if_index, int time)
405 {
407 }
408 
409 int get_wd_autoreset(int if_index)
410 {
412 }
413 
414 int set_tpl(int if_index, int tpl_mode)
415 {
416  DO_BPLIB_SET_ARG_FN(set_tpl, SET_TPL, if_index, tpl_mode);
417 }
418 
419 int get_tpl(int if_index)
420 {
421  DO_BPLIB_GET_ARG_FN(get_tpl, GET_TPL, if_index);
422 }
423 
424 int set_bp_hw_reset(int if_index, int mode)
425 {
426  DO_BPLIB_SET_ARG_FN(set_tpl, SET_BP_HW_RESET, if_index, mode);
427 }
428 
429 int get_bp_hw_reset(int if_index)
430 {
432 }
433 
434 int get_bypass_info(int if_index, struct bp_info *bp_info)
435 {
436  int ret = 0;
437  if (is_dev_sd(if_index)) {
438  SET_BPLIB_INT_FN2(get_bypass_info, int, if_index,
439  struct bp_info *, bp_info, ret);
440  } else {
441  static int (*ioctl) (struct net_device *, struct ifreq *, int);
442  struct net_device *dev;
443 
444  struct net_device *n;
445  for_each_netdev_safe(&init_net, dev, n) {
446  if (dev->ifindex == if_index) {
447  struct if_bypass_info *bypass_cb;
448  struct ifreq ifr;
449 
450  memset(&ifr, 0, sizeof(ifr));
451  bypass_cb = (struct if_bypass_info *)&ifr;
452  bypass_cb->cmd = GET_BYPASS_INFO;
453 
454  if ((dev->netdev_ops) &&
455  (ioctl = dev->netdev_ops->ndo_do_ioctl)) {
456  ret = ioctl(dev, &ifr, SIOCGIFBYPASS);
457  }
458 
459  else
460  ret = -1;
461  if (ret == 0)
462  memcpy(bp_info, &bypass_cb->bp_info,
463  sizeof(struct bp_info));
464  ret = (ret < 0 ? -1 : 0);
465  break;
466  }
467  }
468  }
469  return ret;
470 }
471 
473 {
474 
475  printk(VERSION);
476  return 0;
477 }
478 
480 {
481 }
482 
483 EXPORT_SYMBOL_NOVERS(is_bypass);
527