aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMatt Carlson <mcarlson@broadcom.com>2009-09-01 08:55:02 -0400
committerDavid S. Miller <davem@davemloft.net>2009-09-02 03:43:30 -0400
commit4f125f42dd55390016e21f8b3960f99d02d1001f (patch)
treea976eb6c317db2a93bad2ba339be627deb59b3be /drivers
parent2d31ecaf10c4ae03d49aed516481b2839b0220f6 (diff)
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 <mcarlson@broadcom.com> Reviewed-by: Benjamin Li <benli@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/tg3.c73
-rw-r--r--drivers/net/tg3.h6
2 files changed, 61 insertions, 18 deletions
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:
4729 4729
4730static void tg3_irq_quiesce(struct tg3 *tp) 4730static void tg3_irq_quiesce(struct tg3 *tp)
4731{ 4731{
4732 int i;
4733
4732 BUG_ON(tp->irq_sync); 4734 BUG_ON(tp->irq_sync);
4733 4735
4734 tp->irq_sync = 1; 4736 tp->irq_sync = 1;
4735 smp_mb(); 4737 smp_mb();
4736 4738
4737 synchronize_irq(tp->pdev->irq); 4739 for (i = 0; i < tp->irq_cnt; i++)
4740 synchronize_irq(tp->napi[i].irq_vec);
4738} 4741}
4739 4742
4740static inline int tg3_irq_sync(struct tg3 *tp) 4743static inline int tg3_irq_sync(struct tg3 *tp)
@@ -4947,9 +4950,11 @@ static int tg3_restart_hw(struct tg3 *tp, int reset_phy)
4947#ifdef CONFIG_NET_POLL_CONTROLLER 4950#ifdef CONFIG_NET_POLL_CONTROLLER
4948static void tg3_poll_controller(struct net_device *dev) 4951static void tg3_poll_controller(struct net_device *dev)
4949{ 4952{
4953 int i;
4950 struct tg3 *tp = netdev_priv(dev); 4954 struct tg3 *tp = netdev_priv(dev);
4951 4955
4952 tg3_interrupt(tp->pdev->irq, dev); 4956 for (i = 0; i < tp->irq_cnt; i++)
4957 tg3_interrupt(tp->napi[i].irq_vec, dev);
4953} 4958}
4954#endif 4959#endif
4955 4960
@@ -6244,7 +6249,7 @@ static int tg3_chip_reset(struct tg3 *tp)
6244{ 6249{
6245 u32 val; 6250 u32 val;
6246 void (*write_op)(struct tg3 *, u32, u32); 6251 void (*write_op)(struct tg3 *, u32, u32);
6247 int err; 6252 int i, err;
6248 6253
6249 tg3_nvram_lock(tp); 6254 tg3_nvram_lock(tp);
6250 6255
@@ -6291,7 +6296,9 @@ static int tg3_chip_reset(struct tg3 *tp)
6291 tp->napi[0].last_tag = 0; 6296 tp->napi[0].last_tag = 0;
6292 tp->napi[0].last_irq_tag = 0; 6297 tp->napi[0].last_irq_tag = 0;
6293 smp_mb(); 6298 smp_mb();
6294 synchronize_irq(tp->pdev->irq); 6299
6300 for (i = 0; i < tp->irq_cnt; i++)
6301 synchronize_irq(tp->napi[i].irq_vec);
6295 6302
6296 if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) { 6303 if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) {
6297 val = tr32(TG3_PCIE_LNKCTL) & ~TG3_PCIE_LNKCTL_L1_PLL_PD_EN; 6304 val = tr32(TG3_PCIE_LNKCTL) & ~TG3_PCIE_LNKCTL_L1_PLL_PD_EN;
@@ -7745,11 +7752,20 @@ restart_timer:
7745 add_timer(&tp->timer); 7752 add_timer(&tp->timer);
7746} 7753}
7747 7754
7748static int tg3_request_irq(struct tg3 *tp) 7755static int tg3_request_irq(struct tg3 *tp, int irq_num)
7749{ 7756{
7750 irq_handler_t fn; 7757 irq_handler_t fn;
7751 unsigned long flags; 7758 unsigned long flags;
7752 char *name = tp->dev->name; 7759 char *name;
7760 struct tg3_napi *tnapi = &tp->napi[irq_num];
7761
7762 if (tp->irq_cnt == 1)
7763 name = tp->dev->name;
7764 else {
7765 name = &tnapi->irq_lbl[0];
7766 snprintf(name, IFNAMSIZ, "%s-%d", tp->dev->name, irq_num);
7767 name[IFNAMSIZ-1] = 0;
7768 }
7753 7769
7754 if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) { 7770 if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
7755 fn = tg3_msi; 7771 fn = tg3_msi;
@@ -7762,7 +7778,8 @@ static int tg3_request_irq(struct tg3 *tp)
7762 fn = tg3_interrupt_tagged; 7778 fn = tg3_interrupt_tagged;
7763 flags = IRQF_SHARED | IRQF_SAMPLE_RANDOM; 7779 flags = IRQF_SHARED | IRQF_SAMPLE_RANDOM;
7764 } 7780 }
7765 return request_irq(tp->pdev->irq, fn, flags, name, &tp->napi[0]); 7781
7782 return request_irq(tnapi->irq_vec, fn, flags, name, tnapi);
7766} 7783}
7767 7784
7768static int tg3_test_interrupt(struct tg3 *tp) 7785static int tg3_test_interrupt(struct tg3 *tp)
@@ -7776,9 +7793,9 @@ static int tg3_test_interrupt(struct tg3 *tp)
7776 7793
7777 tg3_disable_ints(tp); 7794 tg3_disable_ints(tp);
7778 7795
7779 free_irq(tp->pdev->irq, tnapi); 7796 free_irq(tnapi->irq_vec, tnapi);
7780 7797
7781 err = request_irq(tp->pdev->irq, tg3_test_isr, 7798 err = request_irq(tnapi->irq_vec, tg3_test_isr,
7782 IRQF_SHARED | IRQF_SAMPLE_RANDOM, dev->name, tnapi); 7799 IRQF_SHARED | IRQF_SAMPLE_RANDOM, dev->name, tnapi);
7783 if (err) 7800 if (err)
7784 return err; 7801 return err;
@@ -7806,9 +7823,9 @@ static int tg3_test_interrupt(struct tg3 *tp)
7806 7823
7807 tg3_disable_ints(tp); 7824 tg3_disable_ints(tp);
7808 7825
7809 free_irq(tp->pdev->irq, tnapi); 7826 free_irq(tnapi->irq_vec, tnapi);
7810 7827
7811 err = tg3_request_irq(tp); 7828 err = tg3_request_irq(tp, 0);
7812 7829
7813 if (err) 7830 if (err)
7814 return err; 7831 return err;
@@ -7854,13 +7871,13 @@ static int tg3_test_msi(struct tg3 *tp)
7854 "the PCI maintainer and include system chipset information.\n", 7871 "the PCI maintainer and include system chipset information.\n",
7855 tp->dev->name); 7872 tp->dev->name);
7856 7873
7857 free_irq(tp->pdev->irq, &tp->napi[0]); 7874 free_irq(tp->napi[0].irq_vec, &tp->napi[0]);
7858 7875
7859 pci_disable_msi(tp->pdev); 7876 pci_disable_msi(tp->pdev);
7860 7877
7861 tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI; 7878 tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI;
7862 7879
7863 err = tg3_request_irq(tp); 7880 err = tg3_request_irq(tp, 0);
7864 if (err) 7881 if (err)
7865 return err; 7882 return err;
7866 7883
@@ -7875,7 +7892,7 @@ static int tg3_test_msi(struct tg3 *tp)
7875 tg3_full_unlock(tp); 7892 tg3_full_unlock(tp);
7876 7893
7877 if (err) 7894 if (err)
7878 free_irq(tp->pdev->irq, &tp->napi[0]); 7895 free_irq(tp->napi[0].irq_vec, &tp->napi[0]);
7879 7896
7880 return err; 7897 return err;
7881} 7898}
@@ -7928,6 +7945,9 @@ static void tg3_ints_init(struct tg3 *tp)
7928 tp->tg3_flags2 |= TG3_FLG2_USING_MSI; 7945 tp->tg3_flags2 |= TG3_FLG2_USING_MSI;
7929 } 7946 }
7930 } 7947 }
7948
7949 tp->irq_cnt = 1;
7950 tp->napi[0].irq_vec = tp->pdev->irq;
7931} 7951}
7932 7952
7933static void tg3_ints_fini(struct tg3 *tp) 7953static void tg3_ints_fini(struct tg3 *tp)
@@ -7941,7 +7961,7 @@ static void tg3_ints_fini(struct tg3 *tp)
7941static int tg3_open(struct net_device *dev) 7961static int tg3_open(struct net_device *dev)
7942{ 7962{
7943 struct tg3 *tp = netdev_priv(dev); 7963 struct tg3 *tp = netdev_priv(dev);
7944 int err; 7964 int i, err;
7945 7965
7946 if (tp->fw_needed) { 7966 if (tp->fw_needed) {
7947 err = tg3_request_firmware(tp); 7967 err = tg3_request_firmware(tp);
@@ -7983,7 +8003,15 @@ static int tg3_open(struct net_device *dev)
7983 8003
7984 napi_enable(&tp->napi[0].napi); 8004 napi_enable(&tp->napi[0].napi);
7985 8005
7986 err = tg3_request_irq(tp); 8006 for (i = 0; i < tp->irq_cnt; i++) {
8007 struct tg3_napi *tnapi = &tp->napi[i];
8008 err = tg3_request_irq(tp, i);
8009 if (err) {
8010 for (i--; i >= 0; i--)
8011 free_irq(tnapi->irq_vec, tnapi);
8012 break;
8013 }
8014 }
7987 8015
7988 if (err) 8016 if (err)
7989 goto err_out1; 8017 goto err_out1;
@@ -8054,7 +8082,10 @@ static int tg3_open(struct net_device *dev)
8054 return 0; 8082 return 0;
8055 8083
8056err_out2: 8084err_out2:
8057 free_irq(tp->pdev->irq, &tp->napi[0]); 8085 for (i = tp->irq_cnt - 1; i >= 0; i--) {
8086 struct tg3_napi *tnapi = &tp->napi[i];
8087 free_irq(tnapi->irq_vec, tnapi);
8088 }
8058 8089
8059err_out1: 8090err_out1:
8060 napi_disable(&tp->napi[0].napi); 8091 napi_disable(&tp->napi[0].napi);
@@ -8298,6 +8329,7 @@ static struct tg3_ethtool_stats *tg3_get_estats(struct tg3 *);
8298 8329
8299static int tg3_close(struct net_device *dev) 8330static int tg3_close(struct net_device *dev)
8300{ 8331{
8332 int i;
8301 struct tg3 *tp = netdev_priv(dev); 8333 struct tg3 *tp = netdev_priv(dev);
8302 8334
8303 napi_disable(&tp->napi[0].napi); 8335 napi_disable(&tp->napi[0].napi);
@@ -8320,7 +8352,10 @@ static int tg3_close(struct net_device *dev)
8320 8352
8321 tg3_full_unlock(tp); 8353 tg3_full_unlock(tp);
8322 8354
8323 free_irq(tp->pdev->irq, &tp->napi[0]); 8355 for (i = tp->irq_cnt - 1; i >= 0; i--) {
8356 struct tg3_napi *tnapi = &tp->napi[i];
8357 free_irq(tnapi->irq_vec, tnapi);
8358 }
8324 8359
8325 tg3_ints_fini(tp); 8360 tg3_ints_fini(tp);
8326 8361
@@ -12151,6 +12186,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
12151 } 12186 }
12152 } 12187 }
12153 12188
12189 tp->irq_max = 1;
12190
12154 if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) || 12191 if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) ||
12155 (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) 12192 (tp->tg3_flags2 & TG3_FLG2_5780_CLASS))
12156 tp->tg3_flags |= TG3_FLAG_JUMBO_CAPABLE; 12193 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 {
2514 dma_addr_t status_mapping; 2514 dma_addr_t status_mapping;
2515 dma_addr_t rx_rcb_mapping; 2515 dma_addr_t rx_rcb_mapping;
2516 dma_addr_t tx_desc_mapping; 2516 dma_addr_t tx_desc_mapping;
2517
2518 char irq_lbl[IFNAMSIZ];
2519 unsigned int irq_vec;
2517}; 2520};
2518 2521
2519struct tg3 { 2522struct tg3 {
@@ -2829,6 +2832,9 @@ struct tg3 {
2829 2832
2830#define SST_25VF0X0_PAGE_SIZE 4098 2833#define SST_25VF0X0_PAGE_SIZE 4098
2831 2834
2835 unsigned int irq_max;
2836 unsigned int irq_cnt;
2837
2832 struct ethtool_coalesce coal; 2838 struct ethtool_coalesce coal;
2833 2839
2834 /* firmware info */ 2840 /* firmware info */