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>
This commit is contained in:
Stephen Hemminger 2008-11-19 21:32:24 -08:00 committed by David S. Miller
parent 6b41e7dd90
commit d314774cf2
6 changed files with 259 additions and 105 deletions

View file

@ -451,6 +451,131 @@ struct netdev_queue {
struct Qdisc *qdisc_sleeping; struct Qdisc *qdisc_sleeping;
} ____cacheline_aligned_in_smp; } ____cacheline_aligned_in_smp;
/*
* This structure defines the management hooks for network devices.
* The following hooks can bed defined and are optonal (can be null)
* unless otherwise noted.
*
* int (*ndo_init)(struct net_device *dev);
* This function is called once when network device is registered.
* The network device can use this to any late stage initializaton
* or semantic validattion. It can fail with an error code which will
* be propogated back to register_netdev
*
* void (*ndo_uninit)(struct net_device *dev);
* This function is called when device is unregistered or when registration
* fails. It is not called if init fails.
*
* int (*ndo_open)(struct net_device *dev);
* This function is called when network device transistions to the up
* state.
*
* int (*ndo_stop)(struct net_device *dev);
* This function is called when network device transistions to the down
* state.
*
* void (*ndo_change_rx_flags)(struct net_device *dev, int flags);
* This function is called to allow device receiver to make
* changes to configuration when multicast or promiscious is enabled.
*
* void (*ndo_set_rx_mode)(struct net_device *dev);
* This function is called device changes address list filtering.
*
* void (*ndo_set_multicast_list)(struct net_device *dev);
* This function is called when the multicast address list changes.
*
* int (*ndo_set_mac_address)(struct net_device *dev, void *addr);
* This function is called when the Media Access Control address
* needs to be changed. If not this interface is not defined, the
* mac address can not be changed.
*
* int (*ndo_validate_addr)(struct net_device *dev);
* Test if Media Access Control address is valid for the device.
*
* int (*ndo_do_ioctl)(struct net_device *dev, struct ifreq *ifr, int cmd);
* Called when a user request an ioctl which can't be handled by
* the generic interface code. If not defined ioctl's return
* not supported error code.
*
* int (*ndo_set_config)(struct net_device *dev, struct ifmap *map);
* Used to set network devices bus interface parameters. This interface
* is retained for legacy reason, new devices should use the bus
* interface (PCI) for low level management.
*
* int (*ndo_change_mtu)(struct net_device *dev, int new_mtu);
* Called when a user wants to change the Maximum Transfer Unit
* of a device. If not defined, any request to change MTU will
* will return an error.
*
* void (*ndo_tx_timeout) (struct net_device *dev);
* Callback uses when the transmitter has not made any progress
* for dev->watchdog ticks.
*
* struct net_device_stats* (*get_stats)(struct net_device *dev);
* Called when a user wants to get the network device usage
* statistics. If not defined, the counters in dev->stats will
* be used.
*
* void (*ndo_vlan_rx_register)(struct net_device *dev, struct vlan_group *grp);
* If device support VLAN receive accleration
* (ie. dev->features & NETIF_F_HW_VLAN_RX), then this function is called
* when vlan groups for the device changes. Note: grp is NULL
* if no vlan's groups are being used.
*
* void (*ndo_vlan_rx_add_vid)(struct net_device *dev, unsigned short vid);
* If device support VLAN filtering (dev->features & NETIF_F_HW_VLAN_FILTER)
* this function is called when a VLAN id is registered.
*
* void (*ndo_vlan_rx_kill_vid)(struct net_device *dev, unsigned short vid);
* If device support VLAN filtering (dev->features & NETIF_F_HW_VLAN_FILTER)
* this function is called when a VLAN id is unregistered.
*
* void (*ndo_poll_controller)(struct net_device *dev);
*/
struct net_device_ops {
int (*ndo_init)(struct net_device *dev);
void (*ndo_uninit)(struct net_device *dev);
int (*ndo_open)(struct net_device *dev);
int (*ndo_stop)(struct net_device *dev);
#define HAVE_CHANGE_RX_FLAGS
void (*ndo_change_rx_flags)(struct net_device *dev,
int flags);
#define HAVE_SET_RX_MODE
void (*ndo_set_rx_mode)(struct net_device *dev);
#define HAVE_MULTICAST
void (*ndo_set_multicast_list)(struct net_device *dev);
#define HAVE_SET_MAC_ADDR
int (*ndo_set_mac_address)(struct net_device *dev,
void *addr);
#define HAVE_VALIDATE_ADDR
int (*ndo_validate_addr)(struct net_device *dev);
#define HAVE_PRIVATE_IOCTL
int (*ndo_do_ioctl)(struct net_device *dev,
struct ifreq *ifr, int cmd);
#define HAVE_SET_CONFIG
int (*ndo_set_config)(struct net_device *dev,
struct ifmap *map);
#define HAVE_CHANGE_MTU
int (*ndo_change_mtu)(struct net_device *dev, int new_mtu);
#define HAVE_TX_TIMEOUT
void (*ndo_tx_timeout) (struct net_device *dev);
struct net_device_stats* (*ndo_get_stats)(struct net_device *dev);
void (*ndo_vlan_rx_register)(struct net_device *dev,
struct vlan_group *grp);
void (*ndo_vlan_rx_add_vid)(struct net_device *dev,
unsigned short vid);
void (*ndo_vlan_rx_kill_vid)(struct net_device *dev,
unsigned short vid);
#ifdef CONFIG_NET_POLL_CONTROLLER
#define HAVE_NETDEV_POLL
void (*ndo_poll_controller)(struct net_device *dev);
#endif
};
/* /*
* The DEVICE structure. * The DEVICE structure.
* Actually, this whole structure is a big mistake. It mixes I/O * Actually, this whole structure is a big mistake. It mixes I/O
@ -498,11 +623,6 @@ struct net_device
#ifdef CONFIG_NETPOLL #ifdef CONFIG_NETPOLL
struct list_head napi_list; struct list_head napi_list;
#endif #endif
/* The device initialization function. Called only once. */
int (*init)(struct net_device *dev);
/* ------- Fields preinitialized in Space.c finish here ------- */
/* Net device features */ /* Net device features */
unsigned long features; unsigned long features;
@ -546,15 +666,13 @@ struct net_device
* for all in netdev_increment_features. * for all in netdev_increment_features.
*/ */
#define NETIF_F_ONE_FOR_ALL (NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ROBUST | \ #define NETIF_F_ONE_FOR_ALL (NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ROBUST | \
NETIF_F_SG | NETIF_F_HIGHDMA | \ NETIF_F_SG | NETIF_F_HIGHDMA | \
NETIF_F_FRAGLIST) NETIF_F_FRAGLIST)
/* Interface index. Unique device identifier */ /* Interface index. Unique device identifier */
int ifindex; int ifindex;
int iflink; int iflink;
struct net_device_stats* (*get_stats)(struct net_device *dev);
struct net_device_stats stats; struct net_device_stats stats;
#ifdef CONFIG_WIRELESS_EXT #ifdef CONFIG_WIRELESS_EXT
@ -564,18 +682,13 @@ struct net_device
/* Instance data managed by the core of Wireless Extensions. */ /* Instance data managed by the core of Wireless Extensions. */
struct iw_public_data * wireless_data; struct iw_public_data * wireless_data;
#endif #endif
/* Management operations */
const struct net_device_ops *netdev_ops;
const struct ethtool_ops *ethtool_ops; const struct ethtool_ops *ethtool_ops;
/* Hardware header description */ /* Hardware header description */
const struct header_ops *header_ops; const struct header_ops *header_ops;
/*
* This marks the end of the "visible" part of the structure. All
* fields hereafter are internal to the system, and may change at
* will (read: may be cleaned up at will).
*/
unsigned int flags; /* interface flags (a la BSD) */ unsigned int flags; /* interface flags (a la BSD) */
unsigned short gflags; unsigned short gflags;
unsigned short priv_flags; /* Like 'flags' but invisible to userspace. */ unsigned short priv_flags; /* Like 'flags' but invisible to userspace. */
@ -634,7 +747,7 @@ struct net_device
unsigned long last_rx; /* Time of last Rx */ unsigned long last_rx; /* Time of last Rx */
/* Interface address info used in eth_type_trans() */ /* Interface address info used in eth_type_trans() */
unsigned char dev_addr[MAX_ADDR_LEN]; /* hw address, (before bcast unsigned char dev_addr[MAX_ADDR_LEN]; /* hw address, (before bcast
because most packets are unicast) */ because most packets are unicast) */
unsigned char broadcast[MAX_ADDR_LEN]; /* hw bcast add */ unsigned char broadcast[MAX_ADDR_LEN]; /* hw bcast add */
@ -648,6 +761,10 @@ struct net_device
/* Number of TX queues currently active in device */ /* Number of TX queues currently active in device */
unsigned int real_num_tx_queues; unsigned int real_num_tx_queues;
/* Map buffer to appropriate transmit queue */
u16 (*select_queue)(struct net_device *dev,
struct sk_buff *skb);
unsigned long tx_queue_len; /* Max frames per queue allowed */ unsigned long tx_queue_len; /* Max frames per queue allowed */
spinlock_t tx_global_lock; spinlock_t tx_global_lock;
/* /*
@ -662,9 +779,6 @@ struct net_device
int watchdog_timeo; /* used by dev_watchdog() */ int watchdog_timeo; /* used by dev_watchdog() */
struct timer_list watchdog_timer; struct timer_list watchdog_timer;
/*
* refcnt is a very hot point, so align it on SMP
*/
/* Number of references to this device */ /* Number of references to this device */
atomic_t refcnt ____cacheline_aligned_in_smp; atomic_t refcnt ____cacheline_aligned_in_smp;
@ -683,56 +797,14 @@ struct net_device
NETREG_RELEASED, /* called free_netdev */ NETREG_RELEASED, /* called free_netdev */
} reg_state; } reg_state;
/* Called after device is detached from network. */ /* Called from unregister, can be used to call free_netdev */
void (*uninit)(struct net_device *dev); void (*destructor)(struct net_device *dev);
/* Called after last user reference disappears. */
void (*destructor)(struct net_device *dev);
/* Pointers to interface service routines. */ int (*neigh_setup)(struct net_device *dev, struct neigh_parms *);
int (*open)(struct net_device *dev);
int (*stop)(struct net_device *dev);
#define HAVE_NETDEV_POLL
#define HAVE_CHANGE_RX_FLAGS
void (*change_rx_flags)(struct net_device *dev,
int flags);
#define HAVE_SET_RX_MODE
void (*set_rx_mode)(struct net_device *dev);
#define HAVE_MULTICAST
void (*set_multicast_list)(struct net_device *dev);
#define HAVE_SET_MAC_ADDR
int (*set_mac_address)(struct net_device *dev,
void *addr);
#define HAVE_VALIDATE_ADDR
int (*validate_addr)(struct net_device *dev);
#define HAVE_PRIVATE_IOCTL
int (*do_ioctl)(struct net_device *dev,
struct ifreq *ifr, int cmd);
#define HAVE_SET_CONFIG
int (*set_config)(struct net_device *dev,
struct ifmap *map);
#define HAVE_CHANGE_MTU
int (*change_mtu)(struct net_device *dev, int new_mtu);
#define HAVE_TX_TIMEOUT
void (*tx_timeout) (struct net_device *dev);
void (*vlan_rx_register)(struct net_device *dev,
struct vlan_group *grp);
void (*vlan_rx_add_vid)(struct net_device *dev,
unsigned short vid);
void (*vlan_rx_kill_vid)(struct net_device *dev,
unsigned short vid);
int (*neigh_setup)(struct net_device *dev, struct neigh_parms *);
#ifdef CONFIG_NETPOLL #ifdef CONFIG_NETPOLL
struct netpoll_info *npinfo; struct netpoll_info *npinfo;
#endif #endif
#ifdef CONFIG_NET_POLL_CONTROLLER
void (*poll_controller)(struct net_device *dev);
#endif
u16 (*select_queue)(struct net_device *dev,
struct sk_buff *skb);
#ifdef CONFIG_NET_NS #ifdef CONFIG_NET_NS
/* Network namespace this network device is inside */ /* Network namespace this network device is inside */
@ -763,6 +835,38 @@ struct net_device
/* for setting kernel sock attribute on TCP connection setup */ /* for setting kernel sock attribute on TCP connection setup */
#define GSO_MAX_SIZE 65536 #define GSO_MAX_SIZE 65536
unsigned int gso_max_size; unsigned int gso_max_size;
#ifdef CONFIG_COMPAT_NET_DEV_OPS
struct {
int (*init)(struct net_device *dev);
void (*uninit)(struct net_device *dev);
int (*open)(struct net_device *dev);
int (*stop)(struct net_device *dev);
void (*change_rx_flags)(struct net_device *dev,
int flags);
void (*set_rx_mode)(struct net_device *dev);
void (*set_multicast_list)(struct net_device *dev);
int (*set_mac_address)(struct net_device *dev,
void *addr);
int (*validate_addr)(struct net_device *dev);
int (*do_ioctl)(struct net_device *dev,
struct ifreq *ifr, int cmd);
int (*set_config)(struct net_device *dev,
struct ifmap *map);
int (*change_mtu)(struct net_device *dev, int new_mtu);
void (*tx_timeout) (struct net_device *dev);
struct net_device_stats* (*get_stats)(struct net_device *dev);
void (*vlan_rx_register)(struct net_device *dev,
struct vlan_group *grp);
void (*vlan_rx_add_vid)(struct net_device *dev,
unsigned short vid);
void (*vlan_rx_kill_vid)(struct net_device *dev,
unsigned short vid);
#ifdef CONFIG_NET_POLL_CONTROLLER
void (*poll_controller)(struct net_device *dev);
#endif
#endif
};
}; };
#define to_net_dev(d) container_of(d, struct net_device, dev) #define to_net_dev(d) container_of(d, struct net_device, dev)

View file

@ -32,6 +32,9 @@ config NET_NS
Allow user space to create what appear to be multiple instances Allow user space to create what appear to be multiple instances
of the network stack. of the network stack.
config COMPAT_NET_DEV_OPS
def_bool y
source "net/packet/Kconfig" source "net/packet/Kconfig"
source "net/unix/Kconfig" source "net/unix/Kconfig"
source "net/xfrm/Kconfig" source "net/xfrm/Kconfig"

View file

@ -1059,6 +1059,7 @@ void dev_load(struct net *net, const char *name)
*/ */
int dev_open(struct net_device *dev) int dev_open(struct net_device *dev)
{ {
const struct net_device_ops *ops = dev->netdev_ops;
int ret = 0; int ret = 0;
ASSERT_RTNL(); ASSERT_RTNL();
@ -1081,11 +1082,11 @@ int dev_open(struct net_device *dev)
*/ */
set_bit(__LINK_STATE_START, &dev->state); set_bit(__LINK_STATE_START, &dev->state);
if (dev->validate_addr) if (ops->ndo_validate_addr)
ret = dev->validate_addr(dev); ret = ops->ndo_validate_addr(dev);
if (!ret && dev->open) if (!ret && ops->ndo_open)
ret = dev->open(dev); ret = ops->ndo_open(dev);
/* /*
* If it went open OK then: * If it went open OK then:
@ -1129,6 +1130,7 @@ int dev_open(struct net_device *dev)
*/ */
int dev_close(struct net_device *dev) int dev_close(struct net_device *dev)
{ {
const struct net_device_ops *ops = dev->netdev_ops;
ASSERT_RTNL(); ASSERT_RTNL();
might_sleep(); might_sleep();
@ -1161,8 +1163,8 @@ int dev_close(struct net_device *dev)
* We allow it to be called even after a DETACH hot-plug * We allow it to be called even after a DETACH hot-plug
* event. * event.
*/ */
if (dev->stop) if (ops->ndo_stop)
dev->stop(dev); ops->ndo_stop(dev);
/* /*
* Device is now down. * Device is now down.
@ -2930,8 +2932,10 @@ int netdev_set_master(struct net_device *slave, struct net_device *master)
static void dev_change_rx_flags(struct net_device *dev, int flags) static void dev_change_rx_flags(struct net_device *dev, int flags)
{ {
if (dev->flags & IFF_UP && dev->change_rx_flags) const struct net_device_ops *ops = dev->netdev_ops;
dev->change_rx_flags(dev, flags);
if ((dev->flags & IFF_UP) && ops->ndo_change_rx_flags)
ops->ndo_change_rx_flags(dev, flags);
} }
static int __dev_set_promiscuity(struct net_device *dev, int inc) static int __dev_set_promiscuity(struct net_device *dev, int inc)
@ -3051,6 +3055,8 @@ int dev_set_allmulti(struct net_device *dev, int inc)
*/ */
void __dev_set_rx_mode(struct net_device *dev) void __dev_set_rx_mode(struct net_device *dev)
{ {
const struct net_device_ops *ops = dev->netdev_ops;
/* dev_open will call this function so the list will stay sane. */ /* dev_open will call this function so the list will stay sane. */
if (!(dev->flags&IFF_UP)) if (!(dev->flags&IFF_UP))
return; return;
@ -3058,8 +3064,8 @@ void __dev_set_rx_mode(struct net_device *dev)
if (!netif_device_present(dev)) if (!netif_device_present(dev))
return; return;
if (dev->set_rx_mode) if (ops->ndo_set_rx_mode)
dev->set_rx_mode(dev); ops->ndo_set_rx_mode(dev);
else { else {
/* Unicast addresses changes may only happen under the rtnl, /* Unicast addresses changes may only happen under the rtnl,
* therefore calling __dev_set_promiscuity here is safe. * therefore calling __dev_set_promiscuity here is safe.
@ -3072,8 +3078,8 @@ void __dev_set_rx_mode(struct net_device *dev)
dev->uc_promisc = 0; dev->uc_promisc = 0;
} }
if (dev->set_multicast_list) if (ops->ndo_set_multicast_list)
dev->set_multicast_list(dev); ops->ndo_set_multicast_list(dev);
} }
} }
@ -3432,6 +3438,7 @@ int dev_change_flags(struct net_device *dev, unsigned flags)
*/ */
int dev_set_mtu(struct net_device *dev, int new_mtu) int dev_set_mtu(struct net_device *dev, int new_mtu)
{ {
const struct net_device_ops *ops = dev->netdev_ops;
int err; int err;
if (new_mtu == dev->mtu) if (new_mtu == dev->mtu)
@ -3445,10 +3452,11 @@ int dev_set_mtu(struct net_device *dev, int new_mtu)
return -ENODEV; return -ENODEV;
err = 0; err = 0;
if (dev->change_mtu) if (ops->ndo_change_mtu)
err = dev->change_mtu(dev, new_mtu); err = ops->ndo_change_mtu(dev, new_mtu);
else else
dev->mtu = new_mtu; dev->mtu = new_mtu;
if (!err && dev->flags & IFF_UP) if (!err && dev->flags & IFF_UP)
call_netdevice_notifiers(NETDEV_CHANGEMTU, dev); call_netdevice_notifiers(NETDEV_CHANGEMTU, dev);
return err; return err;
@ -3463,15 +3471,16 @@ int dev_set_mtu(struct net_device *dev, int new_mtu)
*/ */
int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa) int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa)
{ {
const struct net_device_ops *ops = dev->netdev_ops;
int err; int err;
if (!dev->set_mac_address) if (!ops->ndo_set_mac_address)
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (sa->sa_family != dev->type) if (sa->sa_family != dev->type)
return -EINVAL; return -EINVAL;
if (!netif_device_present(dev)) if (!netif_device_present(dev))
return -ENODEV; return -ENODEV;
err = dev->set_mac_address(dev, sa); err = ops->ndo_set_mac_address(dev, sa);
if (!err) if (!err)
call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
return err; return err;
@ -3551,6 +3560,7 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)
{ {
int err; int err;
struct net_device *dev = __dev_get_by_name(net, ifr->ifr_name); struct net_device *dev = __dev_get_by_name(net, ifr->ifr_name);
const struct net_device_ops *ops = dev->netdev_ops;
if (!dev) if (!dev)
return -ENODEV; return -ENODEV;
@ -3578,15 +3588,15 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)
return 0; return 0;
case SIOCSIFMAP: case SIOCSIFMAP:
if (dev->set_config) { if (ops->ndo_set_config) {
if (!netif_device_present(dev)) if (!netif_device_present(dev))
return -ENODEV; return -ENODEV;
return dev->set_config(dev, &ifr->ifr_map); return ops->ndo_set_config(dev, &ifr->ifr_map);
} }
return -EOPNOTSUPP; return -EOPNOTSUPP;
case SIOCADDMULTI: case SIOCADDMULTI:
if ((!dev->set_multicast_list && !dev->set_rx_mode) || if ((!ops->ndo_set_multicast_list && !ops->ndo_set_rx_mode) ||
ifr->ifr_hwaddr.sa_family != AF_UNSPEC) ifr->ifr_hwaddr.sa_family != AF_UNSPEC)
return -EINVAL; return -EINVAL;
if (!netif_device_present(dev)) if (!netif_device_present(dev))
@ -3595,7 +3605,7 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)
dev->addr_len, 1); dev->addr_len, 1);
case SIOCDELMULTI: case SIOCDELMULTI:
if ((!dev->set_multicast_list && !dev->set_rx_mode) || if ((!ops->ndo_set_multicast_list && !ops->ndo_set_rx_mode) ||
ifr->ifr_hwaddr.sa_family != AF_UNSPEC) ifr->ifr_hwaddr.sa_family != AF_UNSPEC)
return -EINVAL; return -EINVAL;
if (!netif_device_present(dev)) if (!netif_device_present(dev))
@ -3633,10 +3643,9 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)
cmd == SIOCBRDELIF || cmd == SIOCBRDELIF ||
cmd == SIOCWANDEV) { cmd == SIOCWANDEV) {
err = -EOPNOTSUPP; err = -EOPNOTSUPP;
if (dev->do_ioctl) { if (ops->ndo_do_ioctl) {
if (netif_device_present(dev)) if (netif_device_present(dev))
err = dev->do_ioctl(dev, ifr, err = ops->ndo_do_ioctl(dev, ifr, cmd);
cmd);
else else
err = -ENODEV; err = -ENODEV;
} }
@ -3897,8 +3906,8 @@ static void rollback_registered(struct net_device *dev)
*/ */
dev_addr_discard(dev); dev_addr_discard(dev);
if (dev->uninit) if (dev->netdev_ops->ndo_uninit)
dev->uninit(dev); dev->netdev_ops->ndo_uninit(dev);
/* Notifier chain MUST detach us from master device. */ /* Notifier chain MUST detach us from master device. */
WARN_ON(dev->master); WARN_ON(dev->master);
@ -3988,7 +3997,7 @@ int register_netdevice(struct net_device *dev)
struct hlist_head *head; struct hlist_head *head;
struct hlist_node *p; struct hlist_node *p;
int ret; int ret;
struct net *net; struct net *net = dev_net(dev);
BUG_ON(dev_boot_phase); BUG_ON(dev_boot_phase);
ASSERT_RTNL(); ASSERT_RTNL();
@ -3997,8 +4006,7 @@ int register_netdevice(struct net_device *dev)
/* When net_device's are persistent, this will be fatal. */ /* When net_device's are persistent, this will be fatal. */
BUG_ON(dev->reg_state != NETREG_UNINITIALIZED); BUG_ON(dev->reg_state != NETREG_UNINITIALIZED);
BUG_ON(!dev_net(dev)); BUG_ON(!net);
net = dev_net(dev);
spin_lock_init(&dev->addr_list_lock); spin_lock_init(&dev->addr_list_lock);
netdev_set_addr_lockdep_class(dev); netdev_set_addr_lockdep_class(dev);
@ -4006,9 +4014,46 @@ int register_netdevice(struct net_device *dev)
dev->iflink = -1; dev->iflink = -1;
#ifdef CONFIG_COMPAT_NET_DEV_OPS
/* Netdevice_ops API compatiability support.
* This is temporary until all network devices are converted.
*/
if (dev->netdev_ops) {
const struct net_device_ops *ops = dev->netdev_ops;
dev->init = ops->ndo_init;
dev->uninit = ops->ndo_uninit;
dev->open = ops->ndo_open;
dev->change_rx_flags = ops->ndo_change_rx_flags;
dev->set_rx_mode = ops->ndo_set_rx_mode;
dev->set_multicast_list = ops->ndo_set_multicast_list;
dev->set_mac_address = ops->ndo_set_mac_address;
dev->validate_addr = ops->ndo_validate_addr;
dev->do_ioctl = ops->ndo_do_ioctl;
dev->set_config = ops->ndo_set_config;
dev->change_mtu = ops->ndo_change_mtu;
dev->tx_timeout = ops->ndo_tx_timeout;
dev->get_stats = ops->ndo_get_stats;
dev->vlan_rx_register = ops->ndo_vlan_rx_register;
dev->vlan_rx_add_vid = ops->ndo_vlan_rx_add_vid;
dev->vlan_rx_kill_vid = ops->ndo_vlan_rx_kill_vid;
#ifdef CONFIG_NET_POLL_CONTROLLER
dev->poll_controller = ops->ndo_poll_controller;
#endif
} else {
char drivername[64];
pr_info("%s (%s): not using net_device_ops yet\n",
dev->name, netdev_drivername(dev, drivername, 64));
/* This works only because net_device_ops and the
compatiablity structure are the same. */
dev->netdev_ops = (void *) &(dev->init);
}
#endif
/* Init, if this function is available */ /* Init, if this function is available */
if (dev->init) { if (dev->netdev_ops->ndo_init) {
ret = dev->init(dev); ret = dev->netdev_ops->ndo_init(dev);
if (ret) { if (ret) {
if (ret > 0) if (ret > 0)
ret = -EIO; ret = -EIO;
@ -4086,8 +4131,8 @@ out:
return ret; return ret;
err_uninit: err_uninit:
if (dev->uninit) if (dev->netdev_ops->ndo_uninit)
dev->uninit(dev); dev->netdev_ops->ndo_uninit(dev);
goto out; goto out;
} }

View file

@ -172,12 +172,13 @@ static void service_arp_queue(struct netpoll_info *npi)
void netpoll_poll(struct netpoll *np) void netpoll_poll(struct netpoll *np)
{ {
struct net_device *dev = np->dev; struct net_device *dev = np->dev;
const struct net_device_ops *ops = dev->netdev_ops;
if (!dev || !netif_running(dev) || !dev->poll_controller) if (!dev || !netif_running(dev) || !ops->ndo_poll_controller)
return; return;
/* Process pending work on NIC */ /* Process pending work on NIC */
dev->poll_controller(dev); ops->ndo_poll_controller(dev);
poll_napi(dev); poll_napi(dev);
@ -694,7 +695,7 @@ int netpoll_setup(struct netpoll *np)
atomic_inc(&npinfo->refcnt); atomic_inc(&npinfo->refcnt);
} }
if (!ndev->poll_controller) { if (!ndev->netdev_ops->ndo_poll_controller) {
printk(KERN_ERR "%s: %s doesn't support polling, aborting.\n", printk(KERN_ERR "%s: %s doesn't support polling, aborting.\n",
np->name, np->dev_name); np->name, np->dev_name);
err = -ENOTSUPP; err = -ENOTSUPP;

View file

@ -762,6 +762,7 @@ static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[])
static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
struct nlattr **tb, char *ifname, int modified) struct nlattr **tb, char *ifname, int modified)
{ {
const struct net_device_ops *ops = dev->netdev_ops;
int send_addr_notify = 0; int send_addr_notify = 0;
int err; int err;
@ -783,7 +784,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
struct rtnl_link_ifmap *u_map; struct rtnl_link_ifmap *u_map;
struct ifmap k_map; struct ifmap k_map;
if (!dev->set_config) { if (!ops->ndo_set_config) {
err = -EOPNOTSUPP; err = -EOPNOTSUPP;
goto errout; goto errout;
} }
@ -801,7 +802,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
k_map.dma = (unsigned char) u_map->dma; k_map.dma = (unsigned char) u_map->dma;
k_map.port = (unsigned char) u_map->port; k_map.port = (unsigned char) u_map->port;
err = dev->set_config(dev, &k_map); err = ops->ndo_set_config(dev, &k_map);
if (err < 0) if (err < 0)
goto errout; goto errout;
@ -812,7 +813,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
struct sockaddr *sa; struct sockaddr *sa;
int len; int len;
if (!dev->set_mac_address) { if (!ops->ndo_set_mac_address) {
err = -EOPNOTSUPP; err = -EOPNOTSUPP;
goto errout; goto errout;
} }
@ -831,7 +832,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
sa->sa_family = dev->type; sa->sa_family = dev->type;
memcpy(sa->sa_data, nla_data(tb[IFLA_ADDRESS]), memcpy(sa->sa_data, nla_data(tb[IFLA_ADDRESS]),
dev->addr_len); dev->addr_len);
err = dev->set_mac_address(dev, sa); err = ops->ndo_set_mac_address(dev, sa);
kfree(sa); kfree(sa);
if (err) if (err)
goto errout; goto errout;

View file

@ -224,7 +224,7 @@ static void dev_watchdog(unsigned long arg)
char drivername[64]; char drivername[64];
WARN_ONCE(1, KERN_INFO "NETDEV WATCHDOG: %s (%s): transmit timed out\n", WARN_ONCE(1, KERN_INFO "NETDEV WATCHDOG: %s (%s): transmit timed out\n",
dev->name, netdev_drivername(dev, drivername, 64)); dev->name, netdev_drivername(dev, drivername, 64));
dev->tx_timeout(dev); dev->netdev_ops->ndo_tx_timeout(dev);
} }
if (!mod_timer(&dev->watchdog_timer, if (!mod_timer(&dev->watchdog_timer,
round_jiffies(jiffies + round_jiffies(jiffies +
@ -239,7 +239,7 @@ static void dev_watchdog(unsigned long arg)
void __netdev_watchdog_up(struct net_device *dev) void __netdev_watchdog_up(struct net_device *dev)
{ {
if (dev->tx_timeout) { if (dev->netdev_ops->ndo_tx_timeout) {
if (dev->watchdog_timeo <= 0) if (dev->watchdog_timeo <= 0)
dev->watchdog_timeo = 5*HZ; dev->watchdog_timeo = 5*HZ;
if (!mod_timer(&dev->watchdog_timer, if (!mod_timer(&dev->watchdog_timer,