diff options
Diffstat (limited to 'drivers/net/sfc/efx.c')
| -rw-r--r-- | drivers/net/sfc/efx.c | 53 | 
1 files changed, 39 insertions, 14 deletions
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index d890679e4c4..c914729f955 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c @@ -328,7 +328,8 @@ static int efx_poll(struct napi_struct *napi, int budget)   * processing to finish, then directly poll (and ack ) the eventq.   * Finally reenable NAPI and interrupts.   * - * Since we are touching interrupts the caller should hold the suspend lock + * This is for use only during a loopback self-test.  It must not + * deliver any packets up the stack as this can result in deadlock.   */  void efx_process_channel_now(struct efx_channel *channel)  { @@ -336,6 +337,7 @@ void efx_process_channel_now(struct efx_channel *channel)  	BUG_ON(channel->channel >= efx->n_channels);  	BUG_ON(!channel->enabled); +	BUG_ON(!efx->loopback_selftest);  	/* Disable interrupts and wait for ISRs to complete */  	efx_nic_disable_interrupts(efx); @@ -796,11 +798,6 @@ void efx_link_status_changed(struct efx_nic *efx)  	if (!netif_running(efx->net_dev))  		return; -	if (efx->port_inhibited) { -		netif_carrier_off(efx->net_dev); -		return; -	} -  	if (link_state->up != netif_carrier_ok(efx->net_dev)) {  		efx->n_link_state_changes++; @@ -836,7 +833,7 @@ void efx_link_set_advertising(struct efx_nic *efx, u32 advertising)  	}  } -void efx_link_set_wanted_fc(struct efx_nic *efx, enum efx_fc_type wanted_fc) +void efx_link_set_wanted_fc(struct efx_nic *efx, u8 wanted_fc)  {  	efx->wanted_fc = wanted_fc;  	if (efx->link_advertising) { @@ -1317,8 +1314,20 @@ static void efx_remove_interrupts(struct efx_nic *efx)  static void efx_set_channels(struct efx_nic *efx)  { +	struct efx_channel *channel; +	struct efx_tx_queue *tx_queue; +  	efx->tx_channel_offset =  		separate_tx_channels ? efx->n_channels - efx->n_tx_channels : 0; + +	/* We need to adjust the TX queue numbers if we have separate +	 * RX-only and TX-only channels. +	 */ +	efx_for_each_channel(channel, efx) { +		efx_for_each_channel_tx_queue(tx_queue, channel) +			tx_queue->queue -= (efx->tx_channel_offset * +					    EFX_TXQ_TYPES); +	}  }  static int efx_probe_nic(struct efx_nic *efx) @@ -1436,7 +1445,7 @@ static void efx_start_all(struct efx_nic *efx)  	 * restart the transmit interface early so the watchdog timer stops */  	efx_start_port(efx); -	if (efx_dev_registered(efx)) +	if (efx_dev_registered(efx) && netif_device_present(efx->net_dev))  		netif_tx_wake_all_queues(efx->net_dev);  	efx_for_each_channel(channel, efx) @@ -1874,6 +1883,17 @@ static void efx_set_multicast_list(struct net_device *net_dev)  	/* Otherwise efx_start_port() will do this */  } +static int efx_set_features(struct net_device *net_dev, u32 data) +{ +	struct efx_nic *efx = netdev_priv(net_dev); + +	/* If disabling RX n-tuple filtering, clear existing filters */ +	if (net_dev->features & ~data & NETIF_F_NTUPLE) +		efx_filter_clear_rx(efx, EFX_FILTER_PRI_MANUAL); + +	return 0; +} +  static const struct net_device_ops efx_netdev_ops = {  	.ndo_open		= efx_net_open,  	.ndo_stop		= efx_net_stop, @@ -1885,6 +1905,7 @@ static const struct net_device_ops efx_netdev_ops = {  	.ndo_change_mtu		= efx_change_mtu,  	.ndo_set_mac_address	= efx_set_mac_address,  	.ndo_set_multicast_list = efx_set_multicast_list, +	.ndo_set_features	= efx_set_features,  #ifdef CONFIG_NET_POLL_CONTROLLER  	.ndo_poll_controller = efx_netpoll,  #endif @@ -2088,6 +2109,7 @@ int efx_reset(struct efx_nic *efx, enum reset_type method)  	netif_info(efx, drv, efx->net_dev, "resetting (%s)\n",  		   RESET_TYPE(method)); +	netif_device_detach(efx->net_dev);  	efx_reset_down(efx, method);  	rc = efx->type->reset(efx, method); @@ -2121,6 +2143,7 @@ out:  		efx->state = STATE_DISABLED;  	} else {  		netif_dbg(efx, drv, efx->net_dev, "reset complete\n"); +		netif_device_attach(efx->net_dev);  	}  	return rc;  } @@ -2233,7 +2256,7 @@ static bool efx_port_dummy_op_poll(struct efx_nic *efx)  	return false;  } -static struct efx_phy_operations efx_dummy_phy_operations = { +static const struct efx_phy_operations efx_dummy_phy_operations = {  	.init		 = efx_port_dummy_op_int,  	.reconfigure	 = efx_port_dummy_op_int,  	.poll		 = efx_port_dummy_op_poll, @@ -2249,7 +2272,7 @@ static struct efx_phy_operations efx_dummy_phy_operations = {  /* This zeroes out and then fills in the invariants in a struct   * efx_nic (including all sub-structures).   */ -static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type, +static int efx_init_struct(struct efx_nic *efx, const struct efx_nic_type *type,  			   struct pci_dev *pci_dev, struct net_device *net_dev)  {  	int i; @@ -2269,7 +2292,6 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,  	strlcpy(efx->name, pci_name(pci_dev), sizeof(efx->name));  	efx->net_dev = net_dev; -	efx->rx_checksum_enabled = true;  	spin_lock_init(&efx->stats_lock);  	mutex_init(&efx->mac_lock);  	efx->mac_op = type->default_mac_ops; @@ -2440,7 +2462,7 @@ static int efx_pci_probe_main(struct efx_nic *efx)  static int __devinit efx_pci_probe(struct pci_dev *pci_dev,  				   const struct pci_device_id *entry)  { -	struct efx_nic_type *type = (struct efx_nic_type *) entry->driver_data; +	const struct efx_nic_type *type = (const struct efx_nic_type *) entry->driver_data;  	struct net_device *net_dev;  	struct efx_nic *efx;  	int i, rc; @@ -2452,12 +2474,15 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,  		return -ENOMEM;  	net_dev->features |= (type->offload_features | NETIF_F_SG |  			      NETIF_F_HIGHDMA | NETIF_F_TSO | -			      NETIF_F_GRO); +			      NETIF_F_RXCSUM);  	if (type->offload_features & NETIF_F_V6_CSUM)  		net_dev->features |= NETIF_F_TSO6;  	/* Mask for features that also apply to VLAN devices */  	net_dev->vlan_features |= (NETIF_F_ALL_CSUM | NETIF_F_SG | -				   NETIF_F_HIGHDMA | NETIF_F_TSO); +				   NETIF_F_HIGHDMA | NETIF_F_ALL_TSO | +				   NETIF_F_RXCSUM); +	/* All offloads can be toggled */ +	net_dev->hw_features = net_dev->features & ~NETIF_F_HIGHDMA;  	efx = netdev_priv(net_dev);  	pci_set_drvdata(pci_dev, efx);  	SET_NETDEV_DEV(net_dev, &pci_dev->dev);  |