--- /dev/null
+diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+index 6154404..ad01c8b 100644
+--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
++++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+@@ -367,6 +367,9 @@ struct sge_rspq;
+
+ struct port_info {
+ struct adapter *adapter;
++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)
++ struct vlan_group *vlan_grp;
++#endif
+ u16 viid;
+ s16 xact_addr_filt; /* index of exact MAC address filter */
+ u16 rss_size; /* size of VI's RSS table slice */
+@@ -376,6 +379,9 @@ struct port_info {
+ u8 port_id;
+ u8 tx_chan;
+ u8 lport; /* associated offload logical port */
++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0)
++ u8 rx_offload; /* CSO, etc */
++#endif
+ u8 nqsets; /* # of qsets */
+ u8 first_qset; /* index of first qset */
+ u8 rss_mode;
+@@ -383,6 +389,13 @@ struct port_info {
+ u16 *rss;
+ };
+
++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0)
++/* port_info.rx_offload flags */
++enum {
++ RX_CSO = 1 << 0,
++};
++#endif
++
+ struct dentry;
+ struct work_struct;
+
+@@ -417,7 +430,11 @@ struct sge_fl { /* SGE free-buffer queue state */
+
+ /* A packet gather list */
+ struct pkt_gl {
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+ struct page_frag frags[MAX_SKB_FRAGS];
++#else
++ skb_frag_t frags[MAX_SKB_FRAGS];
++#endif
+ void *va; /* virtual address of first byte */
+ unsigned int nfrags; /* # of fragments */
+ unsigned int tot_len; /* total length of fragments */
+diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+index 4c3c875..846cc48 100644
+--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
++++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+@@ -70,8 +70,6 @@
+ #include "t4fw_api.h"
+ #include "l2t.h"
+
+-#include <../drivers/net/bonding/bonding.h>
+-
+ #ifdef DRV_VERSION
+ #undef DRV_VERSION
+ #endif
+@@ -482,14 +480,25 @@ static int set_addr_filters(const struct net_device *dev, bool sleep)
+ u16 filt_idx[7];
+ const u8 *addr[7];
+ int ret, naddr = 0;
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
++ const struct dev_addr_list *d;
++#endif
+ const struct netdev_hw_addr *ha;
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+ int uc_cnt = netdev_uc_count(dev);
+ int mc_cnt = netdev_mc_count(dev);
++#else
++ int uc_cnt = ((&(dev)->uc)->count);
++#endif
+ const struct port_info *pi = netdev_priv(dev);
+ unsigned int mb = pi->adapter->fn;
+
+ /* first do the secondary unicast addresses */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+ netdev_for_each_uc_addr(ha, dev) {
++#else
++ list_for_each_entry(ha, &(&(dev)->uc)->list, list) {
++#endif
+ addr[naddr++] = ha->addr;
+ if (--uc_cnt == 0 || naddr >= ARRAY_SIZE(addr)) {
+ ret = t4_alloc_mac_filt(pi->adapter, mb, pi->viid, free,
+@@ -503,9 +512,15 @@ static int set_addr_filters(const struct net_device *dev, bool sleep)
+ }
+
+ /* next set up the multicast addresses */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+ netdev_for_each_mc_addr(ha, dev) {
+ addr[naddr++] = ha->addr;
+ if (--mc_cnt == 0 || naddr >= ARRAY_SIZE(addr)) {
++#else
++ netdev_for_each_mc_addr(d, dev) {
++ addr[naddr++] = d->dmi_addr;
++ if (naddr >= ARRAY_SIZE(addr) || d->next == NULL) {
++#endif
+ ret = t4_alloc_mac_filt(pi->adapter, mb, pi->viid, free,
+ naddr, addr, filt_idx, &mhash, sleep);
+ if (ret < 0)
+@@ -2682,10 +2697,19 @@ static int set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+ return err;
+ }
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
+ static int cxgb_set_features(struct net_device *dev, netdev_features_t features)
++#else
++static int cxgb_set_features(struct net_device *dev, u32 features)
++#endif
+ {
+ const struct port_info *pi = netdev_priv(dev);
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
+ netdev_features_t changed = dev->features ^ features;
++#else
++ u32 changed = dev->features ^ features;
++#endif
+ int err;
+
+ if (!(changed & NETIF_F_HW_VLAN_CTAG_RX))
+@@ -2698,14 +2722,55 @@ static int cxgb_set_features(struct net_device *dev, netdev_features_t features)
+ dev->features = features ^ NETIF_F_HW_VLAN_CTAG_RX;
+ return err;
+ }
++#else
++#define TSO_FLAGS (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN)
++
++static int set_tso(struct net_device *dev, u32 value)
++{
++ if (value)
++ dev->features |= TSO_FLAGS;
++ else
++ dev->features &= ~TSO_FLAGS;
++ return 0;
++}
++
++static int set_flags(struct net_device *dev, u32 flags)
++{
++ int err;
++ unsigned long old_feat = dev->features;
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
++ err = ethtool_op_set_flags(dev, flags, ETH_FLAG_RXHASH |
++ ETH_FLAG_RXVLAN | ETH_FLAG_TXVLAN);
++#else
++ err = ethtool_op_set_flags(dev, flags);
++#endif
++ if (err)
++ return err;
++
++ if ((old_feat ^ dev->features) & NETIF_F_HW_VLAN_RX) {
++ const struct port_info *pi = netdev_priv(dev);
++
++ err = t4_set_rxmode(pi->adapter, pi->adapter->fn, pi->viid, -1,
++ -1, -1, -1, !!(flags & ETH_FLAG_RXVLAN),
++ true);
++ if (err)
++ dev->features = old_feat;
++ }
++ return err;
++}
++#endif
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
+ static u32 get_rss_table_size(struct net_device *dev)
+ {
+ const struct port_info *pi = netdev_priv(dev);
+
+ return pi->rss_size;
+ }
++#endif
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
+ static int get_rss_table(struct net_device *dev, u32 *p)
+ {
+ const struct port_info *pi = netdev_priv(dev);
+@@ -2727,9 +2792,14 @@ static int set_rss_table(struct net_device *dev, const u32 *p)
+ return write_rss(pi, pi->rss);
+ return 0;
+ }
++#endif
+
+ static int get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info,
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+ u32 *rules)
++#else
++ void *rules)
++#endif
+ {
+ const struct port_info *pi = netdev_priv(dev);
+
+@@ -2808,7 +2878,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 = identify_port,
++#else
++ .phys_id = identify_port,
++#endif
+ .nway_reset = restart_autoneg,
+ .get_sset_count = get_sset_count,
+ .get_ethtool_stats = get_stats,
+@@ -2816,10 +2890,18 @@ static const struct ethtool_ops cxgb_ethtool_ops = {
+ .get_regs = get_regs,
+ .get_wol = get_wol,
+ .set_wol = set_wol,
++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0)
++ .set_tso = set_tso,
++ .set_flags = set_flags,
++#endif
+ .get_rxnfc = get_rxnfc,
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
+ .get_rxfh_indir_size = get_rss_table_size,
++#endif
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
+ .get_rxfh_indir = get_rss_table,
+ .set_rxfh_indir = set_rss_table,
++#endif
+ .flash_device = set_flash,
+ };
+
+@@ -2830,7 +2912,11 @@ static ssize_t mem_read(struct file *file, char __user *buf, size_t count,
+ loff_t *ppos)
+ {
+ loff_t pos = *ppos;
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+ loff_t avail = file_inode(file)->i_size;
++#else
++ loff_t avail = file->f_path.dentry->d_inode->i_size;
++#endif
+ unsigned int mem = (uintptr_t)file->private_data & 3;
+ struct adapter *adap = file->private_data - mem;
+
+@@ -3947,33 +4033,10 @@ static int cxgb4_inet6addr_handler(struct notifier_block *this,
+ struct inet6_ifaddr *ifa = data;
+ struct net_device *event_dev;
+ int ret = NOTIFY_DONE;
+- struct bonding *bond = netdev_priv(ifa->idev->dev);
+- struct slave *slave;
+- struct pci_dev *first_pdev = NULL;
+
+ if (ifa->idev->dev->priv_flags & IFF_802_1Q_VLAN) {
+ event_dev = vlan_dev_real_dev(ifa->idev->dev);
+ ret = clip_add(event_dev, ifa, event);
+- } else if (ifa->idev->dev->flags & IFF_MASTER) {
+- /* It is possible that two different adapters are bonded in one
+- * bond. We need to find such different adapters and add clip
+- * in all of them only once.
+- */
+- read_lock(&bond->lock);
+- bond_for_each_slave(bond, slave) {
+- if (!first_pdev) {
+- ret = clip_add(slave->dev, ifa, event);
+- /* If clip_add is success then only initialize
+- * first_pdev since it means it is our device
+- */
+- if (ret == NOTIFY_OK)
+- first_pdev = to_pci_dev(
+- slave->dev->dev.parent);
+- } else if (first_pdev !=
+- to_pci_dev(slave->dev->dev.parent))
+- ret = clip_add(slave->dev, ifa, event);
+- }
+- read_unlock(&bond->lock);
+ } else
+ ret = clip_add(ifa->idev->dev, ifa, event);
+
+@@ -3999,7 +4062,11 @@ static int update_dev_clip(struct net_device *root_dev, struct net_device *dev)
+ return ret;
+
+ read_lock_bh(&idev->lock);
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+ list_for_each_entry(ifa, &idev->addr_list, if_list) {
++#else
++ for (ifa=idev->addr_list; ifa; ifa=ifa->if_next) {
++#endif
+ ret = cxgb4_clip_get(dev,
+ (const struct in6_addr *)ifa->addr.s6_addr);
+ if (ret < 0)
+@@ -4013,6 +4080,10 @@ static int update_dev_clip(struct net_device *root_dev, struct net_device *dev)
+ static int update_root_dev_clip(struct net_device *dev)
+ {
+ struct net_device *root_dev = NULL;
++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)
++ struct vlan_group *grp;
++ const struct port_info *p = netdev_priv(dev);
++#endif
+ int i, ret = 0;
+
+ /* First populate the real net device's IPv6 addresses */
+@@ -4022,7 +4093,13 @@ static int update_root_dev_clip(struct net_device *dev)
+
+ /* Parse all bond and vlan devices layered on top of the physical dev */
+ for (i = 0; i < VLAN_N_VID; i++) {
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+ root_dev = __vlan_find_dev_deep(dev, htons(ETH_P_8021Q), i);
++#else
++ grp = p->vlan_grp;
++ if (grp)
++ root_dev = vlan_group_get_device(grp, i);
++#endif
+ if (!root_dev)
+ continue;
+
+@@ -4287,6 +4364,7 @@ int cxgb4_remove_server_filter(const struct net_device *dev, unsigned int stid,
+ }
+ EXPORT_SYMBOL(cxgb4_remove_server_filter);
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
+ static struct rtnl_link_stats64 *cxgb_get_stats(struct net_device *dev,
+ struct rtnl_link_stats64 *ns)
+ {
+@@ -4328,6 +4406,50 @@ static struct rtnl_link_stats64 *cxgb_get_stats(struct net_device *dev,
+ ns->rx_length_errors + stats.rx_len_err + ns->rx_fifo_errors;
+ return ns;
+ }
++#else
++static struct net_device_stats *cxgb_get_stats(struct net_device *dev)
++{
++ struct port_stats stats;
++ struct port_info *p = netdev_priv(dev);
++ struct adapter *adapter = p->adapter;
++ struct net_device_stats *ns = &dev->stats;
++
++ spin_lock(&adapter->stats_lock);
++ t4_get_port_stats(adapter, p->tx_chan, &stats);
++ spin_unlock(&adapter->stats_lock);
++
++ ns->tx_bytes = stats.tx_octets;
++ ns->tx_packets = stats.tx_frames;
++ ns->rx_bytes = stats.rx_octets;
++ ns->rx_packets = stats.rx_frames;
++ ns->multicast = stats.rx_mcast_frames;
++
++ /* detailed rx_errors */
++ ns->rx_length_errors = stats.rx_jabber + stats.rx_too_long +
++ stats.rx_runt;
++ ns->rx_over_errors = 0;
++ ns->rx_crc_errors = stats.rx_fcs_err;
++ ns->rx_frame_errors = stats.rx_symbol_err;
++ ns->rx_fifo_errors = stats.rx_ovflow0 + stats.rx_ovflow1 +
++ stats.rx_ovflow2 + stats.rx_ovflow3 +
++ stats.rx_trunc0 + stats.rx_trunc1 +
++ stats.rx_trunc2 + stats.rx_trunc3;
++ ns->rx_missed_errors = 0;
++
++ /* detailed tx_errors */
++ ns->tx_aborted_errors = 0;
++ ns->tx_carrier_errors = 0;
++ ns->tx_fifo_errors = 0;
++ ns->tx_heartbeat_errors = 0;
++ ns->tx_window_errors = 0;
++
++ ns->tx_errors = stats.tx_error_frames;
++ ns->rx_errors = stats.rx_symbol_err + stats.rx_fcs_err +
++ ns->rx_length_errors + stats.rx_len_err + ns->rx_fifo_errors;
++ return ns;
++}
++#endif
++
+
+ static int cxgb_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
+ {
+@@ -4428,10 +4550,16 @@ static const struct net_device_ops cxgb4_netdev_ops = {
+ .ndo_open = cxgb_open,
+ .ndo_stop = cxgb_close,
+ .ndo_start_xmit = t4_eth_xmit,
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
+ .ndo_get_stats64 = cxgb_get_stats,
++#else
++ .ndo_get_stats = cxgb_get_stats,
++#endif
+ .ndo_set_rx_mode = cxgb_set_rxmode,
+ .ndo_set_mac_address = cxgb_set_mac_addr,
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
+ .ndo_set_features = cxgb_set_features,
++#endif
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_do_ioctl = cxgb_ioctl,
+ .ndo_change_mtu = cxgb_change_mtu,
+@@ -5586,11 +5714,19 @@ static void eeh_resume(struct pci_dev *pdev)
+ rtnl_unlock();
+ }
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)
+ static const struct pci_error_handlers cxgb4_eeh = {
+ .error_detected = eeh_err_detected,
+ .slot_reset = eeh_slot_reset,
+ .resume = eeh_resume,
+ };
++#else
++static struct pci_error_handlers cxgb4_eeh = {
++ .error_detected = eeh_err_detected,
++ .slot_reset = eeh_slot_reset,
++ .resume = eeh_resume,
++};
++#endif
+
+ static inline bool is_10g_port(const struct link_config *lc)
+ {
+@@ -5783,7 +5919,11 @@ static int init_rss(struct adapter *adap)
+ if (!pi->rss)
+ return -ENOMEM;
+ for (j = 0; j < pi->rss_size; j++)
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
+ pi->rss[j] = ethtool_rxfh_indir_default(j, pi->nqsets);
++#else
++ pi->rss[j] = j % pi->nqsets;
++#endif
+ }
+ return 0;
+ }
+@@ -5855,7 +5995,9 @@ static void free_some_resources(struct adapter *adapter)
+ t4_fw_bye(adapter, adapter->fn);
+ }
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
+ #define TSO_FLAGS (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN)
++#endif
+ #define VLAN_FEAT (NETIF_F_SG | NETIF_F_IP_CSUM | TSO_FLAGS | \
+ NETIF_F_IPV6_CSUM | NETIF_F_HIGHDMA)
+ #define SEGMENT_SIZE 128
+@@ -5989,19 +6131,35 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ pi = netdev_priv(netdev);
+ pi->adapter = adapter;
+ pi->xact_addr_filt = -1;
++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0)
++ pi->rx_offload = RX_CSO;
++#endif
+ pi->port_id = i;
+ netdev->irq = pdev->irq;
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
+ netdev->hw_features = NETIF_F_SG | TSO_FLAGS |
+ NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
+ NETIF_F_RXCSUM | NETIF_F_RXHASH |
+ NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX;
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
+ if (highdma)
+ netdev->hw_features |= NETIF_F_HIGHDMA;
+ netdev->features |= netdev->hw_features;
++#else
++ netdev->features |= netdev->hw_features | highdma;
++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0) */
++#else
++ netdev->features |= NETIF_F_SG | TSO_FLAGS;
++ netdev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
++ netdev->features |= NETIF_F_GRO | NETIF_F_RXHASH | highdma;
++ netdev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
++#endif
+ netdev->vlan_features = netdev->features & VLAN_FEAT;
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+ netdev->priv_flags |= IFF_UNICAST_FLT;
++#endif
+
+ netdev->netdev_ops = &cxgb4_netdev_ops;
+ SET_ETHTOOL_OPS(netdev, &cxgb_ethtool_ops);
+diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c
+index cc380c3..ae3f8aa 100644
+--- a/drivers/net/ethernet/chelsio/cxgb4/sge.c
++++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c
+@@ -68,6 +68,11 @@
+ */
+ #define RX_PKT_SKB_LEN 512
+
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 6, 0)
++/* Ethernet header padding prepended to RX_PKTs */
++#define RX_PKT_PAD 2
++#endif
++
+ /*
+ * Max number of Tx descriptors we clean up at a time. Should be modest as
+ * freeing skbs isn't cheap and it happens while holding locks. We just need
+@@ -134,6 +139,15 @@
+ */
+ #define MAX_CTRL_WR_LEN SGE_MAX_WR_LEN
+
++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)
++enum {
++ /* packet alignment in FL buffers */
++ FL_ALIGN = L1_CACHE_BYTES < 32 ? 32 : L1_CACHE_BYTES,
++ /* egress status entry size */
++ STAT_LEN = L1_CACHE_BYTES > 64 ? 128 : 64
++};
++#endif
++
+ struct tx_sw_desc { /* SW state per Tx descriptor */
+ struct sk_buff *skb;
+ struct ulptx_sgl *sgl;
+@@ -247,8 +261,13 @@ static int map_skb(struct device *dev, const struct sk_buff *skb,
+ end = &si->frags[si->nr_frags];
+
+ for (fp = si->frags; fp < end; fp++) {
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+ *++addr = skb_frag_dma_map(dev, fp, 0, skb_frag_size(fp),
+ DMA_TO_DEVICE);
++#else
++ *++addr = dma_map_page(dev, fp->page, fp->page_offset,
++ skb_frag_size(fp), DMA_TO_DEVICE);
++#endif
+ if (dma_mapping_error(dev, *addr))
+ goto unwind;
+ }
+@@ -588,7 +607,11 @@ static unsigned int refill_fl(struct adapter *adap, struct sge_fl *q, int n,
+
+ alloc_small_pages:
+ while (n--) {
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+ pg = __skb_alloc_page(gfp, NULL);
++#else
++ pg = alloc_page(gfp);
++#endif
+ if (unlikely(!pg)) {
+ q->alloc_failed++;
+ break;
+@@ -1505,9 +1528,14 @@ int cxgb4_ofld_send(struct net_device *dev, struct sk_buff *skb)
+ }
+ EXPORT_SYMBOL(cxgb4_ofld_send);
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+ static inline void copy_frags(struct sk_buff *skb,
++#else
++static inline void copy_frags(struct skb_shared_info *ssi,
++#endif
+ const struct pkt_gl *gl, unsigned int offset)
+ {
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+ int i;
+
+ /* usually there's just one frag */
+@@ -1522,6 +1550,22 @@ static inline void copy_frags(struct sk_buff *skb,
+
+ /* get a reference to the last page, we don't own it */
+ get_page(gl->frags[gl->nfrags - 1].page);
++#else
++ unsigned int n;
++
++ /* usually there's just one frag */
++ ssi->frags[0].page = gl->frags[0].page;
++ ssi->frags[0].page_offset = gl->frags[0].page_offset + offset;
++ skb_frag_size_set(&ssi->frags[0],
++ skb_frag_size(&gl->frags[0]) - offset);
++ ssi->nr_frags = gl->nfrags;
++ n = gl->nfrags - 1;
++ if (n)
++ memcpy(&ssi->frags[1], &gl->frags[1], n * sizeof(skb_frag_t));
++
++ /* get a reference to the last page, we don't own it */
++ get_page(gl->frags[n].page);
++#endif
+ }
+
+ /**
+@@ -1556,7 +1600,11 @@ struct sk_buff *cxgb4_pktgl_to_skb(const struct pkt_gl *gl,
+ __skb_put(skb, pull_len);
+ skb_copy_to_linear_data(skb, gl->va, pull_len);
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+ copy_frags(skb, gl, pull_len);
++#else
++ copy_frags(skb_shinfo(skb), gl, pull_len);
++#endif
+ skb->len = gl->tot_len;
+ skb->data_len = skb->len - pull_len;
+ skb->truesize += skb->data_len;
+@@ -1575,7 +1623,11 @@ EXPORT_SYMBOL(cxgb4_pktgl_to_skb);
+ static void t4_pktgl_free(const struct pkt_gl *gl)
+ {
+ int n;
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+ const struct page_frag *p;
++#else
++ const skb_frag_t *p;
++#endif
+
+ for (p = gl->frags, n = gl->nfrags - 1; n--; p++)
+ put_page(p->page);
+@@ -1623,7 +1675,11 @@ static void do_gro(struct sge_eth_rxq *rxq, const struct pkt_gl *gl,
+ return;
+ }
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+ copy_frags(skb, gl, s->pktshift);
++#else
++ copy_frags(skb_shinfo(skb), gl, RX_PKT_PAD);
++#endif
+ skb->len = gl->tot_len - s->pktshift;
+ skb->data_len = skb->len;
+ skb->truesize += skb->data_len;
+@@ -1633,7 +1689,16 @@ static void do_gro(struct sge_eth_rxq *rxq, const struct pkt_gl *gl,
+ skb->rxhash = (__force u32)pkt->rsshdr.hash_val;
+
+ if (unlikely(pkt->vlan_ex)) {
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+ __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), ntohs(pkt->vlan));
++#else
++ struct port_info *pi = netdev_priv(rxq->rspq.netdev);
++ struct vlan_group *grp = pi->vlan_grp;
++
++ if (likely(grp))
++ ret = vlan_gro_frags(&rxq->rspq.napi, grp,
++ be16_to_cpu(pkt->vlan));
++#endif
+ rxq->stats.vlan_ex++;
+ }
+ ret = napi_gro_frags(&rxq->rspq.napi);
+@@ -1663,6 +1728,9 @@ int t4_ethrx_handler(struct sge_rspq *q, const __be64 *rsp,
+ struct sge *s = &q->adap->sge;
+ int cpl_trace_pkt = is_t4(q->adap->params.chip) ?
+ CPL_TRACE_PKT : CPL_TRACE_PKT_T5;
++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)
++ struct port_info *pi;
++#endif
+
+ if (unlikely(*(u8 *)rsp == cpl_trace_pkt))
+ return handle_trace_pkt(q->adap, si);
+@@ -1687,10 +1755,17 @@ int t4_ethrx_handler(struct sge_rspq *q, const __be64 *rsp,
+ skb_record_rx_queue(skb, q->idx);
+ if (skb->dev->features & NETIF_F_RXHASH)
+ skb->rxhash = (__force u32)pkt->rsshdr.hash_val;
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 1, 0)
++ pi = netdev_priv(skb->dev);
++#endif
+
+ rxq->stats.pkts++;
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
+ if (csum_ok && (q->netdev->features & NETIF_F_RXCSUM) &&
++#else
++ if (csum_ok && (pi->rx_offload & RX_CSO) &&
++#endif
+ (pkt->l2info & htonl(RXF_UDP | RXF_TCP))) {
+ if (!pkt->ip_frag) {
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+@@ -1705,7 +1780,15 @@ int t4_ethrx_handler(struct sge_rspq *q, const __be64 *rsp,
+ skb_checksum_none_assert(skb);
+
+ if (unlikely(pkt->vlan_ex)) {
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+ __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), ntohs(pkt->vlan));
++#else
++ struct vlan_group *grp = pi->vlan_grp;
++ if (likely(grp))
++ vlan_hwaccel_receive_skb(skb, grp, ntohs(pkt->vlan));
++ else
++ dev_kfree_skb_any(skb);
++#endif
+ rxq->stats.vlan_ex++;
+ }
+ netif_receive_skb(skb);
+@@ -1794,7 +1877,9 @@ static int process_responses(struct sge_rspq *q, int budget)
+ const struct rsp_ctrl *rc;
+ struct sge_eth_rxq *rxq = container_of(q, struct sge_eth_rxq, rspq);
+ struct adapter *adapter = q->adap;
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+ struct sge *s = &adapter->sge;
++#endif
+
+ while (likely(budget_left)) {
+ rc = (void *)q->cur_desc + (q->iqe_len - sizeof(*rc));
+@@ -1804,7 +1889,11 @@ static int process_responses(struct sge_rspq *q, int budget)
+ rmb();
+ rsp_type = RSPD_TYPE(rc->type_gen);
+ if (likely(rsp_type == RSP_TYPE_FLBUF)) {
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+ struct page_frag *fp;
++#else
++ skb_frag_t *fp;
++#endif
+ struct pkt_gl si;
+ const struct rx_sw_desc *rsd;
+ u32 len = ntohl(rc->pldbuflen_qid), bufsz, frags;
+@@ -1823,9 +1912,15 @@ static int process_responses(struct sge_rspq *q, int budget)
+ rsd = &rxq->fl.sdesc[rxq->fl.cidx];
+ bufsz = get_buf_size(adapter, rsd);
+ fp->page = rsd->page;
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+ fp->offset = q->offset;
+ fp->size = min(bufsz, len);
+ len -= fp->size;
++#else
++ fp->page_offset = q->offset;
++ skb_frag_size_set(fp, min(bufsz, len));
++ len -= skb_frag_size(fp);
++#endif
+ if (!len)
+ break;
+ unmap_rx_buf(q->adap, &rxq->fl);
+@@ -1837,16 +1932,29 @@ static int process_responses(struct sge_rspq *q, int budget)
+ */
+ dma_sync_single_for_cpu(q->adap->pdev_dev,
+ get_buf_addr(rsd),
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+ fp->size, DMA_FROM_DEVICE);
++#else
++ skb_frag_size(fp),
++ DMA_FROM_DEVICE);
++#endif
+
+ si.va = page_address(si.frags[0].page) +
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+ si.frags[0].offset;
++#else
++ si.frags[0].page_offset;
++#endif
+ prefetch(si.va);
+
+ si.nfrags = frags + 1;
+ ret = q->handler(q, q->cur_desc, &si);
+ if (likely(ret == 0))
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+ q->offset += ALIGN(fp->size, s->fl_align);
++#else
++ q->offset += ALIGN(skb_frag_size(fp), FL_ALIGN);
++#endif
+ else
+ restore_rx_bufs(&si, &rxq->fl, frags);
+ } else if (likely(rsp_type == RSP_TYPE_CPL)) {