Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

net/mlx5: LAG, replace pf array with xarray

Replace the fixed-size array with a dynamic xarray.

This commit changes:
- Adds mlx5_lag_pf() helper for consistent xarray access
- Converts all direct pf[] accesses to use the new helper/macro
- Dynamically allocates lag_func entries via xa_store/xa_load

No functional changes intended. This prepares the LAG infrastructure
for future flexibility in device indexing.

Signed-off-by: Shay Drory <shayd@nvidia.com>
Reviewed-by: Mark Bloch <mbloch@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Link: https://patch.msgid.link/20260309093435.1850724-4-tariqt@nvidia.com
Signed-off-by: Leon Romanovsky <leon@kernel.org>

authored by

Shay Drory and committed by
Leon Romanovsky
91e9f3e7 691dffc7

+243 -120
+2 -1
drivers/net/ethernet/mellanox/mlx5/core/lag/debugfs.c
··· 145 145 ldev = mlx5_lag_dev(dev); 146 146 mutex_lock(&ldev->lock); 147 147 mlx5_ldev_for_each(i, 0, ldev) 148 - seq_printf(file, "%s\n", dev_name(ldev->pf[i].dev->device)); 148 + seq_printf(file, "%s\n", 149 + dev_name(mlx5_lag_pf(ldev, i)->dev->device)); 149 150 mutex_unlock(&ldev->lock); 150 151 151 152 return 0;
+207 -93
drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
··· 232 232 static void mlx5_ldev_free(struct kref *ref) 233 233 { 234 234 struct mlx5_lag *ldev = container_of(ref, struct mlx5_lag, ref); 235 + struct lag_func *pf; 235 236 struct net *net; 236 237 int i; 237 238 ··· 242 241 } 243 242 244 243 mlx5_ldev_for_each(i, 0, ldev) { 245 - if (ldev->pf[i].dev && 246 - ldev->pf[i].port_change_nb.nb.notifier_call) { 247 - struct mlx5_nb *nb = &ldev->pf[i].port_change_nb; 244 + pf = mlx5_lag_pf(ldev, i); 245 + if (pf->port_change_nb.nb.notifier_call) { 246 + struct mlx5_nb *nb = &pf->port_change_nb; 248 247 249 - mlx5_eq_notifier_unregister(ldev->pf[i].dev, nb); 248 + mlx5_eq_notifier_unregister(pf->dev, nb); 250 249 } 250 + xa_erase(&ldev->pfs, i); 251 + kfree(pf); 251 252 } 253 + xa_destroy(&ldev->pfs); 252 254 253 255 mlx5_lag_mp_cleanup(ldev); 254 256 cancel_delayed_work_sync(&ldev->bond_work); ··· 288 284 289 285 kref_init(&ldev->ref); 290 286 mutex_init(&ldev->lock); 287 + xa_init(&ldev->pfs); 291 288 INIT_DELAYED_WORK(&ldev->bond_work, mlx5_do_bond_work); 292 289 INIT_WORK(&ldev->speed_update_work, mlx5_mpesw_speed_update_work); 293 290 ··· 314 309 int mlx5_lag_dev_get_netdev_idx(struct mlx5_lag *ldev, 315 310 struct net_device *ndev) 316 311 { 312 + struct lag_func *pf; 317 313 int i; 318 314 319 - mlx5_ldev_for_each(i, 0, ldev) 320 - if (ldev->pf[i].netdev == ndev) 315 + mlx5_ldev_for_each(i, 0, ldev) { 316 + pf = mlx5_lag_pf(ldev, i); 317 + if (pf->netdev == ndev) 321 318 return i; 319 + } 322 320 323 321 return -ENOENT; 324 322 } ··· 357 349 358 350 int mlx5_lag_num_netdevs(struct mlx5_lag *ldev) 359 351 { 352 + struct lag_func *pf; 360 353 int i, num = 0; 361 354 362 355 if (!ldev) 363 356 return 0; 364 357 365 - mlx5_ldev_for_each(i, 0, ldev) 366 - if (ldev->pf[i].netdev) 358 + mlx5_ldev_for_each(i, 0, ldev) { 359 + pf = mlx5_lag_pf(ldev, i); 360 + if (pf->netdev) 367 361 num++; 362 + } 368 363 return num; 369 364 } 370 365 ··· 435 424 436 425 static bool mlx5_lag_has_drop_rule(struct mlx5_lag *ldev) 437 426 { 427 + struct lag_func *pf; 438 428 int i; 439 429 440 - mlx5_ldev_for_each(i, 0, ldev) 441 - if (ldev->pf[i].has_drop) 430 + mlx5_ldev_for_each(i, 0, ldev) { 431 + pf = mlx5_lag_pf(ldev, i); 432 + if (pf->has_drop) 442 433 return true; 434 + } 443 435 return false; 444 436 } 445 437 446 438 static void mlx5_lag_drop_rule_cleanup(struct mlx5_lag *ldev) 447 439 { 440 + struct lag_func *pf; 448 441 int i; 449 442 450 443 mlx5_ldev_for_each(i, 0, ldev) { 451 - if (!ldev->pf[i].has_drop) 444 + pf = mlx5_lag_pf(ldev, i); 445 + if (!pf->has_drop) 452 446 continue; 453 447 454 - mlx5_esw_acl_ingress_vport_drop_rule_destroy(ldev->pf[i].dev->priv.eswitch, 448 + mlx5_esw_acl_ingress_vport_drop_rule_destroy(pf->dev->priv.eswitch, 455 449 MLX5_VPORT_UPLINK); 456 - ldev->pf[i].has_drop = false; 450 + pf->has_drop = false; 457 451 } 458 452 } 459 453 ··· 467 451 { 468 452 u8 disabled_ports[MLX5_MAX_PORTS] = {}; 469 453 struct mlx5_core_dev *dev; 454 + struct lag_func *pf; 470 455 int disabled_index; 471 456 int num_disabled; 472 457 int err; ··· 485 468 486 469 for (i = 0; i < num_disabled; i++) { 487 470 disabled_index = disabled_ports[i]; 488 - dev = ldev->pf[disabled_index].dev; 471 + pf = mlx5_lag_pf(ldev, disabled_index); 472 + dev = pf->dev; 489 473 err = mlx5_esw_acl_ingress_vport_drop_rule_create(dev->priv.eswitch, 490 474 MLX5_VPORT_UPLINK); 491 475 if (!err) 492 - ldev->pf[disabled_index].has_drop = true; 476 + pf->has_drop = true; 493 477 else 494 478 mlx5_core_err(dev, 495 479 "Failed to create lag drop rule, error: %d", err); ··· 522 504 if (idx < 0) 523 505 return -EINVAL; 524 506 525 - dev0 = ldev->pf[idx].dev; 507 + dev0 = mlx5_lag_pf(ldev, idx)->dev; 526 508 if (test_bit(MLX5_LAG_MODE_FLAG_HASH_BASED, &ldev->mode_flags)) { 527 509 ret = mlx5_lag_port_sel_modify(ldev, ports); 528 510 if (ret || ··· 539 521 static struct net_device *mlx5_lag_active_backup_get_netdev(struct mlx5_core_dev *dev) 540 522 { 541 523 struct net_device *ndev = NULL; 524 + struct lag_func *pf; 542 525 struct mlx5_lag *ldev; 543 526 unsigned long flags; 544 527 int i, last_idx; ··· 550 531 if (!ldev) 551 532 goto unlock; 552 533 553 - mlx5_ldev_for_each(i, 0, ldev) 534 + mlx5_ldev_for_each(i, 0, ldev) { 535 + pf = mlx5_lag_pf(ldev, i); 554 536 if (ldev->tracker.netdev_state[i].tx_enabled) 555 - ndev = ldev->pf[i].netdev; 537 + ndev = pf->netdev; 538 + } 556 539 if (!ndev) { 557 540 last_idx = mlx5_lag_get_dev_index_by_seq(ldev, ldev->ports - 1); 558 541 if (last_idx < 0) 559 542 goto unlock; 560 - ndev = ldev->pf[last_idx].netdev; 543 + pf = mlx5_lag_pf(ldev, last_idx); 544 + ndev = pf->netdev; 561 545 } 562 546 563 547 dev_hold(ndev); ··· 585 563 if (first_idx < 0) 586 564 return; 587 565 588 - dev0 = ldev->pf[first_idx].dev; 566 + dev0 = mlx5_lag_pf(ldev, first_idx)->dev; 589 567 mlx5_infer_tx_affinity_mapping(tracker, ldev, ldev->buckets, ports); 590 568 591 569 mlx5_ldev_for_each(i, 0, ldev) { ··· 637 615 mode == MLX5_LAG_MODE_MULTIPATH) 638 616 return 0; 639 617 640 - dev0 = ldev->pf[first_idx].dev; 618 + dev0 = mlx5_lag_pf(ldev, first_idx)->dev; 641 619 642 620 if (!MLX5_CAP_PORT_SELECTION(dev0, port_select_flow_table)) { 643 621 if (ldev->ports > 2) ··· 692 670 if (first_idx < 0) 693 671 return -EINVAL; 694 672 695 - dev0 = ldev->pf[first_idx].dev; 673 + dev0 = mlx5_lag_pf(ldev, first_idx)->dev; 696 674 master_esw = dev0->priv.eswitch; 697 675 mlx5_ldev_for_each(i, first_idx + 1, ldev) { 698 - struct mlx5_eswitch *slave_esw = ldev->pf[i].dev->priv.eswitch; 676 + struct mlx5_eswitch *slave_esw; 677 + 678 + slave_esw = mlx5_lag_pf(ldev, i)->dev->priv.eswitch; 699 679 700 680 err = mlx5_eswitch_offloads_single_fdb_add_one(master_esw, 701 681 slave_esw, ldev->ports); ··· 708 684 err: 709 685 mlx5_ldev_for_each_reverse(j, i, first_idx + 1, ldev) 710 686 mlx5_eswitch_offloads_single_fdb_del_one(master_esw, 711 - ldev->pf[j].dev->priv.eswitch); 687 + mlx5_lag_pf(ldev, j)->dev->priv.eswitch); 712 688 return err; 713 689 } 714 690 ··· 726 702 if (first_idx < 0) 727 703 return -EINVAL; 728 704 729 - dev0 = ldev->pf[first_idx].dev; 705 + dev0 = mlx5_lag_pf(ldev, first_idx)->dev; 730 706 if (tracker) 731 707 mlx5_lag_print_mapping(dev0, ldev, tracker, flags); 732 708 mlx5_core_info(dev0, "shared_fdb:%d mode:%s\n", ··· 773 749 if (first_idx < 0) 774 750 return -EINVAL; 775 751 776 - dev0 = ldev->pf[first_idx].dev; 752 + dev0 = mlx5_lag_pf(ldev, first_idx)->dev; 777 753 err = mlx5_lag_set_flags(ldev, mode, tracker, shared_fdb, &flags); 778 754 if (err) 779 755 return err; ··· 829 805 if (first_idx < 0) 830 806 return -EINVAL; 831 807 832 - dev0 = ldev->pf[first_idx].dev; 808 + dev0 = mlx5_lag_pf(ldev, first_idx)->dev; 833 809 master_esw = dev0->priv.eswitch; 834 810 ldev->mode = MLX5_LAG_MODE_NONE; 835 811 ldev->mode_flags = 0; ··· 838 814 if (test_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &flags)) { 839 815 mlx5_ldev_for_each(i, first_idx + 1, ldev) 840 816 mlx5_eswitch_offloads_single_fdb_del_one(master_esw, 841 - ldev->pf[i].dev->priv.eswitch); 817 + mlx5_lag_pf(ldev, i)->dev->priv.eswitch); 842 818 clear_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &flags); 843 819 } 844 820 ··· 873 849 struct mlx5_core_dev *dev; 874 850 u8 mode; 875 851 #endif 852 + struct lag_func *pf; 876 853 bool roce_support; 877 854 int i; 878 855 ··· 882 857 883 858 #ifdef CONFIG_MLX5_ESWITCH 884 859 mlx5_ldev_for_each(i, 0, ldev) { 885 - dev = ldev->pf[i].dev; 860 + pf = mlx5_lag_pf(ldev, i); 861 + dev = pf->dev; 886 862 if (mlx5_eswitch_num_vfs(dev->priv.eswitch) && !is_mdev_switchdev_mode(dev)) 887 863 return false; 888 864 } 889 865 890 - dev = ldev->pf[first_idx].dev; 866 + pf = mlx5_lag_pf(ldev, first_idx); 867 + dev = pf->dev; 891 868 mode = mlx5_eswitch_mode(dev); 892 - mlx5_ldev_for_each(i, 0, ldev) 893 - if (mlx5_eswitch_mode(ldev->pf[i].dev) != mode) 869 + mlx5_ldev_for_each(i, 0, ldev) { 870 + pf = mlx5_lag_pf(ldev, i); 871 + if (mlx5_eswitch_mode(pf->dev) != mode) 894 872 return false; 873 + } 895 874 896 875 #else 897 - mlx5_ldev_for_each(i, 0, ldev) 898 - if (mlx5_sriov_is_enabled(ldev->pf[i].dev)) 876 + mlx5_ldev_for_each(i, 0, ldev) { 877 + pf = mlx5_lag_pf(ldev, i); 878 + if (mlx5_sriov_is_enabled(pf->dev)) 899 879 return false; 880 + } 900 881 #endif 901 - roce_support = mlx5_get_roce_state(ldev->pf[first_idx].dev); 902 - mlx5_ldev_for_each(i, first_idx + 1, ldev) 903 - if (mlx5_get_roce_state(ldev->pf[i].dev) != roce_support) 882 + pf = mlx5_lag_pf(ldev, first_idx); 883 + roce_support = mlx5_get_roce_state(pf->dev); 884 + mlx5_ldev_for_each(i, first_idx + 1, ldev) { 885 + pf = mlx5_lag_pf(ldev, i); 886 + if (mlx5_get_roce_state(pf->dev) != roce_support) 904 887 return false; 888 + } 905 889 906 890 return true; 907 891 } 908 892 909 893 void mlx5_lag_add_devices(struct mlx5_lag *ldev) 910 894 { 895 + struct lag_func *pf; 911 896 int i; 912 897 913 898 mlx5_ldev_for_each(i, 0, ldev) { 914 - if (ldev->pf[i].dev->priv.flags & 915 - MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV) 899 + pf = mlx5_lag_pf(ldev, i); 900 + if (pf->dev->priv.flags & MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV) 916 901 continue; 917 902 918 - ldev->pf[i].dev->priv.flags &= ~MLX5_PRIV_FLAGS_DISABLE_IB_ADEV; 919 - mlx5_rescan_drivers_locked(ldev->pf[i].dev); 903 + pf->dev->priv.flags &= ~MLX5_PRIV_FLAGS_DISABLE_IB_ADEV; 904 + mlx5_rescan_drivers_locked(pf->dev); 920 905 } 921 906 } 922 907 923 908 void mlx5_lag_remove_devices(struct mlx5_lag *ldev) 924 909 { 910 + struct lag_func *pf; 925 911 int i; 926 912 927 913 mlx5_ldev_for_each(i, 0, ldev) { 928 - if (ldev->pf[i].dev->priv.flags & 929 - MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV) 914 + pf = mlx5_lag_pf(ldev, i); 915 + if (pf->dev->priv.flags & MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV) 930 916 continue; 931 917 932 - ldev->pf[i].dev->priv.flags |= MLX5_PRIV_FLAGS_DISABLE_IB_ADEV; 933 - mlx5_rescan_drivers_locked(ldev->pf[i].dev); 918 + pf->dev->priv.flags |= MLX5_PRIV_FLAGS_DISABLE_IB_ADEV; 919 + mlx5_rescan_drivers_locked(pf->dev); 934 920 } 935 921 } 936 922 ··· 957 921 if (idx < 0) 958 922 return; 959 923 960 - dev0 = ldev->pf[idx].dev; 924 + dev0 = mlx5_lag_pf(ldev, idx)->dev; 961 925 roce_lag = __mlx5_lag_is_roce(ldev); 962 926 963 927 if (shared_fdb) { ··· 968 932 mlx5_rescan_drivers_locked(dev0); 969 933 } 970 934 mlx5_ldev_for_each(i, idx + 1, ldev) 971 - mlx5_nic_vport_disable_roce(ldev->pf[i].dev); 935 + mlx5_nic_vport_disable_roce(mlx5_lag_pf(ldev, i)->dev); 972 936 } 973 937 974 938 err = mlx5_deactivate_lag(ldev); ··· 980 944 981 945 if (shared_fdb) 982 946 mlx5_ldev_for_each(i, 0, ldev) 983 - if (!(ldev->pf[i].dev->priv.flags & MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV)) 984 - mlx5_eswitch_reload_ib_reps(ldev->pf[i].dev->priv.eswitch); 947 + if (!(mlx5_lag_pf(ldev, i)->dev->priv.flags & MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV)) 948 + mlx5_eswitch_reload_ib_reps(mlx5_lag_pf(ldev, i)->dev->priv.eswitch); 985 949 } 986 950 987 951 bool mlx5_lag_shared_fdb_supported(struct mlx5_lag *ldev) ··· 994 958 return false; 995 959 996 960 mlx5_ldev_for_each(i, idx + 1, ldev) { 997 - dev = ldev->pf[i].dev; 961 + dev = mlx5_lag_pf(ldev, i)->dev; 998 962 if (is_mdev_switchdev_mode(dev) && 999 963 mlx5_eswitch_vport_match_metadata_enabled(dev->priv.eswitch) && 1000 964 MLX5_CAP_GEN(dev, lag_native_fdb_selection) && ··· 1005 969 return false; 1006 970 } 1007 971 1008 - dev = ldev->pf[idx].dev; 972 + dev = mlx5_lag_pf(ldev, idx)->dev; 1009 973 if (is_mdev_switchdev_mode(dev) && 1010 974 mlx5_eswitch_vport_match_metadata_enabled(dev->priv.eswitch) && 1011 975 mlx5_esw_offloads_devcom_is_ready(dev->priv.eswitch) && ··· 1019 983 static bool mlx5_lag_is_roce_lag(struct mlx5_lag *ldev) 1020 984 { 1021 985 bool roce_lag = true; 986 + struct lag_func *pf; 1022 987 int i; 1023 988 1024 - mlx5_ldev_for_each(i, 0, ldev) 1025 - roce_lag = roce_lag && !mlx5_sriov_is_enabled(ldev->pf[i].dev); 989 + mlx5_ldev_for_each(i, 0, ldev) { 990 + pf = mlx5_lag_pf(ldev, i); 991 + roce_lag = roce_lag && !mlx5_sriov_is_enabled(pf->dev); 992 + } 1026 993 1027 994 #ifdef CONFIG_MLX5_ESWITCH 1028 - mlx5_ldev_for_each(i, 0, ldev) 1029 - roce_lag = roce_lag && is_mdev_legacy_mode(ldev->pf[i].dev); 995 + mlx5_ldev_for_each(i, 0, ldev) { 996 + pf = mlx5_lag_pf(ldev, i); 997 + roce_lag = roce_lag && is_mdev_legacy_mode(pf->dev); 998 + } 1030 999 #endif 1031 1000 1032 1001 return roce_lag; ··· 1055 1014 int (*get_speed)(struct mlx5_core_dev *, u32 *)) 1056 1015 { 1057 1016 struct mlx5_core_dev *pf_mdev; 1017 + struct lag_func *pf; 1058 1018 int pf_idx; 1059 1019 u32 speed; 1060 1020 int ret; 1061 1021 1062 1022 *sum_speed = 0; 1063 1023 mlx5_ldev_for_each(pf_idx, 0, ldev) { 1064 - pf_mdev = ldev->pf[pf_idx].dev; 1024 + pf = mlx5_lag_pf(ldev, pf_idx); 1025 + if (!pf) 1026 + continue; 1027 + pf_mdev = pf->dev; 1065 1028 if (!pf_mdev) 1066 1029 continue; 1067 1030 ··· 1131 1086 void mlx5_lag_set_vports_agg_speed(struct mlx5_lag *ldev) 1132 1087 { 1133 1088 struct mlx5_core_dev *mdev; 1089 + struct lag_func *pf; 1134 1090 u32 speed; 1135 1091 int pf_idx; 1136 1092 ··· 1151 1105 speed = speed / MLX5_MAX_TX_SPEED_UNIT; 1152 1106 1153 1107 mlx5_ldev_for_each(pf_idx, 0, ldev) { 1154 - mdev = ldev->pf[pf_idx].dev; 1108 + pf = mlx5_lag_pf(ldev, pf_idx); 1109 + if (!pf) 1110 + continue; 1111 + mdev = pf->dev; 1155 1112 if (!mdev) 1156 1113 continue; 1157 1114 ··· 1165 1116 void mlx5_lag_reset_vports_speed(struct mlx5_lag *ldev) 1166 1117 { 1167 1118 struct mlx5_core_dev *mdev; 1119 + struct lag_func *pf; 1168 1120 u32 speed; 1169 1121 int pf_idx; 1170 1122 int ret; 1171 1123 1172 1124 mlx5_ldev_for_each(pf_idx, 0, ldev) { 1173 - mdev = ldev->pf[pf_idx].dev; 1125 + pf = mlx5_lag_pf(ldev, pf_idx); 1126 + if (!pf) 1127 + continue; 1128 + mdev = pf->dev; 1174 1129 if (!mdev) 1175 1130 continue; 1176 1131 ··· 1205 1152 if (idx < 0) 1206 1153 return; 1207 1154 1208 - dev0 = ldev->pf[idx].dev; 1155 + dev0 = mlx5_lag_pf(ldev, idx)->dev; 1209 1156 if (!mlx5_lag_is_ready(ldev)) { 1210 1157 do_bond = false; 1211 1158 } else { ··· 1235 1182 mlx5_lag_add_devices(ldev); 1236 1183 if (shared_fdb) { 1237 1184 mlx5_ldev_for_each(i, 0, ldev) 1238 - mlx5_eswitch_reload_ib_reps(ldev->pf[i].dev->priv.eswitch); 1185 + mlx5_eswitch_reload_ib_reps(mlx5_lag_pf(ldev, i)->dev->priv.eswitch); 1239 1186 } 1240 1187 1241 1188 return; 1242 1189 } else if (roce_lag) { 1190 + struct mlx5_core_dev *dev; 1191 + 1243 1192 dev0->priv.flags &= ~MLX5_PRIV_FLAGS_DISABLE_IB_ADEV; 1244 1193 mlx5_rescan_drivers_locked(dev0); 1245 1194 mlx5_ldev_for_each(i, idx + 1, ldev) { 1246 - if (mlx5_get_roce_state(ldev->pf[i].dev)) 1247 - mlx5_nic_vport_enable_roce(ldev->pf[i].dev); 1195 + dev = mlx5_lag_pf(ldev, i)->dev; 1196 + if (mlx5_get_roce_state(dev)) 1197 + mlx5_nic_vport_enable_roce(dev); 1248 1198 } 1249 1199 } else if (shared_fdb) { 1250 1200 int i; ··· 1256 1200 mlx5_rescan_drivers_locked(dev0); 1257 1201 1258 1202 mlx5_ldev_for_each(i, 0, ldev) { 1259 - err = mlx5_eswitch_reload_ib_reps(ldev->pf[i].dev->priv.eswitch); 1203 + err = mlx5_eswitch_reload_ib_reps(mlx5_lag_pf(ldev, i)->dev->priv.eswitch); 1260 1204 if (err) 1261 1205 break; 1262 1206 } ··· 1267 1211 mlx5_deactivate_lag(ldev); 1268 1212 mlx5_lag_add_devices(ldev); 1269 1213 mlx5_ldev_for_each(i, 0, ldev) 1270 - mlx5_eswitch_reload_ib_reps(ldev->pf[i].dev->priv.eswitch); 1214 + mlx5_eswitch_reload_ib_reps(mlx5_lag_pf(ldev, i)->dev->priv.eswitch); 1271 1215 mlx5_core_err(dev0, "Failed to enable lag\n"); 1272 1216 return; 1273 1217 } ··· 1299 1243 struct mlx5_devcom_comp_dev *mlx5_lag_get_devcom_comp(struct mlx5_lag *ldev) 1300 1244 { 1301 1245 struct mlx5_devcom_comp_dev *devcom = NULL; 1246 + struct lag_func *pf; 1302 1247 int i; 1303 1248 1304 1249 mutex_lock(&ldev->lock); 1305 1250 i = mlx5_get_next_ldev_func(ldev, 0); 1306 - if (i < MLX5_MAX_PORTS) 1307 - devcom = ldev->pf[i].dev->priv.hca_devcom_comp; 1251 + if (i < MLX5_MAX_PORTS) { 1252 + pf = mlx5_lag_pf(ldev, i); 1253 + devcom = pf->dev->priv.hca_devcom_comp; 1254 + } 1308 1255 mutex_unlock(&ldev->lock); 1309 1256 return devcom; 1310 1257 } ··· 1356 1297 struct netdev_lag_upper_info *lag_upper_info = NULL; 1357 1298 bool is_bonded, is_in_lag, mode_supported; 1358 1299 bool has_inactive = 0; 1300 + struct lag_func *pf; 1359 1301 struct slave *slave; 1360 1302 u8 bond_status = 0; 1361 1303 int num_slaves = 0; ··· 1377 1317 rcu_read_lock(); 1378 1318 for_each_netdev_in_bond_rcu(upper, ndev_tmp) { 1379 1319 mlx5_ldev_for_each(i, 0, ldev) { 1380 - if (ldev->pf[i].netdev == ndev_tmp) { 1320 + pf = mlx5_lag_pf(ldev, i); 1321 + if (pf->netdev == ndev_tmp) { 1381 1322 idx++; 1382 1323 break; 1383 1324 } ··· 1599 1538 struct net_device *netdev) 1600 1539 { 1601 1540 unsigned int fn = mlx5_get_dev_index(dev); 1541 + struct lag_func *pf; 1602 1542 unsigned long flags; 1603 1543 1604 1544 spin_lock_irqsave(&lag_lock, flags); 1605 - ldev->pf[fn].netdev = netdev; 1545 + pf = mlx5_lag_pf(ldev, fn); 1546 + pf->netdev = netdev; 1606 1547 ldev->tracker.netdev_state[fn].link_up = 0; 1607 1548 ldev->tracker.netdev_state[fn].tx_enabled = 0; 1608 1549 spin_unlock_irqrestore(&lag_lock, flags); ··· 1613 1550 static void mlx5_ldev_remove_netdev(struct mlx5_lag *ldev, 1614 1551 struct net_device *netdev) 1615 1552 { 1553 + struct lag_func *pf; 1616 1554 unsigned long flags; 1617 1555 int i; 1618 1556 1619 1557 spin_lock_irqsave(&lag_lock, flags); 1620 1558 mlx5_ldev_for_each(i, 0, ldev) { 1621 - if (ldev->pf[i].netdev == netdev) { 1622 - ldev->pf[i].netdev = NULL; 1559 + pf = mlx5_lag_pf(ldev, i); 1560 + if (pf->netdev == netdev) { 1561 + pf->netdev = NULL; 1623 1562 break; 1624 1563 } 1625 1564 } 1626 1565 spin_unlock_irqrestore(&lag_lock, flags); 1627 1566 } 1628 1567 1629 - static void mlx5_ldev_add_mdev(struct mlx5_lag *ldev, 1568 + static int mlx5_ldev_add_mdev(struct mlx5_lag *ldev, 1630 1569 struct mlx5_core_dev *dev) 1631 1570 { 1632 1571 unsigned int fn = mlx5_get_dev_index(dev); 1572 + struct lag_func *pf; 1573 + int err; 1633 1574 1634 - ldev->pf[fn].dev = dev; 1575 + pf = xa_load(&ldev->pfs, fn); 1576 + if (!pf) { 1577 + pf = kzalloc_obj(*pf); 1578 + if (!pf) 1579 + return -ENOMEM; 1580 + 1581 + err = xa_err(xa_store(&ldev->pfs, fn, pf, GFP_KERNEL)); 1582 + if (err) { 1583 + kfree(pf); 1584 + return err; 1585 + } 1586 + } 1587 + 1588 + pf->dev = dev; 1635 1589 dev->priv.lag = ldev; 1636 1590 1637 - MLX5_NB_INIT(&ldev->pf[fn].port_change_nb, 1591 + MLX5_NB_INIT(&pf->port_change_nb, 1638 1592 mlx5_lag_mpesw_port_change_event, PORT_CHANGE); 1639 - mlx5_eq_notifier_register(dev, &ldev->pf[fn].port_change_nb); 1593 + mlx5_eq_notifier_register(dev, &pf->port_change_nb); 1594 + 1595 + return 0; 1640 1596 } 1641 1597 1642 1598 static void mlx5_ldev_remove_mdev(struct mlx5_lag *ldev, 1643 1599 struct mlx5_core_dev *dev) 1644 1600 { 1601 + struct lag_func *pf; 1645 1602 int fn; 1646 1603 1647 1604 fn = mlx5_get_dev_index(dev); 1648 - if (ldev->pf[fn].dev != dev) 1605 + pf = xa_load(&ldev->pfs, fn); 1606 + if (!pf || pf->dev != dev) 1649 1607 return; 1650 1608 1651 - if (ldev->pf[fn].port_change_nb.nb.notifier_call) 1652 - mlx5_eq_notifier_unregister(dev, &ldev->pf[fn].port_change_nb); 1609 + if (pf->port_change_nb.nb.notifier_call) 1610 + mlx5_eq_notifier_unregister(dev, &pf->port_change_nb); 1653 1611 1654 - ldev->pf[fn].dev = NULL; 1612 + pf->dev = NULL; 1655 1613 dev->priv.lag = NULL; 1614 + xa_erase(&ldev->pfs, fn); 1615 + kfree(pf); 1656 1616 } 1657 1617 1658 1618 /* Must be called with HCA devcom component lock held */ ··· 1684 1598 struct mlx5_devcom_comp_dev *pos = NULL; 1685 1599 struct mlx5_lag *ldev = NULL; 1686 1600 struct mlx5_core_dev *tmp_dev; 1601 + int err; 1687 1602 1688 1603 tmp_dev = mlx5_devcom_get_next_peer_data(dev->priv.hca_devcom_comp, &pos); 1689 1604 if (tmp_dev) ··· 1696 1609 mlx5_core_err(dev, "Failed to alloc lag dev\n"); 1697 1610 return 0; 1698 1611 } 1699 - mlx5_ldev_add_mdev(ldev, dev); 1612 + err = mlx5_ldev_add_mdev(ldev, dev); 1613 + if (err) { 1614 + mlx5_core_err(dev, "Failed to add mdev to lag dev\n"); 1615 + mlx5_ldev_put(ldev); 1616 + return 0; 1617 + } 1700 1618 return 0; 1701 1619 } 1702 1620 ··· 1711 1619 return -EAGAIN; 1712 1620 } 1713 1621 mlx5_ldev_get(ldev); 1714 - mlx5_ldev_add_mdev(ldev, dev); 1622 + err = mlx5_ldev_add_mdev(ldev, dev); 1623 + if (err) { 1624 + mlx5_ldev_put(ldev); 1625 + mutex_unlock(&ldev->lock); 1626 + return err; 1627 + } 1715 1628 mutex_unlock(&ldev->lock); 1716 1629 1717 1630 return 0; ··· 1843 1746 1844 1747 int mlx5_get_pre_ldev_func(struct mlx5_lag *ldev, int start_idx, int end_idx) 1845 1748 { 1749 + struct lag_func *pf; 1846 1750 int i; 1847 1751 1848 - for (i = start_idx; i >= end_idx; i--) 1849 - if (ldev->pf[i].dev) 1752 + for (i = start_idx; i >= end_idx; i--) { 1753 + pf = xa_load(&ldev->pfs, i); 1754 + if (pf && pf->dev) 1850 1755 return i; 1756 + } 1851 1757 return -1; 1852 1758 } 1853 1759 1854 1760 int mlx5_get_next_ldev_func(struct mlx5_lag *ldev, int start_idx) 1855 1761 { 1856 - int i; 1762 + struct lag_func *pf; 1763 + unsigned long idx; 1857 1764 1858 - for (i = start_idx; i < MLX5_MAX_PORTS; i++) 1859 - if (ldev->pf[i].dev) 1860 - return i; 1765 + xa_for_each_start(&ldev->pfs, idx, pf, start_idx) 1766 + if (pf->dev) 1767 + return idx; 1861 1768 return MLX5_MAX_PORTS; 1862 1769 } 1863 1770 ··· 1915 1814 { 1916 1815 struct mlx5_lag *ldev; 1917 1816 unsigned long flags; 1817 + struct lag_func *pf; 1918 1818 bool res = false; 1919 1819 int idx; 1920 1820 1921 1821 spin_lock_irqsave(&lag_lock, flags); 1922 1822 ldev = mlx5_lag_dev(dev); 1923 1823 idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1); 1924 - res = ldev && __mlx5_lag_is_active(ldev) && idx >= 0 && dev == ldev->pf[idx].dev; 1824 + if (ldev && __mlx5_lag_is_active(ldev) && idx >= 0) { 1825 + pf = mlx5_lag_pf(ldev, idx); 1826 + res = pf && dev == pf->dev; 1827 + } 1925 1828 spin_unlock_irqrestore(&lag_lock, flags); 1926 1829 1927 1830 return res; ··· 2004 1899 { 2005 1900 struct mlx5_lag *ldev; 2006 1901 unsigned long flags; 1902 + struct lag_func *pf; 2007 1903 u8 port = 0; 2008 1904 int i; 2009 1905 ··· 2014 1908 goto unlock; 2015 1909 2016 1910 mlx5_ldev_for_each(i, 0, ldev) { 2017 - if (ldev->pf[i].netdev == slave) { 1911 + pf = mlx5_lag_pf(ldev, i); 1912 + if (pf->netdev == slave) { 2018 1913 port = i; 2019 1914 break; 2020 1915 } ··· 2046 1939 struct mlx5_core_dev *peer_dev = NULL; 2047 1940 struct mlx5_lag *ldev; 2048 1941 unsigned long flags; 1942 + struct lag_func *pf; 2049 1943 int idx; 2050 1944 2051 1945 spin_lock_irqsave(&lag_lock, flags); ··· 2056 1948 2057 1949 if (*i == MLX5_MAX_PORTS) 2058 1950 goto unlock; 2059 - mlx5_ldev_for_each(idx, *i, ldev) 2060 - if (ldev->pf[idx].dev != dev) 1951 + mlx5_ldev_for_each(idx, *i, ldev) { 1952 + pf = mlx5_lag_pf(ldev, idx); 1953 + if (pf->dev != dev) 2061 1954 break; 1955 + } 2062 1956 2063 1957 if (idx == MLX5_MAX_PORTS) { 2064 1958 *i = idx; ··· 2068 1958 } 2069 1959 *i = idx + 1; 2070 1960 2071 - peer_dev = ldev->pf[idx].dev; 1961 + pf = mlx5_lag_pf(ldev, idx); 1962 + peer_dev = pf->dev; 2072 1963 2073 1964 unlock: 2074 1965 spin_unlock_irqrestore(&lag_lock, flags); ··· 2087 1976 int ret = 0, i, j, idx = 0; 2088 1977 struct mlx5_lag *ldev; 2089 1978 unsigned long flags; 1979 + struct lag_func *pf; 2090 1980 int num_ports; 2091 1981 void *out; 2092 1982 ··· 2107 1995 ldev = mlx5_lag_dev(dev); 2108 1996 if (ldev && __mlx5_lag_is_active(ldev)) { 2109 1997 num_ports = ldev->ports; 2110 - mlx5_ldev_for_each(i, 0, ldev) 2111 - mdev[idx++] = ldev->pf[i].dev; 1998 + mlx5_ldev_for_each(i, 0, ldev) { 1999 + pf = mlx5_lag_pf(ldev, i); 2000 + mdev[idx++] = pf->dev; 2001 + } 2112 2002 } else { 2113 2003 num_ports = 1; 2114 2004 mdev[MLX5_LAG_P1] = dev;
+7 -1
drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h
··· 64 64 int mode_changes_in_progress; 65 65 u8 v2p_map[MLX5_MAX_PORTS * MLX5_LAG_MAX_HASH_BUCKETS]; 66 66 struct kref ref; 67 - struct lag_func pf[MLX5_MAX_PORTS]; 67 + struct xarray pfs; 68 68 struct lag_tracker tracker; 69 69 struct workqueue_struct *wq; 70 70 struct delayed_work bond_work; ··· 82 82 mlx5_lag_dev(struct mlx5_core_dev *dev) 83 83 { 84 84 return dev->priv.lag; 85 + } 86 + 87 + static inline struct lag_func * 88 + mlx5_lag_pf(struct mlx5_lag *ldev, unsigned int idx) 89 + { 90 + return xa_load(&ldev->pfs, idx); 85 91 } 86 92 87 93 static inline bool
+10 -10
drivers/net/ethernet/mellanox/mlx5/core/lag/mp.c
··· 29 29 if (ldev->ports > MLX5_LAG_MULTIPATH_OFFLOADS_SUPPORTED_PORTS) 30 30 return false; 31 31 32 - return mlx5_esw_multipath_prereq(ldev->pf[idx0].dev, 33 - ldev->pf[idx1].dev); 32 + return mlx5_esw_multipath_prereq(mlx5_lag_pf(ldev, idx0)->dev, 33 + mlx5_lag_pf(ldev, idx1)->dev); 34 34 } 35 35 36 36 bool mlx5_lag_is_multipath(struct mlx5_core_dev *dev) ··· 80 80 tracker.netdev_state[idx1].link_up = true; 81 81 break; 82 82 default: 83 - mlx5_core_warn(ldev->pf[idx0].dev, 83 + mlx5_core_warn(mlx5_lag_pf(ldev, idx0)->dev, 84 84 "Invalid affinity port %d", port); 85 85 return; 86 86 } 87 87 88 88 if (tracker.netdev_state[idx0].tx_enabled) 89 - mlx5_notifier_call_chain(ldev->pf[idx0].dev->priv.events, 89 + mlx5_notifier_call_chain(mlx5_lag_pf(ldev, idx0)->dev->priv.events, 90 90 MLX5_DEV_EVENT_PORT_AFFINITY, 91 91 (void *)0); 92 92 93 93 if (tracker.netdev_state[idx1].tx_enabled) 94 - mlx5_notifier_call_chain(ldev->pf[idx1].dev->priv.events, 94 + mlx5_notifier_call_chain(mlx5_lag_pf(ldev, idx1)->dev->priv.events, 95 95 MLX5_DEV_EVENT_PORT_AFFINITY, 96 96 (void *)0); 97 97 ··· 146 146 fib_dev = fib_info_nh(fi, i)->fib_nh_dev; 147 147 ldev_idx = mlx5_lag_dev_get_netdev_idx(ldev, fib_dev); 148 148 if (ldev_idx >= 0) 149 - return ldev->pf[ldev_idx].netdev; 149 + return mlx5_lag_pf(ldev, ldev_idx)->netdev; 150 150 } 151 151 152 152 return NULL; ··· 178 178 mp->fib.dst_len <= fen_info->dst_len && 179 179 !(mp->fib.dst_len == fen_info->dst_len && 180 180 fi->fib_priority < mp->fib.priority)) { 181 - mlx5_core_dbg(ldev->pf[idx].dev, 181 + mlx5_core_dbg(mlx5_lag_pf(ldev, idx)->dev, 182 182 "Multipath entry with lower priority was rejected\n"); 183 183 return; 184 184 } ··· 194 194 } 195 195 196 196 if (nh_dev0 == nh_dev1) { 197 - mlx5_core_warn(ldev->pf[idx].dev, 197 + mlx5_core_warn(mlx5_lag_pf(ldev, idx)->dev, 198 198 "Multipath offload doesn't support routes with multiple nexthops of the same device"); 199 199 return; 200 200 } ··· 203 203 if (__mlx5_lag_is_active(ldev)) { 204 204 mlx5_ldev_for_each(i, 0, ldev) { 205 205 dev_idx++; 206 - if (ldev->pf[i].netdev == nh_dev0) 206 + if (mlx5_lag_pf(ldev, i)->netdev == nh_dev0) 207 207 break; 208 208 } 209 209 mlx5_lag_set_port_affinity(ldev, dev_idx); ··· 240 240 /* nh added/removed */ 241 241 if (event == FIB_EVENT_NH_DEL) { 242 242 mlx5_ldev_for_each(i, 0, ldev) { 243 - if (ldev->pf[i].netdev == fib_nh->fib_nh_dev) 243 + if (mlx5_lag_pf(ldev, i)->netdev == fib_nh->fib_nh_dev) 244 244 break; 245 245 dev_idx++; 246 246 }
+6 -6
drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c
··· 16 16 int i; 17 17 18 18 mlx5_ldev_for_each(i, 0, ldev) { 19 - dev = ldev->pf[i].dev; 19 + dev = mlx5_lag_pf(ldev, i)->dev; 20 20 esw = dev->priv.eswitch; 21 21 pf_metadata = ldev->lag_mpesw.pf_metadata[i]; 22 22 if (!pf_metadata) ··· 37 37 int i, err; 38 38 39 39 mlx5_ldev_for_each(i, 0, ldev) { 40 - dev = ldev->pf[i].dev; 40 + dev = mlx5_lag_pf(ldev, i)->dev; 41 41 esw = dev->priv.eswitch; 42 42 pf_metadata = mlx5_esw_match_metadata_alloc(esw); 43 43 if (!pf_metadata) { ··· 53 53 } 54 54 55 55 mlx5_ldev_for_each(i, 0, ldev) { 56 - dev = ldev->pf[i].dev; 56 + dev = mlx5_lag_pf(ldev, i)->dev; 57 57 mlx5_notifier_call_chain(dev->priv.events, MLX5_DEV_EVENT_MULTIPORT_ESW, 58 58 (void *)0); 59 59 } ··· 82 82 if (idx < 0) 83 83 return -EINVAL; 84 84 85 - dev0 = ldev->pf[idx].dev; 85 + dev0 = mlx5_lag_pf(ldev, idx)->dev; 86 86 if (mlx5_eswitch_mode(dev0) != MLX5_ESWITCH_OFFLOADS || 87 87 !MLX5_CAP_PORT_SELECTION(dev0, port_select_flow_table) || 88 88 !MLX5_CAP_GEN(dev0, create_lag_when_not_master_up) || ··· 105 105 dev0->priv.flags &= ~MLX5_PRIV_FLAGS_DISABLE_IB_ADEV; 106 106 mlx5_rescan_drivers_locked(dev0); 107 107 mlx5_ldev_for_each(i, 0, ldev) { 108 - err = mlx5_eswitch_reload_ib_reps(ldev->pf[i].dev->priv.eswitch); 108 + err = mlx5_eswitch_reload_ib_reps(mlx5_lag_pf(ldev, i)->dev->priv.eswitch); 109 109 if (err) 110 110 goto err_rescan_drivers; 111 111 } ··· 121 121 err_add_devices: 122 122 mlx5_lag_add_devices(ldev); 123 123 mlx5_ldev_for_each(i, 0, ldev) 124 - mlx5_eswitch_reload_ib_reps(ldev->pf[i].dev->priv.eswitch); 124 + mlx5_eswitch_reload_ib_reps(mlx5_lag_pf(ldev, i)->dev->priv.eswitch); 125 125 mlx5_mpesw_metadata_cleanup(ldev); 126 126 return err; 127 127 }
+11 -9
drivers/net/ethernet/mellanox/mlx5/core/lag/port_sel.c
··· 50 50 if (first_idx < 0) 51 51 return -EINVAL; 52 52 53 - dev = ldev->pf[first_idx].dev; 53 + dev = mlx5_lag_pf(ldev, first_idx)->dev; 54 54 ft_attr.max_fte = ldev->ports * ldev->buckets; 55 55 ft_attr.level = MLX5_LAG_FT_LEVEL_DEFINER; 56 56 ··· 84 84 idx = i * ldev->buckets + j; 85 85 affinity = ports[idx]; 86 86 87 - dest.vport.vhca_id = MLX5_CAP_GEN(ldev->pf[affinity - 1].dev, 88 - vhca_id); 87 + dest.vport.vhca_id = 88 + MLX5_CAP_GEN(mlx5_lag_pf(ldev, affinity - 1)->dev, 89 + vhca_id); 89 90 lag_definer->rules[idx] = mlx5_add_flow_rules(lag_definer->ft, 90 91 NULL, &flow_act, 91 92 &dest, 1); ··· 308 307 if (first_idx < 0) 309 308 return ERR_PTR(-EINVAL); 310 309 311 - dev = ldev->pf[first_idx].dev; 310 + dev = mlx5_lag_pf(ldev, first_idx)->dev; 312 311 lag_definer = kzalloc_obj(*lag_definer); 313 312 if (!lag_definer) 314 313 return ERR_PTR(-ENOMEM); ··· 357 356 if (first_idx < 0) 358 357 return; 359 358 360 - dev = ldev->pf[first_idx].dev; 359 + dev = mlx5_lag_pf(ldev, first_idx)->dev; 361 360 mlx5_ldev_for_each(i, first_idx, ldev) { 362 361 for (j = 0; j < ldev->buckets; j++) { 363 362 idx = i * ldev->buckets + j; ··· 521 520 if (first_idx < 0) 522 521 return -EINVAL; 523 522 524 - dev = ldev->pf[first_idx].dev; 523 + dev = mlx5_lag_pf(ldev, first_idx)->dev; 525 524 mlx5_lag_set_outer_ttc_params(ldev, &ttc_params); 526 525 port_sel->outer.ttc = mlx5_create_ttc_table(dev, &ttc_params); 527 526 return PTR_ERR_OR_ZERO(port_sel->outer.ttc); ··· 537 536 if (first_idx < 0) 538 537 return -EINVAL; 539 538 540 - dev = ldev->pf[first_idx].dev; 539 + dev = mlx5_lag_pf(ldev, first_idx)->dev; 541 540 mlx5_lag_set_inner_ttc_params(ldev, &ttc_params); 542 541 port_sel->inner.ttc = mlx5_create_inner_ttc_table(dev, &ttc_params); 543 542 return PTR_ERR_OR_ZERO(port_sel->inner.ttc); ··· 595 594 if (ldev->v2p_map[idx] == ports[idx]) 596 595 continue; 597 596 598 - dest.vport.vhca_id = MLX5_CAP_GEN(ldev->pf[ports[idx] - 1].dev, 599 - vhca_id); 597 + dest.vport.vhca_id = 598 + MLX5_CAP_GEN(mlx5_lag_pf(ldev, ports[idx] - 1)->dev, 599 + vhca_id); 600 600 err = mlx5_modify_rule_destination(def->rules[idx], &dest, NULL); 601 601 if (err) 602 602 return err;