diff options
author | Matt Carlson <mcarlson@broadcom.com> | 2009-09-01 08:55:02 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-09-02 03:43:30 -0400 |
commit | 4f125f42dd55390016e21f8b3960f99d02d1001f (patch) | |
tree | a976eb6c317db2a93bad2ba339be627deb59b3be /drivers/net | |
parent | 2d31ecaf10c4ae03d49aed516481b2839b0220f6 (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/net')
-rw-r--r-- | drivers/net/tg3.c | 73 | ||||
-rw-r--r-- | drivers/net/tg3.h | 6 |
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 | ||
4730 | static void tg3_irq_quiesce(struct tg3 *tp) | 4730 | static 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 | ||
4740 | static inline int tg3_irq_sync(struct tg3 *tp) | 4743 | static 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 |
4948 | static void tg3_poll_controller(struct net_device *dev) | 4951 | static 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 | ||
7748 | static int tg3_request_irq(struct tg3 *tp) | 7755 | static 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 | ||
7768 | static int tg3_test_interrupt(struct tg3 *tp) | 7785 | static 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 | ||
7933 | static void tg3_ints_fini(struct tg3 *tp) | 7953 | static void tg3_ints_fini(struct tg3 *tp) |
@@ -7941,7 +7961,7 @@ static void tg3_ints_fini(struct tg3 *tp) | |||
7941 | static int tg3_open(struct net_device *dev) | 7961 | static 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 | ||
8056 | err_out2: | 8084 | err_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 | ||
8059 | err_out1: | 8090 | err_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 | ||
8299 | static int tg3_close(struct net_device *dev) | 8330 | static 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 | ||
2519 | struct tg3 { | 2522 | struct 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 */ |