]> git.openfabrics.org - ~emulex/compat-rdma_3.12.git/commitdiff
cxgb3: Backports for RHEL6.4, RHEL6.5 and SLES11sp3
authorKumar Sanghvi <kumaras@chelsio.com>
Tue, 24 Dec 2013 18:56:27 +0000 (00:26 +0530)
committerVipul Pandya <vipul@chelsio.com>
Thu, 26 Dec 2013 10:08:03 +0000 (02:08 -0800)
Signed-off-by: Kumar Sanghvi <kumaras@chelsio.com>
patches/0007-cxgb3-RHEL64-RHEL65-SLES11SP3-backport.patch [new file with mode: 0644]

diff --git a/patches/0007-cxgb3-RHEL64-RHEL65-SLES11SP3-backport.patch b/patches/0007-cxgb3-RHEL64-RHEL65-SLES11SP3-backport.patch
new file mode 100644 (file)
index 0000000..196cc91
--- /dev/null
@@ -0,0 +1,670 @@
+diff --git a/drivers/net/ethernet/chelsio/cxgb3/adapter.h b/drivers/net/ethernet/chelsio/cxgb3/adapter.h
+index 8b395b5..27bd384 100644
+--- a/drivers/net/ethernet/chelsio/cxgb3/adapter.h
++++ b/drivers/net/ethernet/chelsio/cxgb3/adapter.h
+@@ -45,10 +45,20 @@
+ #include "t3cdev.h"
+ #include <asm/io.h>
++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)
++struct vlan_group;
++#endif
+ struct adapter;
+ struct sge_qset;
+ struct port_info;
++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0)
++enum {                 /* rx_offload flags */
++      T3_RX_CSUM      = 1 << 0,
++      T3_LRO          = 1 << 1,
++};
++#endif
++
+ enum mac_idx_types {
+       LAN_MAC_IDX     = 0,
+       SAN_MAC_IDX,
+@@ -65,8 +75,14 @@ struct iscsi_config {
+ struct port_info {
+       struct adapter *adapter;
++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)
++      struct vlan_group *vlan_grp;
++#endif
+       struct sge_qset *qs;
+       u8 port_id;
++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0)
++      u8 rx_offload;
++#endif
+       u8 nqsets;
+       u8 first_qset;
+       struct cphy phy;
+@@ -204,6 +220,9 @@ struct sge_qset {          /* an SGE queue set */
+       struct sge_fl fl[SGE_RXQ_PER_SET];
+       struct sge_txq txq[SGE_TXQ_PER_SET];
+       int nomem;
++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0)
++      int lro_enabled;
++#endif
+       void *lro_va;
+       struct net_device *netdev;
+       struct netdev_queue *tx_q;      /* associated netdev TX queue */
+diff --git a/drivers/net/ethernet/chelsio/cxgb3/common.h b/drivers/net/ethernet/chelsio/cxgb3/common.h
+index 8c82248..97bd0a7 100644
+--- a/drivers/net/ethernet/chelsio/cxgb3/common.h
++++ b/drivers/net/ethernet/chelsio/cxgb3/common.h
+@@ -316,6 +316,9 @@ struct tp_params {
+ struct qset_params {          /* SGE queue set parameters */
+       unsigned int polling;   /* polling/interrupt service for rspq */
++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0)
++      unsigned int lro;       /* large receive offload */
++#endif
+       unsigned int coalesce_usecs;    /* irq coalescing timer */
+       unsigned int rspq_size; /* # of entries in response queue */
+       unsigned int fl_size;   /* # of entries in regular free list */
+diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
+index b650951..df32cc5 100644
+--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
++++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
+@@ -647,6 +647,28 @@ static void enable_all_napi(struct adapter *adap)
+                       napi_enable(&adap->sge.qs[i].napi);
+ }
++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0)
++/**
++ *     set_qset_lro - Turn a queue set's LRO capability on and off
++ *     @dev: the device the qset is attached to
++ *     @qset_idx: the queue set index
++ *     @val: the LRO switch
++ *
++ *     Sets LRO on or off for a particular queue set.
++ *     the device's features flag is updated to reflect the LRO
++ *     capability when all queues belonging to the device are
++ *     in the same state.
++ */
++static void set_qset_lro(struct net_device *dev, int qset_idx, int val)
++{
++      struct port_info *pi = netdev_priv(dev);
++      struct adapter *adapter = pi->adapter;
++
++      adapter->params.sge.qset[qset_idx].lro = !!val;
++      adapter->sge.qs[qset_idx].lro_enabled = !!val;
++}
++#endif
++
+ /**
+  *    setup_sge_qsets - configure SGE Tx/Rx/response queues
+  *    @adap: the adapter
+@@ -1174,6 +1196,7 @@ static void t3_synchronize_rx(struct adapter *adap, const struct port_info *p)
+       }
+ }
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+ static void cxgb_vlan_mode(struct net_device *dev, netdev_features_t features)
+ {
+       struct port_info *pi = netdev_priv(dev);
+@@ -1195,6 +1218,27 @@ static void cxgb_vlan_mode(struct net_device *dev, netdev_features_t features)
+       }
+       t3_synchronize_rx(adapter, pi);
+ }
++#else
++static void vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
++{
++      struct port_info *pi = netdev_priv(dev);
++      struct adapter *adapter = pi->adapter;
++
++      pi->vlan_grp = grp;
++      if (adapter->params.rev > 0)
++              t3_set_vlan_accel(adapter, 1 << pi->port_id, grp != NULL);
++      else {
++              /* single control for all ports */
++              unsigned int i, have_vlans = 0;
++              for_each_port(adapter, i)
++                      have_vlans |= adap2pinfo(adapter, i)->vlan_grp != NULL;
++
++              t3_set_vlan_accel(adapter, 1, have_vlans);
++      }
++      t3_synchronize_rx(adapter, pi);
++}
++#endif
++
+ /**
+  *    cxgb_up - enable the adapter
+@@ -1208,7 +1252,10 @@ static void cxgb_vlan_mode(struct net_device *dev, netdev_features_t features)
+  */
+ static int cxgb_up(struct adapter *adap)
+ {
+-      int i, err;
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
++      int i;
++#endif
++      int err;
+       if (!(adap->flags & FULL_INIT_DONE)) {
+               err = t3_check_fw_version(adap);
+@@ -1245,8 +1292,10 @@ static int cxgb_up(struct adapter *adap)
+               if (err)
+                       goto out;
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+               for_each_port(adap, i)
+                       cxgb_vlan_mode(adap->port[i], adap->port[i]->features);
++#endif
+               setup_rss(adap);
+               if (!(adap->flags & NAPI_INIT))
+@@ -1775,6 +1824,7 @@ static int restart_autoneg(struct net_device *dev)
+       return 0;
+ }
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
+ static int set_phys_id(struct net_device *dev,
+                      enum ethtool_phys_id_state state)
+ {
+@@ -1797,6 +1847,28 @@ static int set_phys_id(struct net_device *dev,
+       return 0;
+ }
++#else
++static int cxgb3_phys_id(struct net_device *dev, u32 data)
++{
++      struct port_info *pi = netdev_priv(dev);
++      struct adapter *adapter = pi->adapter;
++      int i;
++
++      if (data == 0)
++              data = 2;
++
++      for (i = 0; i < data * 2; i++) {
++              t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, F_GPIO0_OUT_VAL,
++                              (i & 1) ? F_GPIO0_OUT_VAL : 0);
++              if (msleep_interruptible(500))
++                      break;
++      }
++
++      t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, F_GPIO0_OUT_VAL,
++                      F_GPIO0_OUT_VAL);
++      return 0;
++}
++#endif
+ static int get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+ {
+@@ -2110,7 +2182,11 @@ static const struct ethtool_ops cxgb_ethtool_ops = {
+       .set_pauseparam = set_pauseparam,
+       .get_link = ethtool_op_get_link,
+       .get_strings = get_strings,
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
+       .set_phys_id = set_phys_id,
++#else
++      .phys_id = cxgb3_phys_id,
++#endif
+       .nway_reset = restart_autoneg,
+       .get_sset_count = get_sset_count,
+       .get_ethtool_stats = get_stats,
+@@ -2225,6 +2301,7 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr)
+                       }
+               }
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
+               if (t.lro >= 0) {
+                       if (t.lro)
+                               dev->wanted_features |= NETIF_F_GRO;
+@@ -2232,6 +2309,10 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr)
+                               dev->wanted_features &= ~NETIF_F_GRO;
+                       netdev_update_features(dev);
+               }
++#else
++              if (t.lro >= 0)
++                      set_qset_lro(dev, t.qset_idx, t.lro);
++#endif
+               break;
+       }
+@@ -2557,6 +2638,7 @@ static int cxgb_set_mac_addr(struct net_device *dev, void *p)
+       return 0;
+ }
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+ static netdev_features_t cxgb_fix_features(struct net_device *dev,
+       netdev_features_t features)
+ {
+@@ -2581,6 +2663,7 @@ static int cxgb_set_features(struct net_device *dev, netdev_features_t features)
+       return 0;
+ }
++#endif
+ #ifdef CONFIG_NET_POLL_CONTROLLER
+ static void cxgb_netpoll(struct net_device *dev)
+@@ -3042,11 +3125,19 @@ static void t3_io_resume(struct pci_dev *pdev)
+       rtnl_unlock();
+ }
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)
+ static const struct pci_error_handlers t3_err_handler = {
+       .error_detected = t3_io_error_detected,
+       .slot_reset = t3_io_slot_reset,
+       .resume = t3_io_resume,
+ };
++#else
++static struct pci_error_handlers t3_err_handler = {
++      .error_detected = t3_io_error_detected,
++      .slot_reset = t3_io_slot_reset,
++      .resume = t3_io_resume,
++};
++#endif
+ /*
+  * Set the number of qsets based on the number of CPUs and the number of ports,
+@@ -3162,8 +3253,12 @@ static const struct net_device_ops cxgb_netdev_ops = {
+       .ndo_do_ioctl           = cxgb_ioctl,
+       .ndo_change_mtu         = cxgb_change_mtu,
+       .ndo_set_mac_address    = cxgb_set_mac_addr,
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+       .ndo_fix_features       = cxgb_fix_features,
+       .ndo_set_features       = cxgb_set_features,
++#else
++      .ndo_vlan_rx_register   = vlan_rx_register,
++#endif
+ #ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller    = cxgb_netpoll,
+ #endif
+@@ -3290,14 +3385,35 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+               netdev->irq = pdev->irq;
+               netdev->mem_start = mmio_start;
+               netdev->mem_end = mmio_start + mmio_len - 1;
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
++#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 0, 0)
++              netdev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM |
++                      NETIF_F_TSO | NETIF_F_RXCSUM;
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
++              netdev->features |= netdev->hw_features |
++                      NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX;
++#else
++              netdev->features |= netdev->hw_features |
++                      NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0) */
++#else
+               netdev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM |
+                       NETIF_F_TSO | NETIF_F_RXCSUM | NETIF_F_HW_VLAN_CTAG_RX;
+               netdev->features |= netdev->hw_features |
+                                   NETIF_F_HW_VLAN_CTAG_TX;
++#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(3,0, 0) */
++#else
++              netdev->features |= NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO;
++              netdev->features |= NETIF_F_GRO;
++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) */
+               netdev->vlan_features |= netdev->features & VLAN_FEAT;
+               if (pci_using_dac)
+                       netdev->features |= NETIF_F_HIGHDMA;
++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0)
++              netdev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
++#endif
++
+               netdev->netdev_ops = &cxgb_netdev_ops;
+               SET_ETHTOOL_OPS(netdev, &cxgb_ethtool_ops);
+       }
+diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c
+index 76ae099..3033d05 100644
+--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c
++++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c
+@@ -64,8 +64,14 @@ static const unsigned int MAX_ATIDS = 64 * 1024;
+ static const unsigned int ATID_BASE = 0x10000;
+ static void cxgb_neigh_update(struct neighbour *neigh);
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+ static void cxgb_redirect(struct dst_entry *old, struct dst_entry *new,
+-                        struct neighbour *neigh, const void *daddr);
++                          struct neighbour *neigh,
++                          const void *daddr);
++#else
++static void cxgb_redirect(struct dst_entry *old, struct dst_entry *new);
++#endif
+ static inline int offload_activated(struct t3cdev *tdev)
+ {
+@@ -180,18 +186,36 @@ static struct net_device *get_iff_from_mac(struct adapter *adapter,
+       int i;
+       for_each_port(adapter, i) {
++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)
++              struct vlan_group *grp;
++#endif
+               struct net_device *dev = adapter->port[i];
++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)
++              const struct port_info *p = netdev_priv(dev);
++#endif
+               if (!memcmp(dev->dev_addr, mac, ETH_ALEN)) {
+                       rcu_read_lock();
+                       if (vlan && vlan != VLAN_VID_MASK) {
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+                               dev = __vlan_find_dev_deep(dev, htons(ETH_P_8021Q), vlan);
++#else
++                              grp = p->vlan_grp;
++                              dev = NULL;
++                              if (grp)
++                                      dev = vlan_group_get_device(grp, vlan);
++#endif
+                       } else if (netif_is_bond_slave(dev)) {
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+                               struct net_device *upper_dev;
+                               while ((upper_dev =
+                                       netdev_master_upper_dev_get_rcu(dev)))
+                                       dev = upper_dev;
++#else
++                              while (dev->master)
++                                      dev = dev->master;
++#endif
+                       }
+                       rcu_read_unlock();
+                       return dev;
+@@ -969,9 +993,14 @@ static int nb_callback(struct notifier_block *self, unsigned long event,
+       }
+       case (NETEVENT_REDIRECT):{
+               struct netevent_redirect *nr = ctx;
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+               cxgb_redirect(nr->old, nr->new, nr->neigh,
+                             nr->daddr);
+               cxgb_neigh_update(nr->neigh);
++#else
++              cxgb_redirect(nr->old, nr->new);
++              cxgb_neigh_update(dst_get_neighbour(nr->new));
++#endif
+               break;
+       }
+       default:
+@@ -1107,6 +1136,7 @@ static void set_l2t_ix(struct t3cdev *tdev, u32 tid, struct l2t_entry *e)
+       tdev->send(tdev, skb);
+ }
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+ static void cxgb_redirect(struct dst_entry *old, struct dst_entry *new,
+                         struct neighbour *neigh,
+                         const void *daddr)
+@@ -1127,7 +1157,11 @@ static void cxgb_redirect(struct dst_entry *old, struct dst_entry *new,
+       BUG_ON(!tdev);
+       /* Add new L2T entry */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+       e = t3_l2t_get(tdev, new, dev, daddr);
++#else
++      e = t3_l2t_get(tdev, new, dev);
++#endif
+       if (!e) {
+               pr_err("%s: couldn't allocate new l2t entry!\n", __func__);
+               return;
+@@ -1150,6 +1184,77 @@ static void cxgb_redirect(struct dst_entry *old, struct dst_entry *new,
+       }
+       l2t_release(tdev, e);
+ }
++#else
++static void cxgb_redirect(struct dst_entry *old, struct dst_entry *new)
++{
++      struct net_device *olddev, *newdev;
++      struct neighbour *n;
++      struct tid_info *ti;
++      struct t3cdev *tdev;
++      u32 tid;
++      int update_tcb;
++      struct l2t_entry *e;
++      struct t3c_tid_entry *te;
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
++      n = dst_get_neighbour_noref(old);
++#else
++      n = dst_get_neighbour(old);
++#endif
++      if (!n)
++              return;
++      olddev = n->dev;
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
++      n = dst_get_neighbour_noref(new);
++#else
++      n = dst_get_neighbour(new);
++#endif
++      if (!n)
++              return;
++      newdev = n->dev;
++
++      if (!is_offloading(olddev))
++              return;
++      if (!is_offloading(newdev)) {
++              printk(KERN_WARNING "%s: Redirect to non-offload "
++                              "device ignored.\n", __func__);
++              return;
++      }
++      tdev = dev2t3cdev(olddev);
++      BUG_ON(!tdev);
++      if (tdev != dev2t3cdev(newdev)) {
++              printk(KERN_WARNING "%s: Redirect to different "
++                              "offload device ignored.\n", __func__);
++              return;
++      }
++
++      /* Add new L2T entry */
++      e = t3_l2t_get(tdev, new, newdev);
++      if (!e) {
++              printk(KERN_ERR "%s: couldn't allocate new l2t entry!\n",
++                              __func__);
++              return;
++      }
++
++      /* Walk tid table and notify clients of dst change. */
++      ti = &(T3C_DATA(tdev))->tid_maps;
++      for (tid = 0; tid < ti->ntids; tid++) {
++              te = lookup_tid(ti, tid);
++              BUG_ON(!te);
++              if (te && te->ctx && te->client && te->client->redirect) {
++                      update_tcb = te->client->redirect(te->ctx, old, new, e);
++                      if (update_tcb) {
++                              rcu_read_lock();
++                              l2t_hold(L2DATA(tdev), e);
++                              rcu_read_unlock();
++                              set_l2t_ix(tdev, tid, e);
++                      }
++              }
++      }
++      l2t_release(tdev, e);
++}
++#endif
+ /*
+  * Allocate a chunk of memory using kmalloc or, if that fails, vmalloc.
+diff --git a/drivers/net/ethernet/chelsio/cxgb3/l2t.c b/drivers/net/ethernet/chelsio/cxgb3/l2t.c
+index 8d53438..ea9bd19 100644
+--- a/drivers/net/ethernet/chelsio/cxgb3/l2t.c
++++ b/drivers/net/ethernet/chelsio/cxgb3/l2t.c
+@@ -298,8 +298,13 @@ static inline void reuse_entry(struct l2t_entry *e, struct neighbour *neigh)
+       spin_unlock(&e->lock);
+ }
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+ struct l2t_entry *t3_l2t_get(struct t3cdev *cdev, struct dst_entry *dst,
+                            struct net_device *dev, const void *daddr)
++#else
++struct l2t_entry *t3_l2t_get(struct t3cdev *cdev, struct dst_entry *dst,
++                           struct net_device *dev)
++#endif
+ {
+       struct l2t_entry *e = NULL;
+       struct neighbour *neigh;
+@@ -311,7 +316,11 @@ struct l2t_entry *t3_l2t_get(struct t3cdev *cdev, struct dst_entry *dst,
+       int smt_idx;
+       rcu_read_lock();
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+       neigh = dst_neigh_lookup(dst, daddr);
++#else
++      neigh = dst_get_neighbour(dst);
++#endif
+       if (!neigh)
+               goto done_rcu;
+diff --git a/drivers/net/ethernet/chelsio/cxgb3/l2t.h b/drivers/net/ethernet/chelsio/cxgb3/l2t.h
+index 8cffcdf..1db5a71 100644
+--- a/drivers/net/ethernet/chelsio/cxgb3/l2t.h
++++ b/drivers/net/ethernet/chelsio/cxgb3/l2t.h
+@@ -109,8 +109,13 @@ static inline void set_arp_failure_handler(struct sk_buff *skb,
+ void t3_l2e_free(struct l2t_data *d, struct l2t_entry *e);
+ void t3_l2t_update(struct t3cdev *dev, struct neighbour *neigh);
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+ struct l2t_entry *t3_l2t_get(struct t3cdev *cdev, struct dst_entry *dst,
+                            struct net_device *dev, const void *daddr);
++#else
++struct l2t_entry *t3_l2t_get(struct t3cdev *cdev, struct dst_entry *dst,
++                           struct net_device *dev);
++#endif
+ int t3_l2t_send_slow(struct t3cdev *dev, struct sk_buff *skb,
+                    struct l2t_entry *e);
+ void t3_l2t_send_event(struct t3cdev *dev, struct l2t_entry *e);
+diff --git a/drivers/net/ethernet/chelsio/cxgb3/sge.c b/drivers/net/ethernet/chelsio/cxgb3/sge.c
+index 9c89dc8..9414ae0 100644
+--- a/drivers/net/ethernet/chelsio/cxgb3/sge.c
++++ b/drivers/net/ethernet/chelsio/cxgb3/sge.c
+@@ -2019,7 +2019,11 @@ static void rx_eth(struct adapter *adap, struct sge_rspq *rq,
+       skb_pull(skb, sizeof(*p) + pad);
+       skb->protocol = eth_type_trans(skb, adap->port[p->iff]);
+       pi = netdev_priv(skb->dev);
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
+       if ((skb->dev->features & NETIF_F_RXCSUM) && p->csum_valid &&
++#else
++      if ((pi->rx_offload & T3_RX_CSUM) && p->csum_valid &&
++#endif
+           p->csum == htons(0xffff) && !p->fragment) {
+               qs->port_stats[SGE_PSTAT_RX_CSUM_GOOD]++;
+               skb->ip_summed = CHECKSUM_UNNECESSARY;
+@@ -2027,11 +2031,38 @@ static void rx_eth(struct adapter *adap, struct sge_rspq *rq,
+               skb_checksum_none_assert(skb);
+       skb_record_rx_queue(skb, qs - &adap->sge.qs[pi->first_qset]);
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+       if (p->vlan_valid) {
++#else
++      if (unlikely(p->vlan_valid)) {
++              struct vlan_group *grp = pi->vlan_grp;
++#endif
+               qs->port_stats[SGE_PSTAT_VLANEX]++;
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+               __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), ntohs(p->vlan));
+       }
+       if (rq->polling) {
++#else
++      if (likely(grp))
++              if (lro)
++                      vlan_gro_receive(&qs->napi, grp,
++                                      ntohs(p->vlan), skb);
++              else {
++                      if (unlikely(pi->iscsic.flags)) {
++                              unsigned short vtag = ntohs(p->vlan) &
++                                      VLAN_VID_MASK;
++                              skb->dev = vlan_group_get_device(grp,
++                                              vtag);
++                              cxgb3_process_iscsi_prov_pack(pi, skb);
++                      }
++                      __vlan_hwaccel_rx(skb, grp, ntohs(p->vlan),
++                                      rq->polling);
++              }
++      else
++              dev_kfree_skb_any(skb);
++      } else if (rq->polling) {
++#endif
++
+               if (lro)
+                       napi_gro_receive(&qs->napi, skb);
+               else {
+@@ -2103,7 +2134,11 @@ static void lro_add_page(struct adapter *adap, struct sge_qset *qs,
+               offset = 2 + sizeof(struct cpl_rx_pkt);
+               cpl = qs->lro_va = sd->pg_chunk.va + 2;
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
+               if ((qs->netdev->features & NETIF_F_RXCSUM) &&
++#else
++              if ((pi->rx_offload & T3_RX_CSUM) &&
++#endif
+                    cpl->csum_valid && cpl->csum == htons(0xffff)) {
+                       skb->ip_summed = CHECKSUM_UNNECESSARY;
+                       qs->port_stats[SGE_PSTAT_RX_CSUM_GOOD]++;
+@@ -2129,10 +2164,21 @@ static void lro_add_page(struct adapter *adap, struct sge_qset *qs,
+       skb_record_rx_queue(skb, qs - &adap->sge.qs[pi->first_qset]);
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+       if (cpl->vlan_valid) {
+               qs->port_stats[SGE_PSTAT_VLANEX]++;
+               __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), ntohs(cpl->vlan));
+       }
++#else
++      if (unlikely(cpl->vlan_valid)) {
++              struct vlan_group *grp = pi->vlan_grp;
++
++              if (likely(grp != NULL)) {
++                      vlan_gro_frags(&qs->napi, grp, ntohs(cpl->vlan));
++                      return;
++              }
++      }
++#endif
+       napi_gro_frags(&qs->napi);
+ }
+diff --git a/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c b/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c
+index c74a898..83103f0 100644
+--- a/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c
++++ b/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c
+@@ -3307,7 +3307,11 @@ static void config_pcie(struct adapter *adap)
+           G_NUMFSTTRNSEQRX(t3_read_reg(adap, A_PCIE_MODE));
+       log2_width = fls(adap->params.pci.width) - 1;
+       acklat = ack_lat[log2_width][pldsize];
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+       if (val & PCI_EXP_LNKCTL_ASPM_L0S)      /* check LOsEnable */
++#else
++      if (val & 1)
++#endif
+               acklat += fst_trn_tx * 4;
+       rpllmt = rpl_tmr[log2_width][pldsize] + fst_trn_rx * 4;
+diff --git a/drivers/net/ethernet/chelsio/cxgb3/xgmac.c b/drivers/net/ethernet/chelsio/cxgb3/xgmac.c
+index 3af19a5..b3c99fd 100644
+--- a/drivers/net/ethernet/chelsio/cxgb3/xgmac.c
++++ b/drivers/net/ethernet/chelsio/cxgb3/xgmac.c
+@@ -311,17 +311,32 @@ int t3_mac_set_rx_mode(struct cmac *mac, struct net_device *dev)
+       if (dev->flags & IFF_ALLMULTI)
+               hash_lo = hash_hi = 0xffffffff;
+       else {
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+               struct netdev_hw_addr *ha;
++#else
++              struct dev_mc_list *dmi;
++#endif
+               int exact_addr_idx = mac->nucast;
+               hash_lo = hash_hi = 0;
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+               netdev_for_each_mc_addr(ha, dev)
++#else
++              netdev_for_each_mc_addr(dmi, dev)
++#endif
+                       if (exact_addr_idx < EXACT_ADDR_FILTERS)
+                               set_addr_filter(mac, exact_addr_idx++,
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+                                               ha->addr);
++#else
++                                              dmi->dmi_addr);
++#endif
+                       else {
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+                               int hash = hash_hw_addr(ha->addr);
+-
++#else
++                              int hash = hash_hw_addr(dmi->dmi_addr);
++#endif
+                               if (hash < 32)
+                                       hash_lo |= (1 << hash);
+                               else