aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorMichael Chan <mchan@broadcom.com>2007-05-03 16:24:48 -0400
committerDavid S. Miller <davem@davemloft.net>2007-05-03 16:24:48 -0400
commit8e6a72c435bf8bdd738ad08a746d697abedacfc0 (patch)
treec80eede41a92196004a2ce9ee03ba4f200eb803f /drivers/net
parentda3e4fbed21a5d7edab10ffb77a8c04a725f9eff (diff)
[BNX2]: Add 1-shot MSI handler for 5709.
The 5709 supports the one-shot MSI handler similar to some of the tg3 chips. In this mode, the MSI disables itself automatically until it is re-enabled at the end of NAPI poll. Put the request_irq/free_irq logic in common procedures. Signed-off-by: Michael Chan <mchan@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/bnx2.c108
-rw-r--r--drivers/net/bnx2.h14
2 files changed, 81 insertions, 41 deletions
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index f072028e3e3b..97ed4006a345 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -2262,6 +2262,23 @@ bnx2_msi(int irq, void *dev_instance)
2262} 2262}
2263 2263
2264static irqreturn_t 2264static irqreturn_t
2265bnx2_msi_1shot(int irq, void *dev_instance)
2266{
2267 struct net_device *dev = dev_instance;
2268 struct bnx2 *bp = netdev_priv(dev);
2269
2270 prefetch(bp->status_blk);
2271
2272 /* Return here if interrupt is disabled. */
2273 if (unlikely(atomic_read(&bp->intr_sem) != 0))
2274 return IRQ_HANDLED;
2275
2276 netif_rx_schedule(dev);
2277
2278 return IRQ_HANDLED;
2279}
2280
2281static irqreturn_t
2265bnx2_interrupt(int irq, void *dev_instance) 2282bnx2_interrupt(int irq, void *dev_instance)
2266{ 2283{
2267 struct net_device *dev = dev_instance; 2284 struct net_device *dev = dev_instance;
@@ -3759,13 +3776,17 @@ bnx2_init_chip(struct bnx2 *bp)
3759 REG_WR(bp, BNX2_HC_STAT_COLLECT_TICKS, 0xbb8); /* 3ms */ 3776 REG_WR(bp, BNX2_HC_STAT_COLLECT_TICKS, 0xbb8); /* 3ms */
3760 3777
3761 if (CHIP_ID(bp) == CHIP_ID_5706_A1) 3778 if (CHIP_ID(bp) == CHIP_ID_5706_A1)
3762 REG_WR(bp, BNX2_HC_CONFIG, BNX2_HC_CONFIG_COLLECT_STATS); 3779 val = BNX2_HC_CONFIG_COLLECT_STATS;
3763 else { 3780 else {
3764 REG_WR(bp, BNX2_HC_CONFIG, BNX2_HC_CONFIG_RX_TMR_MODE | 3781 val = BNX2_HC_CONFIG_RX_TMR_MODE | BNX2_HC_CONFIG_TX_TMR_MODE |
3765 BNX2_HC_CONFIG_TX_TMR_MODE | 3782 BNX2_HC_CONFIG_COLLECT_STATS;
3766 BNX2_HC_CONFIG_COLLECT_STATS);
3767 } 3783 }
3768 3784
3785 if (bp->flags & ONE_SHOT_MSI_FLAG)
3786 val |= BNX2_HC_CONFIG_ONE_SHOT;
3787
3788 REG_WR(bp, BNX2_HC_CONFIG, val);
3789
3769 /* Clear internal stats counters. */ 3790 /* Clear internal stats counters. */
3770 REG_WR(bp, BNX2_HC_COMMAND, BNX2_HC_COMMAND_CLR_STAT_NOW); 3791 REG_WR(bp, BNX2_HC_COMMAND, BNX2_HC_COMMAND_CLR_STAT_NOW);
3771 3792
@@ -4610,6 +4631,38 @@ bnx2_restart_timer:
4610 mod_timer(&bp->timer, jiffies + bp->current_interval); 4631 mod_timer(&bp->timer, jiffies + bp->current_interval);
4611} 4632}
4612 4633
4634static int
4635bnx2_request_irq(struct bnx2 *bp)
4636{
4637 struct net_device *dev = bp->dev;
4638 int rc = 0;
4639
4640 if (bp->flags & USING_MSI_FLAG) {
4641 irq_handler_t fn = bnx2_msi;
4642
4643 if (bp->flags & ONE_SHOT_MSI_FLAG)
4644 fn = bnx2_msi_1shot;
4645
4646 rc = request_irq(bp->pdev->irq, fn, 0, dev->name, dev);
4647 } else
4648 rc = request_irq(bp->pdev->irq, bnx2_interrupt,
4649 IRQF_SHARED, dev->name, dev);
4650 return rc;
4651}
4652
4653static void
4654bnx2_free_irq(struct bnx2 *bp)
4655{
4656 struct net_device *dev = bp->dev;
4657
4658 if (bp->flags & USING_MSI_FLAG) {
4659 free_irq(bp->pdev->irq, dev);
4660 pci_disable_msi(bp->pdev);
4661 bp->flags &= ~(USING_MSI_FLAG | ONE_SHOT_MSI_FLAG);
4662 } else
4663 free_irq(bp->pdev->irq, dev);
4664}
4665
4613/* Called with rtnl_lock */ 4666/* Called with rtnl_lock */
4614static int 4667static int
4615bnx2_open(struct net_device *dev) 4668bnx2_open(struct net_device *dev)
@@ -4626,24 +4679,15 @@ bnx2_open(struct net_device *dev)
4626 if (rc) 4679 if (rc)
4627 return rc; 4680 return rc;
4628 4681
4629 if ((CHIP_ID(bp) != CHIP_ID_5706_A0) && 4682 if ((bp->flags & MSI_CAP_FLAG) && !disable_msi) {
4630 (CHIP_ID(bp) != CHIP_ID_5706_A1) &&
4631 !disable_msi) {
4632
4633 if (pci_enable_msi(bp->pdev) == 0) { 4683 if (pci_enable_msi(bp->pdev) == 0) {
4634 bp->flags |= USING_MSI_FLAG; 4684 bp->flags |= USING_MSI_FLAG;
4635 rc = request_irq(bp->pdev->irq, bnx2_msi, 0, dev->name, 4685 if (CHIP_NUM(bp) == CHIP_NUM_5709)
4636 dev); 4686 bp->flags |= ONE_SHOT_MSI_FLAG;
4637 } 4687 }
4638 else {
4639 rc = request_irq(bp->pdev->irq, bnx2_interrupt,
4640 IRQF_SHARED, dev->name, dev);
4641 }
4642 }
4643 else {
4644 rc = request_irq(bp->pdev->irq, bnx2_interrupt, IRQF_SHARED,
4645 dev->name, dev);
4646 } 4688 }
4689 rc = bnx2_request_irq(bp);
4690
4647 if (rc) { 4691 if (rc) {
4648 bnx2_free_mem(bp); 4692 bnx2_free_mem(bp);
4649 return rc; 4693 return rc;
@@ -4652,11 +4696,7 @@ bnx2_open(struct net_device *dev)
4652 rc = bnx2_init_nic(bp); 4696 rc = bnx2_init_nic(bp);
4653 4697
4654 if (rc) { 4698 if (rc) {
4655 free_irq(bp->pdev->irq, dev); 4699 bnx2_free_irq(bp);
4656 if (bp->flags & USING_MSI_FLAG) {
4657 pci_disable_msi(bp->pdev);
4658 bp->flags &= ~USING_MSI_FLAG;
4659 }
4660 bnx2_free_skbs(bp); 4700 bnx2_free_skbs(bp);
4661 bnx2_free_mem(bp); 4701 bnx2_free_mem(bp);
4662 return rc; 4702 return rc;
@@ -4680,16 +4720,13 @@ bnx2_open(struct net_device *dev)
4680 bp->dev->name); 4720 bp->dev->name);
4681 4721
4682 bnx2_disable_int(bp); 4722 bnx2_disable_int(bp);
4683 free_irq(bp->pdev->irq, dev); 4723 bnx2_free_irq(bp);
4684 pci_disable_msi(bp->pdev);
4685 bp->flags &= ~USING_MSI_FLAG;
4686 4724
4687 rc = bnx2_init_nic(bp); 4725 rc = bnx2_init_nic(bp);
4688 4726
4689 if (!rc) { 4727 if (!rc)
4690 rc = request_irq(bp->pdev->irq, bnx2_interrupt, 4728 rc = bnx2_request_irq(bp);
4691 IRQF_SHARED, dev->name, dev); 4729
4692 }
4693 if (rc) { 4730 if (rc) {
4694 bnx2_free_skbs(bp); 4731 bnx2_free_skbs(bp);
4695 bnx2_free_mem(bp); 4732 bnx2_free_mem(bp);
@@ -4927,11 +4964,7 @@ bnx2_close(struct net_device *dev)
4927 else 4964 else
4928 reset_code = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL; 4965 reset_code = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL;
4929 bnx2_reset_chip(bp, reset_code); 4966 bnx2_reset_chip(bp, reset_code);
4930 free_irq(bp->pdev->irq, dev); 4967 bnx2_free_irq(bp);
4931 if (bp->flags & USING_MSI_FLAG) {
4932 pci_disable_msi(bp->pdev);
4933 bp->flags &= ~USING_MSI_FLAG;
4934 }
4935 bnx2_free_skbs(bp); 4968 bnx2_free_skbs(bp);
4936 bnx2_free_mem(bp); 4969 bnx2_free_mem(bp);
4937 bp->link_up = 0; 4970 bp->link_up = 0;
@@ -6095,6 +6128,11 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
6095 } 6128 }
6096 } 6129 }
6097 6130
6131 if (CHIP_ID(bp) != CHIP_ID_5706_A0 && CHIP_ID(bp) != CHIP_ID_5706_A1) {
6132 if (pci_find_capability(pdev, PCI_CAP_ID_MSI))
6133 bp->flags |= MSI_CAP_FLAG;
6134 }
6135
6098 /* 5708 cannot support DMA addresses > 40-bit. */ 6136 /* 5708 cannot support DMA addresses > 40-bit. */
6099 if (CHIP_NUM(bp) == CHIP_NUM_5708) 6137 if (CHIP_NUM(bp) == CHIP_NUM_5708)
6100 persist_dma_mask = dma_mask = DMA_40BIT_MASK; 6138 persist_dma_mask = dma_mask = DMA_40BIT_MASK;
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index ba175a800c8e..121576d144d0 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -6468,12 +6468,14 @@ struct bnx2 {
6468 u32 last_status_idx; 6468 u32 last_status_idx;
6469 6469
6470 u32 flags; 6470 u32 flags;
6471#define PCIX_FLAG 1 6471#define PCIX_FLAG 0x00000001
6472#define PCI_32BIT_FLAG 2 6472#define PCI_32BIT_FLAG 0x00000002
6473#define ONE_TDMA_FLAG 4 /* no longer used */ 6473#define ONE_TDMA_FLAG 0x00000004 /* no longer used */
6474#define NO_WOL_FLAG 8 6474#define NO_WOL_FLAG 0x00000008
6475#define USING_MSI_FLAG 0x20 6475#define USING_MSI_FLAG 0x00000020
6476#define ASF_ENABLE_FLAG 0x40 6476#define ASF_ENABLE_FLAG 0x00000040
6477#define MSI_CAP_FLAG 0x00000080
6478#define ONE_SHOT_MSI_FLAG 0x00000100
6477 6479
6478 /* Put tx producer and consumer fields in separate cache lines. */ 6480 /* Put tx producer and consumer fields in separate cache lines. */
6479 6481