diff options
| author | Stephen Rothwell <sfr@canb.auug.org.au> | 2011-07-25 13:59:46 -0400 | 
|---|---|---|
| committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-07-25 14:53:52 -0400 | 
| commit | 5f00bcb38ef9a980a33c6dbdc0044964b05f22dd (patch) | |
| tree | 3175fb9375aecb50bde1be0bf4fa8aa8155131d6 /drivers/net/sfc/efx.c | |
| parent | 34006cee28f7344f9557a4be3816c7891b1bbab1 (diff) | |
| parent | b6844e8f64920cdee620157252169ba63afb0c89 (diff) | |
Merge branch 'master' into devel and apply fixup from Stephen Rothwell:
vfs/nfs: fixup for nfs_open_context change
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'drivers/net/sfc/efx.c')
| -rw-r--r-- | drivers/net/sfc/efx.c | 60 | 
1 files changed, 23 insertions, 37 deletions
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index c914729f955..faca764aa21 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c @@ -229,8 +229,7 @@ static int efx_process_channel(struct efx_channel *channel, int budget)  	struct efx_nic *efx = channel->efx;  	int spent; -	if (unlikely(efx->reset_pending != RESET_TYPE_NONE || -		     !channel->enabled)) +	if (unlikely(efx->reset_pending || !channel->enabled))  		return 0;  	spent = efx_nic_process_eventq(channel, budget); @@ -1461,7 +1460,7 @@ static void efx_start_all(struct efx_nic *efx)  	 * reset_pending [modified from an atomic context], we instead guarantee  	 * that efx_mcdi_mode_poll() isn't reverted erroneously */  	efx_mcdi_mode_event(efx); -	if (efx->reset_pending != RESET_TYPE_NONE) +	if (efx->reset_pending)  		efx_mcdi_mode_poll(efx);  	/* Start the hardware monitor if there is one. Otherwise (we're link @@ -2118,8 +2117,10 @@ int efx_reset(struct efx_nic *efx, enum reset_type method)  		goto out;  	} -	/* Allow resets to be rescheduled. */ -	efx->reset_pending = RESET_TYPE_NONE; +	/* Clear flags for the scopes we covered.  We assume the NIC and +	 * driver are now quiescent so that there is no race here. +	 */ +	efx->reset_pending &= -(1 << (method + 1));  	/* Reinitialise bus-mastering, which may have been turned off before  	 * the reset was scheduled. This is still appropriate, even in the @@ -2154,12 +2155,13 @@ out:  static void efx_reset_work(struct work_struct *data)  {  	struct efx_nic *efx = container_of(data, struct efx_nic, reset_work); +	unsigned long pending = ACCESS_ONCE(efx->reset_pending); -	if (efx->reset_pending == RESET_TYPE_NONE) +	if (!pending)  		return;  	/* If we're not RUNNING then don't reset. Leave the reset_pending -	 * flag set so that efx_pci_probe_main will be retried */ +	 * flags set so that efx_pci_probe_main will be retried */  	if (efx->state != STATE_RUNNING) {  		netif_info(efx, drv, efx->net_dev,  			   "scheduled reset quenched. NIC not RUNNING\n"); @@ -2167,7 +2169,7 @@ static void efx_reset_work(struct work_struct *data)  	}  	rtnl_lock(); -	(void)efx_reset(efx, efx->reset_pending); +	(void)efx_reset(efx, fls(pending) - 1);  	rtnl_unlock();  } @@ -2175,40 +2177,24 @@ void efx_schedule_reset(struct efx_nic *efx, enum reset_type type)  {  	enum reset_type method; -	if (efx->reset_pending != RESET_TYPE_NONE) { -		netif_info(efx, drv, efx->net_dev, -			   "quenching already scheduled reset\n"); -		return; -	} -  	switch (type) {  	case RESET_TYPE_INVISIBLE:  	case RESET_TYPE_ALL:  	case RESET_TYPE_WORLD:  	case RESET_TYPE_DISABLE:  		method = type; +		netif_dbg(efx, drv, efx->net_dev, "scheduling %s reset\n", +			  RESET_TYPE(method));  		break; -	case RESET_TYPE_RX_RECOVERY: -	case RESET_TYPE_RX_DESC_FETCH: -	case RESET_TYPE_TX_DESC_FETCH: -	case RESET_TYPE_TX_SKIP: -		method = RESET_TYPE_INVISIBLE; -		break; -	case RESET_TYPE_MC_FAILURE:  	default: -		method = RESET_TYPE_ALL; -		break; -	} - -	if (method != type) +		method = efx->type->map_reset_reason(type);  		netif_dbg(efx, drv, efx->net_dev,  			  "scheduling %s reset for %s\n",  			  RESET_TYPE(method), RESET_TYPE(type)); -	else -		netif_dbg(efx, drv, efx->net_dev, "scheduling %s reset\n", -			  RESET_TYPE(method)); +		break; +	} -	efx->reset_pending = method; +	set_bit(method, &efx->reset_pending);  	/* efx_process_channel() will no longer read events once a  	 * reset is scheduled. So switch back to poll'd MCDI completions. */ @@ -2288,7 +2274,6 @@ static int efx_init_struct(struct efx_nic *efx, const struct efx_nic_type *type,  	efx->pci_dev = pci_dev;  	efx->msg_enable = debug;  	efx->state = STATE_INIT; -	efx->reset_pending = RESET_TYPE_NONE;  	strlcpy(efx->name, pci_name(pci_dev), sizeof(efx->name));  	efx->net_dev = net_dev; @@ -2491,7 +2476,7 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,  		goto fail1;  	netif_info(efx, probe, efx->net_dev, -		   "Solarflare Communications NIC detected\n"); +		   "Solarflare NIC detected\n");  	/* Set up basic I/O (BAR mappings etc) */  	rc = efx_init_io(efx); @@ -2510,7 +2495,7 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,  		cancel_work_sync(&efx->reset_work);  		if (rc == 0) { -			if (efx->reset_pending != RESET_TYPE_NONE) { +			if (efx->reset_pending) {  				/* If there was a scheduled reset during  				 * probe, the NIC is probably hosed anyway */  				efx_pci_remove_main(efx); @@ -2521,11 +2506,12 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,  		}  		/* Retry if a recoverably reset event has been scheduled */ -		if ((efx->reset_pending != RESET_TYPE_INVISIBLE) && -		    (efx->reset_pending != RESET_TYPE_ALL)) +		if (efx->reset_pending & +		    ~(1 << RESET_TYPE_INVISIBLE | 1 << RESET_TYPE_ALL) || +		    !efx->reset_pending)  			goto fail3; -		efx->reset_pending = RESET_TYPE_NONE; +		efx->reset_pending = 0;  	}  	if (rc) { @@ -2609,7 +2595,7 @@ static int efx_pm_poweroff(struct device *dev)  	efx->type->fini(efx); -	efx->reset_pending = RESET_TYPE_NONE; +	efx->reset_pending = 0;  	pci_save_state(pci_dev);  	return pci_set_power_state(pci_dev, PCI_D3hot);  | 
