compat: add new way to backport the usage of net_device_ops
authorLuis R. Rodriguez <lrodriguez@atheros.com>
Tue, 4 May 2010 23:43:05 +0000 (16:43 -0700)
committerLuis R. Rodriguez <lrodriguez@atheros.com>
Tue, 4 May 2010 23:43:05 +0000 (16:43 -0700)
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 <lrodriguez@atheros.com>
compat/compat-2.6.29.c
include/linux/compat-2.6.29.h

index c8e0183..c2a5f53 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2007      Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
+ * Copyright 2007-2010 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
  *
  * 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
 #include <linux/usb.h>
 #include <linux/etherdevice.h>
 
+/*
+ * 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)
 /**
index c3572a2..165b78c 100644 (file)
 #define LINUX_26_29_COMPAT_H
 
 #include <linux/version.h>
+#include <linux/netdevice.h>
+#include <linux/if_link.h>
+
+/*
+ * 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 <linux/compat-2.6.32.h>
 
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29))
 
-#include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <linux/usb.h>
 
+/*
+ * 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 */