diff options
author | Michael Chan <mchan@broadcom.com> | 2007-05-03 16:24:48 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2007-05-03 16:24:48 -0400 |
commit | 8e6a72c435bf8bdd738ad08a746d697abedacfc0 (patch) | |
tree | c80eede41a92196004a2ce9ee03ba4f200eb803f /drivers | |
parent | da3e4fbed21a5d7edab10ffb77a8c04a725f9eff (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')
-rw-r--r-- | drivers/net/bnx2.c | 108 | ||||
-rw-r--r-- | drivers/net/bnx2.h | 14 |
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 | ||
2264 | static irqreturn_t | 2264 | static irqreturn_t |
2265 | bnx2_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 | |||
2281 | static irqreturn_t | ||
2265 | bnx2_interrupt(int irq, void *dev_instance) | 2282 | bnx2_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 | ||
4634 | static int | ||
4635 | bnx2_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 | |||
4653 | static void | ||
4654 | bnx2_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 */ |
4614 | static int | 4667 | static int |
4615 | bnx2_open(struct net_device *dev) | 4668 | bnx2_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 | ||