diff options
Diffstat (limited to 'drivers/net/sfc')
-rw-r--r-- | drivers/net/sfc/efx.c | 39 | ||||
-rw-r--r-- | drivers/net/sfc/falcon.c | 12 | ||||
-rw-r--r-- | drivers/net/sfc/net_driver.h | 5 |
3 files changed, 42 insertions, 14 deletions
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index 7b2015f9e46..45c72eebb3a 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c @@ -19,6 +19,7 @@ #include <linux/in.h> #include <linux/crc32.h> #include <linux/ethtool.h> +#include <linux/topology.h> #include "net_driver.h" #include "gmii.h" #include "ethtool.h" @@ -832,7 +833,23 @@ static void efx_probe_interrupts(struct efx_nic *efx) if (efx->interrupt_mode == EFX_INT_MODE_MSIX) { BUG_ON(!pci_find_capability(efx->pci_dev, PCI_CAP_ID_MSIX)); - efx->rss_queues = rss_cpus ? rss_cpus : num_online_cpus(); + if (rss_cpus == 0) { + cpumask_t core_mask; + int cpu; + + cpus_clear(core_mask); + efx->rss_queues = 0; + for_each_online_cpu(cpu) { + if (!cpu_isset(cpu, core_mask)) { + ++efx->rss_queues; + cpus_or(core_mask, core_mask, + topology_core_siblings(cpu)); + } + } + } else { + efx->rss_queues = rss_cpus; + } + efx->rss_queues = min(efx->rss_queues, max_channel + 1); efx->rss_queues = min(efx->rss_queues, EFX_MAX_CHANNELS); @@ -1762,7 +1779,7 @@ void efx_schedule_reset(struct efx_nic *efx, enum reset_type type) efx->reset_pending = method; - queue_work(efx->workqueue, &efx->reset_work); + queue_work(efx->reset_workqueue, &efx->reset_work); } /************************************************************************** @@ -1907,14 +1924,28 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type, goto fail1; } + efx->reset_workqueue = create_singlethread_workqueue("sfc_reset"); + if (!efx->reset_workqueue) { + rc = -ENOMEM; + goto fail2; + } + return 0; + fail2: + destroy_workqueue(efx->workqueue); + efx->workqueue = NULL; + fail1: return rc; } static void efx_fini_struct(struct efx_nic *efx) { + if (efx->reset_workqueue) { + destroy_workqueue(efx->reset_workqueue); + efx->reset_workqueue = NULL; + } if (efx->workqueue) { destroy_workqueue(efx->workqueue); efx->workqueue = NULL; @@ -1977,7 +2008,7 @@ static void efx_pci_remove(struct pci_dev *pci_dev) * scheduled from this point because efx_stop_all() has been * called, we are no longer registered with driverlink, and * the net_device's have been removed. */ - flush_workqueue(efx->workqueue); + flush_workqueue(efx->reset_workqueue); efx_pci_remove_main(efx); @@ -2098,7 +2129,7 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev, * scheduled since efx_stop_all() has been called, and we * have not and never have been registered with either * the rtnetlink or driverlink layers. */ - cancel_work_sync(&efx->reset_work); + flush_workqueue(efx->reset_workqueue); /* Retry if a recoverably reset event has been scheduled */ if ((efx->reset_pending != RESET_TYPE_INVISIBLE) && diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index 630406e142e..9138ee5b7b7 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c @@ -223,13 +223,8 @@ static struct i2c_algo_bit_data falcon_i2c_bit_operations = { .getsda = falcon_getsda, .getscl = falcon_getscl, .udelay = 5, - /* - * This is the number of system clock ticks after which - * i2c-algo-bit gives up waiting for SCL to become high. - * It must be at least 2 since the first tick can happen - * immediately after it starts waiting. - */ - .timeout = 2, + /* Wait up to 50 ms for slave to let us pull SCL high */ + .timeout = DIV_ROUND_UP(HZ, 20), }; /************************************************************************** @@ -2479,12 +2474,11 @@ int falcon_probe_nic(struct efx_nic *efx) /* Initialise I2C adapter */ efx->i2c_adap.owner = THIS_MODULE; - efx->i2c_adap.class = I2C_CLASS_HWMON; nic_data->i2c_data = falcon_i2c_bit_operations; nic_data->i2c_data.data = efx; efx->i2c_adap.algo_data = &nic_data->i2c_data; efx->i2c_adap.dev.parent = &efx->pci_dev->dev; - strcpy(efx->i2c_adap.name, "SFC4000 GPIO"); + strlcpy(efx->i2c_adap.name, "SFC4000 GPIO", sizeof(efx->i2c_adap.name)); rc = i2c_bit_add_bus(&efx->i2c_adap); if (rc) goto fail5; diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index d803b86c647..219c74a772c 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h @@ -616,7 +616,9 @@ union efx_multicast_hash { * @pci_dev: The PCI device * @type: Controller type attributes * @legacy_irq: IRQ number - * @workqueue: Workqueue for resets, port reconfigures and the HW monitor + * @workqueue: Workqueue for port reconfigures and the HW monitor. + * Work items do not hold and must not acquire RTNL. + * @reset_workqueue: Workqueue for resets. Work item will acquire RTNL. * @reset_work: Scheduled reset workitem * @monitor_work: Hardware monitor workitem * @membase_phys: Memory BAR value as physical address @@ -684,6 +686,7 @@ struct efx_nic { const struct efx_nic_type *type; int legacy_irq; struct workqueue_struct *workqueue; + struct workqueue_struct *reset_workqueue; struct work_struct reset_work; struct delayed_work monitor_work; resource_size_t membase_phys; |