From: Matt Carlson Date: Tue, 1 Sep 2009 12:55:02 +0000 (+0000) Subject: tg3: Add support code around kernel interrupt API X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=4f125f42dd55390016e21f8b3960f99d02d1001f;p=openwrt%2Fstaging%2Fblogic.git tg3: Add support code around kernel interrupt API This patch adds code to support multiple interrupt vectors around the kernel's interrupt API. Signed-off-by: Matt Carlson Reviewed-by: Benjamin Li Signed-off-by: David S. Miller --- diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 14cead69c4cc..7717eae1221d 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -4729,12 +4729,15 @@ tx_recovery: static void tg3_irq_quiesce(struct tg3 *tp) { + int i; + BUG_ON(tp->irq_sync); tp->irq_sync = 1; smp_mb(); - synchronize_irq(tp->pdev->irq); + for (i = 0; i < tp->irq_cnt; i++) + synchronize_irq(tp->napi[i].irq_vec); } static inline int tg3_irq_sync(struct tg3 *tp) @@ -4947,9 +4950,11 @@ static int tg3_restart_hw(struct tg3 *tp, int reset_phy) #ifdef CONFIG_NET_POLL_CONTROLLER static void tg3_poll_controller(struct net_device *dev) { + int i; struct tg3 *tp = netdev_priv(dev); - tg3_interrupt(tp->pdev->irq, dev); + for (i = 0; i < tp->irq_cnt; i++) + tg3_interrupt(tp->napi[i].irq_vec, dev); } #endif @@ -6244,7 +6249,7 @@ static int tg3_chip_reset(struct tg3 *tp) { u32 val; void (*write_op)(struct tg3 *, u32, u32); - int err; + int i, err; tg3_nvram_lock(tp); @@ -6291,7 +6296,9 @@ static int tg3_chip_reset(struct tg3 *tp) tp->napi[0].last_tag = 0; tp->napi[0].last_irq_tag = 0; smp_mb(); - synchronize_irq(tp->pdev->irq); + + for (i = 0; i < tp->irq_cnt; i++) + synchronize_irq(tp->napi[i].irq_vec); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) { val = tr32(TG3_PCIE_LNKCTL) & ~TG3_PCIE_LNKCTL_L1_PLL_PD_EN; @@ -7745,11 +7752,20 @@ restart_timer: add_timer(&tp->timer); } -static int tg3_request_irq(struct tg3 *tp) +static int tg3_request_irq(struct tg3 *tp, int irq_num) { irq_handler_t fn; unsigned long flags; - char *name = tp->dev->name; + char *name; + struct tg3_napi *tnapi = &tp->napi[irq_num]; + + if (tp->irq_cnt == 1) + name = tp->dev->name; + else { + name = &tnapi->irq_lbl[0]; + snprintf(name, IFNAMSIZ, "%s-%d", tp->dev->name, irq_num); + name[IFNAMSIZ-1] = 0; + } if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) { fn = tg3_msi; @@ -7762,7 +7778,8 @@ static int tg3_request_irq(struct tg3 *tp) fn = tg3_interrupt_tagged; flags = IRQF_SHARED | IRQF_SAMPLE_RANDOM; } - return request_irq(tp->pdev->irq, fn, flags, name, &tp->napi[0]); + + return request_irq(tnapi->irq_vec, fn, flags, name, tnapi); } static int tg3_test_interrupt(struct tg3 *tp) @@ -7776,9 +7793,9 @@ static int tg3_test_interrupt(struct tg3 *tp) tg3_disable_ints(tp); - free_irq(tp->pdev->irq, tnapi); + free_irq(tnapi->irq_vec, tnapi); - err = request_irq(tp->pdev->irq, tg3_test_isr, + err = request_irq(tnapi->irq_vec, tg3_test_isr, IRQF_SHARED | IRQF_SAMPLE_RANDOM, dev->name, tnapi); if (err) return err; @@ -7806,9 +7823,9 @@ static int tg3_test_interrupt(struct tg3 *tp) tg3_disable_ints(tp); - free_irq(tp->pdev->irq, tnapi); + free_irq(tnapi->irq_vec, tnapi); - err = tg3_request_irq(tp); + err = tg3_request_irq(tp, 0); if (err) return err; @@ -7854,13 +7871,13 @@ static int tg3_test_msi(struct tg3 *tp) "the PCI maintainer and include system chipset information.\n", tp->dev->name); - free_irq(tp->pdev->irq, &tp->napi[0]); + free_irq(tp->napi[0].irq_vec, &tp->napi[0]); pci_disable_msi(tp->pdev); tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI; - err = tg3_request_irq(tp); + err = tg3_request_irq(tp, 0); if (err) return err; @@ -7875,7 +7892,7 @@ static int tg3_test_msi(struct tg3 *tp) tg3_full_unlock(tp); if (err) - free_irq(tp->pdev->irq, &tp->napi[0]); + free_irq(tp->napi[0].irq_vec, &tp->napi[0]); return err; } @@ -7928,6 +7945,9 @@ static void tg3_ints_init(struct tg3 *tp) tp->tg3_flags2 |= TG3_FLG2_USING_MSI; } } + + tp->irq_cnt = 1; + tp->napi[0].irq_vec = tp->pdev->irq; } static void tg3_ints_fini(struct tg3 *tp) @@ -7941,7 +7961,7 @@ static void tg3_ints_fini(struct tg3 *tp) static int tg3_open(struct net_device *dev) { struct tg3 *tp = netdev_priv(dev); - int err; + int i, err; if (tp->fw_needed) { err = tg3_request_firmware(tp); @@ -7983,7 +8003,15 @@ static int tg3_open(struct net_device *dev) napi_enable(&tp->napi[0].napi); - err = tg3_request_irq(tp); + for (i = 0; i < tp->irq_cnt; i++) { + struct tg3_napi *tnapi = &tp->napi[i]; + err = tg3_request_irq(tp, i); + if (err) { + for (i--; i >= 0; i--) + free_irq(tnapi->irq_vec, tnapi); + break; + } + } if (err) goto err_out1; @@ -8054,7 +8082,10 @@ static int tg3_open(struct net_device *dev) return 0; err_out2: - free_irq(tp->pdev->irq, &tp->napi[0]); + for (i = tp->irq_cnt - 1; i >= 0; i--) { + struct tg3_napi *tnapi = &tp->napi[i]; + free_irq(tnapi->irq_vec, tnapi); + } err_out1: napi_disable(&tp->napi[0].napi); @@ -8298,6 +8329,7 @@ static struct tg3_ethtool_stats *tg3_get_estats(struct tg3 *); static int tg3_close(struct net_device *dev) { + int i; struct tg3 *tp = netdev_priv(dev); napi_disable(&tp->napi[0].napi); @@ -8320,7 +8352,10 @@ static int tg3_close(struct net_device *dev) tg3_full_unlock(tp); - free_irq(tp->pdev->irq, &tp->napi[0]); + for (i = tp->irq_cnt - 1; i >= 0; i--) { + struct tg3_napi *tnapi = &tp->napi[i]; + free_irq(tnapi->irq_vec, tnapi); + } tg3_ints_fini(tp); @@ -12151,6 +12186,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) } } + tp->irq_max = 1; + if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) || (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) tp->tg3_flags |= TG3_FLAG_JUMBO_CAPABLE; diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 626b96805c3e..a78a0db15a71 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2514,6 +2514,9 @@ struct tg3_napi { dma_addr_t status_mapping; dma_addr_t rx_rcb_mapping; dma_addr_t tx_desc_mapping; + + char irq_lbl[IFNAMSIZ]; + unsigned int irq_vec; }; struct tg3 { @@ -2829,6 +2832,9 @@ struct tg3 { #define SST_25VF0X0_PAGE_SIZE 4098 + unsigned int irq_max; + unsigned int irq_cnt; + struct ethtool_coalesce coal; /* firmware info */