mirror of
https://github.com/adulau/aha.git
synced 2024-12-29 04:06:22 +00:00
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:
parent
6b41e7dd90
commit
d314774cf2
6 changed files with 259 additions and 105 deletions
|
@ -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
|
||||||
|
@ -499,11 +624,6 @@ struct net_device
|
||||||
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;
|
||||||
#define NETIF_F_SG 1 /* Scatter/gather IO. */
|
#define NETIF_F_SG 1 /* Scatter/gather IO. */
|
||||||
|
@ -553,8 +673,6 @@ struct net_device
|
||||||
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. */
|
||||||
|
@ -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);
|
|
||||||
/* Called after last user reference disappears. */
|
|
||||||
void (*destructor)(struct net_device *dev);
|
void (*destructor)(struct net_device *dev);
|
||||||
|
|
||||||
/* Pointers to interface service routines. */
|
|
||||||
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 *);
|
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)
|
||||||
|
|
||||||
|
|
|
@ -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"
|
||||||
|
|
109
net/core/dev.c
109
net/core/dev.c
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in a new issue