aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMoni Shoua <monis@mellanox.com>2015-12-06 11:07:41 -0500
committerDavid S. Miller <davem@davemloft.net>2015-12-06 22:40:45 -0500
commit5f61385d2ebc2bd62bc389c7da0d8d2f263be1eb (patch)
tree2a39c035a40b1064b45ec09453226182b956640e
parent78efed275117b189f06f8937798eab5cba53ed18 (diff)
net/mlx4_core: Keep VLAN/MAC tables mirrored in multifunc HA mode
Due to HW limitations, indexes to MAC and VLAN tables are always taken from the table of the actual port. So, if a resource holds an index to a table, it may refer to different values during the lifetime of the resource, unless the tables are mirrored. Also, even when driver is not in HA mode the policy of allocating an index to these tables is such to make sure, as much as possible, that when the time comes the mirroring will be successful. This means that in multifunction mode the allocation of a free index in a port's table tries to make sure that the same index in the other's port table is also free. Signed-off-by: Moni Shoua <monis@mellanox.com> Reviewed-by: Jack Morgenstein <jackm@dev.mellanox.co.il> Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mlx4.h6
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/port.c598
-rw-r--r--include/linux/mlx4/driver.h5
3 files changed, 586 insertions, 23 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
index 33c4c6f2c4bb..2404c22ad2b2 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
@@ -736,6 +736,7 @@ struct mlx4_catas_err {
736struct mlx4_mac_table { 736struct mlx4_mac_table {
737 __be64 entries[MLX4_MAX_MAC_NUM]; 737 __be64 entries[MLX4_MAX_MAC_NUM];
738 int refs[MLX4_MAX_MAC_NUM]; 738 int refs[MLX4_MAX_MAC_NUM];
739 bool is_dup[MLX4_MAX_MAC_NUM];
739 struct mutex mutex; 740 struct mutex mutex;
740 int total; 741 int total;
741 int max; 742 int max;
@@ -758,6 +759,7 @@ struct mlx4_roce_gid_table {
758struct mlx4_vlan_table { 759struct mlx4_vlan_table {
759 __be32 entries[MLX4_MAX_VLAN_NUM]; 760 __be32 entries[MLX4_MAX_VLAN_NUM];
760 int refs[MLX4_MAX_VLAN_NUM]; 761 int refs[MLX4_MAX_VLAN_NUM];
762 int is_dup[MLX4_MAX_VLAN_NUM];
761 struct mutex mutex; 763 struct mutex mutex;
762 int total; 764 int total;
763 int max; 765 int max;
@@ -1225,6 +1227,10 @@ void mlx4_init_roce_gid_table(struct mlx4_dev *dev,
1225 struct mlx4_roce_gid_table *table); 1227 struct mlx4_roce_gid_table *table);
1226void __mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, u16 vlan); 1228void __mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, u16 vlan);
1227int __mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index); 1229int __mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index);
1230int mlx4_bond_vlan_table(struct mlx4_dev *dev);
1231int mlx4_unbond_vlan_table(struct mlx4_dev *dev);
1232int mlx4_bond_mac_table(struct mlx4_dev *dev);
1233int mlx4_unbond_mac_table(struct mlx4_dev *dev);
1228 1234
1229int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port, int pkey_tbl_sz); 1235int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port, int pkey_tbl_sz);
1230/* resource tracker functions*/ 1236/* resource tracker functions*/
diff --git a/drivers/net/ethernet/mellanox/mlx4/port.c b/drivers/net/ethernet/mellanox/mlx4/port.c
index c2b21313dba7..f2550425c251 100644
--- a/drivers/net/ethernet/mellanox/mlx4/port.c
+++ b/drivers/net/ethernet/mellanox/mlx4/port.c
@@ -61,6 +61,7 @@ void mlx4_init_mac_table(struct mlx4_dev *dev, struct mlx4_mac_table *table)
61 for (i = 0; i < MLX4_MAX_MAC_NUM; i++) { 61 for (i = 0; i < MLX4_MAX_MAC_NUM; i++) {
62 table->entries[i] = 0; 62 table->entries[i] = 0;
63 table->refs[i] = 0; 63 table->refs[i] = 0;
64 table->is_dup[i] = false;
64 } 65 }
65 table->max = 1 << dev->caps.log_num_macs; 66 table->max = 1 << dev->caps.log_num_macs;
66 table->total = 0; 67 table->total = 0;
@@ -74,6 +75,7 @@ void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table)
74 for (i = 0; i < MLX4_MAX_VLAN_NUM; i++) { 75 for (i = 0; i < MLX4_MAX_VLAN_NUM; i++) {
75 table->entries[i] = 0; 76 table->entries[i] = 0;
76 table->refs[i] = 0; 77 table->refs[i] = 0;
78 table->is_dup[i] = false;
77 } 79 }
78 table->max = (1 << dev->caps.log_num_vlans) - MLX4_VLAN_REGULAR; 80 table->max = (1 << dev->caps.log_num_vlans) - MLX4_VLAN_REGULAR;
79 table->total = 0; 81 table->total = 0;
@@ -159,21 +161,94 @@ int mlx4_find_cached_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *idx)
159} 161}
160EXPORT_SYMBOL_GPL(mlx4_find_cached_mac); 162EXPORT_SYMBOL_GPL(mlx4_find_cached_mac);
161 163
164static bool mlx4_need_mf_bond(struct mlx4_dev *dev)
165{
166 int i, num_eth_ports = 0;
167
168 if (!mlx4_is_mfunc(dev))
169 return false;
170 mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH)
171 ++num_eth_ports;
172
173 return (num_eth_ports == 2) ? true : false;
174}
175
162int __mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac) 176int __mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac)
163{ 177{
164 struct mlx4_port_info *info = &mlx4_priv(dev)->port[port]; 178 struct mlx4_port_info *info = &mlx4_priv(dev)->port[port];
165 struct mlx4_mac_table *table = &info->mac_table; 179 struct mlx4_mac_table *table = &info->mac_table;
166 int i, err = 0; 180 int i, err = 0;
167 int free = -1; 181 int free = -1;
182 int free_for_dup = -1;
183 bool dup = mlx4_is_mf_bonded(dev);
184 u8 dup_port = (port == 1) ? 2 : 1;
185 struct mlx4_mac_table *dup_table = &mlx4_priv(dev)->port[dup_port].mac_table;
186 bool need_mf_bond = mlx4_need_mf_bond(dev);
187 bool can_mf_bond = true;
188
189 mlx4_dbg(dev, "Registering MAC: 0x%llx for port %d %s duplicate\n",
190 (unsigned long long)mac, port,
191 dup ? "with" : "without");
192
193 if (need_mf_bond) {
194 if (port == 1) {
195 mutex_lock(&table->mutex);
196 mutex_lock(&dup_table->mutex);
197 } else {
198 mutex_lock(&dup_table->mutex);
199 mutex_lock(&table->mutex);
200 }
201 } else {
202 mutex_lock(&table->mutex);
203 }
204
205 if (need_mf_bond) {
206 int index_at_port = -1;
207 int index_at_dup_port = -1;
168 208
169 mlx4_dbg(dev, "Registering MAC: 0x%llx for port %d\n", 209 for (i = 0; i < MLX4_MAX_MAC_NUM; i++) {
170 (unsigned long long) mac, port); 210 if (((MLX4_MAC_MASK & mac) == (MLX4_MAC_MASK & be64_to_cpu(table->entries[i]))))
211 index_at_port = i;
212 if (((MLX4_MAC_MASK & mac) == (MLX4_MAC_MASK & be64_to_cpu(dup_table->entries[i]))))
213 index_at_dup_port = i;
214 }
215
216 /* check that same mac is not in the tables at different indices */
217 if ((index_at_port != index_at_dup_port) &&
218 (index_at_port >= 0) &&
219 (index_at_dup_port >= 0))
220 can_mf_bond = false;
221
222 /* If the mac is already in the primary table, the slot must be
223 * available in the duplicate table as well.
224 */
225 if (index_at_port >= 0 && index_at_dup_port < 0 &&
226 dup_table->refs[index_at_port]) {
227 can_mf_bond = false;
228 }
229 /* If the mac is already in the duplicate table, check that the
230 * corresponding index is not occupied in the primary table, or
231 * the primary table already contains the mac at the same index.
232 * Otherwise, you cannot bond (primary contains a different mac
233 * at that index).
234 */
235 if (index_at_dup_port >= 0) {
236 if (!table->refs[index_at_dup_port] ||
237 ((MLX4_MAC_MASK & mac) == (MLX4_MAC_MASK & be64_to_cpu(table->entries[index_at_dup_port]))))
238 free_for_dup = index_at_dup_port;
239 else
240 can_mf_bond = false;
241 }
242 }
171 243
172 mutex_lock(&table->mutex);
173 for (i = 0; i < MLX4_MAX_MAC_NUM; i++) { 244 for (i = 0; i < MLX4_MAX_MAC_NUM; i++) {
174 if (!table->refs[i]) { 245 if (!table->refs[i]) {
175 if (free < 0) 246 if (free < 0)
176 free = i; 247 free = i;
248 if (free_for_dup < 0 && need_mf_bond && can_mf_bond) {
249 if (!dup_table->refs[i])
250 free_for_dup = i;
251 }
177 continue; 252 continue;
178 } 253 }
179 254
@@ -182,10 +257,30 @@ int __mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac)
182 /* MAC already registered, increment ref count */ 257 /* MAC already registered, increment ref count */
183 err = i; 258 err = i;
184 ++table->refs[i]; 259 ++table->refs[i];
260 if (dup) {
261 u64 dup_mac = MLX4_MAC_MASK & be64_to_cpu(dup_table->entries[i]);
262
263 if (dup_mac != mac || !dup_table->is_dup[i]) {
264 mlx4_warn(dev, "register mac: expect duplicate mac 0x%llx on port %d index %d\n",
265 mac, dup_port, i);
266 }
267 }
185 goto out; 268 goto out;
186 } 269 }
187 } 270 }
188 271
272 if (need_mf_bond && (free_for_dup < 0)) {
273 if (dup) {
274 mlx4_warn(dev, "Fail to allocate duplicate MAC table entry\n");
275 mlx4_warn(dev, "High Availability for virtual functions may not work as expected\n");
276 dup = false;
277 }
278 can_mf_bond = false;
279 }
280
281 if (need_mf_bond && can_mf_bond)
282 free = free_for_dup;
283
189 mlx4_dbg(dev, "Free MAC index is %d\n", free); 284 mlx4_dbg(dev, "Free MAC index is %d\n", free);
190 285
191 if (table->total == table->max) { 286 if (table->total == table->max) {
@@ -205,10 +300,35 @@ int __mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac)
205 goto out; 300 goto out;
206 } 301 }
207 table->refs[free] = 1; 302 table->refs[free] = 1;
208 err = free; 303 table->is_dup[free] = false;
209 ++table->total; 304 ++table->total;
305 if (dup) {
306 dup_table->refs[free] = 0;
307 dup_table->is_dup[free] = true;
308 dup_table->entries[free] = cpu_to_be64(mac | MLX4_MAC_VALID);
309
310 err = mlx4_set_port_mac_table(dev, dup_port, dup_table->entries);
311 if (unlikely(err)) {
312 mlx4_warn(dev, "Failed adding duplicate mac: 0x%llx\n", mac);
313 dup_table->is_dup[free] = false;
314 dup_table->entries[free] = 0;
315 goto out;
316 }
317 ++dup_table->total;
318 }
319 err = free;
210out: 320out:
211 mutex_unlock(&table->mutex); 321 if (need_mf_bond) {
322 if (port == 2) {
323 mutex_unlock(&table->mutex);
324 mutex_unlock(&dup_table->mutex);
325 } else {
326 mutex_unlock(&dup_table->mutex);
327 mutex_unlock(&table->mutex);
328 }
329 } else {
330 mutex_unlock(&table->mutex);
331 }
212 return err; 332 return err;
213} 333}
214EXPORT_SYMBOL_GPL(__mlx4_register_mac); 334EXPORT_SYMBOL_GPL(__mlx4_register_mac);
@@ -255,6 +375,9 @@ void __mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac)
255 struct mlx4_port_info *info; 375 struct mlx4_port_info *info;
256 struct mlx4_mac_table *table; 376 struct mlx4_mac_table *table;
257 int index; 377 int index;
378 bool dup = mlx4_is_mf_bonded(dev);
379 u8 dup_port = (port == 1) ? 2 : 1;
380 struct mlx4_mac_table *dup_table = &mlx4_priv(dev)->port[dup_port].mac_table;
258 381
259 if (port < 1 || port > dev->caps.num_ports) { 382 if (port < 1 || port > dev->caps.num_ports) {
260 mlx4_warn(dev, "invalid port number (%d), aborting...\n", port); 383 mlx4_warn(dev, "invalid port number (%d), aborting...\n", port);
@@ -262,22 +385,59 @@ void __mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac)
262 } 385 }
263 info = &mlx4_priv(dev)->port[port]; 386 info = &mlx4_priv(dev)->port[port];
264 table = &info->mac_table; 387 table = &info->mac_table;
265 mutex_lock(&table->mutex); 388
389 if (dup) {
390 if (port == 1) {
391 mutex_lock(&table->mutex);
392 mutex_lock(&dup_table->mutex);
393 } else {
394 mutex_lock(&dup_table->mutex);
395 mutex_lock(&table->mutex);
396 }
397 } else {
398 mutex_lock(&table->mutex);
399 }
400
266 index = find_index(dev, table, mac); 401 index = find_index(dev, table, mac);
267 402
268 if (validate_index(dev, table, index)) 403 if (validate_index(dev, table, index))
269 goto out; 404 goto out;
270 if (--table->refs[index]) { 405
406 if (--table->refs[index] || table->is_dup[index]) {
271 mlx4_dbg(dev, "Have more references for index %d, no need to modify mac table\n", 407 mlx4_dbg(dev, "Have more references for index %d, no need to modify mac table\n",
272 index); 408 index);
409 if (!table->refs[index])
410 dup_table->is_dup[index] = false;
273 goto out; 411 goto out;
274 } 412 }
275 413
276 table->entries[index] = 0; 414 table->entries[index] = 0;
277 mlx4_set_port_mac_table(dev, port, table->entries); 415 if (mlx4_set_port_mac_table(dev, port, table->entries))
416 mlx4_warn(dev, "Fail to set mac in port %d during unregister\n", port);
278 --table->total; 417 --table->total;
418
419 if (dup) {
420 dup_table->is_dup[index] = false;
421 if (dup_table->refs[index])
422 goto out;
423 dup_table->entries[index] = 0;
424 if (mlx4_set_port_mac_table(dev, dup_port, dup_table->entries))
425 mlx4_warn(dev, "Fail to set mac in duplicate port %d during unregister\n", dup_port);
426
427 --table->total;
428 }
279out: 429out:
280 mutex_unlock(&table->mutex); 430 if (dup) {
431 if (port == 2) {
432 mutex_unlock(&table->mutex);
433 mutex_unlock(&dup_table->mutex);
434 } else {
435 mutex_unlock(&dup_table->mutex);
436 mutex_unlock(&table->mutex);
437 }
438 } else {
439 mutex_unlock(&table->mutex);
440 }
281} 441}
282EXPORT_SYMBOL_GPL(__mlx4_unregister_mac); 442EXPORT_SYMBOL_GPL(__mlx4_unregister_mac);
283 443
@@ -311,9 +471,22 @@ int __mlx4_replace_mac(struct mlx4_dev *dev, u8 port, int qpn, u64 new_mac)
311 struct mlx4_mac_table *table = &info->mac_table; 471 struct mlx4_mac_table *table = &info->mac_table;
312 int index = qpn - info->base_qpn; 472 int index = qpn - info->base_qpn;
313 int err = 0; 473 int err = 0;
474 bool dup = mlx4_is_mf_bonded(dev);
475 u8 dup_port = (port == 1) ? 2 : 1;
476 struct mlx4_mac_table *dup_table = &mlx4_priv(dev)->port[dup_port].mac_table;
314 477
315 /* CX1 doesn't support multi-functions */ 478 /* CX1 doesn't support multi-functions */
316 mutex_lock(&table->mutex); 479 if (dup) {
480 if (port == 1) {
481 mutex_lock(&table->mutex);
482 mutex_lock(&dup_table->mutex);
483 } else {
484 mutex_lock(&dup_table->mutex);
485 mutex_lock(&table->mutex);
486 }
487 } else {
488 mutex_lock(&table->mutex);
489 }
317 490
318 err = validate_index(dev, table, index); 491 err = validate_index(dev, table, index);
319 if (err) 492 if (err)
@@ -326,9 +499,30 @@ int __mlx4_replace_mac(struct mlx4_dev *dev, u8 port, int qpn, u64 new_mac)
326 mlx4_err(dev, "Failed adding MAC: 0x%llx\n", 499 mlx4_err(dev, "Failed adding MAC: 0x%llx\n",
327 (unsigned long long) new_mac); 500 (unsigned long long) new_mac);
328 table->entries[index] = 0; 501 table->entries[index] = 0;
502 } else {
503 if (dup) {
504 dup_table->entries[index] = cpu_to_be64(new_mac | MLX4_MAC_VALID);
505
506 err = mlx4_set_port_mac_table(dev, dup_port, dup_table->entries);
507 if (unlikely(err)) {
508 mlx4_err(dev, "Failed adding duplicate MAC: 0x%llx\n",
509 (unsigned long long)new_mac);
510 dup_table->entries[index] = 0;
511 }
512 }
329 } 513 }
330out: 514out:
331 mutex_unlock(&table->mutex); 515 if (dup) {
516 if (port == 2) {
517 mutex_unlock(&table->mutex);
518 mutex_unlock(&dup_table->mutex);
519 } else {
520 mutex_unlock(&dup_table->mutex);
521 mutex_unlock(&table->mutex);
522 }
523 } else {
524 mutex_unlock(&table->mutex);
525 }
332 return err; 526 return err;
333} 527}
334EXPORT_SYMBOL_GPL(__mlx4_replace_mac); 528EXPORT_SYMBOL_GPL(__mlx4_replace_mac);
@@ -380,8 +574,28 @@ int __mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan,
380 struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table; 574 struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table;
381 int i, err = 0; 575 int i, err = 0;
382 int free = -1; 576 int free = -1;
383 577 int free_for_dup = -1;
384 mutex_lock(&table->mutex); 578 bool dup = mlx4_is_mf_bonded(dev);
579 u8 dup_port = (port == 1) ? 2 : 1;
580 struct mlx4_vlan_table *dup_table = &mlx4_priv(dev)->port[dup_port].vlan_table;
581 bool need_mf_bond = mlx4_need_mf_bond(dev);
582 bool can_mf_bond = true;
583
584 mlx4_dbg(dev, "Registering VLAN: %d for port %d %s duplicate\n",
585 vlan, port,
586 dup ? "with" : "without");
587
588 if (need_mf_bond) {
589 if (port == 1) {
590 mutex_lock(&table->mutex);
591 mutex_lock(&dup_table->mutex);
592 } else {
593 mutex_lock(&dup_table->mutex);
594 mutex_lock(&table->mutex);
595 }
596 } else {
597 mutex_lock(&table->mutex);
598 }
385 599
386 if (table->total == table->max) { 600 if (table->total == table->max) {
387 /* No free vlan entries */ 601 /* No free vlan entries */
@@ -389,22 +603,85 @@ int __mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan,
389 goto out; 603 goto out;
390 } 604 }
391 605
606 if (need_mf_bond) {
607 int index_at_port = -1;
608 int index_at_dup_port = -1;
609
610 for (i = MLX4_VLAN_REGULAR; i < MLX4_MAX_VLAN_NUM; i++) {
611 if ((vlan == (MLX4_VLAN_MASK & be32_to_cpu(table->entries[i]))))
612 index_at_port = i;
613 if ((vlan == (MLX4_VLAN_MASK & be32_to_cpu(dup_table->entries[i]))))
614 index_at_dup_port = i;
615 }
616 /* check that same vlan is not in the tables at different indices */
617 if ((index_at_port != index_at_dup_port) &&
618 (index_at_port >= 0) &&
619 (index_at_dup_port >= 0))
620 can_mf_bond = false;
621
622 /* If the vlan is already in the primary table, the slot must be
623 * available in the duplicate table as well.
624 */
625 if (index_at_port >= 0 && index_at_dup_port < 0 &&
626 dup_table->refs[index_at_port]) {
627 can_mf_bond = false;
628 }
629 /* If the vlan is already in the duplicate table, check that the
630 * corresponding index is not occupied in the primary table, or
631 * the primary table already contains the vlan at the same index.
632 * Otherwise, you cannot bond (primary contains a different vlan
633 * at that index).
634 */
635 if (index_at_dup_port >= 0) {
636 if (!table->refs[index_at_dup_port] ||
637 (vlan == (MLX4_VLAN_MASK & be32_to_cpu(dup_table->entries[index_at_dup_port]))))
638 free_for_dup = index_at_dup_port;
639 else
640 can_mf_bond = false;
641 }
642 }
643
392 for (i = MLX4_VLAN_REGULAR; i < MLX4_MAX_VLAN_NUM; i++) { 644 for (i = MLX4_VLAN_REGULAR; i < MLX4_MAX_VLAN_NUM; i++) {
393 if (free < 0 && (table->refs[i] == 0)) { 645 if (!table->refs[i]) {
394 free = i; 646 if (free < 0)
395 continue; 647 free = i;
648 if (free_for_dup < 0 && need_mf_bond && can_mf_bond) {
649 if (!dup_table->refs[i])
650 free_for_dup = i;
651 }
396 } 652 }
397 653
398 if (table->refs[i] && 654 if ((table->refs[i] || table->is_dup[i]) &&
399 (vlan == (MLX4_VLAN_MASK & 655 (vlan == (MLX4_VLAN_MASK &
400 be32_to_cpu(table->entries[i])))) { 656 be32_to_cpu(table->entries[i])))) {
401 /* Vlan already registered, increase references count */ 657 /* Vlan already registered, increase references count */
658 mlx4_dbg(dev, "vlan %u is already registered.\n", vlan);
402 *index = i; 659 *index = i;
403 ++table->refs[i]; 660 ++table->refs[i];
661 if (dup) {
662 u16 dup_vlan = MLX4_VLAN_MASK & be32_to_cpu(dup_table->entries[i]);
663
664 if (dup_vlan != vlan || !dup_table->is_dup[i]) {
665 mlx4_warn(dev, "register vlan: expected duplicate vlan %u on port %d index %d\n",
666 vlan, dup_port, i);
667 }
668 }
404 goto out; 669 goto out;
405 } 670 }
406 } 671 }
407 672
673 if (need_mf_bond && (free_for_dup < 0)) {
674 if (dup) {
675 mlx4_warn(dev, "Fail to allocate duplicate VLAN table entry\n");
676 mlx4_warn(dev, "High Availability for virtual functions may not work as expected\n");
677 dup = false;
678 }
679 can_mf_bond = false;
680 }
681
682 if (need_mf_bond && can_mf_bond)
683 free = free_for_dup;
684
408 if (free < 0) { 685 if (free < 0) {
409 err = -ENOMEM; 686 err = -ENOMEM;
410 goto out; 687 goto out;
@@ -412,6 +689,7 @@ int __mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan,
412 689
413 /* Register new VLAN */ 690 /* Register new VLAN */
414 table->refs[free] = 1; 691 table->refs[free] = 1;
692 table->is_dup[free] = false;
415 table->entries[free] = cpu_to_be32(vlan | MLX4_VLAN_VALID); 693 table->entries[free] = cpu_to_be32(vlan | MLX4_VLAN_VALID);
416 694
417 err = mlx4_set_port_vlan_table(dev, port, table->entries); 695 err = mlx4_set_port_vlan_table(dev, port, table->entries);
@@ -421,11 +699,35 @@ int __mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan,
421 table->entries[free] = 0; 699 table->entries[free] = 0;
422 goto out; 700 goto out;
423 } 701 }
702 ++table->total;
703 if (dup) {
704 dup_table->refs[free] = 0;
705 dup_table->is_dup[free] = true;
706 dup_table->entries[free] = cpu_to_be32(vlan | MLX4_VLAN_VALID);
707
708 err = mlx4_set_port_vlan_table(dev, dup_port, dup_table->entries);
709 if (unlikely(err)) {
710 mlx4_warn(dev, "Failed adding duplicate vlan: %u\n", vlan);
711 dup_table->is_dup[free] = false;
712 dup_table->entries[free] = 0;
713 goto out;
714 }
715 ++dup_table->total;
716 }
424 717
425 *index = free; 718 *index = free;
426 ++table->total;
427out: 719out:
428 mutex_unlock(&table->mutex); 720 if (need_mf_bond) {
721 if (port == 2) {
722 mutex_unlock(&table->mutex);
723 mutex_unlock(&dup_table->mutex);
724 } else {
725 mutex_unlock(&dup_table->mutex);
726 mutex_unlock(&table->mutex);
727 }
728 } else {
729 mutex_unlock(&table->mutex);
730 }
429 return err; 731 return err;
430} 732}
431 733
@@ -455,8 +757,22 @@ void __mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, u16 vlan)
455{ 757{
456 struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table; 758 struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table;
457 int index; 759 int index;
760 bool dup = mlx4_is_mf_bonded(dev);
761 u8 dup_port = (port == 1) ? 2 : 1;
762 struct mlx4_vlan_table *dup_table = &mlx4_priv(dev)->port[dup_port].vlan_table;
763
764 if (dup) {
765 if (port == 1) {
766 mutex_lock(&table->mutex);
767 mutex_lock(&dup_table->mutex);
768 } else {
769 mutex_lock(&dup_table->mutex);
770 mutex_lock(&table->mutex);
771 }
772 } else {
773 mutex_lock(&table->mutex);
774 }
458 775
459 mutex_lock(&table->mutex);
460 if (mlx4_find_cached_vlan(dev, port, vlan, &index)) { 776 if (mlx4_find_cached_vlan(dev, port, vlan, &index)) {
461 mlx4_warn(dev, "vlan 0x%x is not in the vlan table\n", vlan); 777 mlx4_warn(dev, "vlan 0x%x is not in the vlan table\n", vlan);
462 goto out; 778 goto out;
@@ -467,16 +783,38 @@ void __mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, u16 vlan)
467 goto out; 783 goto out;
468 } 784 }
469 785
470 if (--table->refs[index]) { 786 if (--table->refs[index] || table->is_dup[index]) {
471 mlx4_dbg(dev, "Have %d more references for index %d, no need to modify vlan table\n", 787 mlx4_dbg(dev, "Have %d more references for index %d, no need to modify vlan table\n",
472 table->refs[index], index); 788 table->refs[index], index);
789 if (!table->refs[index])
790 dup_table->is_dup[index] = false;
473 goto out; 791 goto out;
474 } 792 }
475 table->entries[index] = 0; 793 table->entries[index] = 0;
476 mlx4_set_port_vlan_table(dev, port, table->entries); 794 if (mlx4_set_port_vlan_table(dev, port, table->entries))
795 mlx4_warn(dev, "Fail to set vlan in port %d during unregister\n", port);
477 --table->total; 796 --table->total;
797 if (dup) {
798 dup_table->is_dup[index] = false;
799 if (dup_table->refs[index])
800 goto out;
801 dup_table->entries[index] = 0;
802 if (mlx4_set_port_vlan_table(dev, dup_port, dup_table->entries))
803 mlx4_warn(dev, "Fail to set vlan in duplicate port %d during unregister\n", dup_port);
804 --dup_table->total;
805 }
478out: 806out:
479 mutex_unlock(&table->mutex); 807 if (dup) {
808 if (port == 2) {
809 mutex_unlock(&table->mutex);
810 mutex_unlock(&dup_table->mutex);
811 } else {
812 mutex_unlock(&dup_table->mutex);
813 mutex_unlock(&table->mutex);
814 }
815 } else {
816 mutex_unlock(&table->mutex);
817 }
480} 818}
481 819
482void mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, u16 vlan) 820void mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, u16 vlan)
@@ -495,6 +833,220 @@ void mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, u16 vlan)
495} 833}
496EXPORT_SYMBOL_GPL(mlx4_unregister_vlan); 834EXPORT_SYMBOL_GPL(mlx4_unregister_vlan);
497 835
836int mlx4_bond_mac_table(struct mlx4_dev *dev)
837{
838 struct mlx4_mac_table *t1 = &mlx4_priv(dev)->port[1].mac_table;
839 struct mlx4_mac_table *t2 = &mlx4_priv(dev)->port[2].mac_table;
840 int ret = 0;
841 int i;
842 bool update1 = false;
843 bool update2 = false;
844
845 mutex_lock(&t1->mutex);
846 mutex_lock(&t2->mutex);
847 for (i = 0; i < MLX4_MAX_MAC_NUM; i++) {
848 if ((t1->entries[i] != t2->entries[i]) &&
849 t1->entries[i] && t2->entries[i]) {
850 mlx4_warn(dev, "can't duplicate entry %d in mac table\n", i);
851 ret = -EINVAL;
852 goto unlock;
853 }
854 }
855
856 for (i = 0; i < MLX4_MAX_MAC_NUM; i++) {
857 if (t1->entries[i] && !t2->entries[i]) {
858 t2->entries[i] = t1->entries[i];
859 t2->is_dup[i] = true;
860 update2 = true;
861 } else if (!t1->entries[i] && t2->entries[i]) {
862 t1->entries[i] = t2->entries[i];
863 t1->is_dup[i] = true;
864 update1 = true;
865 } else if (t1->entries[i] && t2->entries[i]) {
866 t1->is_dup[i] = true;
867 t2->is_dup[i] = true;
868 }
869 }
870
871 if (update1) {
872 ret = mlx4_set_port_mac_table(dev, 1, t1->entries);
873 if (ret)
874 mlx4_warn(dev, "failed to set MAC table for port 1 (%d)\n", ret);
875 }
876 if (!ret && update2) {
877 ret = mlx4_set_port_mac_table(dev, 2, t2->entries);
878 if (ret)
879 mlx4_warn(dev, "failed to set MAC table for port 2 (%d)\n", ret);
880 }
881
882 if (ret)
883 mlx4_warn(dev, "failed to create mirror MAC tables\n");
884unlock:
885 mutex_unlock(&t2->mutex);
886 mutex_unlock(&t1->mutex);
887 return ret;
888}
889
890int mlx4_unbond_mac_table(struct mlx4_dev *dev)
891{
892 struct mlx4_mac_table *t1 = &mlx4_priv(dev)->port[1].mac_table;
893 struct mlx4_mac_table *t2 = &mlx4_priv(dev)->port[2].mac_table;
894 int ret = 0;
895 int ret1;
896 int i;
897 bool update1 = false;
898 bool update2 = false;
899
900 mutex_lock(&t1->mutex);
901 mutex_lock(&t2->mutex);
902 for (i = 0; i < MLX4_MAX_MAC_NUM; i++) {
903 if (t1->entries[i] != t2->entries[i]) {
904 mlx4_warn(dev, "mac table is in an unexpected state when trying to unbond\n");
905 ret = -EINVAL;
906 goto unlock;
907 }
908 }
909
910 for (i = 0; i < MLX4_MAX_MAC_NUM; i++) {
911 if (!t1->entries[i])
912 continue;
913 t1->is_dup[i] = false;
914 if (!t1->refs[i]) {
915 t1->entries[i] = 0;
916 update1 = true;
917 }
918 t2->is_dup[i] = false;
919 if (!t2->refs[i]) {
920 t2->entries[i] = 0;
921 update2 = true;
922 }
923 }
924
925 if (update1) {
926 ret = mlx4_set_port_mac_table(dev, 1, t1->entries);
927 if (ret)
928 mlx4_warn(dev, "failed to unmirror MAC tables for port 1(%d)\n", ret);
929 }
930 if (update2) {
931 ret1 = mlx4_set_port_mac_table(dev, 2, t2->entries);
932 if (ret1) {
933 mlx4_warn(dev, "failed to unmirror MAC tables for port 2(%d)\n", ret1);
934 ret = ret1;
935 }
936 }
937unlock:
938 mutex_unlock(&t2->mutex);
939 mutex_unlock(&t1->mutex);
940 return ret;
941}
942
943int mlx4_bond_vlan_table(struct mlx4_dev *dev)
944{
945 struct mlx4_vlan_table *t1 = &mlx4_priv(dev)->port[1].vlan_table;
946 struct mlx4_vlan_table *t2 = &mlx4_priv(dev)->port[2].vlan_table;
947 int ret = 0;
948 int i;
949 bool update1 = false;
950 bool update2 = false;
951
952 mutex_lock(&t1->mutex);
953 mutex_lock(&t2->mutex);
954 for (i = 0; i < MLX4_MAX_VLAN_NUM; i++) {
955 if ((t1->entries[i] != t2->entries[i]) &&
956 t1->entries[i] && t2->entries[i]) {
957 mlx4_warn(dev, "can't duplicate entry %d in vlan table\n", i);
958 ret = -EINVAL;
959 goto unlock;
960 }
961 }
962
963 for (i = 0; i < MLX4_MAX_VLAN_NUM; i++) {
964 if (t1->entries[i] && !t2->entries[i]) {
965 t2->entries[i] = t1->entries[i];
966 t2->is_dup[i] = true;
967 update2 = true;
968 } else if (!t1->entries[i] && t2->entries[i]) {
969 t1->entries[i] = t2->entries[i];
970 t1->is_dup[i] = true;
971 update1 = true;
972 } else if (t1->entries[i] && t2->entries[i]) {
973 t1->is_dup[i] = true;
974 t2->is_dup[i] = true;
975 }
976 }
977
978 if (update1) {
979 ret = mlx4_set_port_vlan_table(dev, 1, t1->entries);
980 if (ret)
981 mlx4_warn(dev, "failed to set VLAN table for port 1 (%d)\n", ret);
982 }
983 if (!ret && update2) {
984 ret = mlx4_set_port_vlan_table(dev, 2, t2->entries);
985 if (ret)
986 mlx4_warn(dev, "failed to set VLAN table for port 2 (%d)\n", ret);
987 }
988
989 if (ret)
990 mlx4_warn(dev, "failed to create mirror VLAN tables\n");
991unlock:
992 mutex_unlock(&t2->mutex);
993 mutex_unlock(&t1->mutex);
994 return ret;
995}
996
997int mlx4_unbond_vlan_table(struct mlx4_dev *dev)
998{
999 struct mlx4_vlan_table *t1 = &mlx4_priv(dev)->port[1].vlan_table;
1000 struct mlx4_vlan_table *t2 = &mlx4_priv(dev)->port[2].vlan_table;
1001 int ret = 0;
1002 int ret1;
1003 int i;
1004 bool update1 = false;
1005 bool update2 = false;
1006
1007 mutex_lock(&t1->mutex);
1008 mutex_lock(&t2->mutex);
1009 for (i = 0; i < MLX4_MAX_VLAN_NUM; i++) {
1010 if (t1->entries[i] != t2->entries[i]) {
1011 mlx4_warn(dev, "vlan table is in an unexpected state when trying to unbond\n");
1012 ret = -EINVAL;
1013 goto unlock;
1014 }
1015 }
1016
1017 for (i = 0; i < MLX4_MAX_VLAN_NUM; i++) {
1018 if (!t1->entries[i])
1019 continue;
1020 t1->is_dup[i] = false;
1021 if (!t1->refs[i]) {
1022 t1->entries[i] = 0;
1023 update1 = true;
1024 }
1025 t2->is_dup[i] = false;
1026 if (!t2->refs[i]) {
1027 t2->entries[i] = 0;
1028 update2 = true;
1029 }
1030 }
1031
1032 if (update1) {
1033 ret = mlx4_set_port_vlan_table(dev, 1, t1->entries);
1034 if (ret)
1035 mlx4_warn(dev, "failed to unmirror VLAN tables for port 1(%d)\n", ret);
1036 }
1037 if (update2) {
1038 ret1 = mlx4_set_port_vlan_table(dev, 2, t2->entries);
1039 if (ret1) {
1040 mlx4_warn(dev, "failed to unmirror VLAN tables for port 2(%d)\n", ret1);
1041 ret = ret1;
1042 }
1043 }
1044unlock:
1045 mutex_unlock(&t2->mutex);
1046 mutex_unlock(&t1->mutex);
1047 return ret;
1048}
1049
498int mlx4_get_port_ib_caps(struct mlx4_dev *dev, u8 port, __be32 *caps) 1050int mlx4_get_port_ib_caps(struct mlx4_dev *dev, u8 port, __be32 *caps)
499{ 1051{
500 struct mlx4_cmd_mailbox *inmailbox, *outmailbox; 1052 struct mlx4_cmd_mailbox *inmailbox, *outmailbox;
diff --git a/include/linux/mlx4/driver.h b/include/linux/mlx4/driver.h
index 5a06d969338e..2e8af001c5da 100644
--- a/include/linux/mlx4/driver.h
+++ b/include/linux/mlx4/driver.h
@@ -75,6 +75,11 @@ static inline int mlx4_is_bonded(struct mlx4_dev *dev)
75 return !!(dev->flags & MLX4_FLAG_BONDED); 75 return !!(dev->flags & MLX4_FLAG_BONDED);
76} 76}
77 77
78static inline int mlx4_is_mf_bonded(struct mlx4_dev *dev)
79{
80 return (mlx4_is_bonded(dev) && mlx4_is_mfunc(dev));
81}
82
78struct mlx4_port_map { 83struct mlx4_port_map {
79 u8 port1; 84 u8 port1;
80 u8 port2; 85 u8 port2;