aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/mlx4
diff options
context:
space:
mode:
authorYevgeny Petrilin <yevgenyp@mellanox.co.il>2011-03-22 18:38:17 -0400
committerDavid S. Miller <davem@davemloft.net>2011-03-23 15:24:21 -0400
commit0345584e0b8be3735a950d17c7e463db20c6ce27 (patch)
treef49fd3824c1f3b620d456c40539f9b1b88832b69 /drivers/net/mlx4
parent725c89997e03d71b09ea3c17c997da0712b9d835 (diff)
mlx4: generalization of multicast steering.
The same packet steering mechanism would be used both for IB and Ethernet, Both multicasts and unicasts. This commit prepares the general infrastructure for this. Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/mlx4')
-rw-r--r--drivers/net/mlx4/en_main.c2
-rw-r--r--drivers/net/mlx4/fw.c2
-rw-r--r--drivers/net/mlx4/fw.h2
-rw-r--r--drivers/net/mlx4/main.c2
-rw-r--r--drivers/net/mlx4/mcg.c113
5 files changed, 85 insertions, 36 deletions
diff --git a/drivers/net/mlx4/en_main.c b/drivers/net/mlx4/en_main.c
index 29aaa430399..9317b61a75b 100644
--- a/drivers/net/mlx4/en_main.c
+++ b/drivers/net/mlx4/en_main.c
@@ -296,7 +296,7 @@ static struct mlx4_interface mlx4_en_interface = {
296 .remove = mlx4_en_remove, 296 .remove = mlx4_en_remove,
297 .event = mlx4_en_event, 297 .event = mlx4_en_event,
298 .get_dev = mlx4_en_get_netdev, 298 .get_dev = mlx4_en_get_netdev,
299 .protocol = MLX4_PROTOCOL_EN, 299 .protocol = MLX4_PROT_ETH,
300}; 300};
301 301
302static int __init mlx4_en_init(void) 302static int __init mlx4_en_init(void)
diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c
index fd1c51b6197..7813913b6d0 100644
--- a/drivers/net/mlx4/fw.c
+++ b/drivers/net/mlx4/fw.c
@@ -274,6 +274,8 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
274 dev_cap->stat_rate_support = stat_rate; 274 dev_cap->stat_rate_support = stat_rate;
275 MLX4_GET(field, outbox, QUERY_DEV_CAP_UDP_RSS_OFFSET); 275 MLX4_GET(field, outbox, QUERY_DEV_CAP_UDP_RSS_OFFSET);
276 dev_cap->udp_rss = field & 0x1; 276 dev_cap->udp_rss = field & 0x1;
277 dev_cap->vep_uc_steering = field & 0x2;
278 dev_cap->vep_mc_steering = field & 0x4;
277 MLX4_GET(field, outbox, QUERY_DEV_CAP_ETH_UC_LOOPBACK_OFFSET); 279 MLX4_GET(field, outbox, QUERY_DEV_CAP_ETH_UC_LOOPBACK_OFFSET);
278 dev_cap->loopback_support = field & 0x1; 280 dev_cap->loopback_support = field & 0x1;
279 dev_cap->wol = field & 0x40; 281 dev_cap->wol = field & 0x40;
diff --git a/drivers/net/mlx4/fw.h b/drivers/net/mlx4/fw.h
index f7b9cc2d1b2..88003ebc618 100644
--- a/drivers/net/mlx4/fw.h
+++ b/drivers/net/mlx4/fw.h
@@ -80,6 +80,8 @@ struct mlx4_dev_cap {
80 u16 stat_rate_support; 80 u16 stat_rate_support;
81 int udp_rss; 81 int udp_rss;
82 int loopback_support; 82 int loopback_support;
83 int vep_uc_steering;
84 int vep_mc_steering;
83 int wol; 85 int wol;
84 u32 flags; 86 u32 flags;
85 int reserved_uars; 87 int reserved_uars;
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index 5bebb8800ab..da0da281d83 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/mlx4/main.c
@@ -227,6 +227,8 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
227 dev->caps.stat_rate_support = dev_cap->stat_rate_support; 227 dev->caps.stat_rate_support = dev_cap->stat_rate_support;
228 dev->caps.udp_rss = dev_cap->udp_rss; 228 dev->caps.udp_rss = dev_cap->udp_rss;
229 dev->caps.loopback_support = dev_cap->loopback_support; 229 dev->caps.loopback_support = dev_cap->loopback_support;
230 dev->caps.vep_uc_steering = dev_cap->vep_uc_steering;
231 dev->caps.vep_mc_steering = dev_cap->vep_mc_steering;
230 dev->caps.wol = dev_cap->wol; 232 dev->caps.wol = dev_cap->wol;
231 dev->caps.max_gso_sz = dev_cap->max_gso_sz; 233 dev->caps.max_gso_sz = dev_cap->max_gso_sz;
232 234
diff --git a/drivers/net/mlx4/mcg.c b/drivers/net/mlx4/mcg.c
index 79cf42db2ea..b103ad23bd8 100644
--- a/drivers/net/mlx4/mcg.c
+++ b/drivers/net/mlx4/mcg.c
@@ -32,6 +32,7 @@
32 */ 32 */
33 33
34#include <linux/string.h> 34#include <linux/string.h>
35#include <linux/etherdevice.h>
35 36
36#include <linux/mlx4/cmd.h> 37#include <linux/mlx4/cmd.h>
37 38
@@ -50,28 +51,28 @@ struct mlx4_mgm {
50 51
51static const u8 zero_gid[16]; /* automatically initialized to 0 */ 52static const u8 zero_gid[16]; /* automatically initialized to 0 */
52 53
53static int mlx4_READ_MCG(struct mlx4_dev *dev, int index, 54static int mlx4_READ_ENTRY(struct mlx4_dev *dev, int index,
54 struct mlx4_cmd_mailbox *mailbox) 55 struct mlx4_cmd_mailbox *mailbox)
55{ 56{
56 return mlx4_cmd_box(dev, 0, mailbox->dma, index, 0, MLX4_CMD_READ_MCG, 57 return mlx4_cmd_box(dev, 0, mailbox->dma, index, 0, MLX4_CMD_READ_MCG,
57 MLX4_CMD_TIME_CLASS_A); 58 MLX4_CMD_TIME_CLASS_A);
58} 59}
59 60
60static int mlx4_WRITE_MCG(struct mlx4_dev *dev, int index, 61static int mlx4_WRITE_ENTRY(struct mlx4_dev *dev, int index,
61 struct mlx4_cmd_mailbox *mailbox) 62 struct mlx4_cmd_mailbox *mailbox)
62{ 63{
63 return mlx4_cmd(dev, mailbox->dma, index, 0, MLX4_CMD_WRITE_MCG, 64 return mlx4_cmd(dev, mailbox->dma, index, 0, MLX4_CMD_WRITE_MCG,
64 MLX4_CMD_TIME_CLASS_A); 65 MLX4_CMD_TIME_CLASS_A);
65} 66}
66 67
67static int mlx4_MGID_HASH(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, 68static int mlx4_GID_HASH(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
68 u16 *hash) 69 u16 *hash, u8 op_mod)
69{ 70{
70 u64 imm; 71 u64 imm;
71 int err; 72 int err;
72 73
73 err = mlx4_cmd_imm(dev, mailbox->dma, &imm, 0, 0, MLX4_CMD_MGID_HASH, 74 err = mlx4_cmd_imm(dev, mailbox->dma, &imm, 0, op_mod,
74 MLX4_CMD_TIME_CLASS_A); 75 MLX4_CMD_MGID_HASH, MLX4_CMD_TIME_CLASS_A);
75 76
76 if (!err) 77 if (!err)
77 *hash = imm; 78 *hash = imm;
@@ -94,15 +95,17 @@ static int mlx4_MGID_HASH(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox
94 * If no AMGM exists for given gid, *index = -1, *prev = index of last 95 * If no AMGM exists for given gid, *index = -1, *prev = index of last
95 * entry in hash chain and *mgm holds end of hash chain. 96 * entry in hash chain and *mgm holds end of hash chain.
96 */ 97 */
97static int find_mgm(struct mlx4_dev *dev, 98static int find_entry(struct mlx4_dev *dev, u8 port,
98 u8 *gid, enum mlx4_protocol protocol, 99 u8 *gid, enum mlx4_protocol prot,
99 struct mlx4_cmd_mailbox *mgm_mailbox, 100 enum mlx4_steer_type steer,
100 u16 *hash, int *prev, int *index) 101 struct mlx4_cmd_mailbox *mgm_mailbox,
102 u16 *hash, int *prev, int *index)
101{ 103{
102 struct mlx4_cmd_mailbox *mailbox; 104 struct mlx4_cmd_mailbox *mailbox;
103 struct mlx4_mgm *mgm = mgm_mailbox->buf; 105 struct mlx4_mgm *mgm = mgm_mailbox->buf;
104 u8 *mgid; 106 u8 *mgid;
105 int err; 107 int err;
108 u8 op_mod = (prot == MLX4_PROT_ETH) ? !!(dev->caps.vep_mc_steering) : 0;
106 109
107 mailbox = mlx4_alloc_cmd_mailbox(dev); 110 mailbox = mlx4_alloc_cmd_mailbox(dev);
108 if (IS_ERR(mailbox)) 111 if (IS_ERR(mailbox))
@@ -111,7 +114,7 @@ static int find_mgm(struct mlx4_dev *dev,
111 114
112 memcpy(mgid, gid, 16); 115 memcpy(mgid, gid, 16);
113 116
114 err = mlx4_MGID_HASH(dev, mailbox, hash); 117 err = mlx4_GID_HASH(dev, mailbox, hash, op_mod);
115 mlx4_free_cmd_mailbox(dev, mailbox); 118 mlx4_free_cmd_mailbox(dev, mailbox);
116 if (err) 119 if (err)
117 return err; 120 return err;
@@ -123,11 +126,11 @@ static int find_mgm(struct mlx4_dev *dev,
123 *prev = -1; 126 *prev = -1;
124 127
125 do { 128 do {
126 err = mlx4_READ_MCG(dev, *index, mgm_mailbox); 129 err = mlx4_READ_ENTRY(dev, *index, mgm_mailbox);
127 if (err) 130 if (err)
128 return err; 131 return err;
129 132
130 if (!memcmp(mgm->gid, zero_gid, 16)) { 133 if (!(be32_to_cpu(mgm->members_count) & 0xffffff)) {
131 if (*index != *hash) { 134 if (*index != *hash) {
132 mlx4_err(dev, "Found zero MGID in AMGM.\n"); 135 mlx4_err(dev, "Found zero MGID in AMGM.\n");
133 err = -EINVAL; 136 err = -EINVAL;
@@ -136,7 +139,7 @@ static int find_mgm(struct mlx4_dev *dev,
136 } 139 }
137 140
138 if (!memcmp(mgm->gid, gid, 16) && 141 if (!memcmp(mgm->gid, gid, 16) &&
139 be32_to_cpu(mgm->members_count) >> 30 == protocol) 142 be32_to_cpu(mgm->members_count) >> 30 == prot)
140 return err; 143 return err;
141 144
142 *prev = *index; 145 *prev = *index;
@@ -147,8 +150,9 @@ static int find_mgm(struct mlx4_dev *dev,
147 return err; 150 return err;
148} 151}
149 152
150int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], 153int mlx4_qp_attach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
151 int block_mcast_loopback, enum mlx4_protocol protocol) 154 int block_mcast_loopback, enum mlx4_protocol prot,
155 enum mlx4_steer_type steer)
152{ 156{
153 struct mlx4_priv *priv = mlx4_priv(dev); 157 struct mlx4_priv *priv = mlx4_priv(dev);
154 struct mlx4_cmd_mailbox *mailbox; 158 struct mlx4_cmd_mailbox *mailbox;
@@ -159,6 +163,7 @@ int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
159 int link = 0; 163 int link = 0;
160 int i; 164 int i;
161 int err; 165 int err;
166 u8 port = gid[5];
162 167
163 mailbox = mlx4_alloc_cmd_mailbox(dev); 168 mailbox = mlx4_alloc_cmd_mailbox(dev);
164 if (IS_ERR(mailbox)) 169 if (IS_ERR(mailbox))
@@ -166,13 +171,13 @@ int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
166 mgm = mailbox->buf; 171 mgm = mailbox->buf;
167 172
168 mutex_lock(&priv->mcg_table.mutex); 173 mutex_lock(&priv->mcg_table.mutex);
169 174 err = find_entry(dev, port, gid, prot, steer,
170 err = find_mgm(dev, gid, protocol, mailbox, &hash, &prev, &index); 175 mailbox, &hash, &prev, &index);
171 if (err) 176 if (err)
172 goto out; 177 goto out;
173 178
174 if (index != -1) { 179 if (index != -1) {
175 if (!memcmp(mgm->gid, zero_gid, 16)) 180 if (!(be32_to_cpu(mgm->members_count) & 0xffffff))
176 memcpy(mgm->gid, gid, 16); 181 memcpy(mgm->gid, gid, 16);
177 } else { 182 } else {
178 link = 1; 183 link = 1;
@@ -209,22 +214,22 @@ int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
209 else 214 else
210 mgm->qp[members_count++] = cpu_to_be32(qp->qpn & MGM_QPN_MASK); 215 mgm->qp[members_count++] = cpu_to_be32(qp->qpn & MGM_QPN_MASK);
211 216
212 mgm->members_count = cpu_to_be32(members_count | (u32) protocol << 30); 217 mgm->members_count = cpu_to_be32(members_count | (u32) prot << 30);
213 218
214 err = mlx4_WRITE_MCG(dev, index, mailbox); 219 err = mlx4_WRITE_ENTRY(dev, index, mailbox);
215 if (err) 220 if (err)
216 goto out; 221 goto out;
217 222
218 if (!link) 223 if (!link)
219 goto out; 224 goto out;
220 225
221 err = mlx4_READ_MCG(dev, prev, mailbox); 226 err = mlx4_READ_ENTRY(dev, prev, mailbox);
222 if (err) 227 if (err)
223 goto out; 228 goto out;
224 229
225 mgm->next_gid_index = cpu_to_be32(index << 6); 230 mgm->next_gid_index = cpu_to_be32(index << 6);
226 231
227 err = mlx4_WRITE_MCG(dev, prev, mailbox); 232 err = mlx4_WRITE_ENTRY(dev, prev, mailbox);
228 if (err) 233 if (err)
229 goto out; 234 goto out;
230 235
@@ -242,10 +247,9 @@ out:
242 mlx4_free_cmd_mailbox(dev, mailbox); 247 mlx4_free_cmd_mailbox(dev, mailbox);
243 return err; 248 return err;
244} 249}
245EXPORT_SYMBOL_GPL(mlx4_multicast_attach);
246 250
247int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], 251int mlx4_qp_detach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
248 enum mlx4_protocol protocol) 252 enum mlx4_protocol prot, enum mlx4_steer_type steer)
249{ 253{
250 struct mlx4_priv *priv = mlx4_priv(dev); 254 struct mlx4_priv *priv = mlx4_priv(dev);
251 struct mlx4_cmd_mailbox *mailbox; 255 struct mlx4_cmd_mailbox *mailbox;
@@ -255,6 +259,7 @@ int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
255 int prev, index; 259 int prev, index;
256 int i, loc; 260 int i, loc;
257 int err; 261 int err;
262 u8 port = gid[5];
258 263
259 mailbox = mlx4_alloc_cmd_mailbox(dev); 264 mailbox = mlx4_alloc_cmd_mailbox(dev);
260 if (IS_ERR(mailbox)) 265 if (IS_ERR(mailbox))
@@ -263,7 +268,8 @@ int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
263 268
264 mutex_lock(&priv->mcg_table.mutex); 269 mutex_lock(&priv->mcg_table.mutex);
265 270
266 err = find_mgm(dev, gid, protocol, mailbox, &hash, &prev, &index); 271 err = find_entry(dev, port, gid, prot, steer,
272 mailbox, &hash, &prev, &index);
267 if (err) 273 if (err)
268 goto out; 274 goto out;
269 275
@@ -285,12 +291,12 @@ int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
285 } 291 }
286 292
287 293
288 mgm->members_count = cpu_to_be32(--members_count | (u32) protocol << 30); 294 mgm->members_count = cpu_to_be32(--members_count | (u32) prot << 30);
289 mgm->qp[loc] = mgm->qp[i - 1]; 295 mgm->qp[loc] = mgm->qp[i - 1];
290 mgm->qp[i - 1] = 0; 296 mgm->qp[i - 1] = 0;
291 297
292 if (i != 1) { 298 if (i != 1) {
293 err = mlx4_WRITE_MCG(dev, index, mailbox); 299 err = mlx4_WRITE_ENTRY(dev, index, mailbox);
294 goto out; 300 goto out;
295 } 301 }
296 302
@@ -298,13 +304,13 @@ int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
298 /* Remove entry from MGM */ 304 /* Remove entry from MGM */
299 int amgm_index = be32_to_cpu(mgm->next_gid_index) >> 6; 305 int amgm_index = be32_to_cpu(mgm->next_gid_index) >> 6;
300 if (amgm_index) { 306 if (amgm_index) {
301 err = mlx4_READ_MCG(dev, amgm_index, mailbox); 307 err = mlx4_READ_ENTRY(dev, amgm_index, mailbox);
302 if (err) 308 if (err)
303 goto out; 309 goto out;
304 } else 310 } else
305 memset(mgm->gid, 0, 16); 311 memset(mgm->gid, 0, 16);
306 312
307 err = mlx4_WRITE_MCG(dev, index, mailbox); 313 err = mlx4_WRITE_ENTRY(dev, index, mailbox);
308 if (err) 314 if (err)
309 goto out; 315 goto out;
310 316
@@ -319,13 +325,13 @@ int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
319 } else { 325 } else {
320 /* Remove entry from AMGM */ 326 /* Remove entry from AMGM */
321 int cur_next_index = be32_to_cpu(mgm->next_gid_index) >> 6; 327 int cur_next_index = be32_to_cpu(mgm->next_gid_index) >> 6;
322 err = mlx4_READ_MCG(dev, prev, mailbox); 328 err = mlx4_READ_ENTRY(dev, prev, mailbox);
323 if (err) 329 if (err)
324 goto out; 330 goto out;
325 331
326 mgm->next_gid_index = cpu_to_be32(cur_next_index << 6); 332 mgm->next_gid_index = cpu_to_be32(cur_next_index << 6);
327 333
328 err = mlx4_WRITE_MCG(dev, prev, mailbox); 334 err = mlx4_WRITE_ENTRY(dev, prev, mailbox);
329 if (err) 335 if (err)
330 goto out; 336 goto out;
331 337
@@ -343,6 +349,43 @@ out:
343 mlx4_free_cmd_mailbox(dev, mailbox); 349 mlx4_free_cmd_mailbox(dev, mailbox);
344 return err; 350 return err;
345} 351}
352
353
354int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
355 int block_mcast_loopback, enum mlx4_protocol prot)
356{
357 enum mlx4_steer_type steer;
358
359 steer = (is_valid_ether_addr(&gid[10])) ? MLX4_UC_STEER : MLX4_MC_STEER;
360
361 if (prot == MLX4_PROT_ETH && !dev->caps.vep_mc_steering)
362 return 0;
363
364 if (prot == MLX4_PROT_ETH)
365 gid[7] |= (steer << 1);
366
367 return mlx4_qp_attach_common(dev, qp, gid,
368 block_mcast_loopback, prot,
369 steer);
370}
371EXPORT_SYMBOL_GPL(mlx4_multicast_attach);
372
373int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
374 enum mlx4_protocol prot)
375{
376 enum mlx4_steer_type steer;
377
378 steer = (is_valid_ether_addr(&gid[10])) ? MLX4_UC_STEER : MLX4_MC_STEER;
379
380 if (prot == MLX4_PROT_ETH && !dev->caps.vep_mc_steering)
381 return 0;
382
383 if (prot == MLX4_PROT_ETH) {
384 gid[7] |= (steer << 1);
385 }
386
387 return mlx4_qp_detach_common(dev, qp, gid, prot, steer);
388}
346EXPORT_SYMBOL_GPL(mlx4_multicast_detach); 389EXPORT_SYMBOL_GPL(mlx4_multicast_detach);
347 390
348int mlx4_init_mcg_table(struct mlx4_dev *dev) 391int mlx4_init_mcg_table(struct mlx4_dev *dev)