fm10k/igb/ixgbe: Use dma_rmb on Rx descriptor reads
[deliverable/linux.git] / drivers / net / ethernet / intel / ixgbe / ixgbe_main.c
index cc51554c9e99a49e74c24ab7bf8f97848a06d7a3..2ed2c7de230444f88c3f06451d7cc8a7167f5f05 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/slab.h>
 #include <net/checksum.h>
 #include <net/ip6_checksum.h>
+#include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/if.h>
 #include <linux/if_vlan.h>
 #include <linux/prefetch.h>
 #include <scsi/fc/fc_fcoe.h>
 
+#ifdef CONFIG_OF
+#include <linux/of_net.h>
+#endif
+
+#ifdef CONFIG_SPARC
+#include <asm/idprom.h>
+#include <asm/prom.h>
+#endif
+
 #include "ixgbe.h"
 #include "ixgbe_common.h"
 #include "ixgbe_dcb_82599.h"
@@ -65,15 +75,17 @@ char ixgbe_default_device_descr[] =
 static char ixgbe_default_device_descr[] =
                              "Intel(R) 10 Gigabit Network Connection";
 #endif
-#define DRV_VERSION "3.19.1-k"
+#define DRV_VERSION "4.0.1-k"
 const char ixgbe_driver_version[] = DRV_VERSION;
 static const char ixgbe_copyright[] =
                                "Copyright (c) 1999-2014 Intel Corporation.";
 
 static const struct ixgbe_info *ixgbe_info_tbl[] = {
-       [board_82598] = &ixgbe_82598_info,
-       [board_82599] = &ixgbe_82599_info,
-       [board_X540] = &ixgbe_X540_info,
+       [board_82598]           = &ixgbe_82598_info,
+       [board_82599]           = &ixgbe_82599_info,
+       [board_X540]            = &ixgbe_X540_info,
+       [board_X550]            = &ixgbe_X550_info,
+       [board_X550EM_x]        = &ixgbe_X550EM_x_info,
 };
 
 /* ixgbe_pci_tbl - PCI Device ID Table
@@ -115,6 +127,9 @@ static const struct pci_device_id ixgbe_pci_tbl[] = {
        {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599EN_SFP), board_82599 },
        {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP_SF_QP), board_82599 },
        {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X540T1), board_X540 },
+       {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550T), board_X550},
+       {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_KX4), board_X550EM_x},
+       {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_KR), board_X550EM_x},
        /* required last entry */
        {0, }
 };
@@ -835,6 +850,8 @@ static void ixgbe_set_ivar(struct ixgbe_adapter *adapter, s8 direction,
                break;
        case ixgbe_mac_82599EB:
        case ixgbe_mac_X540:
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_x:
                if (direction == -1) {
                        /* other causes */
                        msix_vector |= IXGBE_IVAR_ALLOC_VAL;
@@ -871,6 +888,8 @@ static inline void ixgbe_irq_rearm_queues(struct ixgbe_adapter *adapter,
                break;
        case ixgbe_mac_82599EB:
        case ixgbe_mac_X540:
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_x:
                mask = (qmask & 0xFFFFFFFF);
                IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS_EX(0), mask);
                mask = (qmask >> 32);
@@ -1412,41 +1431,21 @@ static inline void ixgbe_rx_checksum(struct ixgbe_ring *ring,
        skb->ip_summed = CHECKSUM_UNNECESSARY;
 }
 
-static inline void ixgbe_release_rx_desc(struct ixgbe_ring *rx_ring, u32 val)
-{
-       rx_ring->next_to_use = val;
-
-       /* update next to alloc since we have filled the ring */
-       rx_ring->next_to_alloc = val;
-       /*
-        * Force memory writes to complete before letting h/w
-        * know there are new descriptors to fetch.  (Only
-        * applicable for weak-ordered memory model archs,
-        * such as IA-64).
-        */
-       wmb();
-       ixgbe_write_tail(rx_ring, val);
-}
-
 static bool ixgbe_alloc_mapped_page(struct ixgbe_ring *rx_ring,
                                    struct ixgbe_rx_buffer *bi)
 {
        struct page *page = bi->page;
-       dma_addr_t dma = bi->dma;
+       dma_addr_t dma;
 
        /* since we are recycling buffers we should seldom need to alloc */
-       if (likely(dma))
+       if (likely(page))
                return true;
 
        /* alloc new page for storage */
-       if (likely(!page)) {
-               page = __skb_alloc_pages(GFP_ATOMIC | __GFP_COLD | __GFP_COMP,
-                                        bi->skb, ixgbe_rx_pg_order(rx_ring));
-               if (unlikely(!page)) {
-                       rx_ring->rx_stats.alloc_rx_page_failed++;
-                       return false;
-               }
-               bi->page = page;
+       page = dev_alloc_pages(ixgbe_rx_pg_order(rx_ring));
+       if (unlikely(!page)) {
+               rx_ring->rx_stats.alloc_rx_page_failed++;
+               return false;
        }
 
        /* map page for use */
@@ -1459,13 +1458,13 @@ static bool ixgbe_alloc_mapped_page(struct ixgbe_ring *rx_ring,
         */
        if (dma_mapping_error(rx_ring->dev, dma)) {
                __free_pages(page, ixgbe_rx_pg_order(rx_ring));
-               bi->page = NULL;
 
                rx_ring->rx_stats.alloc_rx_page_failed++;
                return false;
        }
 
        bi->dma = dma;
+       bi->page = page;
        bi->page_offset = 0;
 
        return true;
@@ -1509,16 +1508,28 @@ void ixgbe_alloc_rx_buffers(struct ixgbe_ring *rx_ring, u16 cleaned_count)
                        i -= rx_ring->count;
                }
 
-               /* clear the hdr_addr for the next_to_use descriptor */
-               rx_desc->read.hdr_addr = 0;
+               /* clear the status bits for the next_to_use descriptor */
+               rx_desc->wb.upper.status_error = 0;
 
                cleaned_count--;
        } while (cleaned_count);
 
        i += rx_ring->count;
 
-       if (rx_ring->next_to_use != i)
-               ixgbe_release_rx_desc(rx_ring, i);
+       if (rx_ring->next_to_use != i) {
+               rx_ring->next_to_use = i;
+
+               /* update next to alloc since we have filled the ring */
+               rx_ring->next_to_alloc = i;
+
+               /* Force memory writes to complete before letting h/w
+                * know there are new descriptors to fetch.  (Only
+                * applicable for weak-ordered memory model archs,
+                * such as IA-64).
+                */
+               wmb();
+               writel(i, rx_ring->tail);
+       }
 }
 
 static void ixgbe_set_rsc_gso_size(struct ixgbe_ring *ring,
@@ -1763,14 +1774,9 @@ static bool ixgbe_cleanup_headers(struct ixgbe_ring *rx_ring,
                return false;
 
 #endif
-       /* if skb_pad returns an error the skb was freed */
-       if (unlikely(skb->len < 60)) {
-               int pad_len = 60 - skb->len;
-
-               if (skb_pad(skb, pad_len))
-                       return true;
-               __skb_put(skb, pad_len);
-       }
+       /* if eth_skb_pad returns an error the skb was freed */
+       if (eth_skb_pad(skb))
+               return true;
 
        return false;
 }
@@ -1795,9 +1801,7 @@ static void ixgbe_reuse_rx_page(struct ixgbe_ring *rx_ring,
        rx_ring->next_to_alloc = (nta < rx_ring->count) ? nta : 0;
 
        /* transfer page from old buffer to new buffer */
-       new_buff->page = old_buff->page;
-       new_buff->dma = old_buff->dma;
-       new_buff->page_offset = old_buff->page_offset;
+       *new_buff = *old_buff;
 
        /* sync the buffer for use by the device */
        dma_sync_single_range_for_device(rx_ring->dev, new_buff->dma,
@@ -1806,6 +1810,11 @@ static void ixgbe_reuse_rx_page(struct ixgbe_ring *rx_ring,
                                         DMA_FROM_DEVICE);
 }
 
+static inline bool ixgbe_page_is_reserved(struct page *page)
+{
+       return (page_to_nid(page) != numa_mem_id()) || page->pfmemalloc;
+}
+
 /**
  * ixgbe_add_rx_frag - Add contents of Rx buffer to sk_buff
  * @rx_ring: rx descriptor ring to transact packets on
@@ -1841,12 +1850,12 @@ static bool ixgbe_add_rx_frag(struct ixgbe_ring *rx_ring,
 
                memcpy(__skb_put(skb, size), va, ALIGN(size, sizeof(long)));
 
-               /* we can reuse buffer as-is, just make sure it is local */
-               if (likely(page_to_nid(page) == numa_node_id()))
+               /* page is not reserved, we can reuse buffer as-is */
+               if (likely(!ixgbe_page_is_reserved(page)))
                        return true;
 
                /* this page cannot be reused so discard it */
-               put_page(page);
+               __free_pages(page, ixgbe_rx_pg_order(rx_ring));
                return false;
        }
 
@@ -1854,7 +1863,7 @@ static bool ixgbe_add_rx_frag(struct ixgbe_ring *rx_ring,
                        rx_buffer->page_offset, size, truesize);
 
        /* avoid re-using remote pages */
-       if (unlikely(page_to_nid(page) != numa_node_id()))
+       if (unlikely(ixgbe_page_is_reserved(page)))
                return false;
 
 #if (PAGE_SIZE < 8192)
@@ -1864,22 +1873,19 @@ static bool ixgbe_add_rx_frag(struct ixgbe_ring *rx_ring,
 
        /* flip page offset to other buffer */
        rx_buffer->page_offset ^= truesize;
-
-       /* Even if we own the page, we are not allowed to use atomic_set()
-        * This would break get_page_unless_zero() users.
-        */
-       atomic_inc(&page->_count);
 #else
        /* move offset up to the next cache line */
        rx_buffer->page_offset += truesize;
 
        if (rx_buffer->page_offset > last_offset)
                return false;
-
-       /* bump ref count on page before it is given to the stack */
-       get_page(page);
 #endif
 
+       /* Even if we own the page, we are not allowed to use atomic_set()
+        * This would break get_page_unless_zero() users.
+        */
+       atomic_inc(&page->_count);
+
        return true;
 }
 
@@ -1907,8 +1913,8 @@ static struct sk_buff *ixgbe_fetch_rx_buffer(struct ixgbe_ring *rx_ring,
 #endif
 
                /* allocate a skb to store the frags */
-               skb = netdev_alloc_skb_ip_align(rx_ring->netdev,
-                                               IXGBE_RX_HDR_SIZE);
+               skb = napi_alloc_skb(&rx_ring->q_vector->napi,
+                                    IXGBE_RX_HDR_SIZE);
                if (unlikely(!skb)) {
                        rx_ring->rx_stats.alloc_rx_buff_failed++;
                        return NULL;
@@ -1942,6 +1948,8 @@ dma_sync:
                                              rx_buffer->page_offset,
                                              ixgbe_rx_bufsz(rx_ring),
                                              DMA_FROM_DEVICE);
+
+               rx_buffer->skb = NULL;
        }
 
        /* pull page into skb */
@@ -1959,8 +1967,6 @@ dma_sync:
        }
 
        /* clear contents of buffer_info */
-       rx_buffer->skb = NULL;
-       rx_buffer->dma = 0;
        rx_buffer->page = NULL;
 
        return skb;
@@ -2003,15 +2009,14 @@ static int ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
 
                rx_desc = IXGBE_RX_DESC(rx_ring, rx_ring->next_to_clean);
 
-               if (!ixgbe_test_staterr(rx_desc, IXGBE_RXD_STAT_DD))
+               if (!rx_desc->wb.upper.status_error)
                        break;
 
-               /*
-                * This memory barrier is needed to keep us from reading
+               /* This memory barrier is needed to keep us from reading
                 * any other fields out of the rx_desc until we know the
-                * RXD_STAT_DD bit is set
+                * descriptor has been written back
                 */
-               rmb();
+               dma_rmb();
 
                /* retrieve a buffer from the ring */
                skb = ixgbe_fetch_rx_buffer(rx_ring, rx_desc);
@@ -2155,6 +2160,8 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter)
                break;
        case ixgbe_mac_82599EB:
        case ixgbe_mac_X540:
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_x:
                ixgbe_set_ivar(adapter, -1, 1, v_idx);
                break;
        default:
@@ -2264,6 +2271,8 @@ void ixgbe_write_eitr(struct ixgbe_q_vector *q_vector)
                break;
        case ixgbe_mac_82599EB:
        case ixgbe_mac_X540:
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_x:
                /*
                 * set the WDIS bit to not clear the timer bits and cause an
                 * immediate assertion of the interrupt
@@ -2467,6 +2476,8 @@ static inline void ixgbe_irq_enable_queues(struct ixgbe_adapter *adapter,
                break;
        case ixgbe_mac_82599EB:
        case ixgbe_mac_X540:
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_x:
                mask = (qmask & 0xFFFFFFFF);
                if (mask)
                        IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(0), mask);
@@ -2493,6 +2504,8 @@ static inline void ixgbe_irq_disable_queues(struct ixgbe_adapter *adapter,
                break;
        case ixgbe_mac_82599EB:
        case ixgbe_mac_X540:
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_x:
                mask = (qmask & 0xFFFFFFFF);
                if (mask)
                        IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(0), mask);
@@ -2525,6 +2538,8 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter, bool queues,
                        mask |= IXGBE_EIMS_GPI_SDP0;
                        break;
                case ixgbe_mac_X540:
+               case ixgbe_mac_X550:
+               case ixgbe_mac_X550EM_x:
                        mask |= IXGBE_EIMS_TS;
                        break;
                default:
@@ -2536,7 +2551,10 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter, bool queues,
        case ixgbe_mac_82599EB:
                mask |= IXGBE_EIMS_GPI_SDP1;
                mask |= IXGBE_EIMS_GPI_SDP2;
+               /* fall through */
        case ixgbe_mac_X540:
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_x:
                mask |= IXGBE_EIMS_ECC;
                mask |= IXGBE_EIMS_MAILBOX;
                break;
@@ -2544,9 +2562,6 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter, bool queues,
                break;
        }
 
-       if (adapter->hw.mac.type == ixgbe_mac_X540)
-               mask |= IXGBE_EIMS_TIMESYNC;
-
        if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) &&
            !(adapter->flags2 & IXGBE_FLAG2_FDIR_REQUIRES_REINIT))
                mask |= IXGBE_EIMS_FLOW_DIR;
@@ -2592,6 +2607,8 @@ static irqreturn_t ixgbe_msix_other(int irq, void *data)
        switch (hw->mac.type) {
        case ixgbe_mac_82599EB:
        case ixgbe_mac_X540:
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_x:
                if (eicr & IXGBE_EICR_ECC) {
                        e_info(link, "Received ECC Err, initiating reset\n");
                        adapter->flags2 |= IXGBE_FLAG2_RESET_REQUESTED;
@@ -2811,6 +2828,8 @@ static irqreturn_t ixgbe_intr(int irq, void *data)
                ixgbe_check_sfp_event(adapter, eicr);
                /* Fall through */
        case ixgbe_mac_X540:
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_x:
                if (eicr & IXGBE_EICR_ECC) {
                        e_info(link, "Received ECC Err, initiating reset\n");
                        adapter->flags2 |= IXGBE_FLAG2_RESET_REQUESTED;
@@ -2905,6 +2924,8 @@ static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter)
                break;
        case ixgbe_mac_82599EB:
        case ixgbe_mac_X540:
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_x:
                IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, 0xFFFF0000);
                IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(0), ~0);
                IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(1), ~0);
@@ -3190,16 +3211,14 @@ static void ixgbe_configure_srrctl(struct ixgbe_adapter *adapter,
        IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(reg_idx), srrctl);
 }
 
-static void ixgbe_setup_mrqc(struct ixgbe_adapter *adapter)
+static void ixgbe_setup_reta(struct ixgbe_adapter *adapter, const u32 *seed)
 {
        struct ixgbe_hw *hw = &adapter->hw;
-       static const u32 seed[10] = { 0xE291D73D, 0x1805EC6C, 0x2A94B30D,
-                         0xA54F2BEC, 0xEA49AF7C, 0xE214AD3D, 0xB855AABE,
-                         0x6A3E67EA, 0x14364D17, 0x3BED200D};
-       u32 mrqc = 0, reta = 0;
-       u32 rxcsum;
+       u32 reta = 0;
        int i, j;
+       int reta_entries = 128;
        u16 rss_i = adapter->ring_feature[RING_F_RSS].indices;
+       int indices_multi;
 
        /*
         * Program table for at least 2 queues w/ SR-IOV so that VFs can
@@ -3213,16 +3232,69 @@ static void ixgbe_setup_mrqc(struct ixgbe_adapter *adapter)
        for (i = 0; i < 10; i++)
                IXGBE_WRITE_REG(hw, IXGBE_RSSRK(i), seed[i]);
 
+       /* Fill out the redirection table as follows:
+        * 82598: 128 (8 bit wide) entries containing pair of 4 bit RSS indices
+        * 82599/X540: 128 (8 bit wide) entries containing 4 bit RSS index
+        * X550: 512 (8 bit wide) entries containing 6 bit RSS index
+        */
+       if (adapter->hw.mac.type == ixgbe_mac_82598EB)
+               indices_multi = 0x11;
+       else
+               indices_multi = 0x1;
+
+       switch (adapter->hw.mac.type) {
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_x:
+               if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED))
+                       reta_entries = 512;
+       default:
+               break;
+       }
+
        /* Fill out redirection table */
-       for (i = 0, j = 0; i < 128; i++, j++) {
+       for (i = 0, j = 0; i < reta_entries; i++, j++) {
                if (j == rss_i)
                        j = 0;
-               /* reta = 4-byte sliding window of
-                * 0x00..(indices-1)(indices-1)00..etc. */
-               reta = (reta << 8) | (j * 0x11);
+               reta = (reta << 8) | (j * indices_multi);
+               if ((i & 3) == 3) {
+                       if (i < 128)
+                               IXGBE_WRITE_REG(hw, IXGBE_RETA(i >> 2), reta);
+                       else
+                               IXGBE_WRITE_REG(hw, IXGBE_ERETA((i >> 2) - 32),
+                                               reta);
+               }
+       }
+}
+
+static void ixgbe_setup_vfreta(struct ixgbe_adapter *adapter, const u32 *seed)
+{
+       struct ixgbe_hw *hw = &adapter->hw;
+       u32 vfreta = 0;
+       u16 rss_i = adapter->ring_feature[RING_F_RSS].indices;
+       unsigned int pf_pool = adapter->num_vfs;
+       int i, j;
+
+       /* Fill out hash function seeds */
+       for (i = 0; i < 10; i++)
+               IXGBE_WRITE_REG(hw, IXGBE_PFVFRSSRK(i, pf_pool), seed[i]);
+
+       /* Fill out the redirection table */
+       for (i = 0, j = 0; i < 64; i++, j++) {
+               if (j == rss_i)
+                       j = 0;
+               vfreta = (vfreta << 8) | j;
                if ((i & 3) == 3)
-                       IXGBE_WRITE_REG(hw, IXGBE_RETA(i >> 2), reta);
+                       IXGBE_WRITE_REG(hw, IXGBE_PFVFRETA(i >> 2, pf_pool),
+                                       vfreta);
        }
+}
+
+static void ixgbe_setup_mrqc(struct ixgbe_adapter *adapter)
+{
+       struct ixgbe_hw *hw = &adapter->hw;
+       u32 mrqc = 0, rss_field = 0, vfmrqc = 0;
+       u32 rss_key[10];
+       u32 rxcsum;
 
        /* Disable indicating checksum in descriptor, enables RSS hash */
        rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM);
@@ -3255,17 +3327,35 @@ static void ixgbe_setup_mrqc(struct ixgbe_adapter *adapter)
        }
 
        /* Perform hash on these packet types */
-       mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4 |
-               IXGBE_MRQC_RSS_FIELD_IPV4_TCP |
-               IXGBE_MRQC_RSS_FIELD_IPV6 |
-               IXGBE_MRQC_RSS_FIELD_IPV6_TCP;
+       rss_field |= IXGBE_MRQC_RSS_FIELD_IPV4 |
+                    IXGBE_MRQC_RSS_FIELD_IPV4_TCP |
+                    IXGBE_MRQC_RSS_FIELD_IPV6 |
+                    IXGBE_MRQC_RSS_FIELD_IPV6_TCP;
 
        if (adapter->flags2 & IXGBE_FLAG2_RSS_FIELD_IPV4_UDP)
-               mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_UDP;
+               rss_field |= IXGBE_MRQC_RSS_FIELD_IPV4_UDP;
        if (adapter->flags2 & IXGBE_FLAG2_RSS_FIELD_IPV6_UDP)
-               mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_UDP;
-
-       IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc);
+               rss_field |= IXGBE_MRQC_RSS_FIELD_IPV6_UDP;
+
+       netdev_rss_key_fill(rss_key, sizeof(rss_key));
+       if ((hw->mac.type >= ixgbe_mac_X550) &&
+           (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)) {
+               unsigned int pf_pool = adapter->num_vfs;
+
+               /* Enable VF RSS mode */
+               mrqc |= IXGBE_MRQC_MULTIPLE_RSS;
+               IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc);
+
+               /* Setup RSS through the VF registers */
+               ixgbe_setup_vfreta(adapter, rss_key);
+               vfmrqc = IXGBE_MRQC_RSSEN;
+               vfmrqc |= rss_field;
+               IXGBE_WRITE_REG(hw, IXGBE_PFVFMRQC(pf_pool), vfmrqc);
+       } else {
+               ixgbe_setup_reta(adapter, rss_key);
+               mrqc |= rss_field;
+               IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc);
+       }
 }
 
 /**
@@ -3534,6 +3624,8 @@ static void ixgbe_setup_rdrxctl(struct ixgbe_adapter *adapter)
        u32 rdrxctl = IXGBE_READ_REG(hw, IXGBE_RDRXCTL);
 
        switch (hw->mac.type) {
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_x:
        case ixgbe_mac_82598EB:
                /*
                 * For VMDq support of different descriptor types or
@@ -3657,6 +3749,8 @@ static void ixgbe_vlan_strip_disable(struct ixgbe_adapter *adapter)
                break;
        case ixgbe_mac_82599EB:
        case ixgbe_mac_X540:
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_x:
                for (i = 0; i < adapter->num_rx_queues; i++) {
                        struct ixgbe_ring *ring = adapter->rx_ring[i];
 
@@ -3691,6 +3785,8 @@ static void ixgbe_vlan_strip_enable(struct ixgbe_adapter *adapter)
                break;
        case ixgbe_mac_82599EB:
        case ixgbe_mac_X540:
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_x:
                for (i = 0; i < adapter->num_rx_queues; i++) {
                        struct ixgbe_ring *ring = adapter->rx_ring[i];
 
@@ -4112,6 +4208,8 @@ static int ixgbe_hpbthresh(struct ixgbe_adapter *adapter, int pb)
        /* Calculate delay value for device */
        switch (hw->mac.type) {
        case ixgbe_mac_X540:
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_x:
                dv_id = IXGBE_DV_X540(link, tc);
                break;
        default:
@@ -4170,6 +4268,8 @@ static int ixgbe_lpbthresh(struct ixgbe_adapter *adapter, int pb)
        /* Calculate delay value for device */
        switch (hw->mac.type) {
        case ixgbe_mac_X540:
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_x:
                dv_id = IXGBE_LOW_DV_X540(tc);
                break;
        default:
@@ -4308,29 +4408,26 @@ static void ixgbe_clean_rx_ring(struct ixgbe_ring *rx_ring)
 
        /* Free all the Rx ring sk_buffs */
        for (i = 0; i < rx_ring->count; i++) {
-               struct ixgbe_rx_buffer *rx_buffer;
+               struct ixgbe_rx_buffer *rx_buffer = &rx_ring->rx_buffer_info[i];
 
-               rx_buffer = &rx_ring->rx_buffer_info[i];
                if (rx_buffer->skb) {
                        struct sk_buff *skb = rx_buffer->skb;
-                       if (IXGBE_CB(skb)->page_released) {
+                       if (IXGBE_CB(skb)->page_released)
                                dma_unmap_page(dev,
                                               IXGBE_CB(skb)->dma,
                                               ixgbe_rx_bufsz(rx_ring),
                                               DMA_FROM_DEVICE);
-                               IXGBE_CB(skb)->page_released = false;
-                       }
                        dev_kfree_skb(skb);
                        rx_buffer->skb = NULL;
                }
-               if (rx_buffer->dma)
-                       dma_unmap_page(dev, rx_buffer->dma,
-                                      ixgbe_rx_pg_size(rx_ring),
-                                      DMA_FROM_DEVICE);
-               rx_buffer->dma = 0;
-               if (rx_buffer->page)
-                       __free_pages(rx_buffer->page,
-                                    ixgbe_rx_pg_order(rx_ring));
+
+               if (!rx_buffer->page)
+                       continue;
+
+               dma_unmap_page(dev, rx_buffer->dma,
+                              ixgbe_rx_pg_size(rx_ring), DMA_FROM_DEVICE);
+               __free_pages(rx_buffer->page, ixgbe_rx_pg_order(rx_ring));
+
                rx_buffer->page = NULL;
        }
 
@@ -4606,6 +4703,8 @@ static void ixgbe_setup_gpie(struct ixgbe_adapter *adapter)
                        break;
                case ixgbe_mac_82599EB:
                case ixgbe_mac_X540:
+               case ixgbe_mac_X550:
+               case ixgbe_mac_X550EM_x:
                default:
                        IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(0), 0xFFFFFFFF);
                        IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(1), 0xFFFFFFFF);
@@ -4948,10 +5047,12 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
                IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(reg_idx), IXGBE_TXDCTL_SWFLSH);
        }
 
-       /* Disable the Tx DMA engine on 82599 and X540 */
+       /* Disable the Tx DMA engine on 82599 and later MAC */
        switch (hw->mac.type) {
        case ixgbe_mac_82599EB:
        case ixgbe_mac_X540:
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_x:
                IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL,
                                (IXGBE_READ_REG(hw, IXGBE_DMATXCTL) &
                                 ~IXGBE_DMATXCTL_TE));
@@ -5016,7 +5117,7 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter)
        hw->subsystem_device_id = pdev->subsystem_device;
 
        /* Set common capability flags and settings */
-       rss = min_t(int, IXGBE_MAX_RSS_INDICES, num_online_cpus());
+       rss = min_t(int, ixgbe_max_rss_indices(adapter), num_online_cpus());
        adapter->ring_feature[RING_F_RSS].limit = rss;
        adapter->flags2 |= IXGBE_FLAG2_RSC_CAPABLE;
        adapter->flags2 |= IXGBE_FLAG2_RSC_ENABLED;
@@ -5071,6 +5172,12 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter)
                if (fwsm & IXGBE_FWSM_TS_ENABLED)
                        adapter->flags2 |= IXGBE_FLAG2_TEMP_SENSOR_CAPABLE;
                break;
+       case ixgbe_mac_X550EM_x:
+       case ixgbe_mac_X550:
+#ifdef CONFIG_IXGBE_DCA
+               adapter->flags &= ~IXGBE_FLAG_DCA_CAPABLE;
+#endif
+               break;
        default:
                break;
        }
@@ -5086,6 +5193,8 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter)
 #ifdef CONFIG_IXGBE_DCB
        switch (hw->mac.type) {
        case ixgbe_mac_X540:
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_x:
                adapter->dcb_cfg.num_tcs.pg_tcs = X540_TRAFFIC_CLASS;
                adapter->dcb_cfg.num_tcs.pfc_tcs = X540_TRAFFIC_CLASS;
                break;
@@ -5675,6 +5784,8 @@ static int __ixgbe_shutdown(struct pci_dev *pdev, bool *enable_wake)
                break;
        case ixgbe_mac_82599EB:
        case ixgbe_mac_X540:
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_x:
                pci_wake_from_d3(pdev, !!wufc);
                break;
        default:
@@ -5806,6 +5917,8 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)
                        break;
                case ixgbe_mac_82599EB:
                case ixgbe_mac_X540:
+               case ixgbe_mac_X550:
+               case ixgbe_mac_X550EM_x:
                        hwstats->pxonrxc[i] +=
                                IXGBE_READ_REG(hw, IXGBE_PXONRXCNT(i));
                        break;
@@ -5819,7 +5932,9 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)
                hwstats->qptc[i] += IXGBE_READ_REG(hw, IXGBE_QPTC(i));
                hwstats->qprc[i] += IXGBE_READ_REG(hw, IXGBE_QPRC(i));
                if ((hw->mac.type == ixgbe_mac_82599EB) ||
-                   (hw->mac.type == ixgbe_mac_X540)) {
+                   (hw->mac.type == ixgbe_mac_X540) ||
+                   (hw->mac.type == ixgbe_mac_X550) ||
+                   (hw->mac.type == ixgbe_mac_X550EM_x)) {
                        hwstats->qbtc[i] += IXGBE_READ_REG(hw, IXGBE_QBTC_L(i));
                        IXGBE_READ_REG(hw, IXGBE_QBTC_H(i)); /* to clear */
                        hwstats->qbrc[i] += IXGBE_READ_REG(hw, IXGBE_QBRC_L(i));
@@ -5842,7 +5957,9 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)
                hwstats->tor += IXGBE_READ_REG(hw, IXGBE_TORH);
                break;
        case ixgbe_mac_X540:
-               /* OS2BMC stats are X540 only*/
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_x:
+               /* OS2BMC stats are X540 and later */
                hwstats->o2bgptc += IXGBE_READ_REG(hw, IXGBE_O2BGPTC);
                hwstats->o2bspc += IXGBE_READ_REG(hw, IXGBE_O2BSPC);
                hwstats->b2ospc += IXGBE_READ_REG(hw, IXGBE_B2OSPC);
@@ -6110,6 +6227,8 @@ static void ixgbe_watchdog_link_is_up(struct ixgbe_adapter *adapter)
        }
                break;
        case ixgbe_mac_X540:
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_x:
        case ixgbe_mac_82599EB: {
                u32 mflcn = IXGBE_READ_REG(hw, IXGBE_MFLCN);
                u32 fccfg = IXGBE_READ_REG(hw, IXGBE_FCCFG);
@@ -6221,6 +6340,10 @@ static bool ixgbe_vf_tx_pending(struct ixgbe_adapter *adapter)
        if (!adapter->num_vfs)
                return false;
 
+       /* resetting the PF is only needed for MAC before X550 */
+       if (hw->mac.type >= ixgbe_mac_X550)
+               return false;
+
        for (i = 0; i < adapter->num_vfs; i++) {
                for (j = 0; j < q_per_pool; j++) {
                        u32 h, t;
@@ -6256,6 +6379,66 @@ static void ixgbe_watchdog_flush_tx(struct ixgbe_adapter *adapter)
        }
 }
 
+#ifdef CONFIG_PCI_IOV
+static inline void ixgbe_issue_vf_flr(struct ixgbe_adapter *adapter,
+                                     struct pci_dev *vfdev)
+{
+       if (!pci_wait_for_pending_transaction(vfdev))
+               e_dev_warn("Issuing VFLR with pending transactions\n");
+
+       e_dev_err("Issuing VFLR for VF %s\n", pci_name(vfdev));
+       pcie_capability_set_word(vfdev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_BCR_FLR);
+
+       msleep(100);
+}
+
+static void ixgbe_check_for_bad_vf(struct ixgbe_adapter *adapter)
+{
+       struct ixgbe_hw *hw = &adapter->hw;
+       struct pci_dev *pdev = adapter->pdev;
+       struct pci_dev *vfdev;
+       u32 gpc;
+       int pos;
+       unsigned short vf_id;
+
+       if (!(netif_carrier_ok(adapter->netdev)))
+               return;
+
+       gpc = IXGBE_READ_REG(hw, IXGBE_TXDGPC);
+       if (gpc) /* If incrementing then no need for the check below */
+               return;
+       /* Check to see if a bad DMA write target from an errant or
+        * malicious VF has caused a PCIe error.  If so then we can
+        * issue a VFLR to the offending VF(s) and then resume without
+        * requesting a full slot reset.
+        */
+
+       if (!pdev)
+               return;
+
+       pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_SRIOV);
+       if (!pos)
+               return;
+
+       /* get the device ID for the VF */
+       pci_read_config_word(pdev, pos + PCI_SRIOV_VF_DID, &vf_id);
+
+       /* check status reg for all VFs owned by this PF */
+       vfdev = pci_get_device(pdev->vendor, vf_id, NULL);
+       while (vfdev) {
+               if (vfdev->is_virtfn && (vfdev->physfn == pdev)) {
+                       u16 status_reg;
+
+                       pci_read_config_word(vfdev, PCI_STATUS, &status_reg);
+                       if (status_reg & PCI_STATUS_REC_MASTER_ABORT)
+                               /* issue VFLR */
+                               ixgbe_issue_vf_flr(adapter, vfdev);
+               }
+
+               vfdev = pci_get_device(pdev->vendor, vf_id, vfdev);
+       }
+}
+
 static void ixgbe_spoof_check(struct ixgbe_adapter *adapter)
 {
        u32 ssvpc;
@@ -6276,6 +6459,17 @@ static void ixgbe_spoof_check(struct ixgbe_adapter *adapter)
 
        e_warn(drv, "%u Spoofed packets detected\n", ssvpc);
 }
+#else
+static void ixgbe_spoof_check(struct ixgbe_adapter __always_unused *adapter)
+{
+}
+
+static void
+ixgbe_check_for_bad_vf(struct ixgbe_adapter __always_unused *adapter)
+{
+}
+#endif /* CONFIG_PCI_IOV */
+
 
 /**
  * ixgbe_watchdog_subtask - check and bring link up
@@ -6296,6 +6490,7 @@ static void ixgbe_watchdog_subtask(struct ixgbe_adapter *adapter)
        else
                ixgbe_watchdog_link_is_down(adapter);
 
+       ixgbe_check_for_bad_vf(adapter);
        ixgbe_spoof_check(adapter);
        ixgbe_update_stats(adapter);
 
@@ -6407,51 +6602,6 @@ static void ixgbe_sfp_link_config_subtask(struct ixgbe_adapter *adapter)
        clear_bit(__IXGBE_IN_SFP_INIT, &adapter->state);
 }
 
-#ifdef CONFIG_PCI_IOV
-static void ixgbe_check_for_bad_vf(struct ixgbe_adapter *adapter)
-{
-       int vf;
-       struct ixgbe_hw *hw = &adapter->hw;
-       struct net_device *netdev = adapter->netdev;
-       u32 gpc;
-       u32 ciaa, ciad;
-
-       gpc = IXGBE_READ_REG(hw, IXGBE_TXDGPC);
-       if (gpc) /* If incrementing then no need for the check below */
-               return;
-       /*
-        * Check to see if a bad DMA write target from an errant or
-        * malicious VF has caused a PCIe error.  If so then we can
-        * issue a VFLR to the offending VF(s) and then resume without
-        * requesting a full slot reset.
-        */
-
-       for (vf = 0; vf < adapter->num_vfs; vf++) {
-               ciaa = (vf << 16) | 0x80000000;
-               /* 32 bit read so align, we really want status at offset 6 */
-               ciaa |= PCI_COMMAND;
-               IXGBE_WRITE_REG(hw, IXGBE_CIAA_82599, ciaa);
-               ciad = IXGBE_READ_REG(hw, IXGBE_CIAD_82599);
-               ciaa &= 0x7FFFFFFF;
-               /* disable debug mode asap after reading data */
-               IXGBE_WRITE_REG(hw, IXGBE_CIAA_82599, ciaa);
-               /* Get the upper 16 bits which will be the PCI status reg */
-               ciad >>= 16;
-               if (ciad & PCI_STATUS_REC_MASTER_ABORT) {
-                       netdev_err(netdev, "VF %d Hung DMA\n", vf);
-                       /* Issue VFLR */
-                       ciaa = (vf << 16) | 0x80000000;
-                       ciaa |= 0xA8;
-                       IXGBE_WRITE_REG(hw, IXGBE_CIAA_82599, ciaa);
-                       ciad = 0x00008000;  /* VFLR */
-                       IXGBE_WRITE_REG(hw, IXGBE_CIAD_82599, ciad);
-                       ciaa &= 0x7FFFFFFF;
-                       IXGBE_WRITE_REG(hw, IXGBE_CIAA_82599, ciaa);
-               }
-       }
-}
-
-#endif
 /**
  * ixgbe_service_timer - Timer Call-back
  * @data: pointer to adapter cast into an unsigned long
@@ -6460,7 +6610,6 @@ static void ixgbe_service_timer(unsigned long data)
 {
        struct ixgbe_adapter *adapter = (struct ixgbe_adapter *)data;
        unsigned long next_event_offset;
-       bool ready = true;
 
        /* poll faster when waiting for link */
        if (adapter->flags & IXGBE_FLAG_NEED_LINK_UPDATE)
@@ -6468,32 +6617,10 @@ static void ixgbe_service_timer(unsigned long data)
        else
                next_event_offset = HZ * 2;
 
-#ifdef CONFIG_PCI_IOV
-       /*
-        * don't bother with SR-IOV VF DMA hang check if there are
-        * no VFs or the link is down
-        */
-       if (!adapter->num_vfs ||
-           (adapter->flags & IXGBE_FLAG_NEED_LINK_UPDATE))
-               goto normal_timer_service;
-
-       /* If we have VFs allocated then we must check for DMA hangs */
-       ixgbe_check_for_bad_vf(adapter);
-       next_event_offset = HZ / 50;
-       adapter->timer_event_accumulator++;
-
-       if (adapter->timer_event_accumulator >= 100)
-               adapter->timer_event_accumulator = 0;
-       else
-               ready = false;
-
-normal_timer_service:
-#endif
        /* Reset the timer */
        mod_timer(&adapter->service_timer, next_event_offset + jiffies);
 
-       if (ready)
-               ixgbe_service_event_schedule(adapter);
+       ixgbe_service_event_schedule(adapter);
 }
 
 static void ixgbe_reset_subtask(struct ixgbe_adapter *adapter)
@@ -6898,8 +7025,12 @@ static void ixgbe_tx_map(struct ixgbe_ring *tx_ring,
        ixgbe_maybe_stop_tx(tx_ring, DESC_NEEDED);
 
        if (netif_xmit_stopped(txring_txq(tx_ring)) || !skb->xmit_more) {
-               /* notify HW of packet */
-               ixgbe_write_tail(tx_ring, i);
+               writel(i, tx_ring->tail);
+
+               /* we need this if more than one processor can write to our tail
+                * at a time, it synchronizes IO on IA64/Altix systems
+                */
+               mmiowb();
        }
 
        return;
@@ -7197,12 +7328,8 @@ static netdev_tx_t __ixgbe_xmit_frame(struct sk_buff *skb,
         * The minimum packet size for olinfo paylen is 17 so pad the skb
         * in order to meet this minimum size requirement.
         */
-       if (unlikely(skb->len < 17)) {
-               if (skb_pad(skb, 17 - skb->len))
-                       return NETDEV_TX_OK;
-               skb->len = 17;
-               skb_set_tail_pointer(skb, 17);
-       }
+       if (skb_put_padto(skb, 17))
+               return NETDEV_TX_OK;
 
        tx_ring = ring ? ring : adapter->tx_ring[skb->queue_mapping];
 
@@ -7646,7 +7773,7 @@ static int ixgbe_set_features(struct net_device *netdev,
 
 static int ixgbe_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
                             struct net_device *dev,
-                            const unsigned char *addr,
+                            const unsigned char *addr, u16 vid,
                             u16 flags)
 {
        /* guarantee we can provide a unique filter for the unicast address */
@@ -7655,7 +7782,7 @@ static int ixgbe_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
                        return -ENOMEM;
        }
 
-       return ndo_dflt_fdb_add(ndm, tb, dev, addr, flags);
+       return ndo_dflt_fdb_add(ndm, tb, dev, addr, vid, flags);
 }
 
 static int ixgbe_ndo_bridge_setlink(struct net_device *dev,
@@ -7716,7 +7843,7 @@ static int ixgbe_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
        else
                mode = BRIDGE_MODE_VEPA;
 
-       return ndo_dflt_bridge_getlink(skb, pid, seq, dev, mode);
+       return ndo_dflt_bridge_getlink(skb, pid, seq, dev, mode, 0, 0);
 }
 
 static void *ixgbe_fwd_add(struct net_device *pdev, struct net_device *vdev)
@@ -7964,6 +8091,29 @@ int ixgbe_wol_supported(struct ixgbe_adapter *adapter, u16 device_id,
        return is_wol_supported;
 }
 
+/**
+ * ixgbe_get_platform_mac_addr - Look up MAC address in Open Firmware / IDPROM
+ * @adapter: Pointer to adapter struct
+ */
+static void ixgbe_get_platform_mac_addr(struct ixgbe_adapter *adapter)
+{
+#ifdef CONFIG_OF
+       struct device_node *dp = pci_device_to_OF_node(adapter->pdev);
+       struct ixgbe_hw *hw = &adapter->hw;
+       const unsigned char *addr;
+
+       addr = of_get_mac_address(dp);
+       if (addr) {
+               ether_addr_copy(hw->mac.perm_addr, addr);
+               return;
+       }
+#endif /* CONFIG_OF */
+
+#ifdef CONFIG_SPARC
+       ether_addr_copy(hw->mac.perm_addr, idprom->id_ethaddr);
+#endif /* CONFIG_SPARC */
+}
+
 /**
  * ixgbe_probe - Device Initialization Routine
  * @pdev: PCI device information struct
@@ -8046,7 +8196,6 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        SET_NETDEV_DEV(netdev, &pdev->dev);
 
        adapter = netdev_priv(netdev);
-       pci_set_drvdata(pdev, adapter);
 
        adapter->netdev = netdev;
        adapter->pdev = pdev;
@@ -8104,6 +8253,8 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        switch (adapter->hw.mac.type) {
        case ixgbe_mac_82599EB:
        case ixgbe_mac_X540:
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_x:
                IXGBE_WRITE_REG(&adapter->hw, IXGBE_WUS, ~0);
                break;
        default:
@@ -8167,6 +8318,8 @@ skip_sriov:
        switch (adapter->hw.mac.type) {
        case ixgbe_mac_82599EB:
        case ixgbe_mac_X540:
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_x:
                netdev->features |= NETIF_F_SCTP_CSUM;
                netdev->hw_features |= NETIF_F_SCTP_CSUM |
                                       NETIF_F_NTUPLE;
@@ -8229,6 +8382,8 @@ skip_sriov:
                goto err_sw_init;
        }
 
+       ixgbe_get_platform_mac_addr(adapter);
+
        memcpy(netdev->dev_addr, hw->mac.perm_addr, netdev->addr_len);
 
        if (!is_valid_ether_addr(netdev->dev_addr)) {
@@ -8320,6 +8475,8 @@ skip_sriov:
        if (err)
                goto err_register;
 
+       pci_set_drvdata(pdev, adapter);
+
        /* power down the optics for 82599 SFP+ fiber */
        if (hw->mac.ops.disable_tx_laser)
                hw->mac.ops.disable_tx_laser(hw);
@@ -8399,9 +8556,14 @@ err_dma:
 static void ixgbe_remove(struct pci_dev *pdev)
 {
        struct ixgbe_adapter *adapter = pci_get_drvdata(pdev);
-       struct net_device *netdev = adapter->netdev;
+       struct net_device *netdev;
        bool disable_dev;
 
+       /* if !adapter then we already cleaned up in probe */
+       if (!adapter)
+               return;
+
+       netdev  = adapter->netdev;
        ixgbe_dbg_adapter_exit(adapter);
 
        set_bit(__IXGBE_REMOVING, &adapter->state);
@@ -8523,6 +8685,12 @@ static pci_ers_result_t ixgbe_io_error_detected(struct pci_dev *pdev,
                case ixgbe_mac_X540:
                        device_id = IXGBE_X540_VF_DEVICE_ID;
                        break;
+               case ixgbe_mac_X550:
+                       device_id = IXGBE_DEV_ID_X550_VF;
+                       break;
+               case ixgbe_mac_X550EM_x:
+                       device_id = IXGBE_DEV_ID_X550EM_X_VF;
+                       break;
                default:
                        device_id = 0;
                        break;
@@ -8542,8 +8710,7 @@ static pci_ers_result_t ixgbe_io_error_detected(struct pci_dev *pdev,
                 * VFLR.  Just clean up the AER in that case.
                 */
                if (vfdev) {
-                       e_dev_err("Issuing VFLR to VF %d\n", vf);
-                       pci_write_config_dword(vfdev, 0xA8, 0x00008000);
+                       ixgbe_issue_vf_flr(adapter, vfdev);
                        /* Free device reference count */
                        pci_dev_put(vfdev);
                }
This page took 0.053903 seconds and 5 git commands to generate.