xref: /linux/drivers/net/ethernet/mellanox/mlx4/port.c (revision f2ee442115c9b6219083c019939a9cc0c9abb2f8)
1 /*
2  * Copyright (c) 2007 Mellanox Technologies. All rights reserved.
3  *
4  * This software is available to you under a choice of one of two
5  * licenses.  You may choose to be licensed under the terms of the GNU
6  * General Public License (GPL) Version 2, available from the file
7  * COPYING in the main directory of this source tree, or the
8  * OpenIB.org BSD license below:
9  *
10  *     Redistribution and use in source and binary forms, with or
11  *     without modification, are permitted provided that the following
12  *     conditions are met:
13  *
14  *      - Redistributions of source code must retain the above
15  *        copyright notice, this list of conditions and the following
16  *        disclaimer.
17  *
18  *      - Redistributions in binary form must reproduce the above
19  *        copyright notice, this list of conditions and the following
20  *        disclaimer in the documentation and/or other materials
21  *        provided with the distribution.
22  *
23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30  * SOFTWARE.
31  */
32 
33 #include <linux/errno.h>
34 #include <linux/if_ether.h>
35 #include <linux/export.h>
36 
37 #include <linux/mlx4/cmd.h>
38 
39 #include "mlx4.h"
40 
41 #define MLX4_MAC_VALID		(1ull << 63)
42 #define MLX4_MAC_MASK		0xffffffffffffULL
43 
44 #define MLX4_VLAN_VALID		(1u << 31)
45 #define MLX4_VLAN_MASK		0xfff
46 
47 void mlx4_init_mac_table(struct mlx4_dev *dev, struct mlx4_mac_table *table)
48 {
49 	int i;
50 
51 	mutex_init(&table->mutex);
52 	for (i = 0; i < MLX4_MAX_MAC_NUM; i++) {
53 		table->entries[i] = 0;
54 		table->refs[i]	 = 0;
55 	}
56 	table->max   = 1 << dev->caps.log_num_macs;
57 	table->total = 0;
58 }
59 
60 void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table)
61 {
62 	int i;
63 
64 	mutex_init(&table->mutex);
65 	for (i = 0; i < MLX4_MAX_VLAN_NUM; i++) {
66 		table->entries[i] = 0;
67 		table->refs[i]	 = 0;
68 	}
69 	table->max   = (1 << dev->caps.log_num_vlans) - MLX4_VLAN_REGULAR;
70 	table->total = 0;
71 }
72 
73 static int mlx4_set_port_mac_table(struct mlx4_dev *dev, u8 port,
74 				   __be64 *entries)
75 {
76 	struct mlx4_cmd_mailbox *mailbox;
77 	u32 in_mod;
78 	int err;
79 
80 	mailbox = mlx4_alloc_cmd_mailbox(dev);
81 	if (IS_ERR(mailbox))
82 		return PTR_ERR(mailbox);
83 
84 	memcpy(mailbox->buf, entries, MLX4_MAC_TABLE_SIZE);
85 
86 	in_mod = MLX4_SET_PORT_MAC_TABLE << 8 | port;
87 	err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT,
88 		       MLX4_CMD_TIME_CLASS_B);
89 
90 	mlx4_free_cmd_mailbox(dev, mailbox);
91 	return err;
92 }
93 
94 static int mlx4_uc_steer_add(struct mlx4_dev *dev, u8 port,
95 			     u64 mac, int *qpn, u8 reserve)
96 {
97 	struct mlx4_qp qp;
98 	u8 gid[16] = {0};
99 	int err;
100 
101 	if (reserve) {
102 		err = mlx4_qp_reserve_range(dev, 1, 1, qpn);
103 		if (err) {
104 			mlx4_err(dev, "Failed to reserve qp for mac registration\n");
105 			return err;
106 		}
107 	}
108 	qp.qpn = *qpn;
109 
110 	mac &= 0xffffffffffffULL;
111 	mac = cpu_to_be64(mac << 16);
112 	memcpy(&gid[10], &mac, ETH_ALEN);
113 	gid[5] = port;
114 	gid[7] = MLX4_UC_STEER << 1;
115 
116 	err = mlx4_qp_attach_common(dev, &qp, gid, 0,
117 				    MLX4_PROT_ETH, MLX4_UC_STEER);
118 	if (err && reserve)
119 		mlx4_qp_release_range(dev, *qpn, 1);
120 
121 	return err;
122 }
123 
124 static void mlx4_uc_steer_release(struct mlx4_dev *dev, u8 port,
125 				  u64 mac, int qpn, u8 free)
126 {
127 	struct mlx4_qp qp;
128 	u8 gid[16] = {0};
129 
130 	qp.qpn = qpn;
131 	mac &= 0xffffffffffffULL;
132 	mac = cpu_to_be64(mac << 16);
133 	memcpy(&gid[10], &mac, ETH_ALEN);
134 	gid[5] = port;
135 	gid[7] = MLX4_UC_STEER << 1;
136 
137 	mlx4_qp_detach_common(dev, &qp, gid, MLX4_PROT_ETH, MLX4_UC_STEER);
138 	if (free)
139 		mlx4_qp_release_range(dev, qpn, 1);
140 }
141 
142 int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn, u8 wrap)
143 {
144 	struct mlx4_port_info *info = &mlx4_priv(dev)->port[port];
145 	struct mlx4_mac_table *table = &info->mac_table;
146 	struct mlx4_mac_entry *entry;
147 	int i, err = 0;
148 	int free = -1;
149 
150 	if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER) {
151 		err = mlx4_uc_steer_add(dev, port, mac, qpn, 1);
152 		if (err)
153 			return err;
154 
155 		entry = kmalloc(sizeof *entry, GFP_KERNEL);
156 		if (!entry) {
157 			mlx4_uc_steer_release(dev, port, mac, *qpn, 1);
158 			return -ENOMEM;
159 		}
160 
161 		entry->mac = mac;
162 		err = radix_tree_insert(&info->mac_tree, *qpn, entry);
163 		if (err) {
164 			kfree(entry);
165 			mlx4_uc_steer_release(dev, port, mac, *qpn, 1);
166 			return err;
167 		}
168 	}
169 
170 	mlx4_dbg(dev, "Registering MAC: 0x%llx\n", (unsigned long long) mac);
171 
172 	mutex_lock(&table->mutex);
173 	for (i = 0; i < MLX4_MAX_MAC_NUM - 1; i++) {
174 		if (free < 0 && !table->refs[i]) {
175 			free = i;
176 			continue;
177 		}
178 
179 		if (mac == (MLX4_MAC_MASK & be64_to_cpu(table->entries[i]))) {
180 			/* MAC already registered, increase references count */
181 			++table->refs[i];
182 			goto out;
183 		}
184 	}
185 
186 	if (free < 0) {
187 		err = -ENOMEM;
188 		goto out;
189 	}
190 
191 	mlx4_dbg(dev, "Free MAC index is %d\n", free);
192 
193 	if (table->total == table->max) {
194 		/* No free mac entries */
195 		err = -ENOSPC;
196 		goto out;
197 	}
198 
199 	/* Register new MAC */
200 	table->refs[free] = 1;
201 	table->entries[free] = cpu_to_be64(mac | MLX4_MAC_VALID);
202 
203 	err = mlx4_set_port_mac_table(dev, port, table->entries);
204 	if (unlikely(err)) {
205 		mlx4_err(dev, "Failed adding MAC: 0x%llx\n", (unsigned long long) mac);
206 		table->refs[free] = 0;
207 		table->entries[free] = 0;
208 		goto out;
209 	}
210 
211 	if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER))
212 		*qpn = info->base_qpn + free;
213 	++table->total;
214 out:
215 	mutex_unlock(&table->mutex);
216 	return err;
217 }
218 EXPORT_SYMBOL_GPL(mlx4_register_mac);
219 
220 static int validate_index(struct mlx4_dev *dev,
221 			  struct mlx4_mac_table *table, int index)
222 {
223 	int err = 0;
224 
225 	if (index < 0 || index >= table->max || !table->entries[index]) {
226 		mlx4_warn(dev, "No valid Mac entry for the given index\n");
227 		err = -EINVAL;
228 	}
229 	return err;
230 }
231 
232 static int find_index(struct mlx4_dev *dev,
233 		      struct mlx4_mac_table *table, u64 mac)
234 {
235 	int i;
236 	for (i = 0; i < MLX4_MAX_MAC_NUM; i++) {
237 		if (mac == (MLX4_MAC_MASK & be64_to_cpu(table->entries[i])))
238 			return i;
239 	}
240 	/* Mac not found */
241 	return -EINVAL;
242 }
243 
244 void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, int qpn)
245 {
246 	struct mlx4_port_info *info = &mlx4_priv(dev)->port[port];
247 	struct mlx4_mac_table *table = &info->mac_table;
248 	int index = qpn - info->base_qpn;
249 	struct mlx4_mac_entry *entry;
250 
251 	if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER) {
252 		entry = radix_tree_lookup(&info->mac_tree, qpn);
253 		if (entry) {
254 			mlx4_uc_steer_release(dev, port, entry->mac, qpn, 1);
255 			radix_tree_delete(&info->mac_tree, qpn);
256 			index = find_index(dev, table, entry->mac);
257 			kfree(entry);
258 		}
259 	}
260 
261 	mutex_lock(&table->mutex);
262 
263 	if (validate_index(dev, table, index))
264 		goto out;
265 
266 	/* Check whether this address has reference count */
267 	if (!(--table->refs[index])) {
268 		table->entries[index] = 0;
269 		mlx4_set_port_mac_table(dev, port, table->entries);
270 		--table->total;
271 	}
272 out:
273 	mutex_unlock(&table->mutex);
274 }
275 EXPORT_SYMBOL_GPL(mlx4_unregister_mac);
276 
277 int mlx4_replace_mac(struct mlx4_dev *dev, u8 port, int qpn, u64 new_mac, u8 wrap)
278 {
279 	struct mlx4_port_info *info = &mlx4_priv(dev)->port[port];
280 	struct mlx4_mac_table *table = &info->mac_table;
281 	int index = qpn - info->base_qpn;
282 	struct mlx4_mac_entry *entry;
283 	int err;
284 
285 	if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER) {
286 		entry = radix_tree_lookup(&info->mac_tree, qpn);
287 		if (!entry)
288 			return -EINVAL;
289 		index = find_index(dev, table, entry->mac);
290 		mlx4_uc_steer_release(dev, port, entry->mac, qpn, 0);
291 		entry->mac = new_mac;
292 		err = mlx4_uc_steer_add(dev, port, entry->mac, &qpn, 0);
293 		if (err || index < 0)
294 			return err;
295 	}
296 
297 	mutex_lock(&table->mutex);
298 
299 	err = validate_index(dev, table, index);
300 	if (err)
301 		goto out;
302 
303 	table->entries[index] = cpu_to_be64(new_mac | MLX4_MAC_VALID);
304 
305 	err = mlx4_set_port_mac_table(dev, port, table->entries);
306 	if (unlikely(err)) {
307 		mlx4_err(dev, "Failed adding MAC: 0x%llx\n", (unsigned long long) new_mac);
308 		table->entries[index] = 0;
309 	}
310 out:
311 	mutex_unlock(&table->mutex);
312 	return err;
313 }
314 EXPORT_SYMBOL_GPL(mlx4_replace_mac);
315 static int mlx4_set_port_vlan_table(struct mlx4_dev *dev, u8 port,
316 				    __be32 *entries)
317 {
318 	struct mlx4_cmd_mailbox *mailbox;
319 	u32 in_mod;
320 	int err;
321 
322 	mailbox = mlx4_alloc_cmd_mailbox(dev);
323 	if (IS_ERR(mailbox))
324 		return PTR_ERR(mailbox);
325 
326 	memcpy(mailbox->buf, entries, MLX4_VLAN_TABLE_SIZE);
327 	in_mod = MLX4_SET_PORT_VLAN_TABLE << 8 | port;
328 	err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT,
329 		       MLX4_CMD_TIME_CLASS_B);
330 
331 	mlx4_free_cmd_mailbox(dev, mailbox);
332 
333 	return err;
334 }
335 
336 int mlx4_find_cached_vlan(struct mlx4_dev *dev, u8 port, u16 vid, int *idx)
337 {
338 	struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table;
339 	int i;
340 
341 	for (i = 0; i < MLX4_MAX_VLAN_NUM; ++i) {
342 		if (table->refs[i] &&
343 		    (vid == (MLX4_VLAN_MASK &
344 			      be32_to_cpu(table->entries[i])))) {
345 			/* VLAN already registered, increase reference count */
346 			*idx = i;
347 			return 0;
348 		}
349 	}
350 
351 	return -ENOENT;
352 }
353 EXPORT_SYMBOL_GPL(mlx4_find_cached_vlan);
354 
355 int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index)
356 {
357 	struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table;
358 	int i, err = 0;
359 	int free = -1;
360 
361 	mutex_lock(&table->mutex);
362 
363 	if (table->total == table->max) {
364 		/* No free vlan entries */
365 		err = -ENOSPC;
366 		goto out;
367 	}
368 
369 	for (i = MLX4_VLAN_REGULAR; i < MLX4_MAX_VLAN_NUM; i++) {
370 		if (free < 0 && (table->refs[i] == 0)) {
371 			free = i;
372 			continue;
373 		}
374 
375 		if (table->refs[i] &&
376 		    (vlan == (MLX4_VLAN_MASK &
377 			      be32_to_cpu(table->entries[i])))) {
378 			/* Vlan already registered, increase references count */
379 			*index = i;
380 			++table->refs[i];
381 			goto out;
382 		}
383 	}
384 
385 	if (free < 0) {
386 		err = -ENOMEM;
387 		goto out;
388 	}
389 
390 	/* Register new MAC */
391 	table->refs[free] = 1;
392 	table->entries[free] = cpu_to_be32(vlan | MLX4_VLAN_VALID);
393 
394 	err = mlx4_set_port_vlan_table(dev, port, table->entries);
395 	if (unlikely(err)) {
396 		mlx4_warn(dev, "Failed adding vlan: %u\n", vlan);
397 		table->refs[free] = 0;
398 		table->entries[free] = 0;
399 		goto out;
400 	}
401 
402 	*index = free;
403 	++table->total;
404 out:
405 	mutex_unlock(&table->mutex);
406 	return err;
407 }
408 EXPORT_SYMBOL_GPL(mlx4_register_vlan);
409 
410 void mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index)
411 {
412 	struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table;
413 
414 	if (index < MLX4_VLAN_REGULAR) {
415 		mlx4_warn(dev, "Trying to free special vlan index %d\n", index);
416 		return;
417 	}
418 
419 	mutex_lock(&table->mutex);
420 	if (!table->refs[index]) {
421 		mlx4_warn(dev, "No vlan entry for index %d\n", index);
422 		goto out;
423 	}
424 	if (--table->refs[index]) {
425 		mlx4_dbg(dev, "Have more references for index %d,"
426 			 "no need to modify vlan table\n", index);
427 		goto out;
428 	}
429 	table->entries[index] = 0;
430 	mlx4_set_port_vlan_table(dev, port, table->entries);
431 	--table->total;
432 out:
433 	mutex_unlock(&table->mutex);
434 }
435 EXPORT_SYMBOL_GPL(mlx4_unregister_vlan);
436 
437 int mlx4_get_port_ib_caps(struct mlx4_dev *dev, u8 port, __be32 *caps)
438 {
439 	struct mlx4_cmd_mailbox *inmailbox, *outmailbox;
440 	u8 *inbuf, *outbuf;
441 	int err;
442 
443 	inmailbox = mlx4_alloc_cmd_mailbox(dev);
444 	if (IS_ERR(inmailbox))
445 		return PTR_ERR(inmailbox);
446 
447 	outmailbox = mlx4_alloc_cmd_mailbox(dev);
448 	if (IS_ERR(outmailbox)) {
449 		mlx4_free_cmd_mailbox(dev, inmailbox);
450 		return PTR_ERR(outmailbox);
451 	}
452 
453 	inbuf = inmailbox->buf;
454 	outbuf = outmailbox->buf;
455 	memset(inbuf, 0, 256);
456 	memset(outbuf, 0, 256);
457 	inbuf[0] = 1;
458 	inbuf[1] = 1;
459 	inbuf[2] = 1;
460 	inbuf[3] = 1;
461 	*(__be16 *) (&inbuf[16]) = cpu_to_be16(0x0015);
462 	*(__be32 *) (&inbuf[20]) = cpu_to_be32(port);
463 
464 	err = mlx4_cmd_box(dev, inmailbox->dma, outmailbox->dma, port, 3,
465 			   MLX4_CMD_MAD_IFC, MLX4_CMD_TIME_CLASS_C);
466 	if (!err)
467 		*caps = *(__be32 *) (outbuf + 84);
468 	mlx4_free_cmd_mailbox(dev, inmailbox);
469 	mlx4_free_cmd_mailbox(dev, outmailbox);
470 	return err;
471 }
472 
473 int mlx4_check_ext_port_caps(struct mlx4_dev *dev, u8 port)
474 {
475 	struct mlx4_cmd_mailbox *inmailbox, *outmailbox;
476 	u8 *inbuf, *outbuf;
477 	int err, packet_error;
478 
479 	inmailbox = mlx4_alloc_cmd_mailbox(dev);
480 	if (IS_ERR(inmailbox))
481 		return PTR_ERR(inmailbox);
482 
483 	outmailbox = mlx4_alloc_cmd_mailbox(dev);
484 	if (IS_ERR(outmailbox)) {
485 		mlx4_free_cmd_mailbox(dev, inmailbox);
486 		return PTR_ERR(outmailbox);
487 	}
488 
489 	inbuf = inmailbox->buf;
490 	outbuf = outmailbox->buf;
491 	memset(inbuf, 0, 256);
492 	memset(outbuf, 0, 256);
493 	inbuf[0] = 1;
494 	inbuf[1] = 1;
495 	inbuf[2] = 1;
496 	inbuf[3] = 1;
497 
498 	*(__be16 *) (&inbuf[16]) = MLX4_ATTR_EXTENDED_PORT_INFO;
499 	*(__be32 *) (&inbuf[20]) = cpu_to_be32(port);
500 
501 	err = mlx4_cmd_box(dev, inmailbox->dma, outmailbox->dma, port, 3,
502 			   MLX4_CMD_MAD_IFC, MLX4_CMD_TIME_CLASS_C);
503 
504 	packet_error = be16_to_cpu(*(__be16 *) (outbuf + 4));
505 
506 	dev->caps.ext_port_cap[port] = (!err && !packet_error) ?
507 				       MLX_EXT_PORT_CAP_FLAG_EXTENDED_PORT_INFO
508 				       : 0;
509 
510 	mlx4_free_cmd_mailbox(dev, inmailbox);
511 	mlx4_free_cmd_mailbox(dev, outmailbox);
512 	return err;
513 }
514 
515 int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port)
516 {
517 	struct mlx4_cmd_mailbox *mailbox;
518 	int err;
519 
520 	if (dev->caps.port_type[port] == MLX4_PORT_TYPE_ETH)
521 		return 0;
522 
523 	mailbox = mlx4_alloc_cmd_mailbox(dev);
524 	if (IS_ERR(mailbox))
525 		return PTR_ERR(mailbox);
526 
527 	memset(mailbox->buf, 0, 256);
528 
529 	((__be32 *) mailbox->buf)[1] = dev->caps.ib_port_def_cap[port];
530 	err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_SET_PORT,
531 		       MLX4_CMD_TIME_CLASS_B);
532 
533 	mlx4_free_cmd_mailbox(dev, mailbox);
534 	return err;
535 }
536