aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSivakumar Subramani <sivakumar.subramani@neterion.com>2007-09-15 17:24:03 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:51:10 -0400
commit596c5c97431eab8465739c169401ea611127b9ad (patch)
tree97e1316dc08c452104631c25eb879ba496181e13
parent92b84437a6cddf5dc00ab179e38d2baa2264d46a (diff)
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 @@
84#include "s2io.h" 84#include "s2io.h"
85#include "s2io-regs.h" 85#include "s2io-regs.h"
86 86
87#define DRV_VERSION "2.0.26.1" 87#define DRV_VERSION "2.0.26.2"
88 88
89/* S2io Driver name & version. */ 89/* S2io Driver name & version. */
90static char s2io_driver_name[] = "Neterion"; 90static char s2io_driver_name[] = "Neterion";
@@ -2715,12 +2715,8 @@ static int s2io_poll(struct napi_struct *napi, int budget)
2715 struct XENA_dev_config __iomem *bar0 = nic->bar0; 2715 struct XENA_dev_config __iomem *bar0 = nic->bar0;
2716 int i; 2716 int i;
2717 2717
2718 atomic_inc(&nic->isr_cnt); 2718 if (!is_s2io_card_up(nic))
2719
2720 if (!is_s2io_card_up(nic)) {
2721 atomic_dec(&nic->isr_cnt);
2722 return 0; 2719 return 0;
2723 }
2724 2720
2725 mac_control = &nic->mac_control; 2721 mac_control = &nic->mac_control;
2726 config = &nic->config; 2722 config = &nic->config;
@@ -2752,7 +2748,6 @@ static int s2io_poll(struct napi_struct *napi, int budget)
2752 /* Re enable the Rx interrupts. */ 2748 /* Re enable the Rx interrupts. */
2753 writeq(0x0, &bar0->rx_traffic_mask); 2749 writeq(0x0, &bar0->rx_traffic_mask);
2754 readl(&bar0->rx_traffic_mask); 2750 readl(&bar0->rx_traffic_mask);
2755 atomic_dec(&nic->isr_cnt);
2756 return pkt_cnt; 2751 return pkt_cnt;
2757 2752
2758no_rx: 2753no_rx:
@@ -2763,7 +2758,6 @@ no_rx:
2763 break; 2758 break;
2764 } 2759 }
2765 } 2760 }
2766 atomic_dec(&nic->isr_cnt);
2767 return pkt_cnt; 2761 return pkt_cnt;
2768} 2762}
2769 2763
@@ -2791,7 +2785,6 @@ static void s2io_netpoll(struct net_device *dev)
2791 2785
2792 disable_irq(dev->irq); 2786 disable_irq(dev->irq);
2793 2787
2794 atomic_inc(&nic->isr_cnt);
2795 mac_control = &nic->mac_control; 2788 mac_control = &nic->mac_control;
2796 config = &nic->config; 2789 config = &nic->config;
2797 2790
@@ -2816,7 +2809,6 @@ static void s2io_netpoll(struct net_device *dev)
2816 break; 2809 break;
2817 } 2810 }
2818 } 2811 }
2819 atomic_dec(&nic->isr_cnt);
2820 enable_irq(dev->irq); 2812 enable_irq(dev->irq);
2821 return; 2813 return;
2822} 2814}
@@ -4187,17 +4179,12 @@ static irqreturn_t s2io_msix_ring_handle(int irq, void *dev_id)
4187 struct ring_info *ring = (struct ring_info *)dev_id; 4179 struct ring_info *ring = (struct ring_info *)dev_id;
4188 struct s2io_nic *sp = ring->nic; 4180 struct s2io_nic *sp = ring->nic;
4189 4181
4190 atomic_inc(&sp->isr_cnt); 4182 if (!is_s2io_card_up(sp))
4191
4192 if (!is_s2io_card_up(sp)) {
4193 atomic_dec(&sp->isr_cnt);
4194 return IRQ_HANDLED; 4183 return IRQ_HANDLED;
4195 }
4196 4184
4197 rx_intr_handler(ring); 4185 rx_intr_handler(ring);
4198 s2io_chk_rx_buffers(sp, ring->ring_no); 4186 s2io_chk_rx_buffers(sp, ring->ring_no);
4199 4187
4200 atomic_dec(&sp->isr_cnt);
4201 return IRQ_HANDLED; 4188 return IRQ_HANDLED;
4202} 4189}
4203 4190
@@ -4206,15 +4193,10 @@ static irqreturn_t s2io_msix_fifo_handle(int irq, void *dev_id)
4206 struct fifo_info *fifo = (struct fifo_info *)dev_id; 4193 struct fifo_info *fifo = (struct fifo_info *)dev_id;
4207 struct s2io_nic *sp = fifo->nic; 4194 struct s2io_nic *sp = fifo->nic;
4208 4195
4209 atomic_inc(&sp->isr_cnt); 4196 if (!is_s2io_card_up(sp))
4210
4211 if (!is_s2io_card_up(sp)) {
4212 atomic_dec(&sp->isr_cnt);
4213 return IRQ_HANDLED; 4197 return IRQ_HANDLED;
4214 }
4215 4198
4216 tx_intr_handler(fifo); 4199 tx_intr_handler(fifo);
4217 atomic_dec(&sp->isr_cnt);
4218 return IRQ_HANDLED; 4200 return IRQ_HANDLED;
4219} 4201}
4220static void s2io_txpic_intr_handle(struct s2io_nic *sp) 4202static void s2io_txpic_intr_handle(struct s2io_nic *sp)
@@ -4591,12 +4573,8 @@ static irqreturn_t s2io_isr(int irq, void *dev_id)
4591 if (pci_channel_offline(sp->pdev)) 4573 if (pci_channel_offline(sp->pdev))
4592 return IRQ_NONE; 4574 return IRQ_NONE;
4593 4575
4594 atomic_inc(&sp->isr_cnt); 4576 if (!is_s2io_card_up(sp))
4595
4596 if (!is_s2io_card_up(sp)) {
4597 atomic_dec(&sp->isr_cnt);
4598 return IRQ_NONE; 4577 return IRQ_NONE;
4599 }
4600 4578
4601 mac_control = &sp->mac_control; 4579 mac_control = &sp->mac_control;
4602 config = &sp->config; 4580 config = &sp->config;
@@ -4607,73 +4585,75 @@ static irqreturn_t s2io_isr(int irq, void *dev_id)
4607 * 1. Rx of packet. 4585 * 1. Rx of packet.
4608 * 2. Tx complete. 4586 * 2. Tx complete.
4609 * 3. Link down. 4587 * 3. Link down.
4610 * 4. Error in any functional blocks of the NIC.
4611 */ 4588 */
4612 reason = readq(&bar0->general_int_status); 4589 reason = readq(&bar0->general_int_status);
4613 4590
4614 if (!reason) { 4591 if (unlikely(reason == S2IO_MINUS_ONE) ) {
4615 /* The interrupt was not raised by us. */ 4592 /* Nothing much can be done. Get out */
4616 atomic_dec(&sp->isr_cnt); 4593 return IRQ_HANDLED;
4617 return IRQ_NONE;
4618 }
4619 else if (unlikely(reason == S2IO_MINUS_ONE) ) {
4620 /* Disable device and get out */
4621 atomic_dec(&sp->isr_cnt);
4622 return IRQ_NONE;
4623 } 4594 }
4624 4595
4625 if (napi) { 4596 if (reason & (GEN_INTR_RXTRAFFIC |
4626 if (reason & GEN_INTR_RXTRAFFIC) { 4597 GEN_INTR_TXTRAFFIC | GEN_INTR_TXPIC))
4627 if (likely (netif_rx_schedule_prep(dev, &sp->napi))) { 4598 {
4628 __netif_rx_schedule(dev, &sp->napi); 4599 writeq(S2IO_MINUS_ONE, &bar0->general_int_mask);
4629 writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_mask); 4600
4601 if (config->napi) {
4602 if (reason & GEN_INTR_RXTRAFFIC) {
4603 if (likely(netif_rx_schedule_prep(dev,
4604 &sp->napi))) {
4605 __netif_rx_schedule(dev, &sp->napi);
4606 writeq(S2IO_MINUS_ONE,
4607 &bar0->rx_traffic_mask);
4608 } else
4609 writeq(S2IO_MINUS_ONE,
4610 &bar0->rx_traffic_int);
4630 } 4611 }
4631 else 4612 } else {
4613 /*
4614 * rx_traffic_int reg is an R1 register, writing all 1's
4615 * will ensure that the actual interrupt causing bit
4616 * get's cleared and hence a read can be avoided.
4617 */
4618 if (reason & GEN_INTR_RXTRAFFIC)
4632 writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_int); 4619 writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_int);
4620
4621 for (i = 0; i < config->rx_ring_num; i++)
4622 rx_intr_handler(&mac_control->rings[i]);
4633 } 4623 }
4634 } else { 4624
4635 /* 4625 /*
4636 * Rx handler is called by default, without checking for the 4626 * tx_traffic_int reg is an R1 register, writing all 1's
4637 * cause of interrupt.
4638 * rx_traffic_int reg is an R1 register, writing all 1's
4639 * will ensure that the actual interrupt causing bit get's 4627 * will ensure that the actual interrupt causing bit get's
4640 * cleared and hence a read can be avoided. 4628 * cleared and hence a read can be avoided.
4641 */ 4629 */
4642 if (reason & GEN_INTR_RXTRAFFIC) 4630 if (reason & GEN_INTR_TXTRAFFIC)
4643 writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_int); 4631 writeq(S2IO_MINUS_ONE, &bar0->tx_traffic_int);
4644 4632
4645 for (i = 0; i < config->rx_ring_num; i++) { 4633 for (i = 0; i < config->tx_fifo_num; i++)
4646 rx_intr_handler(&mac_control->rings[i]); 4634 tx_intr_handler(&mac_control->fifos[i]);
4647 }
4648 }
4649 4635
4650 /* 4636 if (reason & GEN_INTR_TXPIC)
4651 * tx_traffic_int reg is an R1 register, writing all 1's 4637 s2io_txpic_intr_handle(sp);
4652 * will ensure that the actual interrupt causing bit get's
4653 * cleared and hence a read can be avoided.
4654 */
4655 if (reason & GEN_INTR_TXTRAFFIC)
4656 writeq(S2IO_MINUS_ONE, &bar0->tx_traffic_int);
4657 4638
4658 for (i = 0; i < config->tx_fifo_num; i++) 4639 /*
4659 tx_intr_handler(&mac_control->fifos[i]); 4640 * Reallocate the buffers from the interrupt handler itself.
4641 */
4642 if (!config->napi) {
4643 for (i = 0; i < config->rx_ring_num; i++)
4644 s2io_chk_rx_buffers(sp, i);
4645 }
4646 writeq(sp->general_int_mask, &bar0->general_int_mask);
4647 readl(&bar0->general_int_status);
4660 4648
4661 if (reason & GEN_INTR_TXPIC) 4649 return IRQ_HANDLED;
4662 s2io_txpic_intr_handle(sp);
4663 /*
4664 * If the Rx buffer count is below the panic threshold then
4665 * reallocate the buffers from the interrupt handler itself,
4666 * else schedule a tasklet to reallocate the buffers.
4667 */
4668 if (!napi) {
4669 for (i = 0; i < config->rx_ring_num; i++)
4670 s2io_chk_rx_buffers(sp, i);
4671 }
4672 4650
4673 writeq(0, &bar0->general_int_mask); 4651 }
4674 readl(&bar0->general_int_status); 4652 else if (!reason) {
4653 /* The interrupt was not raised by us */
4654 return IRQ_NONE;
4655 }
4675 4656
4676 atomic_dec(&sp->isr_cnt);
4677 return IRQ_HANDLED; 4657 return IRQ_HANDLED;
4678} 4658}
4679 4659
@@ -6795,7 +6775,6 @@ static int s2io_add_isr(struct s2io_nic * sp)
6795} 6775}
6796static void s2io_rem_isr(struct s2io_nic * sp) 6776static void s2io_rem_isr(struct s2io_nic * sp)
6797{ 6777{
6798 int cnt = 0;
6799 struct net_device *dev = sp->dev; 6778 struct net_device *dev = sp->dev;
6800 struct swStat *stats = &sp->mac_control.stats_info->sw_stat; 6779 struct swStat *stats = &sp->mac_control.stats_info->sw_stat;
6801 6780
@@ -6808,6 +6787,7 @@ static void s2io_rem_isr(struct s2io_nic * sp)
6808 int vector = sp->entries[i].vector; 6787 int vector = sp->entries[i].vector;
6809 void *arg = sp->s2io_entries[i].arg; 6788 void *arg = sp->s2io_entries[i].arg;
6810 6789
6790 synchronize_irq(vector);
6811 free_irq(vector, arg); 6791 free_irq(vector, arg);
6812 } 6792 }
6813 6793
@@ -6826,16 +6806,9 @@ static void s2io_rem_isr(struct s2io_nic * sp)
6826 6806
6827 pci_disable_msix(sp->pdev); 6807 pci_disable_msix(sp->pdev);
6828 } else { 6808 } else {
6809 synchronize_irq(sp->pdev->irq);
6829 free_irq(sp->pdev->irq, dev); 6810 free_irq(sp->pdev->irq, dev);
6830 } 6811 }
6831 /* Waiting till all Interrupt handlers are complete */
6832 cnt = 0;
6833 do {
6834 msleep(10);
6835 if (!atomic_read(&sp->isr_cnt))
6836 break;
6837 cnt++;
6838 } while(cnt < 5);
6839} 6812}
6840 6813
6841static void do_s2io_card_down(struct s2io_nic * sp, int do_io) 6814static 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)
7365 if (*dev_intr_type != INTA) 7338 if (*dev_intr_type != INTA)
7366 napi = 0; 7339 napi = 0;
7367 7340
7368#ifndef CONFIG_PCI_MSI
7369 if (*dev_intr_type != INTA) {
7370 DBG_PRINT(ERR_DBG, "s2io: This kernel does not support"
7371 "MSI/MSI-X. Defaulting to INTA\n");
7372 *dev_intr_type = INTA;
7373 }
7374#else
7375 if ((*dev_intr_type != INTA) && (*dev_intr_type != MSI_X)) { 7341 if ((*dev_intr_type != INTA) && (*dev_intr_type != MSI_X)) {
7376 DBG_PRINT(ERR_DBG, "s2io: Wrong intr_type requested. " 7342 DBG_PRINT(ERR_DBG, "s2io: Wrong intr_type requested. "
7377 "Defaulting to INTA\n"); 7343 "Defaulting to INTA\n");
7378 *dev_intr_type = INTA; 7344 *dev_intr_type = INTA;
7379 } 7345 }
7380#endif 7346
7381 if ((*dev_intr_type == MSI_X) && 7347 if ((*dev_intr_type == MSI_X) &&
7382 ((pdev->device != PCI_DEVICE_ID_HERC_WIN) && 7348 ((pdev->device != PCI_DEVICE_ID_HERC_WIN) &&
7383 (pdev->device != PCI_DEVICE_ID_HERC_UNI))) { 7349 (pdev->device != PCI_DEVICE_ID_HERC_UNI))) {
@@ -7535,6 +7501,8 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
7535 mac_control = &sp->mac_control; 7501 mac_control = &sp->mac_control;
7536 config = &sp->config; 7502 config = &sp->config;
7537 7503
7504 config->napi = napi;
7505
7538 /* Tx side parameters. */ 7506 /* Tx side parameters. */
7539 config->tx_fifo_num = tx_fifo_num; 7507 config->tx_fifo_num = tx_fifo_num;
7540 for (i = 0; i < MAX_TX_FIFOS; i++) { 7508 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)
7582 for (i = 0; i < config->rx_ring_num; i++) 7550 for (i = 0; i < config->rx_ring_num; i++)
7583 atomic_set(&sp->rx_bufs_left[i], 0); 7551 atomic_set(&sp->rx_bufs_left[i], 0);
7584 7552
7585 /* Initialize the number of ISRs currently running */
7586 atomic_set(&sp->isr_cnt, 0);
7587
7588 /* initialize the shared memory used by the NIC and the host */ 7553 /* initialize the shared memory used by the NIC and the host */
7589 if (init_shared_mem(sp)) { 7554 if (init_shared_mem(sp)) {
7590 DBG_PRINT(ERR_DBG, "%s: Memory allocation failed\n", 7555 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 {
911 u16 lro_max_aggr_per_sess; 911 u16 lro_max_aggr_per_sess;
912 volatile unsigned long state; 912 volatile unsigned long state;
913 spinlock_t rx_lock; 913 spinlock_t rx_lock;
914 atomic_t isr_cnt;
915 u64 general_int_mask; 914 u64 general_int_mask;
916 u64 *ufo_in_band_v; 915 u64 *ufo_in_band_v;
917#define VPD_STRING_LEN 80 916#define VPD_STRING_LEN 80