summaryrefslogtreecommitdiffstats
path: root/drivers/net/netxen/netxen_nic_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/netxen/netxen_nic_main.c')
-rw-r--r--drivers/net/netxen/netxen_nic_main.c157
1 files changed, 118 insertions, 39 deletions
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index 00eaeee235e..274d1e0c893 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -135,20 +135,71 @@ static uint32_t msi_tgt_status[8] = {
static struct netxen_legacy_intr_set legacy_intr[] = NX_LEGACY_INTR_CONFIG;
-static inline void netxen_nic_disable_int(struct netxen_adapter *adapter)
+static inline void netxen_nic_disable_int(struct nx_host_sds_ring *sds_ring)
{
- adapter->pci_write_normalize(adapter, adapter->crb_intr_mask, 0);
+ struct netxen_adapter *adapter = sds_ring->adapter;
+
+ adapter->pci_write_normalize(adapter, sds_ring->crb_intr_mask, 0);
}
-static inline void netxen_nic_enable_int(struct netxen_adapter *adapter)
+static inline void netxen_nic_enable_int(struct nx_host_sds_ring *sds_ring)
{
- adapter->pci_write_normalize(adapter, adapter->crb_intr_mask, 0x1);
+ struct netxen_adapter *adapter = sds_ring->adapter;
+
+ adapter->pci_write_normalize(adapter, sds_ring->crb_intr_mask, 0x1);
if (!NETXEN_IS_MSI_FAMILY(adapter))
adapter->pci_write_immediate(adapter,
adapter->legacy_intr.tgt_mask_reg, 0xfbff);
}
+static void
+netxen_napi_add(struct netxen_adapter *adapter, struct net_device *netdev)
+{
+ int ring;
+ struct nx_host_sds_ring *sds_ring;
+ struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
+
+ if (adapter->flags & NETXEN_NIC_MSIX_ENABLED)
+ adapter->max_sds_rings = (num_online_cpus() >= 4) ? 4 : 2;
+ else
+ adapter->max_sds_rings = 1;
+
+ for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+ sds_ring = &recv_ctx->sds_rings[ring];
+ netif_napi_add(netdev, &sds_ring->napi,
+ netxen_nic_poll, NETXEN_NETDEV_WEIGHT);
+ }
+}
+
+static void
+netxen_napi_enable(struct netxen_adapter *adapter)
+{
+ int ring;
+ struct nx_host_sds_ring *sds_ring;
+ struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
+
+ for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+ sds_ring = &recv_ctx->sds_rings[ring];
+ napi_enable(&sds_ring->napi);
+ netxen_nic_enable_int(sds_ring);
+ }
+}
+
+static void
+netxen_napi_disable(struct netxen_adapter *adapter)
+{
+ int ring;
+ struct nx_host_sds_ring *sds_ring;
+ struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
+
+ for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+ sds_ring = &recv_ctx->sds_rings[ring];
+ netxen_nic_disable_int(sds_ring);
+ napi_disable(&sds_ring->napi);
+ }
+}
+
static int nx_set_dma_mask(struct netxen_adapter *adapter, uint8_t revision_id)
{
struct pci_dev *pdev = adapter->pdev;
@@ -226,7 +277,6 @@ static void netxen_check_options(struct netxen_adapter *adapter)
adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS;
adapter->num_lro_rxd = MAX_LRO_RCV_DESCRIPTORS;
- adapter->max_possible_rss_rings = 1;
return;
}
@@ -447,6 +497,7 @@ request_msi:
dev_info(&pdev->dev, "using msi interrupts\n");
} else
dev_info(&pdev->dev, "using legacy interrupts\n");
+ adapter->msix_entries[0].vector = pdev->irq;
}
}
@@ -671,8 +722,12 @@ static int
netxen_nic_request_irq(struct netxen_adapter *adapter)
{
irq_handler_t handler;
+ struct nx_host_sds_ring *sds_ring;
+ int err, ring;
+
unsigned long flags = IRQF_SAMPLE_RANDOM;
struct net_device *netdev = adapter->netdev;
+ struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
if ((adapter->msi_mode != MSI_MODE_MULTIFUNC) ||
(adapter->intr_scheme != INTR_SCHEME_PERPORT)) {
@@ -693,8 +748,30 @@ netxen_nic_request_irq(struct netxen_adapter *adapter)
}
adapter->irq = netdev->irq;
- return request_irq(adapter->irq, handler,
- flags, netdev->name, adapter);
+ for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+ sds_ring = &recv_ctx->sds_rings[ring];
+ sprintf(sds_ring->name, "%16s[%d]", netdev->name, ring);
+ err = request_irq(sds_ring->irq, handler,
+ flags, sds_ring->name, sds_ring);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+static void
+netxen_nic_free_irq(struct netxen_adapter *adapter)
+{
+ int ring;
+ struct nx_host_sds_ring *sds_ring;
+
+ struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
+
+ for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+ sds_ring = &recv_ctx->sds_rings[ring];
+ free_irq(sds_ring->irq, sds_ring);
+ }
}
static int
@@ -719,8 +796,10 @@ netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev)
adapter->ahw.linkup = 0;
mod_timer(&adapter->watchdog_timer, jiffies);
- napi_enable(&adapter->napi);
- netxen_nic_enable_int(adapter);
+ netxen_napi_enable(adapter);
+
+ if (adapter->max_sds_rings > 1)
+ netxen_config_rss(adapter, 1);
return 0;
}
@@ -730,13 +809,11 @@ netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev)
{
netif_carrier_off(netdev);
netif_stop_queue(netdev);
- napi_disable(&adapter->napi);
+ netxen_napi_disable(adapter);
if (adapter->stop_port)
adapter->stop_port(adapter);
- netxen_nic_disable_int(adapter);
-
netxen_release_tx_buffers(adapter);
FLUSH_SCHEDULED_WORK();
@@ -750,6 +827,7 @@ netxen_nic_attach(struct netxen_adapter *adapter)
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
int err, ring;
+ struct nx_host_rds_ring *rds_ring;
err = netxen_init_firmware(adapter);
if (err != 0) {
@@ -788,8 +866,10 @@ netxen_nic_attach(struct netxen_adapter *adapter)
netxen_nic_update_cmd_consumer(adapter, 0);
}
- for (ring = 0; ring < adapter->max_rds_rings; ring++)
- netxen_post_rx_buffers(adapter, ring);
+ for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+ rds_ring = &adapter->recv_ctx.rds_rings[ring];
+ netxen_post_rx_buffers(adapter, ring, rds_ring);
+ }
err = netxen_nic_request_irq(adapter);
if (err) {
@@ -812,8 +892,7 @@ err_out_free_sw:
static void
netxen_nic_detach(struct netxen_adapter *adapter)
{
- if (adapter->irq)
- free_irq(adapter->irq, adapter);
+ netxen_nic_free_irq(adapter);
netxen_release_rx_buffers(adapter);
netxen_free_hw_resources(adapter);
@@ -883,14 +962,12 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out_free_netdev;
rwlock_init(&adapter->adapter_lock);
+ spin_lock_init(&adapter->tx_clean_lock);
err = netxen_setup_pci_map(adapter);
if (err)
goto err_out_free_netdev;
- netif_napi_add(netdev, &adapter->napi,
- netxen_nic_poll, NETXEN_NETDEV_WEIGHT);
-
/* This will be reset for mezz cards */
adapter->portnum = pci_func_id;
adapter->rx_csum = 1;
@@ -963,10 +1040,9 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netxen_setup_intr(adapter);
- if (adapter->flags & NETXEN_NIC_MSIX_ENABLED)
- netdev->irq = adapter->msix_entries[0].vector;
- else
- netdev->irq = pdev->irq;
+ netdev->irq = adapter->msix_entries[0].vector;
+
+ netxen_napi_add(adapter, netdev);
err = netxen_receive_peg_ready(adapter);
if (err)
@@ -1520,13 +1596,11 @@ static void netxen_tx_timeout_task(struct work_struct *work)
printk(KERN_ERR "%s %s: transmit timeout, resetting.\n",
netxen_nic_driver_name, adapter->netdev->name);
- netxen_nic_disable_int(adapter);
- napi_disable(&adapter->napi);
+ netxen_napi_disable(adapter);
adapter->netdev->trans_start = jiffies;
- napi_enable(&adapter->napi);
- netxen_nic_enable_int(adapter);
+ netxen_napi_enable(adapter);
netif_wake_queue(adapter->netdev);
}
@@ -1564,7 +1638,8 @@ struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev)
static irqreturn_t netxen_intr(int irq, void *data)
{
- struct netxen_adapter *adapter = data;
+ struct nx_host_sds_ring *sds_ring = data;
+ struct netxen_adapter *adapter = sds_ring->adapter;
u32 status = 0;
status = adapter->pci_read_immediate(adapter, ISR_INT_VECTOR);
@@ -1595,7 +1670,7 @@ static irqreturn_t netxen_intr(int irq, void *data)
/* clear interrupt */
if (adapter->fw_major < 4)
- netxen_nic_disable_int(adapter);
+ netxen_nic_disable_int(sds_ring);
adapter->pci_write_immediate(adapter,
adapter->legacy_intr.tgt_status_reg,
@@ -1604,45 +1679,49 @@ static irqreturn_t netxen_intr(int irq, void *data)
adapter->pci_read_immediate(adapter, ISR_INT_VECTOR);
adapter->pci_read_immediate(adapter, ISR_INT_VECTOR);
- napi_schedule(&adapter->napi);
+ napi_schedule(&sds_ring->napi);
return IRQ_HANDLED;
}
static irqreturn_t netxen_msi_intr(int irq, void *data)
{
- struct netxen_adapter *adapter = data;
+ struct nx_host_sds_ring *sds_ring = data;
+ struct netxen_adapter *adapter = sds_ring->adapter;
/* clear interrupt */
adapter->pci_write_immediate(adapter,
msi_tgt_status[adapter->ahw.pci_func], 0xffffffff);
- napi_schedule(&adapter->napi);
+ napi_schedule(&sds_ring->napi);
return IRQ_HANDLED;
}
static irqreturn_t netxen_msix_intr(int irq, void *data)
{
- struct netxen_adapter *adapter = data;
+ struct nx_host_sds_ring *sds_ring = data;
- napi_schedule(&adapter->napi);
+ napi_schedule(&sds_ring->napi);
return IRQ_HANDLED;
}
static int netxen_nic_poll(struct napi_struct *napi, int budget)
{
- struct netxen_adapter *adapter =
- container_of(napi, struct netxen_adapter, napi);
+ struct nx_host_sds_ring *sds_ring =
+ container_of(napi, struct nx_host_sds_ring, napi);
+
+ struct netxen_adapter *adapter = sds_ring->adapter;
+
int tx_complete;
int work_done;
tx_complete = netxen_process_cmd_ring(adapter);
- work_done = netxen_process_rcv_ring(adapter, budget);
+ work_done = netxen_process_rcv_ring(sds_ring, budget);
if ((work_done < budget) && tx_complete) {
- napi_complete(&adapter->napi);
- netxen_nic_enable_int(adapter);
+ napi_complete(&sds_ring->napi);
+ netxen_nic_enable_int(sds_ring);
}
return work_done;