aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/tg3.c
diff options
context:
space:
mode:
authorMatt Carlson <mcarlson@broadcom.com>2009-09-01 08:55:46 -0400
committerDavid S. Miller <davem@davemloft.net>2009-09-02 03:43:33 -0400
commit679563f47cd2547a0e091b5bd3ddf30027af6b08 (patch)
treeefb6a8a9e6d080447b89014725bfcfad0b33a3e6 /drivers/net/tg3.c
parent4f125f42dd55390016e21f8b3960f99d02d1001f (diff)
tg3: Add MSI-X support
This patch adds MSI-X support. 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/tg3.c')
-rw-r--r--drivers/net/tg3.c108
1 files changed, 81 insertions, 27 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 7717eae1221d..12ead83bd06f 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -160,6 +160,7 @@ MODULE_FIRMWARE(FIRMWARE_TG3);
160MODULE_FIRMWARE(FIRMWARE_TG3TSO); 160MODULE_FIRMWARE(FIRMWARE_TG3TSO);
161MODULE_FIRMWARE(FIRMWARE_TG3TSO5); 161MODULE_FIRMWARE(FIRMWARE_TG3TSO5);
162 162
163#define TG3_RSS_MIN_NUM_MSIX_VECS 2
163 164
164static int tg3_debug = -1; /* -1 == use TG3_DEF_MSG_ENABLE as value */ 165static int tg3_debug = -1; /* -1 == use TG3_DEF_MSG_ENABLE as value */
165module_param(tg3_debug, int, 0); 166module_param(tg3_debug, int, 0);
@@ -7767,7 +7768,7 @@ static int tg3_request_irq(struct tg3 *tp, int irq_num)
7767 name[IFNAMSIZ-1] = 0; 7768 name[IFNAMSIZ-1] = 0;
7768 } 7769 }
7769 7770
7770 if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) { 7771 if (tp->tg3_flags2 & TG3_FLG2_USING_MSI_OR_MSIX) {
7771 fn = tg3_msi; 7772 fn = tg3_msi;
7772 if (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI) 7773 if (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI)
7773 fn = tg3_msi_1shot; 7774 fn = tg3_msi_1shot;
@@ -7928,34 +7929,81 @@ static int tg3_request_firmware(struct tg3 *tp)
7928 return 0; 7929 return 0;
7929} 7930}
7930 7931
7932static bool tg3_enable_msix(struct tg3 *tp)
7933{
7934 int i, rc, cpus = num_online_cpus();
7935 struct msix_entry msix_ent[tp->irq_max];
7936
7937 if (cpus == 1)
7938 /* Just fallback to the simpler MSI mode. */
7939 return false;
7940
7941 /*
7942 * We want as many rx rings enabled as there are cpus.
7943 * The first MSIX vector only deals with link interrupts, etc,
7944 * so we add one to the number of vectors we are requesting.
7945 */
7946 tp->irq_cnt = min_t(unsigned, cpus + 1, tp->irq_max);
7947
7948 for (i = 0; i < tp->irq_max; i++) {
7949 msix_ent[i].entry = i;
7950 msix_ent[i].vector = 0;
7951 }
7952
7953 rc = pci_enable_msix(tp->pdev, msix_ent, tp->irq_cnt);
7954 if (rc != 0) {
7955 if (rc < TG3_RSS_MIN_NUM_MSIX_VECS)
7956 return false;
7957 if (pci_enable_msix(tp->pdev, msix_ent, rc))
7958 return false;
7959 printk(KERN_NOTICE
7960 "%s: Requested %d MSI-X vectors, received %d\n",
7961 tp->dev->name, tp->irq_cnt, rc);
7962 tp->irq_cnt = rc;
7963 }
7964
7965 for (i = 0; i < tp->irq_max; i++)
7966 tp->napi[i].irq_vec = msix_ent[i].vector;
7967
7968 return true;
7969}
7970
7931static void tg3_ints_init(struct tg3 *tp) 7971static void tg3_ints_init(struct tg3 *tp)
7932{ 7972{
7933 if (tp->tg3_flags & TG3_FLAG_SUPPORT_MSI) { 7973 if ((tp->tg3_flags & TG3_FLAG_SUPPORT_MSI_OR_MSIX) &&
7974 !(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)) {
7934 /* All MSI supporting chips should support tagged 7975 /* All MSI supporting chips should support tagged
7935 * status. Assert that this is the case. 7976 * status. Assert that this is the case.
7936 */ 7977 */
7937 if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)) { 7978 printk(KERN_WARNING PFX "%s: MSI without TAGGED? "
7938 printk(KERN_WARNING PFX "%s: MSI without TAGGED? " 7979 "Not using MSI.\n", tp->dev->name);
7939 "Not using MSI.\n", tp->dev->name); 7980 goto defcfg;
7940 } else if (pci_enable_msi(tp->pdev) == 0) {
7941 u32 msi_mode;
7942
7943 msi_mode = tr32(MSGINT_MODE);
7944 tw32(MSGINT_MODE, msi_mode | MSGINT_MODE_ENABLE);
7945 tp->tg3_flags2 |= TG3_FLG2_USING_MSI;
7946 }
7947 } 7981 }
7948 7982
7949 tp->irq_cnt = 1; 7983 if ((tp->tg3_flags & TG3_FLAG_SUPPORT_MSIX) && tg3_enable_msix(tp))
7950 tp->napi[0].irq_vec = tp->pdev->irq; 7984 tp->tg3_flags2 |= TG3_FLG2_USING_MSIX;
7985 else if ((tp->tg3_flags & TG3_FLAG_SUPPORT_MSI) &&
7986 pci_enable_msi(tp->pdev) == 0)
7987 tp->tg3_flags2 |= TG3_FLG2_USING_MSI;
7988
7989 if (tp->tg3_flags2 & TG3_FLG2_USING_MSI_OR_MSIX) {
7990 u32 msi_mode = tr32(MSGINT_MODE);
7991 tw32(MSGINT_MODE, msi_mode | MSGINT_MODE_ENABLE);
7992 }
7993defcfg:
7994 if (!(tp->tg3_flags2 & TG3_FLG2_USING_MSIX)) {
7995 tp->irq_cnt = 1;
7996 tp->napi[0].irq_vec = tp->pdev->irq;
7997 }
7951} 7998}
7952 7999
7953static void tg3_ints_fini(struct tg3 *tp) 8000static void tg3_ints_fini(struct tg3 *tp)
7954{ 8001{
7955 if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) { 8002 if (tp->tg3_flags2 & TG3_FLG2_USING_MSIX)
7956 pci_disable_msi(tp->pdev); 8003 pci_disable_msix(tp->pdev);
7957 tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI; 8004 else if (tp->tg3_flags2 & TG3_FLG2_USING_MSI)
7958 } 8005 pci_disable_msi(tp->pdev);
8006 tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI_OR_MSIX;
7959} 8007}
7960 8008
7961static int tg3_open(struct net_device *dev) 8009static int tg3_open(struct net_device *dev)
@@ -7992,14 +8040,18 @@ static int tg3_open(struct net_device *dev)
7992 8040
7993 tg3_full_unlock(tp); 8041 tg3_full_unlock(tp);
7994 8042
8043 /*
8044 * Setup interrupts first so we know how
8045 * many NAPI resources to allocate
8046 */
8047 tg3_ints_init(tp);
8048
7995 /* The placement of this call is tied 8049 /* The placement of this call is tied
7996 * to the setup and use of Host TX descriptors. 8050 * to the setup and use of Host TX descriptors.
7997 */ 8051 */
7998 err = tg3_alloc_consistent(tp); 8052 err = tg3_alloc_consistent(tp);
7999 if (err) 8053 if (err)
8000 return err; 8054 goto err_out1;
8001
8002 tg3_ints_init(tp);
8003 8055
8004 napi_enable(&tp->napi[0].napi); 8056 napi_enable(&tp->napi[0].napi);
8005 8057
@@ -8014,7 +8066,7 @@ static int tg3_open(struct net_device *dev)
8014 } 8066 }
8015 8067
8016 if (err) 8068 if (err)
8017 goto err_out1; 8069 goto err_out2;
8018 8070
8019 tg3_full_lock(tp, 0); 8071 tg3_full_lock(tp, 0);
8020 8072
@@ -8043,7 +8095,7 @@ static int tg3_open(struct net_device *dev)
8043 tg3_full_unlock(tp); 8095 tg3_full_unlock(tp);
8044 8096
8045 if (err) 8097 if (err)
8046 goto err_out2; 8098 goto err_out3;
8047 8099
8048 if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) { 8100 if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
8049 err = tg3_test_msi(tp); 8101 err = tg3_test_msi(tp);
@@ -8054,7 +8106,7 @@ static int tg3_open(struct net_device *dev)
8054 tg3_free_rings(tp); 8106 tg3_free_rings(tp);
8055 tg3_full_unlock(tp); 8107 tg3_full_unlock(tp);
8056 8108
8057 goto err_out1; 8109 goto err_out2;
8058 } 8110 }
8059 8111
8060 if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) { 8112 if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
@@ -8081,16 +8133,18 @@ static int tg3_open(struct net_device *dev)
8081 8133
8082 return 0; 8134 return 0;
8083 8135
8084err_out2: 8136err_out3:
8085 for (i = tp->irq_cnt - 1; i >= 0; i--) { 8137 for (i = tp->irq_cnt - 1; i >= 0; i--) {
8086 struct tg3_napi *tnapi = &tp->napi[i]; 8138 struct tg3_napi *tnapi = &tp->napi[i];
8087 free_irq(tnapi->irq_vec, tnapi); 8139 free_irq(tnapi->irq_vec, tnapi);
8088 } 8140 }
8089 8141
8090err_out1: 8142err_out2:
8091 napi_disable(&tp->napi[0].napi); 8143 napi_disable(&tp->napi[0].napi);
8092 tg3_ints_fini(tp);
8093 tg3_free_consistent(tp); 8144 tg3_free_consistent(tp);
8145
8146err_out1:
8147 tg3_ints_fini(tp);
8094 return err; 8148 return err;
8095} 8149}
8096 8150