From: Luis R. Rodriguez Date: Tue, 4 May 2010 23:43:05 +0000 (-0700) Subject: compat: add new way to backport the usage of net_device_ops X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=7349fb77e7b24102f4539a8022e9fd75147b5012;p=openwrt%2Fstaging%2Fblogic.git compat: add new way to backport the usage of net_device_ops We tend to #ifdef code that uses the new net_device_ops on kernels older than 2.6.29. This tends to create a burden on the upkeeping of the hunks. We can minimize our work by instead definining a new netdev_attach_ops() which will do our backport work for the older kernels and simply attach the ops for newer kernels. This should simplify backporting of network drivers considerably. Signed-off-by: Luis R. Rodriguez --- diff --git a/compat/compat-2.6.29.c b/compat/compat-2.6.29.c index c8e0183fa08b..c2a5f5316356 100644 --- a/compat/compat-2.6.29.c +++ b/compat/compat-2.6.29.c @@ -1,5 +1,5 @@ /* - * Copyright 2007 Luis R. Rodriguez + * Copyright 2007-2010 Luis R. Rodriguez * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -15,6 +15,26 @@ #include #include +/* + * Expand this as drivers require more ops, for now this + * only sets the ones we need. + */ +void netdev_attach_ops(struct net_device *dev, + const struct net_device_ops *ops) +{ +#define SET_NETDEVOP(_op) (_op ? _op : NULL) + dev->open = SET_NETDEVOP(ops->ndo_open); + dev->stop = SET_NETDEVOP(ops->ndo_stop); + dev->hard_start_xmit = SET_NETDEVOP(ops->ndo_start_xmit); + dev->set_multicast_list = SET_NETDEVOP(ops->ndo_set_multicast_list); + dev->change_mtu = SET_NETDEVOP(ops->ndo_change_mtu); + dev->set_mac_address = SET_NETDEVOP(ops->ndo_set_mac_address); + dev->tx_timeout = SET_NETDEVOP(ops->ndo_tx_timeout); + dev->get_stats = SET_NETDEVOP(ops->ndo_get_stats); +#undef SET_NETDEVOP +} +EXPORT_SYMBOL(netdev_attach_ops); + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)) #if defined(CONFIG_USB) || defined(CONFIG_USB_MODULE) /** diff --git a/include/linux/compat-2.6.29.h b/include/linux/compat-2.6.29.h index c3572a2026a3..165b78c33c27 100644 --- a/include/linux/compat-2.6.29.h +++ b/include/linux/compat-2.6.29.h @@ -2,13 +2,199 @@ #define LINUX_26_29_COMPAT_H #include +#include +#include + +/* + * I kow this looks odd.. but 2.6.32 added the netdev_tx_t + * and we backport that there so inlcude that header first + * as we need it for the netdev ops. + */ +#include #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)) -#include #include #include +/* + * Older kernels do not have struct net_device_ops but what we can + * do is just define the data structure and use a caller to let us + * set the data structure's routines onto the old netdev, essentially + * doing it the old way. This avoids huge deltas on our backports. + */ + +/* + * This structure defines the management hooks for network devices. + * The following hooks can be defined; unless noted otherwise, they are + * optional and can be filled with a null pointer. + * + * 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. + * + * netdev_tx_t (*ndo_start_xmit)(struct sk_buff *skb, + * struct net_device *dev); + * Called when a packet needs to be transmitted. + * Must return NETDEV_TX_OK , NETDEV_TX_BUSY. + * (can also return NETDEV_TX_LOCKED iff NETIF_F_LLTX) + * Required can not be NULL. + * + * u16 (*ndo_select_queue)(struct net_device *dev, struct sk_buff *skb); + * Called to decide which queue to when device supports multiple + * transmit queues. + * + * 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 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* (*ndo_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); + * + * SR-IOV management functions. + * int (*ndo_set_vf_mac)(struct net_device *dev, int vf, u8* mac); + * int (*ndo_set_vf_vlan)(struct net_device *dev, int vf, u16 vlan, u8 qos); + * int (*ndo_set_vf_tx_rate)(struct net_device *dev, int vf, int rate); + * int (*ndo_get_vf_config)(struct net_device *dev, + * int vf, struct ifla_vf_info *ivf); + */ +#define HAVE_NET_DEVICE_OPS +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); + netdev_tx_t (*ndo_start_xmit) (struct sk_buff *skb, + struct net_device *dev); + u16 (*ndo_select_queue)(struct net_device *dev, + struct sk_buff *skb); + void (*ndo_change_rx_flags)(struct net_device *dev, + int flags); + void (*ndo_set_rx_mode)(struct net_device *dev); + void (*ndo_set_multicast_list)(struct net_device *dev); + int (*ndo_set_mac_address)(struct net_device *dev, + void *addr); + int (*ndo_validate_addr)(struct net_device *dev); + int (*ndo_do_ioctl)(struct net_device *dev, + struct ifreq *ifr, int cmd); + int (*ndo_set_config)(struct net_device *dev, + struct ifmap *map); + int (*ndo_change_mtu)(struct net_device *dev, + int new_mtu); + int (*ndo_neigh_setup)(struct net_device *dev, + struct neigh_parms *); + 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 + void (*ndo_poll_controller)(struct net_device *dev); +#endif + int (*ndo_set_vf_mac)(struct net_device *dev, + int queue, u8 *mac); + int (*ndo_set_vf_vlan)(struct net_device *dev, + int queue, u16 vlan, u8 qos); + int (*ndo_set_vf_tx_rate)(struct net_device *dev, + int vf, int rate); +/* + * The struct ifla_vf_info was added via b280da8d54b8d82b52f368a8703b7ada6c1744d5 + * on the v2.6.34-rc1~233^2~338 release + */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34)) + int (*ndo_get_vf_config)(struct net_device *dev, + int vf, + struct ifla_vf_info *ivf); +#endif +#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE) + int (*ndo_fcoe_enable)(struct net_device *dev); + int (*ndo_fcoe_disable)(struct net_device *dev); + int (*ndo_fcoe_ddp_setup)(struct net_device *dev, + u16 xid, + struct scatterlist *sgl, + unsigned int sgc); + int (*ndo_fcoe_ddp_done)(struct net_device *dev, + u16 xid); +#define NETDEV_FCOE_WWNN 0 +#define NETDEV_FCOE_WWPN 1 + int (*ndo_fcoe_get_wwn)(struct net_device *dev, + u64 *wwn, int type); +#endif +}; + +void netdev_attach_ops(struct net_device *dev, + const struct net_device_ops *ops); + /** * skb_queue_is_first - check if skb is the first entry in the queue * @list: queue head @@ -61,6 +247,13 @@ extern void usb_unpoison_anchored_urbs(struct usb_anchor *anchor); extern int eth_mac_addr(struct net_device *dev, void *p); +#else + +static inline void netdev_attach_ops(struct net_device *dev, + const struct net_device_ops *ops) +{ + dev->netdev_ops = ops; +} #endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)) */ #endif /* LINUX_26_29_COMPAT_H */