ethernet: use eth_hw_addr_set() instead of ether_addr_copy()
[linux-2.6-microblaze.git] / drivers / net / ethernet / intel / iavf / iavf_main.c
index 606a01c..7f812ab 100644 (file)
@@ -131,6 +131,27 @@ enum iavf_status iavf_free_virt_mem_d(struct iavf_hw *hw,
        return 0;
 }
 
+/**
+ * iavf_lock_timeout - try to lock mutex but give up after timeout
+ * @lock: mutex that should be locked
+ * @msecs: timeout in msecs
+ *
+ * Returns 0 on success, negative on failure
+ **/
+static int iavf_lock_timeout(struct mutex *lock, unsigned int msecs)
+{
+       unsigned int wait, delay = 10;
+
+       for (wait = 0; wait < msecs; wait += delay) {
+               if (mutex_trylock(lock))
+                       return 0;
+
+               msleep(delay);
+       }
+
+       return -1;
+}
+
 /**
  * iavf_schedule_reset - Set the flags and schedule a reset event
  * @adapter: board private structure
@@ -1826,7 +1847,7 @@ static int iavf_init_get_resources(struct iavf_adapter *adapter)
                eth_hw_addr_random(netdev);
                ether_addr_copy(adapter->hw.mac.addr, netdev->dev_addr);
        } else {
-               ether_addr_copy(netdev->dev_addr, adapter->hw.mac.addr);
+               eth_hw_addr_set(netdev, adapter->hw.mac.addr);
                ether_addr_copy(netdev->perm_addr, adapter->hw.mac.addr);
        }
 
@@ -1916,7 +1937,7 @@ static void iavf_watchdog_task(struct work_struct *work)
        struct iavf_hw *hw = &adapter->hw;
        u32 reg_val;
 
-       if (test_and_set_bit(__IAVF_IN_CRITICAL_TASK, &adapter->crit_section))
+       if (!mutex_trylock(&adapter->crit_lock))
                goto restart_watchdog;
 
        if (adapter->flags & IAVF_FLAG_PF_COMMS_FAILED)
@@ -1934,8 +1955,7 @@ static void iavf_watchdog_task(struct work_struct *work)
                        adapter->state = __IAVF_STARTUP;
                        adapter->flags &= ~IAVF_FLAG_PF_COMMS_FAILED;
                        queue_delayed_work(iavf_wq, &adapter->init_task, 10);
-                       clear_bit(__IAVF_IN_CRITICAL_TASK,
-                                 &adapter->crit_section);
+                       mutex_unlock(&adapter->crit_lock);
                        /* 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
@@ -1945,14 +1965,13 @@ static void iavf_watchdog_task(struct work_struct *work)
                }
                adapter->aq_required = 0;
                adapter->current_op = VIRTCHNL_OP_UNKNOWN;
-               clear_bit(__IAVF_IN_CRITICAL_TASK,
-                         &adapter->crit_section);
+               mutex_unlock(&adapter->crit_lock);
                queue_delayed_work(iavf_wq,
                                   &adapter->watchdog_task,
                                   msecs_to_jiffies(10));
                goto watchdog_done;
        case __IAVF_RESETTING:
-               clear_bit(__IAVF_IN_CRITICAL_TASK, &adapter->crit_section);
+               mutex_unlock(&adapter->crit_lock);
                queue_delayed_work(iavf_wq, &adapter->watchdog_task, HZ * 2);
                return;
        case __IAVF_DOWN:
@@ -1975,7 +1994,7 @@ static void iavf_watchdog_task(struct work_struct *work)
                }
                break;
        case __IAVF_REMOVE:
-               clear_bit(__IAVF_IN_CRITICAL_TASK, &adapter->crit_section);
+               mutex_unlock(&adapter->crit_lock);
                return;
        default:
                goto restart_watchdog;
@@ -1984,7 +2003,6 @@ static void iavf_watchdog_task(struct work_struct *work)
                /* check for hw reset */
        reg_val = rd32(hw, IAVF_VF_ARQLEN1) & IAVF_VF_ARQLEN1_ARQENABLE_MASK;
        if (!reg_val) {
-               adapter->state = __IAVF_RESETTING;
                adapter->flags |= IAVF_FLAG_RESET_PENDING;
                adapter->aq_required = 0;
                adapter->current_op = VIRTCHNL_OP_UNKNOWN;
@@ -1998,7 +2016,7 @@ watchdog_done:
        if (adapter->state == __IAVF_RUNNING ||
            adapter->state == __IAVF_COMM_FAILED)
                iavf_detect_recover_hung(&adapter->vsi);
-       clear_bit(__IAVF_IN_CRITICAL_TASK, &adapter->crit_section);
+       mutex_unlock(&adapter->crit_lock);
 restart_watchdog:
        if (adapter->aq_required)
                queue_delayed_work(iavf_wq, &adapter->watchdog_task,
@@ -2062,7 +2080,7 @@ static void iavf_disable_vf(struct iavf_adapter *adapter)
        memset(adapter->vf_res, 0, IAVF_VIRTCHNL_VF_RESOURCE_SIZE);
        iavf_shutdown_adminq(&adapter->hw);
        adapter->netdev->flags &= ~IFF_UP;
-       clear_bit(__IAVF_IN_CRITICAL_TASK, &adapter->crit_section);
+       mutex_unlock(&adapter->crit_lock);
        adapter->flags &= ~IAVF_FLAG_RESET_PENDING;
        adapter->state = __IAVF_DOWN;
        wake_up(&adapter->down_waitqueue);
@@ -2095,11 +2113,14 @@ static void iavf_reset_task(struct work_struct *work)
        /* When device is being removed it doesn't make sense to run the reset
         * task, just return in such a case.
         */
-       if (test_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section))
+       if (mutex_is_locked(&adapter->remove_lock))
                return;
 
-       while (test_and_set_bit(__IAVF_IN_CLIENT_TASK,
-                               &adapter->crit_section))
+       if (iavf_lock_timeout(&adapter->crit_lock, 200)) {
+               schedule_work(&adapter->reset_task);
+               return;
+       }
+       while (!mutex_trylock(&adapter->client_lock))
                usleep_range(500, 1000);
        if (CLIENT_ENABLED(adapter)) {
                adapter->flags &= ~(IAVF_FLAG_CLIENT_NEEDS_OPEN |
@@ -2151,7 +2172,7 @@ static void iavf_reset_task(struct work_struct *work)
                dev_err(&adapter->pdev->dev, "Reset never finished (%x)\n",
                        reg_val);
                iavf_disable_vf(adapter);
-               clear_bit(__IAVF_IN_CLIENT_TASK, &adapter->crit_section);
+               mutex_unlock(&adapter->client_lock);
                return; /* Do not attempt to reinit. It's dead, Jim. */
        }
 
@@ -2278,13 +2299,13 @@ continue_reset:
                adapter->state = __IAVF_DOWN;
                wake_up(&adapter->down_waitqueue);
        }
-       clear_bit(__IAVF_IN_CLIENT_TASK, &adapter->crit_section);
-       clear_bit(__IAVF_IN_CRITICAL_TASK, &adapter->crit_section);
+       mutex_unlock(&adapter->client_lock);
+       mutex_unlock(&adapter->crit_lock);
 
        return;
 reset_err:
-       clear_bit(__IAVF_IN_CLIENT_TASK, &adapter->crit_section);
-       clear_bit(__IAVF_IN_CRITICAL_TASK, &adapter->crit_section);
+       mutex_unlock(&adapter->client_lock);
+       mutex_unlock(&adapter->crit_lock);
        dev_err(&adapter->pdev->dev, "failed to allocate resources during reinit\n");
        iavf_close(netdev);
 }
@@ -2312,6 +2333,8 @@ static void iavf_adminq_task(struct work_struct *work)
        if (!event.msg_buf)
                goto out;
 
+       if (iavf_lock_timeout(&adapter->crit_lock, 200))
+               goto freedom;
        do {
                ret = iavf_clean_arq_element(hw, &event, &pending);
                v_op = (enum virtchnl_ops)le32_to_cpu(event.desc.cookie_high);
@@ -2325,6 +2348,7 @@ static void iavf_adminq_task(struct work_struct *work)
                if (pending != 0)
                        memset(event.msg_buf, 0, IAVF_MAX_AQ_BUF_SIZE);
        } while (pending);
+       mutex_unlock(&adapter->crit_lock);
 
        if ((adapter->flags &
             (IAVF_FLAG_RESET_PENDING | IAVF_FLAG_RESET_NEEDED)) ||
@@ -2391,7 +2415,7 @@ static void iavf_client_task(struct work_struct *work)
         * later.
         */
 
-       if (test_and_set_bit(__IAVF_IN_CLIENT_TASK, &adapter->crit_section))
+       if (!mutex_trylock(&adapter->client_lock))
                return;
 
        if (adapter->flags & IAVF_FLAG_SERVICE_CLIENT_REQUESTED) {
@@ -2414,7 +2438,7 @@ static void iavf_client_task(struct work_struct *work)
                adapter->flags &= ~IAVF_FLAG_CLIENT_NEEDS_OPEN;
        }
 out:
-       clear_bit(__IAVF_IN_CLIENT_TASK, &adapter->crit_section);
+       mutex_unlock(&adapter->client_lock);
 }
 
 /**
@@ -3017,8 +3041,7 @@ static int iavf_configure_clsflower(struct iavf_adapter *adapter,
        if (!filter)
                return -ENOMEM;
 
-       while (test_and_set_bit(__IAVF_IN_CRITICAL_TASK,
-                               &adapter->crit_section)) {
+       while (!mutex_trylock(&adapter->crit_lock)) {
                if (--count == 0)
                        goto err;
                udelay(1);
@@ -3049,7 +3072,7 @@ err:
        if (err)
                kfree(filter);
 
-       clear_bit(__IAVF_IN_CRITICAL_TASK, &adapter->crit_section);
+       mutex_unlock(&adapter->crit_lock);
        return err;
 }
 
@@ -3196,8 +3219,7 @@ static int iavf_open(struct net_device *netdev)
                return -EIO;
        }
 
-       while (test_and_set_bit(__IAVF_IN_CRITICAL_TASK,
-                               &adapter->crit_section))
+       while (!mutex_trylock(&adapter->crit_lock))
                usleep_range(500, 1000);
 
        if (adapter->state != __IAVF_DOWN) {
@@ -3232,7 +3254,7 @@ static int iavf_open(struct net_device *netdev)
 
        iavf_irq_enable(adapter, true);
 
-       clear_bit(__IAVF_IN_CRITICAL_TASK, &adapter->crit_section);
+       mutex_unlock(&adapter->crit_lock);
 
        return 0;
 
@@ -3244,7 +3266,7 @@ err_setup_rx:
 err_setup_tx:
        iavf_free_all_tx_resources(adapter);
 err_unlock:
-       clear_bit(__IAVF_IN_CRITICAL_TASK, &adapter->crit_section);
+       mutex_unlock(&adapter->crit_lock);
 
        return err;
 }
@@ -3268,8 +3290,7 @@ static int iavf_close(struct net_device *netdev)
        if (adapter->state <= __IAVF_DOWN_PENDING)
                return 0;
 
-       while (test_and_set_bit(__IAVF_IN_CRITICAL_TASK,
-                               &adapter->crit_section))
+       while (!mutex_trylock(&adapter->crit_lock))
                usleep_range(500, 1000);
 
        set_bit(__IAVF_VSI_DOWN, adapter->vsi.state);
@@ -3280,7 +3301,7 @@ static int iavf_close(struct net_device *netdev)
        adapter->state = __IAVF_DOWN_PENDING;
        iavf_free_traffic_irqs(adapter);
 
-       clear_bit(__IAVF_IN_CRITICAL_TASK, &adapter->crit_section);
+       mutex_unlock(&adapter->crit_lock);
 
        /* We explicitly don't free resources here because the hardware is
         * still active and can DMA into memory. Resources are cleared in
@@ -3629,6 +3650,10 @@ static void iavf_init_task(struct work_struct *work)
                                                    init_task.work);
        struct iavf_hw *hw = &adapter->hw;
 
+       if (iavf_lock_timeout(&adapter->crit_lock, 5000)) {
+               dev_warn(&adapter->pdev->dev, "failed to acquire crit_lock in %s\n", __FUNCTION__);
+               return;
+       }
        switch (adapter->state) {
        case __IAVF_STARTUP:
                if (iavf_startup(adapter) < 0)
@@ -3641,14 +3666,14 @@ static void iavf_init_task(struct work_struct *work)
        case __IAVF_INIT_GET_RESOURCES:
                if (iavf_init_get_resources(adapter) < 0)
                        goto init_failed;
-               return;
+               goto out;
        default:
                goto init_failed;
        }
 
        queue_delayed_work(iavf_wq, &adapter->init_task,
                           msecs_to_jiffies(30));
-       return;
+       goto out;
 init_failed:
        if (++adapter->aq_wait_count > IAVF_AQ_MAX_ERR) {
                dev_err(&adapter->pdev->dev,
@@ -3657,9 +3682,11 @@ init_failed:
                iavf_shutdown_adminq(hw);
                adapter->state = __IAVF_STARTUP;
                queue_delayed_work(iavf_wq, &adapter->init_task, HZ * 5);
-               return;
+               goto out;
        }
        queue_delayed_work(iavf_wq, &adapter->init_task, HZ);
+out:
+       mutex_unlock(&adapter->crit_lock);
 }
 
 /**
@@ -3676,9 +3703,12 @@ static void iavf_shutdown(struct pci_dev *pdev)
        if (netif_running(netdev))
                iavf_close(netdev);
 
+       if (iavf_lock_timeout(&adapter->crit_lock, 5000))
+               dev_warn(&adapter->pdev->dev, "failed to acquire crit_lock in %s\n", __FUNCTION__);
        /* Prevent the watchdog from running. */
        adapter->state = __IAVF_REMOVE;
        adapter->aq_required = 0;
+       mutex_unlock(&adapter->crit_lock);
 
 #ifdef CONFIG_PM
        pci_save_state(pdev);
@@ -3772,6 +3802,9 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        /* set up the locks for the AQ, do this only once in probe
         * and destroy them only once in remove
         */
+       mutex_init(&adapter->crit_lock);
+       mutex_init(&adapter->client_lock);
+       mutex_init(&adapter->remove_lock);
        mutex_init(&hw->aq.asq_mutex);
        mutex_init(&hw->aq.arq_mutex);
 
@@ -3823,8 +3856,7 @@ static int __maybe_unused iavf_suspend(struct device *dev_d)
 
        netif_device_detach(netdev);
 
-       while (test_and_set_bit(__IAVF_IN_CRITICAL_TASK,
-                               &adapter->crit_section))
+       while (!mutex_trylock(&adapter->crit_lock))
                usleep_range(500, 1000);
 
        if (netif_running(netdev)) {
@@ -3835,7 +3867,7 @@ static int __maybe_unused iavf_suspend(struct device *dev_d)
        iavf_free_misc_irq(adapter);
        iavf_reset_interrupt_capability(adapter);
 
-       clear_bit(__IAVF_IN_CRITICAL_TASK, &adapter->crit_section);
+       mutex_unlock(&adapter->crit_lock);
 
        return 0;
 }
@@ -3897,7 +3929,7 @@ static void iavf_remove(struct pci_dev *pdev)
        struct iavf_hw *hw = &adapter->hw;
        int err;
        /* Indicate we are in remove and not to run reset_task */
-       set_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section);
+       mutex_lock(&adapter->remove_lock);
        cancel_delayed_work_sync(&adapter->init_task);
        cancel_work_sync(&adapter->reset_task);
        cancel_delayed_work_sync(&adapter->client_task);
@@ -3912,10 +3944,6 @@ static void iavf_remove(struct pci_dev *pdev)
                                 err);
        }
 
-       /* Shut down all the garbage mashers on the detention level */
-       adapter->state = __IAVF_REMOVE;
-       adapter->aq_required = 0;
-       adapter->flags &= ~IAVF_FLAG_REINIT_ITR_NEEDED;
        iavf_request_reset(adapter);
        msleep(50);
        /* If the FW isn't responding, kick it once, but only once. */
@@ -3923,6 +3951,13 @@ static void iavf_remove(struct pci_dev *pdev)
                iavf_request_reset(adapter);
                msleep(50);
        }
+       if (iavf_lock_timeout(&adapter->crit_lock, 5000))
+               dev_warn(&adapter->pdev->dev, "failed to acquire crit_lock in %s\n", __FUNCTION__);
+
+       /* Shut down all the garbage mashers on the detention level */
+       adapter->state = __IAVF_REMOVE;
+       adapter->aq_required = 0;
+       adapter->flags &= ~IAVF_FLAG_REINIT_ITR_NEEDED;
        iavf_free_all_tx_resources(adapter);
        iavf_free_all_rx_resources(adapter);
        iavf_misc_irq_disable(adapter);
@@ -3942,6 +3977,11 @@ static void iavf_remove(struct pci_dev *pdev)
        /* destroy the locks only once, here */
        mutex_destroy(&hw->aq.arq_mutex);
        mutex_destroy(&hw->aq.asq_mutex);
+       mutex_destroy(&adapter->client_lock);
+       mutex_unlock(&adapter->crit_lock);
+       mutex_destroy(&adapter->crit_lock);
+       mutex_unlock(&adapter->remove_lock);
+       mutex_destroy(&adapter->remove_lock);
 
        iounmap(hw->hw_addr);
        pci_release_regions(pdev);