diff options
| author | Thomas Gleixner <tglx@linutronix.de> | 2020-12-15 10:48:07 +0100 | 
|---|---|---|
| committer | Thomas Gleixner <tglx@linutronix.de> | 2020-12-15 10:48:07 +0100 | 
| commit | 3c41e57a1e168d879e923c5583adeae47eec9f64 (patch) | |
| tree | e6272012c4b766189be2821316a3d23d115f5195 /drivers/net/ethernet/ibm/ibmvnic.c | |
| parent | d14ce74f1fb376ccbbc0b05ded477ada51253729 (diff) | |
| parent | 2f5fbc4305d07725bfebaedb09e57271315691ef (diff) | |
Merge tag 'irqchip-5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms into irq/core
Pull irqchip updates for 5.11 from Marc Zyngier:
  - Preliminary support for managed interrupts on platform devices
  - Correctly identify allocation of MSIs proxyied by another device
  - Remove the fasteoi IPI flow which has been proved useless
  - Generalise the Ocelot support to new SoCs
  - Improve GICv4.1 vcpu entry, matching the corresponding KVM optimisation
  - Work around spurious interrupts on Qualcomm PDC
  - Random fixes and cleanups
Link: https://lore.kernel.org/r/20201212135626.1479884-1-maz@kernel.org
Diffstat (limited to 'drivers/net/ethernet/ibm/ibmvnic.c')
| -rw-r--r-- | drivers/net/ethernet/ibm/ibmvnic.c | 59 | 
1 files changed, 52 insertions, 7 deletions
| diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index af4dfbe28d56..2491ebc97871 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -1185,18 +1185,27 @@ static int ibmvnic_open(struct net_device *netdev)  	if (adapter->state != VNIC_CLOSED) {  		rc = ibmvnic_login(netdev);  		if (rc) -			return rc; +			goto out;  		rc = init_resources(adapter);  		if (rc) {  			netdev_err(netdev, "failed to initialize resources\n");  			release_resources(adapter); -			return rc; +			goto out;  		}  	}  	rc = __ibmvnic_open(netdev); +out: +	/* +	 * If open fails due to a pending failover, set device state and +	 * return. Device operation will be handled by reset routine. +	 */ +	if (rc && adapter->failover_pending) { +		adapter->state = VNIC_OPEN; +		rc = 0; +	}  	return rc;  } @@ -1922,6 +1931,13 @@ static int do_reset(struct ibmvnic_adapter *adapter,  		   rwi->reset_reason);  	rtnl_lock(); +	/* +	 * Now that we have the rtnl lock, clear any pending failover. +	 * This will ensure ibmvnic_open() has either completed or will +	 * block until failover is complete. +	 */ +	if (rwi->reset_reason == VNIC_RESET_FAILOVER) +		adapter->failover_pending = false;  	netif_carrier_off(netdev);  	adapter->reset_reason = rwi->reset_reason; @@ -2058,8 +2074,11 @@ static int do_reset(struct ibmvnic_adapter *adapter,  	for (i = 0; i < adapter->req_rx_queues; i++)  		napi_schedule(&adapter->napi[i]); -	if (adapter->reset_reason != VNIC_RESET_FAILOVER) +	if (adapter->reset_reason == VNIC_RESET_FAILOVER || +	    adapter->reset_reason == VNIC_RESET_MOBILITY) {  		call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, netdev); +		call_netdevice_notifiers(NETDEV_RESEND_IGMP, netdev); +	}  	rc = 0; @@ -2129,6 +2148,9 @@ static int do_hard_reset(struct ibmvnic_adapter *adapter,  	if (rc)  		return IBMVNIC_OPEN_FAILED; +	call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, netdev); +	call_netdevice_notifiers(NETDEV_RESEND_IGMP, netdev); +  	return 0;  } @@ -2193,7 +2215,6 @@ static void __ibmvnic_reset(struct work_struct *work)  		if (!saved_state) {  			reset_state = adapter->state; -			adapter->state = VNIC_RESETTING;  			saved_state = true;  		}  		spin_unlock_irqrestore(&adapter->state_lock, flags); @@ -2202,6 +2223,13 @@ static void __ibmvnic_reset(struct work_struct *work)  			/* CHANGE_PARAM requestor holds rtnl_lock */  			rc = do_change_param_reset(adapter, rwi, reset_state);  		} else if (adapter->force_reset_recovery) { +			/* +			 * Since we are doing a hard reset now, clear the +			 * failover_pending flag so we don't ignore any +			 * future MOBILITY or other resets. +			 */ +			adapter->failover_pending = false; +  			/* Transport event occurred during previous reset */  			if (adapter->wait_for_reset) {  				/* Previous was CHANGE_PARAM; caller locked */ @@ -2266,9 +2294,15 @@ static int ibmvnic_reset(struct ibmvnic_adapter *adapter,  	unsigned long flags;  	int ret; +	/* +	 * If failover is pending don't schedule any other reset. +	 * Instead let the failover complete. If there is already a +	 * a failover reset scheduled, we will detect and drop the +	 * duplicate reset when walking the ->rwi_list below. +	 */  	if (adapter->state == VNIC_REMOVING ||  	    adapter->state == VNIC_REMOVED || -	    adapter->failover_pending) { +	    (adapter->failover_pending && reason != VNIC_RESET_FAILOVER)) {  		ret = EBUSY;  		netdev_dbg(netdev, "Adapter removing or pending failover, skipping reset\n");  		goto err; @@ -2321,6 +2355,12 @@ static void ibmvnic_tx_timeout(struct net_device *dev, unsigned int txqueue)  {  	struct ibmvnic_adapter *adapter = netdev_priv(dev); +	if (test_bit(0, &adapter->resetting)) { +		netdev_err(adapter->netdev, +			   "Adapter is resetting, skip timeout reset\n"); +		return; +	} +  	ibmvnic_reset(adapter, VNIC_RESET_TIMEOUT);  } @@ -2839,6 +2879,9 @@ static int reset_sub_crq_queues(struct ibmvnic_adapter *adapter)  {  	int i, rc; +	if (!adapter->tx_scrq || !adapter->rx_scrq) +		return -EINVAL; +  	for (i = 0; i < adapter->req_tx_queues; i++) {  		netdev_dbg(adapter->netdev, "Re-setting tx_scrq[%d]\n", i);  		rc = reset_one_sub_crq_queue(adapter, adapter->tx_scrq[i]); @@ -4713,7 +4756,6 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,  		case IBMVNIC_CRQ_INIT:  			dev_info(dev, "Partner initialized\n");  			adapter->from_passive_init = true; -			adapter->failover_pending = false;  			if (!completion_done(&adapter->init_done)) {  				complete(&adapter->init_done);  				adapter->init_done_rc = -EIO; @@ -4930,6 +4972,9 @@ static int ibmvnic_reset_crq(struct ibmvnic_adapter *adapter)  	} while (rc == H_BUSY || H_IS_LONG_BUSY(rc));  	/* Clean out the queue */ +	if (!crq->msgs) +		return -EINVAL; +  	memset(crq->msgs, 0, PAGE_SIZE);  	crq->cur = 0;  	crq->active = false; @@ -5234,7 +5279,7 @@ static int ibmvnic_remove(struct vio_dev *dev)  	unsigned long flags;  	spin_lock_irqsave(&adapter->state_lock, flags); -	if (adapter->state == VNIC_RESETTING) { +	if (test_bit(0, &adapter->resetting)) {  		spin_unlock_irqrestore(&adapter->state_lock, flags);  		return -EBUSY;  	} | 
