aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@vyatta.com>2008-11-20 00:32:24 -0500
committerDavid S. Miller <davem@davemloft.net>2008-11-20 00:32:24 -0500
commitd314774cf2cd5dfeb39a00d37deee65d4c627927 (patch)
tree1c7778b509cea814aa2b7115949667941037d07c /net
parent6b41e7dd90c6a628ab5fb8d781302d60a243b2ce (diff)
netdev: network device operations infrastructure
This patch changes the network device internal API to move adminstrative operations out of the network device structure and into a separate structure. This patch involves some hackery to maintain compatablity between the new and old model, so all 300+ drivers don't have to be changed at once. For drivers that aren't converted yet, the netdevice_ops virt function list still resides in the net_device structure. For old protocols, the new net_device_ops are copied out to the old net_device pointers. After the transistion is completed the nag message can be changed to an WARN_ON, and the compatiablity code can be made configurable. Some function pointers aren't moved: * destructor can't be in net_device_ops because it may need to be referenced after the module is unloaded. * neighbor setup is manipulated in a couple of places that need special consideration * hard_start_xmit is in the fast path for transmit. Signed-off-by: Stephen Hemminger <shemminger@vyatta.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/Kconfig3
-rw-r--r--net/core/dev.c109
-rw-r--r--net/core/netpoll.c7
-rw-r--r--net/core/rtnetlink.c9
-rw-r--r--net/sched/sch_generic.c4
5 files changed, 91 insertions, 41 deletions
diff --git a/net/Kconfig b/net/Kconfig
index 8c3d97ca0d96..4e2e40ba8ba6 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -32,6 +32,9 @@ config NET_NS
32 Allow user space to create what appear to be multiple instances 32 Allow user space to create what appear to be multiple instances
33 of the network stack. 33 of the network stack.
34 34
35config COMPAT_NET_DEV_OPS
36 def_bool y
37
35source "net/packet/Kconfig" 38source "net/packet/Kconfig"
36source "net/unix/Kconfig" 39source "net/unix/Kconfig"
37source "net/xfrm/Kconfig" 40source "net/xfrm/Kconfig"
diff --git a/net/core/dev.c b/net/core/dev.c
index e08c0fcd603b..ca14ab407b33 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1059,6 +1059,7 @@ void dev_load(struct net *net, const char *name)
1059 */ 1059 */
1060int dev_open(struct net_device *dev) 1060int dev_open(struct net_device *dev)
1061{ 1061{
1062 const struct net_device_ops *ops = dev->netdev_ops;
1062 int ret = 0; 1063 int ret = 0;
1063 1064
1064 ASSERT_RTNL(); 1065 ASSERT_RTNL();
@@ -1081,11 +1082,11 @@ int dev_open(struct net_device *dev)
1081 */ 1082 */
1082 set_bit(__LINK_STATE_START, &dev->state); 1083 set_bit(__LINK_STATE_START, &dev->state);
1083 1084
1084 if (dev->validate_addr) 1085 if (ops->ndo_validate_addr)
1085 ret = dev->validate_addr(dev); 1086 ret = ops->ndo_validate_addr(dev);
1086 1087
1087 if (!ret && dev->open) 1088 if (!ret && ops->ndo_open)
1088 ret = dev->open(dev); 1089 ret = ops->ndo_open(dev);
1089 1090
1090 /* 1091 /*
1091 * If it went open OK then: 1092 * If it went open OK then:
@@ -1129,6 +1130,7 @@ int dev_open(struct net_device *dev)
1129 */ 1130 */
1130int dev_close(struct net_device *dev) 1131int dev_close(struct net_device *dev)
1131{ 1132{
1133 const struct net_device_ops *ops = dev->netdev_ops;
1132 ASSERT_RTNL(); 1134 ASSERT_RTNL();
1133 1135
1134 might_sleep(); 1136 might_sleep();
@@ -1161,8 +1163,8 @@ int dev_close(struct net_device *dev)
1161 * We allow it to be called even after a DETACH hot-plug 1163 * We allow it to be called even after a DETACH hot-plug
1162 * event. 1164 * event.
1163 */ 1165 */
1164 if (dev->stop) 1166 if (ops->ndo_stop)
1165 dev->stop(dev); 1167 ops->ndo_stop(dev);
1166 1168
1167 /* 1169 /*
1168 * Device is now down. 1170 * Device is now down.
@@ -2930,8 +2932,10 @@ int netdev_set_master(struct net_device *slave, struct net_device *master)
2930 2932
2931static void dev_change_rx_flags(struct net_device *dev, int flags) 2933static void dev_change_rx_flags(struct net_device *dev, int flags)
2932{ 2934{
2933 if (dev->flags & IFF_UP && dev->change_rx_flags) 2935 const struct net_device_ops *ops = dev->netdev_ops;
2934 dev->change_rx_flags(dev, flags); 2936
2937 if ((dev->flags & IFF_UP) && ops->ndo_change_rx_flags)
2938 ops->ndo_change_rx_flags(dev, flags);
2935} 2939}
2936 2940
2937static int __dev_set_promiscuity(struct net_device *dev, int inc) 2941static int __dev_set_promiscuity(struct net_device *dev, int inc)
@@ -3051,6 +3055,8 @@ int dev_set_allmulti(struct net_device *dev, int inc)
3051 */ 3055 */
3052void __dev_set_rx_mode(struct net_device *dev) 3056void __dev_set_rx_mode(struct net_device *dev)
3053{ 3057{
3058 const struct net_device_ops *ops = dev->netdev_ops;
3059
3054 /* dev_open will call this function so the list will stay sane. */ 3060 /* dev_open will call this function so the list will stay sane. */
3055 if (!(dev->flags&IFF_UP)) 3061 if (!(dev->flags&IFF_UP))
3056 return; 3062 return;
@@ -3058,8 +3064,8 @@ void __dev_set_rx_mode(struct net_device *dev)
3058 if (!netif_device_present(dev)) 3064 if (!netif_device_present(dev))
3059 return; 3065 return;
3060 3066
3061 if (dev->set_rx_mode) 3067 if (ops->ndo_set_rx_mode)
3062 dev->set_rx_mode(dev); 3068 ops->ndo_set_rx_mode(dev);
3063 else { 3069 else {
3064 /* Unicast addresses changes may only happen under the rtnl, 3070 /* Unicast addresses changes may only happen under the rtnl,
3065 * therefore calling __dev_set_promiscuity here is safe. 3071 * therefore calling __dev_set_promiscuity here is safe.
@@ -3072,8 +3078,8 @@ void __dev_set_rx_mode(struct net_device *dev)
3072 dev->uc_promisc = 0; 3078 dev->uc_promisc = 0;
3073 } 3079 }
3074 3080
3075 if (dev->set_multicast_list) 3081 if (ops->ndo_set_multicast_list)
3076 dev->set_multicast_list(dev); 3082 ops->ndo_set_multicast_list(dev);
3077 } 3083 }
3078} 3084}
3079 3085
@@ -3432,6 +3438,7 @@ int dev_change_flags(struct net_device *dev, unsigned flags)
3432 */ 3438 */
3433int dev_set_mtu(struct net_device *dev, int new_mtu) 3439int dev_set_mtu(struct net_device *dev, int new_mtu)
3434{ 3440{
3441 const struct net_device_ops *ops = dev->netdev_ops;
3435 int err; 3442 int err;
3436 3443
3437 if (new_mtu == dev->mtu) 3444 if (new_mtu == dev->mtu)
@@ -3445,10 +3452,11 @@ int dev_set_mtu(struct net_device *dev, int new_mtu)
3445 return -ENODEV; 3452 return -ENODEV;
3446 3453
3447 err = 0; 3454 err = 0;
3448 if (dev->change_mtu) 3455 if (ops->ndo_change_mtu)
3449 err = dev->change_mtu(dev, new_mtu); 3456 err = ops->ndo_change_mtu(dev, new_mtu);
3450 else 3457 else
3451 dev->mtu = new_mtu; 3458 dev->mtu = new_mtu;
3459
3452 if (!err && dev->flags & IFF_UP) 3460 if (!err && dev->flags & IFF_UP)
3453 call_netdevice_notifiers(NETDEV_CHANGEMTU, dev); 3461 call_netdevice_notifiers(NETDEV_CHANGEMTU, dev);
3454 return err; 3462 return err;
@@ -3463,15 +3471,16 @@ int dev_set_mtu(struct net_device *dev, int new_mtu)
3463 */ 3471 */
3464int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa) 3472int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa)
3465{ 3473{
3474 const struct net_device_ops *ops = dev->netdev_ops;
3466 int err; 3475 int err;
3467 3476
3468 if (!dev->set_mac_address) 3477 if (!ops->ndo_set_mac_address)
3469 return -EOPNOTSUPP; 3478 return -EOPNOTSUPP;
3470 if (sa->sa_family != dev->type) 3479 if (sa->sa_family != dev->type)
3471 return -EINVAL; 3480 return -EINVAL;
3472 if (!netif_device_present(dev)) 3481 if (!netif_device_present(dev))
3473 return -ENODEV; 3482 return -ENODEV;
3474 err = dev->set_mac_address(dev, sa); 3483 err = ops->ndo_set_mac_address(dev, sa);
3475 if (!err) 3484 if (!err)
3476 call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); 3485 call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
3477 return err; 3486 return err;
@@ -3551,6 +3560,7 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)
3551{ 3560{
3552 int err; 3561 int err;
3553 struct net_device *dev = __dev_get_by_name(net, ifr->ifr_name); 3562 struct net_device *dev = __dev_get_by_name(net, ifr->ifr_name);
3563 const struct net_device_ops *ops = dev->netdev_ops;
3554 3564
3555 if (!dev) 3565 if (!dev)
3556 return -ENODEV; 3566 return -ENODEV;
@@ -3578,15 +3588,15 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)
3578 return 0; 3588 return 0;
3579 3589
3580 case SIOCSIFMAP: 3590 case SIOCSIFMAP:
3581 if (dev->set_config) { 3591 if (ops->ndo_set_config) {
3582 if (!netif_device_present(dev)) 3592 if (!netif_device_present(dev))
3583 return -ENODEV; 3593 return -ENODEV;
3584 return dev->set_config(dev, &ifr->ifr_map); 3594 return ops->ndo_set_config(dev, &ifr->ifr_map);
3585 } 3595 }
3586 return -EOPNOTSUPP; 3596 return -EOPNOTSUPP;
3587 3597
3588 case SIOCADDMULTI: 3598 case SIOCADDMULTI:
3589 if ((!dev->set_multicast_list && !dev->set_rx_mode) || 3599 if ((!ops->ndo_set_multicast_list && !ops->ndo_set_rx_mode) ||
3590 ifr->ifr_hwaddr.sa_family != AF_UNSPEC) 3600 ifr->ifr_hwaddr.sa_family != AF_UNSPEC)
3591 return -EINVAL; 3601 return -EINVAL;
3592 if (!netif_device_present(dev)) 3602 if (!netif_device_present(dev))
@@ -3595,7 +3605,7 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)
3595 dev->addr_len, 1); 3605 dev->addr_len, 1);
3596 3606
3597 case SIOCDELMULTI: 3607 case SIOCDELMULTI:
3598 if ((!dev->set_multicast_list && !dev->set_rx_mode) || 3608 if ((!ops->ndo_set_multicast_list && !ops->ndo_set_rx_mode) ||
3599 ifr->ifr_hwaddr.sa_family != AF_UNSPEC) 3609 ifr->ifr_hwaddr.sa_family != AF_UNSPEC)
3600 return -EINVAL; 3610 return -EINVAL;
3601 if (!netif_device_present(dev)) 3611 if (!netif_device_present(dev))
@@ -3633,10 +3643,9 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)
3633 cmd == SIOCBRDELIF || 3643 cmd == SIOCBRDELIF ||
3634 cmd == SIOCWANDEV) { 3644 cmd == SIOCWANDEV) {
3635 err = -EOPNOTSUPP; 3645 err = -EOPNOTSUPP;
3636 if (dev->do_ioctl) { 3646 if (ops->ndo_do_ioctl) {
3637 if (netif_device_present(dev)) 3647 if (netif_device_present(dev))
3638 err = dev->do_ioctl(dev, ifr, 3648 err = ops->ndo_do_ioctl(dev, ifr, cmd);
3639 cmd);
3640 else 3649 else
3641 err = -ENODEV; 3650 err = -ENODEV;
3642 } 3651 }
@@ -3897,8 +3906,8 @@ static void rollback_registered(struct net_device *dev)
3897 */ 3906 */
3898 dev_addr_discard(dev); 3907 dev_addr_discard(dev);
3899 3908
3900 if (dev->uninit) 3909 if (dev->netdev_ops->ndo_uninit)
3901 dev->uninit(dev); 3910 dev->netdev_ops->ndo_uninit(dev);
3902 3911
3903 /* Notifier chain MUST detach us from master device. */ 3912 /* Notifier chain MUST detach us from master device. */
3904 WARN_ON(dev->master); 3913 WARN_ON(dev->master);
@@ -3988,7 +3997,7 @@ int register_netdevice(struct net_device *dev)
3988 struct hlist_head *head; 3997 struct hlist_head *head;
3989 struct hlist_node *p; 3998 struct hlist_node *p;
3990 int ret; 3999 int ret;
3991 struct net *net; 4000 struct net *net = dev_net(dev);
3992 4001
3993 BUG_ON(dev_boot_phase); 4002 BUG_ON(dev_boot_phase);
3994 ASSERT_RTNL(); 4003 ASSERT_RTNL();
@@ -3997,8 +4006,7 @@ int register_netdevice(struct net_device *dev)
3997 4006
3998 /* When net_device's are persistent, this will be fatal. */ 4007 /* When net_device's are persistent, this will be fatal. */
3999 BUG_ON(dev->reg_state != NETREG_UNINITIALIZED); 4008 BUG_ON(dev->reg_state != NETREG_UNINITIALIZED);
4000 BUG_ON(!dev_net(dev)); 4009 BUG_ON(!net);
4001 net = dev_net(dev);
4002 4010
4003 spin_lock_init(&dev->addr_list_lock); 4011 spin_lock_init(&dev->addr_list_lock);
4004 netdev_set_addr_lockdep_class(dev); 4012 netdev_set_addr_lockdep_class(dev);
@@ -4006,9 +4014,46 @@ int register_netdevice(struct net_device *dev)
4006 4014
4007 dev->iflink = -1; 4015 dev->iflink = -1;
4008 4016
4017#ifdef CONFIG_COMPAT_NET_DEV_OPS
4018 /* Netdevice_ops API compatiability support.
4019 * This is temporary until all network devices are converted.
4020 */
4021 if (dev->netdev_ops) {
4022 const struct net_device_ops *ops = dev->netdev_ops;
4023
4024 dev->init = ops->ndo_init;
4025 dev->uninit = ops->ndo_uninit;
4026 dev->open = ops->ndo_open;
4027 dev->change_rx_flags = ops->ndo_change_rx_flags;
4028 dev->set_rx_mode = ops->ndo_set_rx_mode;
4029 dev->set_multicast_list = ops->ndo_set_multicast_list;
4030 dev->set_mac_address = ops->ndo_set_mac_address;
4031 dev->validate_addr = ops->ndo_validate_addr;
4032 dev->do_ioctl = ops->ndo_do_ioctl;
4033 dev->set_config = ops->ndo_set_config;
4034 dev->change_mtu = ops->ndo_change_mtu;
4035 dev->tx_timeout = ops->ndo_tx_timeout;
4036 dev->get_stats = ops->ndo_get_stats;
4037 dev->vlan_rx_register = ops->ndo_vlan_rx_register;
4038 dev->vlan_rx_add_vid = ops->ndo_vlan_rx_add_vid;
4039 dev->vlan_rx_kill_vid = ops->ndo_vlan_rx_kill_vid;
4040#ifdef CONFIG_NET_POLL_CONTROLLER
4041 dev->poll_controller = ops->ndo_poll_controller;
4042#endif
4043 } else {
4044 char drivername[64];
4045 pr_info("%s (%s): not using net_device_ops yet\n",
4046 dev->name, netdev_drivername(dev, drivername, 64));
4047
4048 /* This works only because net_device_ops and the
4049 compatiablity structure are the same. */
4050 dev->netdev_ops = (void *) &(dev->init);
4051 }
4052#endif
4053
4009 /* Init, if this function is available */ 4054 /* Init, if this function is available */
4010 if (dev->init) { 4055 if (dev->netdev_ops->ndo_init) {
4011 ret = dev->init(dev); 4056 ret = dev->netdev_ops->ndo_init(dev);
4012 if (ret) { 4057 if (ret) {
4013 if (ret > 0) 4058 if (ret > 0)
4014 ret = -EIO; 4059 ret = -EIO;
@@ -4086,8 +4131,8 @@ out:
4086 return ret; 4131 return ret;
4087 4132
4088err_uninit: 4133err_uninit:
4089 if (dev->uninit) 4134 if (dev->netdev_ops->ndo_uninit)
4090 dev->uninit(dev); 4135 dev->netdev_ops->ndo_uninit(dev);
4091 goto out; 4136 goto out;
4092} 4137}
4093 4138
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index fc4e28e23b89..630df6034444 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -172,12 +172,13 @@ static void service_arp_queue(struct netpoll_info *npi)
172void netpoll_poll(struct netpoll *np) 172void netpoll_poll(struct netpoll *np)
173{ 173{
174 struct net_device *dev = np->dev; 174 struct net_device *dev = np->dev;
175 const struct net_device_ops *ops = dev->netdev_ops;
175 176
176 if (!dev || !netif_running(dev) || !dev->poll_controller) 177 if (!dev || !netif_running(dev) || !ops->ndo_poll_controller)
177 return; 178 return;
178 179
179 /* Process pending work on NIC */ 180 /* Process pending work on NIC */
180 dev->poll_controller(dev); 181 ops->ndo_poll_controller(dev);
181 182
182 poll_napi(dev); 183 poll_napi(dev);
183 184
@@ -694,7 +695,7 @@ int netpoll_setup(struct netpoll *np)
694 atomic_inc(&npinfo->refcnt); 695 atomic_inc(&npinfo->refcnt);
695 } 696 }
696 697
697 if (!ndev->poll_controller) { 698 if (!ndev->netdev_ops->ndo_poll_controller) {
698 printk(KERN_ERR "%s: %s doesn't support polling, aborting.\n", 699 printk(KERN_ERR "%s: %s doesn't support polling, aborting.\n",
699 np->name, np->dev_name); 700 np->name, np->dev_name);
700 err = -ENOTSUPP; 701 err = -ENOTSUPP;
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 4dfb6b4d4559..6f8e0778e565 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -762,6 +762,7 @@ static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[])
762static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, 762static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
763 struct nlattr **tb, char *ifname, int modified) 763 struct nlattr **tb, char *ifname, int modified)
764{ 764{
765 const struct net_device_ops *ops = dev->netdev_ops;
765 int send_addr_notify = 0; 766 int send_addr_notify = 0;
766 int err; 767 int err;
767 768
@@ -783,7 +784,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
783 struct rtnl_link_ifmap *u_map; 784 struct rtnl_link_ifmap *u_map;
784 struct ifmap k_map; 785 struct ifmap k_map;
785 786
786 if (!dev->set_config) { 787 if (!ops->ndo_set_config) {
787 err = -EOPNOTSUPP; 788 err = -EOPNOTSUPP;
788 goto errout; 789 goto errout;
789 } 790 }
@@ -801,7 +802,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
801 k_map.dma = (unsigned char) u_map->dma; 802 k_map.dma = (unsigned char) u_map->dma;
802 k_map.port = (unsigned char) u_map->port; 803 k_map.port = (unsigned char) u_map->port;
803 804
804 err = dev->set_config(dev, &k_map); 805 err = ops->ndo_set_config(dev, &k_map);
805 if (err < 0) 806 if (err < 0)
806 goto errout; 807 goto errout;
807 808
@@ -812,7 +813,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
812 struct sockaddr *sa; 813 struct sockaddr *sa;
813 int len; 814 int len;
814 815
815 if (!dev->set_mac_address) { 816 if (!ops->ndo_set_mac_address) {
816 err = -EOPNOTSUPP; 817 err = -EOPNOTSUPP;
817 goto errout; 818 goto errout;
818 } 819 }
@@ -831,7 +832,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
831 sa->sa_family = dev->type; 832 sa->sa_family = dev->type;
832 memcpy(sa->sa_data, nla_data(tb[IFLA_ADDRESS]), 833 memcpy(sa->sa_data, nla_data(tb[IFLA_ADDRESS]),
833 dev->addr_len); 834 dev->addr_len);
834 err = dev->set_mac_address(dev, sa); 835 err = ops->ndo_set_mac_address(dev, sa);
835 kfree(sa); 836 kfree(sa);
836 if (err) 837 if (err)
837 goto errout; 838 goto errout;
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 80c8f3dbbea1..95ab55c064f1 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -224,7 +224,7 @@ static void dev_watchdog(unsigned long arg)
224 char drivername[64]; 224 char drivername[64];
225 WARN_ONCE(1, KERN_INFO "NETDEV WATCHDOG: %s (%s): transmit timed out\n", 225 WARN_ONCE(1, KERN_INFO "NETDEV WATCHDOG: %s (%s): transmit timed out\n",
226 dev->name, netdev_drivername(dev, drivername, 64)); 226 dev->name, netdev_drivername(dev, drivername, 64));
227 dev->tx_timeout(dev); 227 dev->netdev_ops->ndo_tx_timeout(dev);
228 } 228 }
229 if (!mod_timer(&dev->watchdog_timer, 229 if (!mod_timer(&dev->watchdog_timer,
230 round_jiffies(jiffies + 230 round_jiffies(jiffies +
@@ -239,7 +239,7 @@ static void dev_watchdog(unsigned long arg)
239 239
240void __netdev_watchdog_up(struct net_device *dev) 240void __netdev_watchdog_up(struct net_device *dev)
241{ 241{
242 if (dev->tx_timeout) { 242 if (dev->netdev_ops->ndo_tx_timeout) {
243 if (dev->watchdog_timeo <= 0) 243 if (dev->watchdog_timeo <= 0)
244 dev->watchdog_timeo = 5*HZ; 244 dev->watchdog_timeo = 5*HZ;
245 if (!mod_timer(&dev->watchdog_timer, 245 if (!mod_timer(&dev->watchdog_timer,