/* Restart special buffer allocation */
efx->next_buffer_table = 0;
- efx_for_each_channel(channel, efx) {
+ /* Probe channels in reverse, so that any 'extra' channels
+ * use the start of the buffer table. This allows the traffic
+ * channels to be resized without moving them or wasting the
+ * entries before them.
+ */
+ efx_for_each_channel_rev(channel, efx) {
rc = efx_probe_channel(channel);
if (rc) {
netif_err(efx, probe, efx->net_dev,
unsigned int count;
int cpu;
- if (rss_cpus)
- return rss_cpus;
+ if (rss_cpus) {
+ count = rss_cpus;
+ } else {
+ if (unlikely(!zalloc_cpumask_var(&thread_mask, GFP_KERNEL))) {
+ netif_warn(efx, probe, efx->net_dev,
+ "RSS disabled due to allocation failure\n");
+ return 1;
+ }
- if (unlikely(!zalloc_cpumask_var(&thread_mask, GFP_KERNEL))) {
- netif_warn(efx, probe, efx->net_dev,
- "RSS disabled due to allocation failure\n");
- return 1;
+ count = 0;
+ for_each_online_cpu(cpu) {
+ if (!cpumask_test_cpu(cpu, thread_mask)) {
+ ++count;
+ cpumask_or(thread_mask, thread_mask,
+ topology_thread_cpumask(cpu));
+ }
+ }
+
+ free_cpumask_var(thread_mask);
}
- count = 0;
- for_each_online_cpu(cpu) {
- if (!cpumask_test_cpu(cpu, thread_mask)) {
- ++count;
- cpumask_or(thread_mask, thread_mask,
- topology_thread_cpumask(cpu));
- }
+ /* If RSS is requested for the PF *and* VFs then we can't write RSS
+ * table entries that are inaccessible to VFs
+ */
+ if (efx_sriov_wanted(efx) && efx_vf_size(efx) > 1 &&
+ count > efx_vf_size(efx)) {
+ netif_warn(efx, probe, efx->net_dev,
+ "Reducing number of RSS channels from %u to %u for "
+ "VF support. Increase vf-msix-limit to use more "
+ "channels on the PF.\n",
+ count, efx_vf_size(efx));
+ count = efx_vf_size(efx);
}
- free_cpumask_var(thread_mask);
return count;
}
}
}
+ /* RSS might be usable on VFs even if it is disabled on the PF */
+ efx->rss_spread = (efx->n_rx_channels > 1 ?
+ efx->n_rx_channels : efx_vf_size(efx));
+
return 0;
}
if (rc)
goto fail;
+ efx->type->dimension_resources(efx);
+
if (efx->n_channels > 1)
get_random_bytes(&efx->rx_hash_key, sizeof(efx->rx_hash_key));
for (i = 0; i < ARRAY_SIZE(efx->rx_indir_table); i++)
efx->rx_indir_table[i] =
- ethtool_rxfh_indir_default(i, efx->n_rx_channels);
+ ethtool_rxfh_indir_default(i, efx->rss_spread);
efx_set_channels(efx);
netif_set_real_num_tx_queues(efx->net_dev, efx->n_tx_channels);
netif_err(efx, drv, efx->net_dev,
"invalid ethernet MAC address requested: %pM\n",
new_addr);
- return -EINVAL;
+ return -EADDRNOTAVAIL;
}
memcpy(net_dev->dev_addr, new_addr, net_dev->addr_len);
+ efx_sriov_mac_address_changed(efx);
/* Reconfigure the MAC */
mutex_lock(&efx->mac_lock);
.ndo_set_mac_address = efx_set_mac_address,
.ndo_set_rx_mode = efx_set_rx_mode,
.ndo_set_features = efx_set_features,
+#ifdef CONFIG_SFC_SRIOV
+ .ndo_set_vf_mac = efx_sriov_set_vf_mac,
+ .ndo_set_vf_vlan = efx_sriov_set_vf_vlan,
+ .ndo_set_vf_spoofchk = efx_sriov_set_vf_spoofchk,
+ .ndo_get_vf_config = efx_sriov_get_vf_config,
+#endif
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = efx_netpoll,
#endif
efx_start_interrupts(efx, false);
efx_restore_filters(efx);
+ efx_sriov_reset(efx);
mutex_unlock(&efx->mac_lock);
rtnl_unlock();
efx_stop_interrupts(efx, false);
+ efx_sriov_fini(efx);
efx_unregister_netdev(efx);
efx_mtd_remove(efx);
if (rc)
goto fail4;
+ rc = efx_sriov_init(efx);
+ if (rc)
+ netif_err(efx, probe, efx->net_dev,
+ "SR-IOV can't be enabled rc %d\n", rc);
+
netif_dbg(efx, probe, efx->net_dev, "initialisation successful\n");
/* Try to create MTDs, but allow this to fail */
if (rc)
goto err_notifier;
+ rc = efx_init_sriov();
+ if (rc)
+ goto err_sriov;
+
reset_workqueue = create_singlethread_workqueue("sfc_reset");
if (!reset_workqueue) {
rc = -ENOMEM;
err_pci:
destroy_workqueue(reset_workqueue);
err_reset:
+ efx_fini_sriov();
+ err_sriov:
unregister_netdevice_notifier(&efx_netdev_notifier);
err_notifier:
return rc;
pci_unregister_driver(&efx_pci_driver);
destroy_workqueue(reset_workqueue);
+ efx_fini_sriov();
unregister_netdevice_notifier(&efx_netdev_notifier);
}