summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSivakumar Subramani <sivakumar.subramani@neterion.com>2007-09-15 23:24:03 +0200
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-11 01:51:10 +0200
commit596c5c97431eab8465739c169401ea611127b9ad (patch)
tree97e1316dc08c452104631c25eb879ba496181e13
parentS2io: Check for device state before handling traffic (diff)
downloadlinux-596c5c97431eab8465739c169401ea611127b9ad.tar.xz
linux-596c5c97431eab8465739c169401ea611127b9ad.zip
S2io: code Optimization of isr function
- Code Optimization of s2io_isr function. - Isr check using per device napi variable instead of driver global. - Reduced from 3 to 1 if condition before check for processing packet receive packets. - Implemented Jeff's comment to use synchronize_irq. Removed the isr_cnt variable as it became redundant. - One time de assert the interrupts by writing all F's to the general_int_mask register instead of de asserting by clearing the source of interrupts with multiple writes which causes loss of interrupts (race conditions). It is entirely possible that before the driver has a chance to mask the asserted alarm bit, another alarm/traffic interrupt bit gets asserted as well. In this case Herc will keep the INTA line asserted and the bridge will not send a new Assert_INTA message upstream. [ Resolved conflicts due to napi_struct changes... -DaveM ] Signed-off-by: Sivakumar Subramani <sivakumar.subramani@neterion.com> Signed-off-by: Santosh Rastapur <santosh.rastapur@neterion.com> Signed-off-by: Ramkrishna Vepa <ram.vepa@neterion.com> Signed-off-by: Jeff Garzik <jeff@garzik.org> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/s2io.c157
-rw-r--r--drivers/net/s2io.h1
2 files changed, 61 insertions, 97 deletions
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index d167bc0ae951..ac6b9b93c025 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -84,7 +84,7 @@
#include "s2io.h"
#include "s2io-regs.h"
-#define DRV_VERSION "2.0.26.1"
+#define DRV_VERSION "2.0.26.2"
/* S2io Driver name & version. */
static char s2io_driver_name[] = "Neterion";
@@ -2715,12 +2715,8 @@ static int s2io_poll(struct napi_struct *napi, int budget)
struct XENA_dev_config __iomem *bar0 = nic->bar0;
int i;
- atomic_inc(&nic->isr_cnt);
-
- if (!is_s2io_card_up(nic)) {
- atomic_dec(&nic->isr_cnt);
+ if (!is_s2io_card_up(nic))
return 0;
- }
mac_control = &nic->mac_control;
config = &nic->config;
@@ -2752,7 +2748,6 @@ static int s2io_poll(struct napi_struct *napi, int budget)
/* Re enable the Rx interrupts. */
writeq(0x0, &bar0->rx_traffic_mask);
readl(&bar0->rx_traffic_mask);
- atomic_dec(&nic->isr_cnt);
return pkt_cnt;
no_rx:
@@ -2763,7 +2758,6 @@ no_rx:
break;
}
}
- atomic_dec(&nic->isr_cnt);
return pkt_cnt;
}
@@ -2791,7 +2785,6 @@ static void s2io_netpoll(struct net_device *dev)
disable_irq(dev->irq);
- atomic_inc(&nic->isr_cnt);
mac_control = &nic->mac_control;
config = &nic->config;
@@ -2816,7 +2809,6 @@ static void s2io_netpoll(struct net_device *dev)
break;
}
}
- atomic_dec(&nic->isr_cnt);
enable_irq(dev->irq);
return;
}
@@ -4187,17 +4179,12 @@ static irqreturn_t s2io_msix_ring_handle(int irq, void *dev_id)
struct ring_info *ring = (struct ring_info *)dev_id;
struct s2io_nic *sp = ring->nic;
- atomic_inc(&sp->isr_cnt);
-
- if (!is_s2io_card_up(sp)) {
- atomic_dec(&sp->isr_cnt);
+ if (!is_s2io_card_up(sp))
return IRQ_HANDLED;
- }
rx_intr_handler(ring);
s2io_chk_rx_buffers(sp, ring->ring_no);
- atomic_dec(&sp->isr_cnt);
return IRQ_HANDLED;
}
@@ -4206,15 +4193,10 @@ static irqreturn_t s2io_msix_fifo_handle(int irq, void *dev_id)
struct fifo_info *fifo = (struct fifo_info *)dev_id;
struct s2io_nic *sp = fifo->nic;
- atomic_inc(&sp->isr_cnt);
-
- if (!is_s2io_card_up(sp)) {
- atomic_dec(&sp->isr_cnt);
+ if (!is_s2io_card_up(sp))
return IRQ_HANDLED;
- }
tx_intr_handler(fifo);
- atomic_dec(&sp->isr_cnt);
return IRQ_HANDLED;
}
static void s2io_txpic_intr_handle(struct s2io_nic *sp)
@@ -4591,12 +4573,8 @@ static irqreturn_t s2io_isr(int irq, void *dev_id)
if (pci_channel_offline(sp->pdev))
return IRQ_NONE;
- atomic_inc(&sp->isr_cnt);
-
- if (!is_s2io_card_up(sp)) {
- atomic_dec(&sp->isr_cnt);
+ if (!is_s2io_card_up(sp))
return IRQ_NONE;
- }
mac_control = &sp->mac_control;
config = &sp->config;
@@ -4607,73 +4585,75 @@ static irqreturn_t s2io_isr(int irq, void *dev_id)
* 1. Rx of packet.
* 2. Tx complete.
* 3. Link down.
- * 4. Error in any functional blocks of the NIC.
*/
reason = readq(&bar0->general_int_status);
- if (!reason) {
- /* The interrupt was not raised by us. */
- atomic_dec(&sp->isr_cnt);
- return IRQ_NONE;
- }
- else if (unlikely(reason == S2IO_MINUS_ONE) ) {
- /* Disable device and get out */
- atomic_dec(&sp->isr_cnt);
- return IRQ_NONE;
+ if (unlikely(reason == S2IO_MINUS_ONE) ) {
+ /* Nothing much can be done. Get out */
+ return IRQ_HANDLED;
}
- if (napi) {
- if (reason & GEN_INTR_RXTRAFFIC) {
- if (likely (netif_rx_schedule_prep(dev, &sp->napi))) {
- __netif_rx_schedule(dev, &sp->napi);
- writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_mask);
+ if (reason & (GEN_INTR_RXTRAFFIC |
+ GEN_INTR_TXTRAFFIC | GEN_INTR_TXPIC))
+ {
+ writeq(S2IO_MINUS_ONE, &bar0->general_int_mask);
+
+ if (config->napi) {
+ if (reason & GEN_INTR_RXTRAFFIC) {
+ if (likely(netif_rx_schedule_prep(dev,
+ &sp->napi))) {
+ __netif_rx_schedule(dev, &sp->napi);
+ writeq(S2IO_MINUS_ONE,
+ &bar0->rx_traffic_mask);
+ } else
+ writeq(S2IO_MINUS_ONE,
+ &bar0->rx_traffic_int);
}
- else
+ } else {
+ /*
+ * rx_traffic_int reg is an R1 register, writing all 1's
+ * will ensure that the actual interrupt causing bit
+ * get's cleared and hence a read can be avoided.
+ */
+ if (reason & GEN_INTR_RXTRAFFIC)
writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_int);
+
+ for (i = 0; i < config->rx_ring_num; i++)
+ rx_intr_handler(&mac_control->rings[i]);
}
- } else {
+
/*
- * Rx handler is called by default, without checking for the
- * cause of interrupt.
- * rx_traffic_int reg is an R1 register, writing all 1's
+ * tx_traffic_int reg is an R1 register, writing all 1's
* will ensure that the actual interrupt causing bit get's
* cleared and hence a read can be avoided.
*/
- if (reason & GEN_INTR_RXTRAFFIC)
- writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_int);
+ if (reason & GEN_INTR_TXTRAFFIC)
+ writeq(S2IO_MINUS_ONE, &bar0->tx_traffic_int);
- for (i = 0; i < config->rx_ring_num; i++) {
- rx_intr_handler(&mac_control->rings[i]);
- }
- }
+ for (i = 0; i < config->tx_fifo_num; i++)
+ tx_intr_handler(&mac_control->fifos[i]);
- /*
- * tx_traffic_int reg is an R1 register, writing all 1's
- * will ensure that the actual interrupt causing bit get's
- * cleared and hence a read can be avoided.
- */
- if (reason & GEN_INTR_TXTRAFFIC)
- writeq(S2IO_MINUS_ONE, &bar0->tx_traffic_int);
+ if (reason & GEN_INTR_TXPIC)
+ s2io_txpic_intr_handle(sp);
- for (i = 0; i < config->tx_fifo_num; i++)
- tx_intr_handler(&mac_control->fifos[i]);
+ /*
+ * Reallocate the buffers from the interrupt handler itself.
+ */
+ if (!config->napi) {
+ for (i = 0; i < config->rx_ring_num; i++)
+ s2io_chk_rx_buffers(sp, i);
+ }
+ writeq(sp->general_int_mask, &bar0->general_int_mask);
+ readl(&bar0->general_int_status);
- if (reason & GEN_INTR_TXPIC)
- s2io_txpic_intr_handle(sp);
- /*
- * If the Rx buffer count is below the panic threshold then
- * reallocate the buffers from the interrupt handler itself,
- * else schedule a tasklet to reallocate the buffers.
- */
- if (!napi) {
- for (i = 0; i < config->rx_ring_num; i++)
- s2io_chk_rx_buffers(sp, i);
- }
+ return IRQ_HANDLED;
- writeq(0, &bar0->general_int_mask);
- readl(&bar0->general_int_status);
+ }
+ else if (!reason) {
+ /* The interrupt was not raised by us */
+ return IRQ_NONE;
+ }
- atomic_dec(&sp->isr_cnt);
return IRQ_HANDLED;
}
@@ -6795,7 +6775,6 @@ static int s2io_add_isr(struct s2io_nic * sp)
}
static void s2io_rem_isr(struct s2io_nic * sp)
{
- int cnt = 0;
struct net_device *dev = sp->dev;
struct swStat *stats = &sp->mac_control.stats_info->sw_stat;
@@ -6808,6 +6787,7 @@ static void s2io_rem_isr(struct s2io_nic * sp)
int vector = sp->entries[i].vector;
void *arg = sp->s2io_entries[i].arg;
+ synchronize_irq(vector);
free_irq(vector, arg);
}
@@ -6826,16 +6806,9 @@ static void s2io_rem_isr(struct s2io_nic * sp)
pci_disable_msix(sp->pdev);
} else {
+ synchronize_irq(sp->pdev->irq);
free_irq(sp->pdev->irq, dev);
}
- /* Waiting till all Interrupt handlers are complete */
- cnt = 0;
- do {
- msleep(10);
- if (!atomic_read(&sp->isr_cnt))
- break;
- cnt++;
- } while(cnt < 5);
}
static void do_s2io_card_down(struct s2io_nic * sp, int do_io)
@@ -7365,19 +7338,12 @@ static int s2io_verify_parm(struct pci_dev *pdev, u8 *dev_intr_type)
if (*dev_intr_type != INTA)
napi = 0;
-#ifndef CONFIG_PCI_MSI
- if (*dev_intr_type != INTA) {
- DBG_PRINT(ERR_DBG, "s2io: This kernel does not support"
- "MSI/MSI-X. Defaulting to INTA\n");
- *dev_intr_type = INTA;
- }
-#else
if ((*dev_intr_type != INTA) && (*dev_intr_type != MSI_X)) {
DBG_PRINT(ERR_DBG, "s2io: Wrong intr_type requested. "
"Defaulting to INTA\n");
*dev_intr_type = INTA;
}
-#endif
+
if ((*dev_intr_type == MSI_X) &&
((pdev->device != PCI_DEVICE_ID_HERC_WIN) &&
(pdev->device != PCI_DEVICE_ID_HERC_UNI))) {
@@ -7535,6 +7501,8 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
mac_control = &sp->mac_control;
config = &sp->config;
+ config->napi = napi;
+
/* Tx side parameters. */
config->tx_fifo_num = tx_fifo_num;
for (i = 0; i < MAX_TX_FIFOS; i++) {
@@ -7582,9 +7550,6 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
for (i = 0; i < config->rx_ring_num; i++)
atomic_set(&sp->rx_bufs_left[i], 0);
- /* Initialize the number of ISRs currently running */
- atomic_set(&sp->isr_cnt, 0);
-
/* initialize the shared memory used by the NIC and the host */
if (init_shared_mem(sp)) {
DBG_PRINT(ERR_DBG, "%s: Memory allocation failed\n",
diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h
index 33e812ea7d18..1a70cf02c915 100644
--- a/drivers/net/s2io.h
+++ b/drivers/net/s2io.h
@@ -911,7 +911,6 @@ struct s2io_nic {
u16 lro_max_aggr_per_sess;
volatile unsigned long state;
spinlock_t rx_lock;
- atomic_t isr_cnt;
u64 general_int_mask;
u64 *ufo_in_band_v;
#define VPD_STRING_LEN 80