diff options
Diffstat (limited to 'drivers/net/ethernet/intel/iavf/iavf_main.c')
| -rw-r--r-- | drivers/net/ethernet/intel/iavf/iavf_main.c | 137 | 
1 files changed, 91 insertions, 46 deletions
| diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c index e612c24fa384..23762a7ef740 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_main.c +++ b/drivers/net/ethernet/intel/iavf/iavf_main.c @@ -132,6 +132,27 @@ enum iavf_status iavf_free_virt_mem_d(struct iavf_hw *hw,  }  /** + * 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   **/ @@ -751,6 +772,7 @@ struct iavf_mac_filter *iavf_add_filter(struct iavf_adapter *adapter,  		list_add_tail(&f->list, &adapter->mac_filter_list);  		f->add = true; +		f->is_new_mac = true;  		adapter->aq_required |= IAVF_FLAG_AQ_ADD_MAC_FILTER;  	} else {  		f->remove = false; @@ -1506,11 +1528,6 @@ static int iavf_reinit_interrupt_scheme(struct iavf_adapter *adapter)  	set_bit(__IAVF_VSI_DOWN, adapter->vsi.state);  	iavf_map_rings_to_vectors(adapter); - -	if (RSS_AQ(adapter)) -		adapter->aq_required |= IAVF_FLAG_AQ_CONFIGURE_RSS; -	else -		err = iavf_init_rss(adapter);  err:  	return err;  } @@ -1920,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) @@ -1938,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 @@ -1949,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: @@ -1979,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; @@ -1988,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; @@ -2002,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, @@ -2066,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); @@ -2099,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 | @@ -2155,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. */  	} @@ -2200,6 +2217,14 @@ continue_reset:  			goto reset_err;  	} +	if (RSS_AQ(adapter)) { +		adapter->aq_required |= IAVF_FLAG_AQ_CONFIGURE_RSS; +	} else { +		err = iavf_init_rss(adapter); +		if (err) +			goto reset_err; +	} +  	adapter->aq_required |= IAVF_FLAG_AQ_GET_CONFIG;  	adapter->aq_required |= IAVF_FLAG_AQ_MAP_VECTORS; @@ -2274,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);  } @@ -2308,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); @@ -2321,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)) || @@ -2387,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) { @@ -2410,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);  }  /** @@ -3013,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); @@ -3045,7 +3072,7 @@ err:  	if (err)  		kfree(filter); -	clear_bit(__IAVF_IN_CRITICAL_TASK, &adapter->crit_section); +	mutex_unlock(&adapter->crit_lock);  	return err;  } @@ -3192,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) { @@ -3228,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; @@ -3240,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;  } @@ -3264,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); @@ -3276,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 @@ -3625,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) @@ -3637,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, @@ -3653,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);  }  /** @@ -3672,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); @@ -3768,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); @@ -3798,6 +3835,7 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  err_ioremap:  	free_netdev(netdev);  err_alloc_etherdev: +	pci_disable_pcie_error_reporting(pdev);  	pci_release_regions(pdev);  err_pci_reg:  err_dma: @@ -3818,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)) { @@ -3830,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;  } @@ -3892,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); @@ -3907,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. */ @@ -3918,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); @@ -3937,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); |