diff options
Diffstat (limited to 'drivers/net/mlx4/mcg.c')
-rw-r--r-- | drivers/net/mlx4/mcg.c | 113 |
1 files changed, 78 insertions, 35 deletions
diff --git a/drivers/net/mlx4/mcg.c b/drivers/net/mlx4/mcg.c index 79cf42db2ea9..b103ad23bd84 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 | ||
51 | static const u8 zero_gid[16]; /* automatically initialized to 0 */ | 52 | static const u8 zero_gid[16]; /* automatically initialized to 0 */ |
52 | 53 | ||
53 | static int mlx4_READ_MCG(struct mlx4_dev *dev, int index, | 54 | static 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 | ||
60 | static int mlx4_WRITE_MCG(struct mlx4_dev *dev, int index, | 61 | static 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 | ||
67 | static int mlx4_MGID_HASH(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, | 68 | static 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 | */ |
97 | static int find_mgm(struct mlx4_dev *dev, | 98 | static 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 | ||
150 | int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], | 153 | int 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 | } |
245 | EXPORT_SYMBOL_GPL(mlx4_multicast_attach); | ||
246 | 250 | ||
247 | int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], | 251 | int 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 | |||
354 | int 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 | } | ||
371 | EXPORT_SYMBOL_GPL(mlx4_multicast_attach); | ||
372 | |||
373 | int 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 | } | ||
346 | EXPORT_SYMBOL_GPL(mlx4_multicast_detach); | 389 | EXPORT_SYMBOL_GPL(mlx4_multicast_detach); |
347 | 390 | ||
348 | int mlx4_init_mcg_table(struct mlx4_dev *dev) | 391 | int mlx4_init_mcg_table(struct mlx4_dev *dev) |