提交 8e6a72c4 编写于 作者: M Michael Chan 提交者: David S. Miller

[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: NMichael Chan <mchan@broadcom.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 da3e4fbe
...@@ -2261,6 +2261,23 @@ bnx2_msi(int irq, void *dev_instance) ...@@ -2261,6 +2261,23 @@ bnx2_msi(int irq, void *dev_instance)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static irqreturn_t
bnx2_msi_1shot(int irq, void *dev_instance)
{
struct net_device *dev = dev_instance;
struct bnx2 *bp = netdev_priv(dev);
prefetch(bp->status_blk);
/* Return here if interrupt is disabled. */
if (unlikely(atomic_read(&bp->intr_sem) != 0))
return IRQ_HANDLED;
netif_rx_schedule(dev);
return IRQ_HANDLED;
}
static irqreturn_t static irqreturn_t
bnx2_interrupt(int irq, void *dev_instance) bnx2_interrupt(int irq, void *dev_instance)
{ {
...@@ -3759,13 +3776,17 @@ bnx2_init_chip(struct bnx2 *bp) ...@@ -3759,13 +3776,17 @@ bnx2_init_chip(struct bnx2 *bp)
REG_WR(bp, BNX2_HC_STAT_COLLECT_TICKS, 0xbb8); /* 3ms */ REG_WR(bp, BNX2_HC_STAT_COLLECT_TICKS, 0xbb8); /* 3ms */
if (CHIP_ID(bp) == CHIP_ID_5706_A1) if (CHIP_ID(bp) == CHIP_ID_5706_A1)
REG_WR(bp, BNX2_HC_CONFIG, BNX2_HC_CONFIG_COLLECT_STATS); val = BNX2_HC_CONFIG_COLLECT_STATS;
else { else {
REG_WR(bp, BNX2_HC_CONFIG, BNX2_HC_CONFIG_RX_TMR_MODE | val = BNX2_HC_CONFIG_RX_TMR_MODE | BNX2_HC_CONFIG_TX_TMR_MODE |
BNX2_HC_CONFIG_TX_TMR_MODE | BNX2_HC_CONFIG_COLLECT_STATS;
BNX2_HC_CONFIG_COLLECT_STATS);
} }
if (bp->flags & ONE_SHOT_MSI_FLAG)
val |= BNX2_HC_CONFIG_ONE_SHOT;
REG_WR(bp, BNX2_HC_CONFIG, val);
/* Clear internal stats counters. */ /* Clear internal stats counters. */
REG_WR(bp, BNX2_HC_COMMAND, BNX2_HC_COMMAND_CLR_STAT_NOW); REG_WR(bp, BNX2_HC_COMMAND, BNX2_HC_COMMAND_CLR_STAT_NOW);
...@@ -4610,6 +4631,38 @@ bnx2_timer(unsigned long data) ...@@ -4610,6 +4631,38 @@ bnx2_timer(unsigned long data)
mod_timer(&bp->timer, jiffies + bp->current_interval); mod_timer(&bp->timer, jiffies + bp->current_interval);
} }
static int
bnx2_request_irq(struct bnx2 *bp)
{
struct net_device *dev = bp->dev;
int rc = 0;
if (bp->flags & USING_MSI_FLAG) {
irq_handler_t fn = bnx2_msi;
if (bp->flags & ONE_SHOT_MSI_FLAG)
fn = bnx2_msi_1shot;
rc = request_irq(bp->pdev->irq, fn, 0, dev->name, dev);
} else
rc = request_irq(bp->pdev->irq, bnx2_interrupt,
IRQF_SHARED, dev->name, dev);
return rc;
}
static void
bnx2_free_irq(struct bnx2 *bp)
{
struct net_device *dev = bp->dev;
if (bp->flags & USING_MSI_FLAG) {
free_irq(bp->pdev->irq, dev);
pci_disable_msi(bp->pdev);
bp->flags &= ~(USING_MSI_FLAG | ONE_SHOT_MSI_FLAG);
} else
free_irq(bp->pdev->irq, dev);
}
/* Called with rtnl_lock */ /* Called with rtnl_lock */
static int static int
bnx2_open(struct net_device *dev) bnx2_open(struct net_device *dev)
...@@ -4626,24 +4679,15 @@ bnx2_open(struct net_device *dev) ...@@ -4626,24 +4679,15 @@ bnx2_open(struct net_device *dev)
if (rc) if (rc)
return rc; return rc;
if ((CHIP_ID(bp) != CHIP_ID_5706_A0) && if ((bp->flags & MSI_CAP_FLAG) && !disable_msi) {
(CHIP_ID(bp) != CHIP_ID_5706_A1) &&
!disable_msi) {
if (pci_enable_msi(bp->pdev) == 0) { if (pci_enable_msi(bp->pdev) == 0) {
bp->flags |= USING_MSI_FLAG; bp->flags |= USING_MSI_FLAG;
rc = request_irq(bp->pdev->irq, bnx2_msi, 0, dev->name, if (CHIP_NUM(bp) == CHIP_NUM_5709)
dev); bp->flags |= ONE_SHOT_MSI_FLAG;
} }
else {
rc = request_irq(bp->pdev->irq, bnx2_interrupt,
IRQF_SHARED, dev->name, dev);
}
}
else {
rc = request_irq(bp->pdev->irq, bnx2_interrupt, IRQF_SHARED,
dev->name, dev);
} }
rc = bnx2_request_irq(bp);
if (rc) { if (rc) {
bnx2_free_mem(bp); bnx2_free_mem(bp);
return rc; return rc;
...@@ -4652,11 +4696,7 @@ bnx2_open(struct net_device *dev) ...@@ -4652,11 +4696,7 @@ bnx2_open(struct net_device *dev)
rc = bnx2_init_nic(bp); rc = bnx2_init_nic(bp);
if (rc) { if (rc) {
free_irq(bp->pdev->irq, dev); bnx2_free_irq(bp);
if (bp->flags & USING_MSI_FLAG) {
pci_disable_msi(bp->pdev);
bp->flags &= ~USING_MSI_FLAG;
}
bnx2_free_skbs(bp); bnx2_free_skbs(bp);
bnx2_free_mem(bp); bnx2_free_mem(bp);
return rc; return rc;
...@@ -4680,16 +4720,13 @@ bnx2_open(struct net_device *dev) ...@@ -4680,16 +4720,13 @@ bnx2_open(struct net_device *dev)
bp->dev->name); bp->dev->name);
bnx2_disable_int(bp); bnx2_disable_int(bp);
free_irq(bp->pdev->irq, dev); bnx2_free_irq(bp);
pci_disable_msi(bp->pdev);
bp->flags &= ~USING_MSI_FLAG;
rc = bnx2_init_nic(bp); rc = bnx2_init_nic(bp);
if (!rc) { if (!rc)
rc = request_irq(bp->pdev->irq, bnx2_interrupt, rc = bnx2_request_irq(bp);
IRQF_SHARED, dev->name, dev);
}
if (rc) { if (rc) {
bnx2_free_skbs(bp); bnx2_free_skbs(bp);
bnx2_free_mem(bp); bnx2_free_mem(bp);
...@@ -4927,11 +4964,7 @@ bnx2_close(struct net_device *dev) ...@@ -4927,11 +4964,7 @@ bnx2_close(struct net_device *dev)
else else
reset_code = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL; reset_code = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL;
bnx2_reset_chip(bp, reset_code); bnx2_reset_chip(bp, reset_code);
free_irq(bp->pdev->irq, dev); bnx2_free_irq(bp);
if (bp->flags & USING_MSI_FLAG) {
pci_disable_msi(bp->pdev);
bp->flags &= ~USING_MSI_FLAG;
}
bnx2_free_skbs(bp); bnx2_free_skbs(bp);
bnx2_free_mem(bp); bnx2_free_mem(bp);
bp->link_up = 0; bp->link_up = 0;
...@@ -6095,6 +6128,11 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) ...@@ -6095,6 +6128,11 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
} }
} }
if (CHIP_ID(bp) != CHIP_ID_5706_A0 && CHIP_ID(bp) != CHIP_ID_5706_A1) {
if (pci_find_capability(pdev, PCI_CAP_ID_MSI))
bp->flags |= MSI_CAP_FLAG;
}
/* 5708 cannot support DMA addresses > 40-bit. */ /* 5708 cannot support DMA addresses > 40-bit. */
if (CHIP_NUM(bp) == CHIP_NUM_5708) if (CHIP_NUM(bp) == CHIP_NUM_5708)
persist_dma_mask = dma_mask = DMA_40BIT_MASK; persist_dma_mask = dma_mask = DMA_40BIT_MASK;
......
...@@ -6468,12 +6468,14 @@ struct bnx2 { ...@@ -6468,12 +6468,14 @@ struct bnx2 {
u32 last_status_idx; u32 last_status_idx;
u32 flags; u32 flags;
#define PCIX_FLAG 1 #define PCIX_FLAG 0x00000001
#define PCI_32BIT_FLAG 2 #define PCI_32BIT_FLAG 0x00000002
#define ONE_TDMA_FLAG 4 /* no longer used */ #define ONE_TDMA_FLAG 0x00000004 /* no longer used */
#define NO_WOL_FLAG 8 #define NO_WOL_FLAG 0x00000008
#define USING_MSI_FLAG 0x20 #define USING_MSI_FLAG 0x00000020
#define ASF_ENABLE_FLAG 0x40 #define ASF_ENABLE_FLAG 0x00000040
#define MSI_CAP_FLAG 0x00000080
#define ONE_SHOT_MSI_FLAG 0x00000100
/* Put tx producer and consumer fields in separate cache lines. */ /* Put tx producer and consumer fields in separate cache lines. */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册