diff options
author | Andrew Gallatin <gallatin@myri.com> | 2010-09-28 04:13:12 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-09-29 22:45:37 -0400 |
commit | ef09aadf7bf1a17f4d4938855238c0fd8749a99f (patch) | |
tree | eb30777402c9f8f36e0751d1a6854bdc7abe02c1 /drivers/net/myri10ge/myri10ge.c | |
parent | 8681dc3abd54e845a2effab441921b4c4457c241 (diff) |
myri10ge: DCA update (resubmit)
This patch contains the following DCA improvements to myri10ge:
1) Finally move myri10ge to use dca3 API
2) Disable PCIe relaxed ordering when enabling DCA on
myri10ge. This provides a performance boost on Nehalem
based Xeons
3) Make sure to properly initialize NIC's DCA state when it is enabled,
rather than giving the NIC a bogus tag (0) and waiting for
the first received packet to trigger an update. Not using a
real tag can cause hardware exceptions on some motherboards
when a CPU socket is empty.
3) Always update the cached CPU when our interrupt affinity changes
so as to avoid excessive calls to dca3_get_tag()
Signed-off-by: Andrew Gallatin <gallatin@myri.com>
Signed-off-by: Loic Prylli <loic@myri.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/myri10ge/myri10ge.c')
-rw-r--r-- | drivers/net/myri10ge/myri10ge.c | 34 |
1 files changed, 30 insertions, 4 deletions
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 3ad1a21ca8ce..8524cc40ec57 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c | |||
@@ -225,6 +225,7 @@ struct myri10ge_priv { | |||
225 | struct msix_entry *msix_vectors; | 225 | struct msix_entry *msix_vectors; |
226 | #ifdef CONFIG_MYRI10GE_DCA | 226 | #ifdef CONFIG_MYRI10GE_DCA |
227 | int dca_enabled; | 227 | int dca_enabled; |
228 | int relaxed_order; | ||
228 | #endif | 229 | #endif |
229 | u32 link_state; | 230 | u32 link_state; |
230 | unsigned int rdma_tags_available; | 231 | unsigned int rdma_tags_available; |
@@ -1074,10 +1075,28 @@ static int myri10ge_reset(struct myri10ge_priv *mgp) | |||
1074 | } | 1075 | } |
1075 | 1076 | ||
1076 | #ifdef CONFIG_MYRI10GE_DCA | 1077 | #ifdef CONFIG_MYRI10GE_DCA |
1078 | static int myri10ge_toggle_relaxed(struct pci_dev *pdev, int on) | ||
1079 | { | ||
1080 | int ret, cap, err; | ||
1081 | u16 ctl; | ||
1082 | |||
1083 | cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); | ||
1084 | if (!cap) | ||
1085 | return 0; | ||
1086 | |||
1087 | err = pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl); | ||
1088 | ret = (ctl & PCI_EXP_DEVCTL_RELAX_EN) >> 4; | ||
1089 | if (ret != on) { | ||
1090 | ctl &= ~PCI_EXP_DEVCTL_RELAX_EN; | ||
1091 | ctl |= (on << 4); | ||
1092 | pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl); | ||
1093 | } | ||
1094 | return ret; | ||
1095 | } | ||
1096 | |||
1077 | static void | 1097 | static void |
1078 | myri10ge_write_dca(struct myri10ge_slice_state *ss, int cpu, int tag) | 1098 | myri10ge_write_dca(struct myri10ge_slice_state *ss, int cpu, int tag) |
1079 | { | 1099 | { |
1080 | ss->cpu = cpu; | ||
1081 | ss->cached_dca_tag = tag; | 1100 | ss->cached_dca_tag = tag; |
1082 | put_be32(htonl(tag), ss->dca_tag); | 1101 | put_be32(htonl(tag), ss->dca_tag); |
1083 | } | 1102 | } |
@@ -1088,9 +1107,10 @@ static inline void myri10ge_update_dca(struct myri10ge_slice_state *ss) | |||
1088 | int tag; | 1107 | int tag; |
1089 | 1108 | ||
1090 | if (cpu != ss->cpu) { | 1109 | if (cpu != ss->cpu) { |
1091 | tag = dca_get_tag(cpu); | 1110 | tag = dca3_get_tag(&ss->mgp->pdev->dev, cpu); |
1092 | if (ss->cached_dca_tag != tag) | 1111 | if (ss->cached_dca_tag != tag) |
1093 | myri10ge_write_dca(ss, cpu, tag); | 1112 | myri10ge_write_dca(ss, cpu, tag); |
1113 | ss->cpu = cpu; | ||
1094 | } | 1114 | } |
1095 | put_cpu(); | 1115 | put_cpu(); |
1096 | } | 1116 | } |
@@ -1113,9 +1133,13 @@ static void myri10ge_setup_dca(struct myri10ge_priv *mgp) | |||
1113 | "dca_add_requester() failed, err=%d\n", err); | 1133 | "dca_add_requester() failed, err=%d\n", err); |
1114 | return; | 1134 | return; |
1115 | } | 1135 | } |
1136 | mgp->relaxed_order = myri10ge_toggle_relaxed(pdev, 0); | ||
1116 | mgp->dca_enabled = 1; | 1137 | mgp->dca_enabled = 1; |
1117 | for (i = 0; i < mgp->num_slices; i++) | 1138 | for (i = 0; i < mgp->num_slices; i++) { |
1118 | myri10ge_write_dca(&mgp->ss[i], -1, 0); | 1139 | mgp->ss[i].cpu = -1; |
1140 | mgp->ss[i].cached_dca_tag = -1; | ||
1141 | myri10ge_update_dca(&mgp->ss[i]); | ||
1142 | } | ||
1119 | } | 1143 | } |
1120 | 1144 | ||
1121 | static void myri10ge_teardown_dca(struct myri10ge_priv *mgp) | 1145 | static void myri10ge_teardown_dca(struct myri10ge_priv *mgp) |
@@ -1126,6 +1150,8 @@ static void myri10ge_teardown_dca(struct myri10ge_priv *mgp) | |||
1126 | if (!mgp->dca_enabled) | 1150 | if (!mgp->dca_enabled) |
1127 | return; | 1151 | return; |
1128 | mgp->dca_enabled = 0; | 1152 | mgp->dca_enabled = 0; |
1153 | if (mgp->relaxed_order) | ||
1154 | myri10ge_toggle_relaxed(pdev, 1); | ||
1129 | err = dca_remove_requester(&pdev->dev); | 1155 | err = dca_remove_requester(&pdev->dev); |
1130 | } | 1156 | } |
1131 | 1157 | ||