i40evf: program RSS LUT correctly
[pandora-kernel.git] / drivers / net / ethernet / intel / i40evf / i40evf_main.c
index f5caf44..2797548 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Intel Ethernet Controller XL710 Family Linux Virtual Function Driver
- * Copyright(c) 2013 Intel Corporation.
+ * Copyright(c) 2013 - 2014 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -31,10 +31,10 @@ char i40evf_driver_name[] = "i40evf";
 static const char i40evf_driver_string[] =
        "Intel(R) XL710 X710 Virtual Function Network Driver";
 
-#define DRV_VERSION "0.9.11"
+#define DRV_VERSION "0.9.16"
 const char i40evf_driver_version[] = DRV_VERSION;
 static const char i40evf_copyright[] =
-       "Copyright (c) 2013 Intel Corporation.";
+       "Copyright (c) 2013 - 2014 Intel Corporation.";
 
 /* i40evf_pci_tbl - PCI Device ID Table
  *
@@ -167,9 +167,11 @@ static void i40evf_tx_timeout(struct net_device *netdev)
        struct i40evf_adapter *adapter = netdev_priv(netdev);
 
        adapter->tx_timeout_count++;
-
-       /* Do the reset outside of interrupt context */
-       schedule_work(&adapter->reset_task);
+       dev_info(&adapter->pdev->dev, "TX timeout detected.\n");
+       if (!(adapter->flags & I40EVF_FLAG_RESET_PENDING)) {
+               adapter->flags |= I40EVF_FLAG_RESET_NEEDED;
+               schedule_work(&adapter->reset_task);
+       }
 }
 
 /**
@@ -211,6 +213,9 @@ static void i40evf_irq_disable(struct i40evf_adapter *adapter)
        int i;
        struct i40e_hw *hw = &adapter->hw;
 
+       if (!adapter->msix_entries)
+               return;
+
        for (i = 1; i < adapter->num_msix_vectors; i++) {
                wr32(hw, I40E_VFINT_DYN_CTLN1(i - 1), 0);
                synchronize_irq(adapter->msix_entries[i].vector);
@@ -511,12 +516,14 @@ static int i40evf_request_misc_irq(struct i40evf_adapter *adapter)
        struct net_device *netdev = adapter->netdev;
        int err;
 
-       sprintf(adapter->name[0], "i40evf:mbx");
+       sprintf(adapter->misc_vector_name, "i40evf:mbx");
        err = request_irq(adapter->msix_entries[0].vector,
-                         &i40evf_msix_aq, 0, adapter->name[0], netdev);
+                         &i40evf_msix_aq, 0,
+                         adapter->misc_vector_name, netdev);
        if (err) {
                dev_err(&adapter->pdev->dev,
-                       "request_irq for msix_aq failed: %d\n", err);
+                       "request_irq for %s failed: %d\n",
+                       adapter->misc_vector_name, err);
                free_irq(adapter->msix_entries[0].vector, netdev);
        }
        return err;
@@ -963,16 +970,23 @@ void i40evf_down(struct i40evf_adapter *adapter)
        struct net_device *netdev = adapter->netdev;
        struct i40evf_mac_filter *f;
 
-       /* remove all MAC filters from the VSI */
+       /* remove all MAC filters */
        list_for_each_entry(f, &adapter->mac_filter_list, list) {
                f->remove = true;
        }
-       adapter->aq_required |= I40EVF_FLAG_AQ_DEL_MAC_FILTER;
-       /* disable receives */
-       adapter->aq_required |= I40EVF_FLAG_AQ_DISABLE_QUEUES;
-       mod_timer_pending(&adapter->watchdog_timer, jiffies + 1);
-       msleep(20);
-
+       /* remove all VLAN filters */
+       list_for_each_entry(f, &adapter->vlan_filter_list, list) {
+               f->remove = true;
+       }
+       if (!(adapter->flags & I40EVF_FLAG_PF_COMMS_FAILED) &&
+           adapter->state != __I40EVF_RESETTING) {
+               adapter->aq_required |= I40EVF_FLAG_AQ_DEL_MAC_FILTER;
+               adapter->aq_required |= I40EVF_FLAG_AQ_DEL_VLAN_FILTER;
+               /* disable receives */
+               adapter->aq_required |= I40EVF_FLAG_AQ_DISABLE_QUEUES;
+               mod_timer_pending(&adapter->watchdog_timer, jiffies + 1);
+               msleep(20);
+       }
        netif_tx_disable(netdev);
 
        netif_tx_stop_all_queues(netdev);
@@ -1124,8 +1138,8 @@ static int i40evf_set_interrupt_capability(struct i40evf_adapter *adapter)
         * than CPU's.  So let's be conservative and only ask for
         * (roughly) twice the number of vectors as there are CPU's.
         */
-       v_budget = min(pairs, (int)(num_online_cpus() * 2)) + NONQ_VECS;
-       v_budget = min(v_budget, (int)adapter->vf_res->max_vectors + 1);
+       v_budget = min_t(int, pairs, (int)(num_online_cpus() * 2)) + NONQ_VECS;
+       v_budget = min_t(int, v_budget, (int)adapter->vf_res->max_vectors);
 
        /* A failure in MSI-X entry allocation isn't fatal, but it does
         * mean we disable MSI-X capabilities of the adapter.
@@ -1291,19 +1305,47 @@ static void i40evf_watchdog_task(struct work_struct *work)
                                          watchdog_task);
        struct i40e_hw *hw = &adapter->hw;
 
-       if (adapter->state < __I40EVF_DOWN)
+       if (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section))
+               goto restart_watchdog;
+
+       if (adapter->flags & I40EVF_FLAG_PF_COMMS_FAILED) {
+               dev_info(&adapter->pdev->dev, "Checking for redemption\n");
+               if ((rd32(hw, I40E_VFGEN_RSTAT) & 0x3) == I40E_VFR_VFACTIVE) {
+                       /* A chance for redemption! */
+                       dev_err(&adapter->pdev->dev, "Hardware came out of reset. Attempting reinit.\n");
+                       adapter->state = __I40EVF_STARTUP;
+                       adapter->flags &= ~I40EVF_FLAG_PF_COMMS_FAILED;
+                       schedule_delayed_work(&adapter->init_task, 10);
+                       clear_bit(__I40EVF_IN_CRITICAL_TASK,
+                                 &adapter->crit_section);
+                       /* Don't reschedule the watchdog, since we've restarted
+                        * the init task. When init_task contacts the PF and
+                        * gets everything set up again, it'll restart the
+                        * watchdog for us. Down, boy. Sit. Stay. Woof.
+                        */
+                       return;
+               }
+               adapter->aq_pending = 0;
+               adapter->aq_required = 0;
+               adapter->current_op = I40E_VIRTCHNL_OP_UNKNOWN;
                goto watchdog_done;
+       }
 
-       if (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section))
+       if ((adapter->state < __I40EVF_DOWN) ||
+           (adapter->flags & I40EVF_FLAG_RESET_PENDING))
                goto watchdog_done;
 
-       /* check for unannounced reset */
-       if ((adapter->state != __I40EVF_RESETTING) &&
+       /* check for reset */
+       if (!(adapter->flags & I40EVF_FLAG_RESET_PENDING) &&
            (rd32(hw, I40E_VFGEN_RSTAT) & 0x3) != I40E_VFR_VFACTIVE) {
                adapter->state = __I40EVF_RESETTING;
+               adapter->flags |= I40EVF_FLAG_RESET_PENDING;
+               dev_err(&adapter->pdev->dev, "Hardware reset detected.\n");
+               dev_info(&adapter->pdev->dev, "Scheduling reset task\n");
                schedule_work(&adapter->reset_task);
-               dev_info(&adapter->pdev->dev, "%s: hardware reset detected\n",
-                        __func__);
+               adapter->aq_pending = 0;
+               adapter->aq_required = 0;
+               adapter->current_op = I40E_VIRTCHNL_OP_UNKNOWN;
                goto watchdog_done;
        }
 
@@ -1358,16 +1400,33 @@ static void i40evf_watchdog_task(struct work_struct *work)
 
        i40evf_irq_enable(adapter, true);
        i40evf_fire_sw_int(adapter, 0xFF);
+
 watchdog_done:
+       clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
+restart_watchdog:
        if (adapter->aq_required)
                mod_timer(&adapter->watchdog_timer,
                          jiffies + msecs_to_jiffies(20));
        else
                mod_timer(&adapter->watchdog_timer, jiffies + (HZ * 2));
-       clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
        schedule_work(&adapter->adminq_task);
 }
 
+/**
+ * i40evf_configure_rss - increment to next available tx queue
+ * @adapter: board private structure
+ * @j: queue counter
+ *
+ * Helper function for RSS programming to increment through available
+ * queus. Returns the next queue value.
+ **/
+static int next_queue(struct i40evf_adapter *adapter, int j)
+{
+       j += 1;
+
+       return j >= adapter->vsi_res->num_queue_pairs ? 0 : j;
+}
+
 /**
  * i40evf_configure_rss - Prepare for RSS if used
  * @adapter: board private structure
@@ -1398,19 +1457,23 @@ static void i40evf_configure_rss(struct i40evf_adapter *adapter)
        wr32(hw, I40E_VFQF_HENA(1), (u32)(hena >> 32));
 
        /* Populate the LUT with max no. of queues in round robin fashion */
-       for (i = 0, j = 0; i < I40E_VFQF_HLUT_MAX_INDEX; i++, j++) {
-               if (j == adapter->vsi_res->num_queue_pairs)
-                       j = 0;
-               /* lut = 4-byte sliding window of 4 lut entries */
-               lut = (lut << 8) | (j &
-                        ((0x1 << 8) - 1));
-               /* On i = 3, we have 4 entries in lut; write to the register */
-               if ((i & 3) == 3)
-                       wr32(hw, I40E_VFQF_HLUT(i >> 2), lut);
+       j = adapter->vsi_res->num_queue_pairs;
+       for (i = 0; i <= I40E_VFQF_HLUT_MAX_INDEX; i++) {
+               j = next_queue(adapter, j);
+               lut = j;
+               j = next_queue(adapter, j);
+               lut |= j << 8;
+               j = next_queue(adapter, j);
+               lut |= j << 16;
+               j = next_queue(adapter, j);
+               lut |= j << 24;
+               wr32(hw, I40E_VFQF_HLUT(i), lut);
        }
        i40e_flush(hw);
 }
 
+#define I40EVF_RESET_WAIT_MS 100
+#define I40EVF_RESET_WAIT_COUNT 200
 /**
  * i40evf_reset_task - Call-back task to handle hardware reset
  * @work: pointer to work_struct
@@ -1421,8 +1484,9 @@ static void i40evf_configure_rss(struct i40evf_adapter *adapter)
  **/
 static void i40evf_reset_task(struct work_struct *work)
 {
-       struct i40evf_adapter *adapter =
-                       container_of(work, struct i40evf_adapter, reset_task);
+       struct i40evf_adapter *adapter = container_of(work,
+                                                     struct i40evf_adapter,
+                                                     reset_task);
        struct i40e_hw *hw = &adapter->hw;
        int i = 0, err;
        uint32_t rstat_val;
@@ -1431,21 +1495,61 @@ static void i40evf_reset_task(struct work_struct *work)
                                &adapter->crit_section))
                udelay(500);
 
-       /* wait until the reset is complete */
-       for (i = 0; i < 20; i++) {
+       if (adapter->flags & I40EVF_FLAG_RESET_NEEDED) {
+               dev_info(&adapter->pdev->dev, "Requesting reset from PF\n");
+               i40evf_request_reset(adapter);
+       }
+
+       /* poll until we see the reset actually happen */
+       for (i = 0; i < I40EVF_RESET_WAIT_COUNT; i++) {
                rstat_val = rd32(hw, I40E_VFGEN_RSTAT) &
                            I40E_VFGEN_RSTAT_VFR_STATE_MASK;
-               if (rstat_val == I40E_VFR_COMPLETED)
+               if (rstat_val != I40E_VFR_VFACTIVE) {
+                       dev_info(&adapter->pdev->dev, "Reset now occurring\n");
                        break;
-               else
-                       mdelay(100);
+               } else {
+                       msleep(I40EVF_RESET_WAIT_MS);
+               }
+       }
+       if (i == I40EVF_RESET_WAIT_COUNT) {
+               dev_err(&adapter->pdev->dev, "Reset was not detected\n");
+               adapter->flags &= ~I40EVF_FLAG_RESET_PENDING;
+               goto continue_reset; /* act like the reset happened */
+       }
+
+       /* wait until the reset is complete and the PF is responding to us */
+       for (i = 0; i < I40EVF_RESET_WAIT_COUNT; i++) {
+               rstat_val = rd32(hw, I40E_VFGEN_RSTAT) &
+                           I40E_VFGEN_RSTAT_VFR_STATE_MASK;
+               if (rstat_val == I40E_VFR_VFACTIVE) {
+                       dev_info(&adapter->pdev->dev, "Reset is complete. Reinitializing.\n");
+                       break;
+               } else {
+                       msleep(I40EVF_RESET_WAIT_MS);
+               }
        }
-       if (i == 20) {
+       if (i == I40EVF_RESET_WAIT_COUNT) {
                /* reset never finished */
-               dev_info(&adapter->pdev->dev, "%s: reset never finished: %x\n",
-                       __func__, rstat_val);
-               /* carry on anyway */
+               dev_err(&adapter->pdev->dev, "Reset never finished (%x). PF driver is dead, and so am I.\n",
+                       rstat_val);
+               adapter->flags |= I40EVF_FLAG_PF_COMMS_FAILED;
+
+               if (netif_running(adapter->netdev))
+                       i40evf_close(adapter->netdev);
+
+               i40evf_free_misc_irq(adapter);
+               i40evf_reset_interrupt_capability(adapter);
+               i40evf_free_queues(adapter);
+               kfree(adapter->vf_res);
+               i40evf_shutdown_adminq(hw);
+               adapter->netdev->flags &= ~IFF_UP;
+               clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
+               return; /* Do not attempt to reinit. It's dead, Jim. */
        }
+
+continue_reset:
+       adapter->flags &= ~I40EVF_FLAG_RESET_PENDING;
+
        i40evf_down(adapter);
        adapter->state = __I40EVF_RESETTING;
 
@@ -1505,6 +1609,9 @@ static void i40evf_adminq_task(struct work_struct *work)
        i40e_status ret;
        u16 pending;
 
+       if (adapter->flags & I40EVF_FLAG_PF_COMMS_FAILED)
+               return;
+
        event.msg_size = I40EVF_MAX_AQ_BUF_SIZE;
        event.msg_buf = kzalloc(event.msg_size, GFP_KERNEL);
        if (!event.msg_buf) {
@@ -1636,6 +1743,10 @@ static int i40evf_open(struct net_device *netdev)
        struct i40evf_adapter *adapter = netdev_priv(netdev);
        int err;
 
+       if (adapter->flags & I40EVF_FLAG_PF_COMMS_FAILED) {
+               dev_err(&adapter->pdev->dev, "Unable to open device due to PF driver failure.\n");
+               return -EIO;
+       }
        if (adapter->state != __I40EVF_DOWN)
                return -EBUSY;
 
@@ -1690,8 +1801,12 @@ static int i40evf_close(struct net_device *netdev)
 {
        struct i40evf_adapter *adapter = netdev_priv(netdev);
 
+       if (adapter->state <= __I40EVF_DOWN)
+               return 0;
+
        /* signal that we are down to the interrupt handler */
        adapter->state = __I40EVF_DOWN;
+
        set_bit(__I40E_DOWN, &adapter->vsi.state);
 
        i40evf_down(adapter);
@@ -1842,16 +1957,18 @@ static void i40evf_init_task(struct work_struct *work)
        switch (adapter->state) {
        case __I40EVF_STARTUP:
                /* driver loaded, probe complete */
+               adapter->flags &= ~I40EVF_FLAG_PF_COMMS_FAILED;
+               adapter->flags &= ~I40EVF_FLAG_RESET_PENDING;
                err = i40e_set_mac_type(hw);
                if (err) {
-                       dev_info(&pdev->dev, "%s: set_mac_type failed: %d\n",
-                               __func__, err);
+                       dev_err(&pdev->dev, "Failed to set MAC type (%d)\n",
+                               err);
                goto err;
                }
                err = i40evf_check_reset_complete(hw);
                if (err) {
-                       dev_info(&pdev->dev, "%s: device is still in reset (%d).\n",
-                               __func__, err);
+                       dev_err(&pdev->dev, "Device is still in reset (%d)\n",
+                               err);
                        goto err;
                }
                hw->aq.num_arq_entries = I40EVF_AQ_LEN;
@@ -1861,14 +1978,13 @@ static void i40evf_init_task(struct work_struct *work)
 
                err = i40evf_init_adminq(hw);
                if (err) {
-                       dev_info(&pdev->dev, "%s: init_adminq failed: %d\n",
-                               __func__, err);
+                       dev_err(&pdev->dev, "Failed to init Admin Queue (%d)\n",
+                               err);
                        goto err;
                }
                err = i40evf_send_api_ver(adapter);
                if (err) {
-                       dev_info(&pdev->dev, "%s: unable to send to PF (%d)\n",
-                               __func__, err);
+                       dev_err(&pdev->dev, "Unable to send to PF (%d)\n", err);
                        i40evf_shutdown_adminq(hw);
                        goto err;
                }
@@ -1876,19 +1992,21 @@ static void i40evf_init_task(struct work_struct *work)
                goto restart;
                break;
        case __I40EVF_INIT_VERSION_CHECK:
-               if (!i40evf_asq_done(hw))
+               if (!i40evf_asq_done(hw)) {
+                       dev_err(&pdev->dev, "Admin queue command never completed.\n");
                        goto err;
+               }
 
                /* aq msg sent, awaiting reply */
                err = i40evf_verify_api_ver(adapter);
                if (err) {
-                       dev_err(&pdev->dev, "Unable to verify API version, error %d\n",
+                       dev_err(&pdev->dev, "Unable to verify API version (%d)\n",
                                err);
                        goto err;
                }
                err = i40evf_send_vf_config_msg(adapter);
                if (err) {
-                       dev_err(&pdev->dev, "Unable send config request, error %d\n",
+                       dev_err(&pdev->dev, "Unable send config request (%d)\n",
                                err);
                        goto err;
                }
@@ -1902,18 +2020,15 @@ static void i40evf_init_task(struct work_struct *work)
                                (I40E_MAX_VF_VSI *
                                 sizeof(struct i40e_virtchnl_vsi_resource));
                        adapter->vf_res = kzalloc(bufsz, GFP_KERNEL);
-                       if (!adapter->vf_res) {
-                               dev_err(&pdev->dev, "%s: unable to allocate memory\n",
-                                       __func__);
+                       if (!adapter->vf_res)
                                goto err;
-                       }
                }
                err = i40evf_get_vf_config(adapter);
                if (err == I40E_ERR_ADMIN_QUEUE_NO_WORK)
                        goto restart;
                if (err) {
-                       dev_info(&pdev->dev, "%s: unable to get VF config (%d)\n",
-                               __func__, err);
+                       dev_err(&pdev->dev, "Unable to get VF config (%d)\n",
+                               err);
                        goto err_alloc;
                }
                adapter->state = __I40EVF_INIT_SW;
@@ -1927,25 +2042,23 @@ static void i40evf_init_task(struct work_struct *work)
                        adapter->vsi_res = &adapter->vf_res->vsi_res[i];
        }
        if (!adapter->vsi_res) {
-               dev_info(&pdev->dev, "%s: no LAN VSI found\n", __func__);
+               dev_err(&pdev->dev, "No LAN VSI found\n");
                goto err_alloc;
        }
 
        adapter->flags |= I40EVF_FLAG_RX_CSUM_ENABLED;
 
-       adapter->txd_count = I40EVF_DEFAULT_TXD;
-       adapter->rxd_count = I40EVF_DEFAULT_RXD;
-
        netdev->netdev_ops = &i40evf_netdev_ops;
        i40evf_set_ethtool_ops(netdev);
        netdev->watchdog_timeo = 5 * HZ;
-
-       netdev->features |= NETIF_F_SG |
+       netdev->features |= NETIF_F_HIGHDMA |
+                           NETIF_F_SG |
                            NETIF_F_IP_CSUM |
                            NETIF_F_SCTP_CSUM |
                            NETIF_F_IPV6_CSUM |
                            NETIF_F_TSO |
                            NETIF_F_TSO6 |
+                           NETIF_F_RXCSUM |
                            NETIF_F_GRO;
 
        if (adapter->vf_res->vf_offload_flags
@@ -1956,11 +2069,13 @@ static void i40evf_init_task(struct work_struct *work)
                                    NETIF_F_HW_VLAN_CTAG_FILTER;
        }
 
-       /* The HW MAC address was set and/or determined in sw_init */
+       /* copy netdev features into list of user selectable features */
+       netdev->hw_features |= netdev->features;
+       netdev->hw_features &= ~NETIF_F_RXCSUM;
+
        if (!is_valid_ether_addr(adapter->hw.mac.addr)) {
-               dev_info(&pdev->dev,
-                       "Invalid MAC address %pMAC, using random\n",
-                       adapter->hw.mac.addr);
+               dev_info(&pdev->dev, "Invalid MAC address %pMAC, using random\n",
+                        adapter->hw.mac.addr);
                random_ether_addr(adapter->hw.mac.addr);
        }
        memcpy(netdev->dev_addr, adapter->hw.mac.addr, netdev->addr_len);
@@ -1994,8 +2109,6 @@ static void i40evf_init_task(struct work_struct *work)
 
        netif_carrier_off(netdev);
 
-       strcpy(netdev->name, "eth%d");
-
        adapter->vsi.id = adapter->vsi_res->vsi_id;
        adapter->vsi.seid = adapter->vsi_res->vsi_id; /* dummy */
        adapter->vsi.back = adapter;
@@ -2005,9 +2118,11 @@ static void i40evf_init_task(struct work_struct *work)
        adapter->vsi.tx_itr_setting = I40E_ITR_DYNAMIC;
        adapter->vsi.netdev = adapter->netdev;
 
-       err = register_netdev(netdev);
-       if (err)
-               goto err_register;
+       if (!adapter->netdev_registered) {
+               err = register_netdev(netdev);
+               if (err)
+                       goto err_register;
+       }
 
        adapter->netdev_registered = true;
 
@@ -2031,7 +2146,6 @@ err_register:
        i40evf_free_misc_irq(adapter);
 err_sw_init:
        i40evf_reset_interrupt_capability(adapter);
-       adapter->state = __I40EVF_FAILED;
 err_alloc:
        kfree(adapter->vf_res);
        adapter->vf_res = NULL;
@@ -2039,9 +2153,7 @@ err:
        /* Things went into the weeds, so try again later */
        if (++adapter->aq_wait_count > I40EVF_AQ_MAX_ERR) {
                dev_err(&pdev->dev, "Failed to communicate with PF; giving up.\n");
-               if (hw->aq.asq.count)
-                       i40evf_shutdown_adminq(hw); /* ignore error */
-               adapter->state = __I40EVF_FAILED;
+               adapter->flags |= I40EVF_FLAG_PF_COMMS_FAILED;
                return; /* do not reschedule */
        }
        schedule_delayed_work(&adapter->init_task, HZ * 3);
@@ -2084,26 +2196,20 @@ static int i40evf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        struct net_device *netdev;
        struct i40evf_adapter *adapter = NULL;
        struct i40e_hw *hw = NULL;
-       int err, pci_using_dac;
+       int err;
 
        err = pci_enable_device(pdev);
        if (err)
                return err;
 
-       if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) {
-               pci_using_dac = true;
-               /* coherent mask for the same size will always succeed if
-                * dma_set_mask does
-                */
-               dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
-       } else if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(32))) {
-               pci_using_dac = false;
-               dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
-       } else {
-               dev_err(&pdev->dev, "%s: DMA configuration failed: %d\n",
-                        __func__, err);
-               err = -EIO;
-               goto err_dma;
+       err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
+       if (err) {
+               err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+               if (err) {
+                       dev_err(&pdev->dev,
+                               "DMA configuration failed: 0x%x\n", err);
+                       goto err_dma;
+               }
        }
 
        err = pci_request_regions(pdev, i40evf_driver_name);
@@ -2128,8 +2234,6 @@ static int i40evf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        pci_set_drvdata(pdev, netdev);
        adapter = netdev_priv(netdev);
-       if (pci_using_dac)
-               netdev->features |= NETIF_F_HIGHDMA;
 
        adapter->netdev = netdev;
        adapter->pdev = pdev;
@@ -2271,6 +2375,7 @@ static void i40evf_remove(struct pci_dev *pdev)
        struct i40e_hw *hw = &adapter->hw;
 
        cancel_delayed_work_sync(&adapter->init_task);
+       cancel_work_sync(&adapter->reset_task);
 
        if (adapter->netdev_registered) {
                unregister_netdev(netdev);
@@ -2278,17 +2383,15 @@ static void i40evf_remove(struct pci_dev *pdev)
        }
        adapter->state = __I40EVF_REMOVE;
 
-       if (adapter->num_msix_vectors) {
+       if (adapter->msix_entries) {
                i40evf_misc_irq_disable(adapter);
-               del_timer_sync(&adapter->watchdog_timer);
-
-               flush_scheduled_work();
-
                i40evf_free_misc_irq(adapter);
-
                i40evf_reset_interrupt_capability(adapter);
        }
 
+       del_timer_sync(&adapter->watchdog_timer);
+       flush_scheduled_work();
+
        if (hw->aq.asq.count)
                i40evf_shutdown_adminq(hw);