]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/net/ethernet/intel/i40evf/i40evf_main.c
i40evf: avoid an extra msleep while
[karo-tx-linux.git] / drivers / net / ethernet / intel / i40evf / i40evf_main.c
index 14372810fc27aefc36ed1244641051eda34ec184..db36744c6691f941085bd97b3df46c8bec412cea 100644 (file)
@@ -38,7 +38,7 @@ static const char i40evf_driver_string[] =
 
 #define DRV_VERSION_MAJOR 1
 #define DRV_VERSION_MINOR 6
-#define DRV_VERSION_BUILD 16
+#define DRV_VERSION_BUILD 21
 #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \
             __stringify(DRV_VERSION_MINOR) "." \
             __stringify(DRV_VERSION_BUILD) \
@@ -495,6 +495,33 @@ static void i40evf_netpoll(struct net_device *netdev)
 }
 
 #endif
+/**
+ * i40evf_irq_affinity_notify - Callback for affinity changes
+ * @notify: context as to what irq was changed
+ * @mask: the new affinity mask
+ *
+ * This is a callback function used by the irq_set_affinity_notifier function
+ * so that we may register to receive changes to the irq affinity masks.
+ **/
+static void i40evf_irq_affinity_notify(struct irq_affinity_notify *notify,
+                                      const cpumask_t *mask)
+{
+       struct i40e_q_vector *q_vector =
+               container_of(notify, struct i40e_q_vector, affinity_notify);
+
+       q_vector->affinity_mask = *mask;
+}
+
+/**
+ * i40evf_irq_affinity_release - Callback for affinity notifier release
+ * @ref: internal core kernel usage
+ *
+ * This is a callback function used by the irq_set_affinity_notifier function
+ * to inform the current notification subscriber that they will no longer
+ * receive notifications.
+ **/
+static void i40evf_irq_affinity_release(struct kref *ref) {}
+
 /**
  * i40evf_request_traffic_irqs - Initialize MSI-X interrupts
  * @adapter: board private structure
@@ -507,6 +534,7 @@ i40evf_request_traffic_irqs(struct i40evf_adapter *adapter, char *basename)
 {
        int vector, err, q_vectors;
        int rx_int_idx = 0, tx_int_idx = 0;
+       int irq_num;
 
        i40evf_irq_disable(adapter);
        /* Decrement for Other and TCP Timer vectors */
@@ -514,6 +542,7 @@ i40evf_request_traffic_irqs(struct i40evf_adapter *adapter, char *basename)
 
        for (vector = 0; vector < q_vectors; vector++) {
                struct i40e_q_vector *q_vector = &adapter->q_vectors[vector];
+               irq_num = adapter->msix_entries[vector + NONQ_VECS].vector;
 
                if (q_vector->tx.ring && q_vector->rx.ring) {
                        snprintf(q_vector->name, sizeof(q_vector->name) - 1,
@@ -532,21 +561,23 @@ i40evf_request_traffic_irqs(struct i40evf_adapter *adapter, char *basename)
                        /* skip this unused q_vector */
                        continue;
                }
-               err = request_irq(
-                       adapter->msix_entries[vector + NONQ_VECS].vector,
-                       i40evf_msix_clean_rings,
-                       0,
-                       q_vector->name,
-                       q_vector);
+               err = request_irq(irq_num,
+                                 i40evf_msix_clean_rings,
+                                 0,
+                                 q_vector->name,
+                                 q_vector);
                if (err) {
                        dev_info(&adapter->pdev->dev,
                                 "Request_irq failed, error: %d\n", err);
                        goto free_queue_irqs;
                }
+               /* register for affinity change notifications */
+               q_vector->affinity_notify.notify = i40evf_irq_affinity_notify;
+               q_vector->affinity_notify.release =
+                                                  i40evf_irq_affinity_release;
+               irq_set_affinity_notifier(irq_num, &q_vector->affinity_notify);
                /* assign the mask for this irq */
-               irq_set_affinity_hint(
-                       adapter->msix_entries[vector + NONQ_VECS].vector,
-                       q_vector->affinity_mask);
+               irq_set_affinity_hint(irq_num, &q_vector->affinity_mask);
        }
 
        return 0;
@@ -554,11 +585,10 @@ i40evf_request_traffic_irqs(struct i40evf_adapter *adapter, char *basename)
 free_queue_irqs:
        while (vector) {
                vector--;
-               irq_set_affinity_hint(
-                       adapter->msix_entries[vector + NONQ_VECS].vector,
-                       NULL);
-               free_irq(adapter->msix_entries[vector + NONQ_VECS].vector,
-                        &adapter->q_vectors[vector]);
+               irq_num = adapter->msix_entries[vector + NONQ_VECS].vector;
+               irq_set_affinity_notifier(irq_num, NULL);
+               irq_set_affinity_hint(irq_num, NULL);
+               free_irq(irq_num, &adapter->q_vectors[vector]);
        }
        return err;
 }
@@ -599,16 +629,15 @@ static int i40evf_request_misc_irq(struct i40evf_adapter *adapter)
  **/
 static void i40evf_free_traffic_irqs(struct i40evf_adapter *adapter)
 {
-       int i;
-       int q_vectors;
+       int vector, irq_num, q_vectors;
 
        q_vectors = adapter->num_msix_vectors - NONQ_VECS;
 
-       for (i = 0; i < q_vectors; i++) {
-               irq_set_affinity_hint(adapter->msix_entries[i+1].vector,
-                                     NULL);
-               free_irq(adapter->msix_entries[i+1].vector,
-                        &adapter->q_vectors[i]);
+       for (vector = 0; vector < q_vectors; vector++) {
+               irq_num = adapter->msix_entries[vector + NONQ_VECS].vector;
+               irq_set_affinity_notifier(irq_num, NULL);
+               irq_set_affinity_hint(irq_num, NULL);
+               free_irq(irq_num, &adapter->q_vectors[vector]);
        }
 }
 
@@ -1717,15 +1746,17 @@ static void i40evf_reset_task(struct work_struct *work)
 
        /* wait until the reset is complete and the PF is responding to us */
        for (i = 0; i < I40EVF_RESET_WAIT_COUNT; i++) {
+               /* sleep first to make sure a minimum wait time is met */
+               msleep(I40EVF_RESET_WAIT_MS);
+
                reg_val = rd32(hw, I40E_VFGEN_RSTAT) &
                          I40E_VFGEN_RSTAT_VFR_STATE_MASK;
                if (reg_val == I40E_VFR_VFACTIVE)
                        break;
-               msleep(I40EVF_RESET_WAIT_MS);
        }
+
        pci_set_master(adapter->pdev);
-       /* extra wait to make sure minimum wait is met */
-       msleep(I40EVF_RESET_WAIT_MS);
+
        if (i == I40EVF_RESET_WAIT_COUNT) {
                struct i40evf_mac_filter *ftmp;
                struct i40evf_vlan_filter *fv, *fvtmp;
@@ -2133,10 +2164,6 @@ static struct net_device_stats *i40evf_get_stats(struct net_device *netdev)
 static int i40evf_change_mtu(struct net_device *netdev, int new_mtu)
 {
        struct i40evf_adapter *adapter = netdev_priv(netdev);
-       int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
-
-       if ((new_mtu < 68) || (max_frame > I40E_MAX_RXBUFFER))
-               return -EINVAL;
 
        netdev->mtu = new_mtu;
        adapter->flags |= I40EVF_FLAG_RESET_NEEDED;
@@ -2424,6 +2451,10 @@ static void i40evf_init_task(struct work_struct *work)
        i40evf_set_ethtool_ops(netdev);
        netdev->watchdog_timeo = 5 * HZ;
 
+       /* MTU range: 68 - 9710 */
+       netdev->min_mtu = ETH_MIN_MTU;
+       netdev->max_mtu = I40E_MAX_RXBUFFER - (ETH_HLEN + ETH_FCS_LEN);
+
        if (!is_valid_ether_addr(adapter->hw.mac.addr)) {
                dev_info(&pdev->dev, "Invalid MAC address %pM, using random\n",
                         adapter->hw.mac.addr);