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

Merge tag 'mlx5-socket-direct-v3' of git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux

Saeed Mahameed says:

====================
Support Multi-PF netdev (Socket Direct)

This series adds support for combining multiple devices (PFs) of the
same port under one netdev instance. Passing traffic through different
devices belonging to different NUMA sockets saves cross-numa traffic and
allows apps running on the same netdev from different numas to still
feel a sense of proximity to the device and achieve improved
performance.

We achieve this by grouping PFs together, and creating the netdev only
once all group members are probed. Symmetrically, we destroy the netdev
once any of the PFs is removed.

The channels are distributed between all devices, a proper configuration
would utilize the correct close numa when working on a certain app/cpu.

We pick one device to be a primary (leader), and it fills a special
role. The other devices (secondaries) are disconnected from the network
in the chip level (set to silent mode). All RX/TX traffic is steered
through the primary to/from the secondaries.

Currently, we limit the support to PFs only, and up to two devices
(sockets).

* tag 'mlx5-socket-direct-v3' of git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux:
Documentation: networking: Add description for multi-pf netdev
net/mlx5: Enable SD feature
net/mlx5e: Block TLS device offload on combined SD netdev
net/mlx5e: Support per-mdev queue counter
net/mlx5e: Support cross-vhca RSS
net/mlx5e: Let channels be SD-aware
net/mlx5e: Create EN core HW resources for all secondary devices
net/mlx5e: Create single netdev per SD group
net/mlx5: SD, Add debugfs
net/mlx5: SD, Add informative prints in kernel log
net/mlx5: SD, Implement steering for primary and secondaries
net/mlx5: SD, Implement devcom communication and primary election
net/mlx5: SD, Implement basic query and instantiation
net/mlx5: SD, Introduce SD lib
net/mlx5: Add MPIR bit in mcam_access_reg
====================

Link: https://lore.kernel.org/r/20240307084229.500776-1-saeed@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+1171 -176
+1
Documentation/networking/index.rst
··· 74 74 mpls-sysctl 75 75 mptcp-sysctl 76 76 multiqueue 77 + multi-pf-netdev 77 78 napi 78 79 net_cachelines/index 79 80 netconsole
+174
Documentation/networking/multi-pf-netdev.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + .. include:: <isonum.txt> 3 + 4 + =============== 5 + Multi-PF Netdev 6 + =============== 7 + 8 + Contents 9 + ======== 10 + 11 + - `Background`_ 12 + - `Overview`_ 13 + - `mlx5 implementation`_ 14 + - `Channels distribution`_ 15 + - `Observability`_ 16 + - `Steering`_ 17 + - `Mutually exclusive features`_ 18 + 19 + Background 20 + ========== 21 + 22 + The Multi-PF NIC technology enables several CPUs within a multi-socket server to connect directly to 23 + the network, each through its own dedicated PCIe interface. Through either a connection harness that 24 + splits the PCIe lanes between two cards or by bifurcating a PCIe slot for a single card. This 25 + results in eliminating the network traffic traversing over the internal bus between the sockets, 26 + significantly reducing overhead and latency, in addition to reducing CPU utilization and increasing 27 + network throughput. 28 + 29 + Overview 30 + ======== 31 + 32 + The feature adds support for combining multiple PFs of the same port in a Multi-PF environment under 33 + one netdev instance. It is implemented in the netdev layer. Lower-layer instances like pci func, 34 + sysfs entry, and devlink are kept separate. 35 + Passing traffic through different devices belonging to different NUMA sockets saves cross-NUMA 36 + traffic and allows apps running on the same netdev from different NUMAs to still feel a sense of 37 + proximity to the device and achieve improved performance. 38 + 39 + mlx5 implementation 40 + =================== 41 + 42 + Multi-PF or Socket-direct in mlx5 is achieved by grouping PFs together which belong to the same 43 + NIC and has the socket-direct property enabled, once all PFs are probed, we create a single netdev 44 + to represent all of them, symmetrically, we destroy the netdev whenever any of the PFs is removed. 45 + 46 + The netdev network channels are distributed between all devices, a proper configuration would utilize 47 + the correct close NUMA node when working on a certain app/CPU. 48 + 49 + We pick one PF to be a primary (leader), and it fills a special role. The other devices 50 + (secondaries) are disconnected from the network at the chip level (set to silent mode). In silent 51 + mode, no south <-> north traffic flowing directly through a secondary PF. It needs the assistance of 52 + the leader PF (east <-> west traffic) to function. All Rx/Tx traffic is steered through the primary 53 + to/from the secondaries. 54 + 55 + Currently, we limit the support to PFs only, and up to two PFs (sockets). 56 + 57 + Channels distribution 58 + ===================== 59 + 60 + We distribute the channels between the different PFs to achieve local NUMA node performance 61 + on multiple NUMA nodes. 62 + 63 + Each combined channel works against one specific PF, creating all its datapath queues against it. We 64 + distribute channels to PFs in a round-robin policy. 65 + 66 + :: 67 + 68 + Example for 2 PFs and 5 channels: 69 + +--------+--------+ 70 + | ch idx | PF idx | 71 + +--------+--------+ 72 + | 0 | 0 | 73 + | 1 | 1 | 74 + | 2 | 0 | 75 + | 3 | 1 | 76 + | 4 | 0 | 77 + +--------+--------+ 78 + 79 + 80 + The reason we prefer round-robin is, it is less influenced by changes in the number of channels. The 81 + mapping between a channel index and a PF is fixed, no matter how many channels the user configures. 82 + As the channel stats are persistent across channel's closure, changing the mapping every single time 83 + would turn the accumulative stats less representing of the channel's history. 84 + 85 + This is achieved by using the correct core device instance (mdev) in each channel, instead of them 86 + all using the same instance under "priv->mdev". 87 + 88 + Observability 89 + ============= 90 + The relation between PF, irq, napi, and queue can be observed via netlink spec: 91 + 92 + $ ./tools/net/ynl/cli.py --spec Documentation/netlink/specs/netdev.yaml --dump queue-get --json='{"ifindex": 13}' 93 + [{'id': 0, 'ifindex': 13, 'napi-id': 539, 'type': 'rx'}, 94 + {'id': 1, 'ifindex': 13, 'napi-id': 540, 'type': 'rx'}, 95 + {'id': 2, 'ifindex': 13, 'napi-id': 541, 'type': 'rx'}, 96 + {'id': 3, 'ifindex': 13, 'napi-id': 542, 'type': 'rx'}, 97 + {'id': 4, 'ifindex': 13, 'napi-id': 543, 'type': 'rx'}, 98 + {'id': 0, 'ifindex': 13, 'napi-id': 539, 'type': 'tx'}, 99 + {'id': 1, 'ifindex': 13, 'napi-id': 540, 'type': 'tx'}, 100 + {'id': 2, 'ifindex': 13, 'napi-id': 541, 'type': 'tx'}, 101 + {'id': 3, 'ifindex': 13, 'napi-id': 542, 'type': 'tx'}, 102 + {'id': 4, 'ifindex': 13, 'napi-id': 543, 'type': 'tx'}] 103 + 104 + $ ./tools/net/ynl/cli.py --spec Documentation/netlink/specs/netdev.yaml --dump napi-get --json='{"ifindex": 13}' 105 + [{'id': 543, 'ifindex': 13, 'irq': 42}, 106 + {'id': 542, 'ifindex': 13, 'irq': 41}, 107 + {'id': 541, 'ifindex': 13, 'irq': 40}, 108 + {'id': 540, 'ifindex': 13, 'irq': 39}, 109 + {'id': 539, 'ifindex': 13, 'irq': 36}] 110 + 111 + Here you can clearly observe our channels distribution policy: 112 + 113 + $ ls /proc/irq/{36,39,40,41,42}/mlx5* -d -1 114 + /proc/irq/36/mlx5_comp1@pci:0000:08:00.0 115 + /proc/irq/39/mlx5_comp1@pci:0000:09:00.0 116 + /proc/irq/40/mlx5_comp2@pci:0000:08:00.0 117 + /proc/irq/41/mlx5_comp2@pci:0000:09:00.0 118 + /proc/irq/42/mlx5_comp3@pci:0000:08:00.0 119 + 120 + Steering 121 + ======== 122 + Secondary PFs are set to "silent" mode, meaning they are disconnected from the network. 123 + 124 + In Rx, the steering tables belong to the primary PF only, and it is its role to distribute incoming 125 + traffic to other PFs, via cross-vhca steering capabilities. Still maintain a single default RSS table, 126 + that is capable of pointing to the receive queues of a different PF. 127 + 128 + In Tx, the primary PF creates a new Tx flow table, which is aliased by the secondaries, so they can 129 + go out to the network through it. 130 + 131 + In addition, we set default XPS configuration that, based on the CPU, selects an SQ belonging to the 132 + PF on the same node as the CPU. 133 + 134 + XPS default config example: 135 + 136 + NUMA node(s): 2 137 + NUMA node0 CPU(s): 0-11 138 + NUMA node1 CPU(s): 12-23 139 + 140 + PF0 on node0, PF1 on node1. 141 + 142 + - /sys/class/net/eth2/queues/tx-0/xps_cpus:000001 143 + - /sys/class/net/eth2/queues/tx-1/xps_cpus:001000 144 + - /sys/class/net/eth2/queues/tx-2/xps_cpus:000002 145 + - /sys/class/net/eth2/queues/tx-3/xps_cpus:002000 146 + - /sys/class/net/eth2/queues/tx-4/xps_cpus:000004 147 + - /sys/class/net/eth2/queues/tx-5/xps_cpus:004000 148 + - /sys/class/net/eth2/queues/tx-6/xps_cpus:000008 149 + - /sys/class/net/eth2/queues/tx-7/xps_cpus:008000 150 + - /sys/class/net/eth2/queues/tx-8/xps_cpus:000010 151 + - /sys/class/net/eth2/queues/tx-9/xps_cpus:010000 152 + - /sys/class/net/eth2/queues/tx-10/xps_cpus:000020 153 + - /sys/class/net/eth2/queues/tx-11/xps_cpus:020000 154 + - /sys/class/net/eth2/queues/tx-12/xps_cpus:000040 155 + - /sys/class/net/eth2/queues/tx-13/xps_cpus:040000 156 + - /sys/class/net/eth2/queues/tx-14/xps_cpus:000080 157 + - /sys/class/net/eth2/queues/tx-15/xps_cpus:080000 158 + - /sys/class/net/eth2/queues/tx-16/xps_cpus:000100 159 + - /sys/class/net/eth2/queues/tx-17/xps_cpus:100000 160 + - /sys/class/net/eth2/queues/tx-18/xps_cpus:000200 161 + - /sys/class/net/eth2/queues/tx-19/xps_cpus:200000 162 + - /sys/class/net/eth2/queues/tx-20/xps_cpus:000400 163 + - /sys/class/net/eth2/queues/tx-21/xps_cpus:400000 164 + - /sys/class/net/eth2/queues/tx-22/xps_cpus:000800 165 + - /sys/class/net/eth2/queues/tx-23/xps_cpus:800000 166 + 167 + Mutually exclusive features 168 + =========================== 169 + 170 + The nature of Multi-PF, where different channels work with different PFs, conflicts with 171 + stateful features where the state is maintained in one of the PFs. 172 + For example, in the TLS device-offload feature, special context objects are created per connection 173 + and maintained in the PF. Transitioning between different RQs/SQs would break the feature. Hence, 174 + we disable this combination for now.
+1 -1
drivers/net/ethernet/mellanox/mlx5/core/Makefile
··· 29 29 en/reporter_tx.o en/reporter_rx.o en/params.o en/xsk/pool.o \ 30 30 en/xsk/setup.o en/xsk/rx.o en/xsk/tx.o en/devlink.o en/ptp.o \ 31 31 en/qos.o en/htb.o en/trap.o en/fs_tt_redirect.o en/selq.o \ 32 - lib/crypto.o 32 + lib/crypto.o lib/sd.o 33 33 34 34 # 35 35 # Netdev extra
+6 -3
drivers/net/ethernet/mellanox/mlx5/core/en.h
··· 60 60 #include "lib/clock.h" 61 61 #include "en/rx_res.h" 62 62 #include "en/selq.h" 63 + #include "lib/sd.h" 63 64 64 65 extern const struct net_device_ops mlx5e_netdev_ops; 65 66 struct page_pool; ··· 792 791 struct hwtstamp_config *tstamp; 793 792 DECLARE_BITMAP(state, MLX5E_CHANNEL_NUM_STATES); 794 793 int ix; 794 + int vec_ix; 795 + int sd_ix; 795 796 int cpu; 796 797 /* Sync between icosq recovery and XSK enable/disable. */ 797 798 struct mutex icosq_recovery_lock; ··· 917 914 bool tx_ptp_opened; 918 915 bool rx_ptp_opened; 919 916 struct hwtstamp_config tstamp; 920 - u16 q_counter; 917 + u16 q_counter[MLX5_SD_MAX_GROUP_SZ]; 921 918 u16 drop_rq_q_counter; 922 919 struct notifier_block events_nb; 923 920 struct notifier_block blocking_events_nb; ··· 1032 1029 1033 1030 struct mlx5e_rq_param; 1034 1031 int mlx5e_open_rq(struct mlx5e_params *params, struct mlx5e_rq_param *param, 1035 - struct mlx5e_xsk_param *xsk, int node, 1032 + struct mlx5e_xsk_param *xsk, int node, u16 q_counter, 1036 1033 struct mlx5e_rq *rq); 1037 1034 #define MLX5E_RQ_WQES_TIMEOUT 20000 /* msecs */ 1038 1035 int mlx5e_wait_for_min_rx_wqes(struct mlx5e_rq *rq, int wait_time); 1039 1036 void mlx5e_close_rq(struct mlx5e_rq *rq); 1040 - int mlx5e_create_rq(struct mlx5e_rq *rq, struct mlx5e_rq_param *param); 1037 + int mlx5e_create_rq(struct mlx5e_rq *rq, struct mlx5e_rq_param *param, u16 q_counter); 1041 1038 void mlx5e_destroy_rq(struct mlx5e_rq *rq); 1042 1039 1043 1040 struct mlx5e_sq_param;
+8 -2
drivers/net/ethernet/mellanox/mlx5/core/en/channels.c
··· 23 23 return test_bit(MLX5E_CHANNEL_STATE_XSK, c->state); 24 24 } 25 25 26 - void mlx5e_channels_get_regular_rqn(struct mlx5e_channels *chs, unsigned int ix, u32 *rqn) 26 + void mlx5e_channels_get_regular_rqn(struct mlx5e_channels *chs, unsigned int ix, u32 *rqn, 27 + u32 *vhca_id) 27 28 { 28 29 struct mlx5e_channel *c = mlx5e_channels_get(chs, ix); 29 30 30 31 *rqn = c->rq.rqn; 32 + if (vhca_id) 33 + *vhca_id = MLX5_CAP_GEN(c->mdev, vhca_id); 31 34 } 32 35 33 - void mlx5e_channels_get_xsk_rqn(struct mlx5e_channels *chs, unsigned int ix, u32 *rqn) 36 + void mlx5e_channels_get_xsk_rqn(struct mlx5e_channels *chs, unsigned int ix, u32 *rqn, 37 + u32 *vhca_id) 34 38 { 35 39 struct mlx5e_channel *c = mlx5e_channels_get(chs, ix); 36 40 37 41 WARN_ON_ONCE(!test_bit(MLX5E_CHANNEL_STATE_XSK, c->state)); 38 42 39 43 *rqn = c->xskrq.rqn; 44 + if (vhca_id) 45 + *vhca_id = MLX5_CAP_GEN(c->mdev, vhca_id); 40 46 } 41 47 42 48 bool mlx5e_channels_get_ptp_rqn(struct mlx5e_channels *chs, u32 *rqn)
+4 -2
drivers/net/ethernet/mellanox/mlx5/core/en/channels.h
··· 10 10 11 11 unsigned int mlx5e_channels_get_num(struct mlx5e_channels *chs); 12 12 bool mlx5e_channels_is_xsk(struct mlx5e_channels *chs, unsigned int ix); 13 - void mlx5e_channels_get_regular_rqn(struct mlx5e_channels *chs, unsigned int ix, u32 *rqn); 14 - void mlx5e_channels_get_xsk_rqn(struct mlx5e_channels *chs, unsigned int ix, u32 *rqn); 13 + void mlx5e_channels_get_regular_rqn(struct mlx5e_channels *chs, unsigned int ix, u32 *rqn, 14 + u32 *vhca_id); 15 + void mlx5e_channels_get_xsk_rqn(struct mlx5e_channels *chs, unsigned int ix, u32 *rqn, 16 + u32 *vhca_id); 15 17 bool mlx5e_channels_get_ptp_rqn(struct mlx5e_channels *chs, u32 *rqn); 16 18 17 19 #endif /* __MLX5_EN_CHANNELS_H__ */
+33 -15
drivers/net/ethernet/mellanox/mlx5/core/en/monitor_stats.c
··· 20 20 #define NUM_REQ_PPCNT_COUNTER_S1 MLX5_CMD_SET_MONITOR_NUM_PPCNT_COUNTER_SET1 21 21 #define NUM_REQ_Q_COUNTERS_S1 MLX5_CMD_SET_MONITOR_NUM_Q_COUNTERS_SET1 22 22 23 - int mlx5e_monitor_counter_supported(struct mlx5e_priv *priv) 23 + static int mlx5e_monitor_counter_cap(struct mlx5_core_dev *mdev) 24 24 { 25 - struct mlx5_core_dev *mdev = priv->mdev; 26 - 27 25 if (!MLX5_CAP_GEN(mdev, max_num_of_monitor_counters)) 28 26 return false; 29 27 if (MLX5_CAP_PCAM_REG(mdev, ppcnt) && ··· 34 36 return true; 35 37 } 36 38 37 - static void mlx5e_monitor_counter_arm(struct mlx5e_priv *priv) 39 + int mlx5e_monitor_counter_supported(struct mlx5e_priv *priv) 40 + { 41 + struct mlx5_core_dev *pos; 42 + int i; 43 + 44 + mlx5_sd_for_each_dev(i, priv->mdev, pos) 45 + if (!mlx5e_monitor_counter_cap(pos)) 46 + return false; 47 + return true; 48 + } 49 + 50 + static void mlx5e_monitor_counter_arm(struct mlx5_core_dev *mdev) 38 51 { 39 52 u32 in[MLX5_ST_SZ_DW(arm_monitor_counter_in)] = {}; 40 53 41 54 MLX5_SET(arm_monitor_counter_in, in, opcode, 42 55 MLX5_CMD_OP_ARM_MONITOR_COUNTER); 43 - mlx5_cmd_exec_in(priv->mdev, arm_monitor_counter, in); 56 + mlx5_cmd_exec_in(mdev, arm_monitor_counter, in); 44 57 } 45 58 46 59 static void mlx5e_monitor_counters_work(struct work_struct *work) 47 60 { 48 61 struct mlx5e_priv *priv = container_of(work, struct mlx5e_priv, 49 62 monitor_counters_work); 63 + struct mlx5_core_dev *pos; 64 + int i; 50 65 51 66 mutex_lock(&priv->state_lock); 52 67 mlx5e_stats_update_ndo_stats(priv); 53 68 mutex_unlock(&priv->state_lock); 54 - mlx5e_monitor_counter_arm(priv); 69 + mlx5_sd_for_each_dev(i, priv->mdev, pos) 70 + mlx5e_monitor_counter_arm(pos); 55 71 } 56 72 57 73 static int mlx5e_monitor_event_handler(struct notifier_block *nb, ··· 109 97 } 110 98 111 99 /* check if mlx5e_monitor_counter_supported before calling this function*/ 112 - static void mlx5e_set_monitor_counter(struct mlx5e_priv *priv) 100 + static void mlx5e_set_monitor_counter(struct mlx5_core_dev *mdev, int q_counter) 113 101 { 114 - struct mlx5_core_dev *mdev = priv->mdev; 115 102 int max_num_of_counters = MLX5_CAP_GEN(mdev, max_num_of_monitor_counters); 116 103 int num_q_counters = MLX5_CAP_GEN(mdev, num_q_monitor_counters); 117 104 int num_ppcnt_counters = !MLX5_CAP_PCAM_REG(mdev, ppcnt) ? 0 : 118 105 MLX5_CAP_GEN(mdev, num_ppcnt_monitor_counters); 119 106 u32 in[MLX5_ST_SZ_DW(set_monitor_counter_in)] = {}; 120 - int q_counter = priv->q_counter; 121 107 int cnt = 0; 122 108 123 109 if (num_ppcnt_counters >= NUM_REQ_PPCNT_COUNTER_S1 && ··· 137 127 /* check if mlx5e_monitor_counter_supported before calling this function*/ 138 128 void mlx5e_monitor_counter_init(struct mlx5e_priv *priv) 139 129 { 130 + struct mlx5_core_dev *pos; 131 + int i; 132 + 140 133 INIT_WORK(&priv->monitor_counters_work, mlx5e_monitor_counters_work); 141 134 MLX5_NB_INIT(&priv->monitor_counters_nb, mlx5e_monitor_event_handler, 142 135 MONITOR_COUNTER); 143 - mlx5_eq_notifier_register(priv->mdev, &priv->monitor_counters_nb); 144 - 145 - mlx5e_set_monitor_counter(priv); 146 - mlx5e_monitor_counter_arm(priv); 136 + mlx5_sd_for_each_dev(i, priv->mdev, pos) { 137 + mlx5_eq_notifier_register(pos, &priv->monitor_counters_nb); 138 + mlx5e_set_monitor_counter(pos, priv->q_counter[i]); 139 + mlx5e_monitor_counter_arm(pos); 140 + } 147 141 queue_work(priv->wq, &priv->update_stats_work); 148 142 } 149 143 ··· 155 141 void mlx5e_monitor_counter_cleanup(struct mlx5e_priv *priv) 156 142 { 157 143 u32 in[MLX5_ST_SZ_DW(set_monitor_counter_in)] = {}; 144 + struct mlx5_core_dev *pos; 145 + int i; 158 146 159 147 MLX5_SET(set_monitor_counter_in, in, opcode, 160 148 MLX5_CMD_OP_SET_MONITOR_COUNTER); 161 149 162 - mlx5_cmd_exec_in(priv->mdev, set_monitor_counter, in); 163 - mlx5_eq_notifier_unregister(priv->mdev, &priv->monitor_counters_nb); 150 + mlx5_sd_for_each_dev(i, priv->mdev, pos) { 151 + mlx5_cmd_exec_in(pos, set_monitor_counter, in); 152 + mlx5_eq_notifier_unregister(pos, &priv->monitor_counters_nb); 153 + } 164 154 cancel_work_sync(&priv->monitor_counters_work); 165 155 }
+2 -7
drivers/net/ethernet/mellanox/mlx5/core/en/params.c
··· 688 688 .napi = &c->napi, 689 689 .ch_stats = c->stats, 690 690 .node = cpu_to_node(c->cpu), 691 - .ix = c->ix, 691 + .ix = c->vec_ix, 692 692 }; 693 693 } 694 694 ··· 959 959 int mlx5e_build_rq_param(struct mlx5_core_dev *mdev, 960 960 struct mlx5e_params *params, 961 961 struct mlx5e_xsk_param *xsk, 962 - u16 q_counter, 963 962 struct mlx5e_rq_param *param) 964 963 { 965 964 void *rqc = param->rqc; ··· 1020 1021 MLX5_SET(wq, wq, log_wq_stride, 1021 1022 mlx5e_get_rqwq_log_stride(params->rq_wq_type, ndsegs)); 1022 1023 MLX5_SET(wq, wq, pd, mdev->mlx5e_res.hw_objs.pdn); 1023 - MLX5_SET(rqc, rqc, counter_set_id, q_counter); 1024 1024 MLX5_SET(rqc, rqc, vsd, params->vlan_strip_disable); 1025 1025 MLX5_SET(rqc, rqc, scatter_fcs, params->scatter_fcs_en); 1026 1026 ··· 1030 1032 } 1031 1033 1032 1034 void mlx5e_build_drop_rq_param(struct mlx5_core_dev *mdev, 1033 - u16 q_counter, 1034 1035 struct mlx5e_rq_param *param) 1035 1036 { 1036 1037 void *rqc = param->rqc; ··· 1038 1041 MLX5_SET(wq, wq, wq_type, MLX5_WQ_TYPE_CYCLIC); 1039 1042 MLX5_SET(wq, wq, log_wq_stride, 1040 1043 mlx5e_get_rqwq_log_stride(MLX5_WQ_TYPE_CYCLIC, 1)); 1041 - MLX5_SET(rqc, rqc, counter_set_id, q_counter); 1042 1044 1043 1045 param->wq.buf_numa_node = dev_to_node(mlx5_core_dma_dev(mdev)); 1044 1046 } ··· 1302 1306 1303 1307 int mlx5e_build_channel_param(struct mlx5_core_dev *mdev, 1304 1308 struct mlx5e_params *params, 1305 - u16 q_counter, 1306 1309 struct mlx5e_channel_param *cparam) 1307 1310 { 1308 1311 u8 icosq_log_wq_sz, async_icosq_log_wq_sz; 1309 1312 int err; 1310 1313 1311 - err = mlx5e_build_rq_param(mdev, params, NULL, q_counter, &cparam->rq); 1314 + err = mlx5e_build_rq_param(mdev, params, NULL, &cparam->rq); 1312 1315 if (err) 1313 1316 return err; 1314 1317
-3
drivers/net/ethernet/mellanox/mlx5/core/en/params.h
··· 130 130 int mlx5e_build_rq_param(struct mlx5_core_dev *mdev, 131 131 struct mlx5e_params *params, 132 132 struct mlx5e_xsk_param *xsk, 133 - u16 q_counter, 134 133 struct mlx5e_rq_param *param); 135 134 void mlx5e_build_drop_rq_param(struct mlx5_core_dev *mdev, 136 - u16 q_counter, 137 135 struct mlx5e_rq_param *param); 138 136 void mlx5e_build_sq_param_common(struct mlx5_core_dev *mdev, 139 137 struct mlx5e_sq_param *param); ··· 147 149 struct mlx5e_sq_param *param); 148 150 int mlx5e_build_channel_param(struct mlx5_core_dev *mdev, 149 151 struct mlx5e_params *params, 150 - u16 q_counter, 151 152 struct mlx5e_channel_param *cparam); 152 153 153 154 u16 mlx5e_calc_sq_stop_room(struct mlx5_core_dev *mdev, struct mlx5e_params *params);
+7 -5
drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c
··· 646 646 647 647 static void mlx5e_ptp_build_rq_param(struct mlx5_core_dev *mdev, 648 648 struct net_device *netdev, 649 - u16 q_counter, 650 649 struct mlx5e_ptp_params *ptp_params) 651 650 { 652 651 struct mlx5e_rq_param *rq_params = &ptp_params->rq_param; ··· 654 655 params->rq_wq_type = MLX5_WQ_TYPE_CYCLIC; 655 656 mlx5e_init_rq_type_params(mdev, params); 656 657 params->sw_mtu = netdev->max_mtu; 657 - mlx5e_build_rq_param(mdev, params, NULL, q_counter, rq_params); 658 + mlx5e_build_rq_param(mdev, params, NULL, rq_params); 658 659 } 659 660 660 661 static void mlx5e_ptp_build_params(struct mlx5e_ptp *c, ··· 680 681 /* RQ */ 681 682 if (test_bit(MLX5E_PTP_STATE_RX, c->state)) { 682 683 params->vlan_strip_disable = orig->vlan_strip_disable; 683 - mlx5e_ptp_build_rq_param(c->mdev, c->netdev, c->priv->q_counter, cparams); 684 + mlx5e_ptp_build_rq_param(c->mdev, c->netdev, cparams); 684 685 } 685 686 } 686 687 ··· 713 714 struct mlx5e_rq_param *rq_param) 714 715 { 715 716 int node = dev_to_node(c->mdev->device); 716 - int err; 717 + int err, sd_ix; 718 + u16 q_counter; 717 719 718 720 err = mlx5e_init_ptp_rq(c, params, &c->rq); 719 721 if (err) 720 722 return err; 721 723 722 - return mlx5e_open_rq(params, rq_param, NULL, node, &c->rq); 724 + sd_ix = mlx5_sd_ch_ix_get_dev_ix(c->mdev, MLX5E_PTP_CHANNEL_IX); 725 + q_counter = c->priv->q_counter[sd_ix]; 726 + return mlx5e_open_rq(params, rq_param, NULL, node, q_counter, &c->rq); 723 727 } 724 728 725 729 static int mlx5e_ptp_open_queues(struct mlx5e_ptp *c,
+4 -4
drivers/net/ethernet/mellanox/mlx5/core/en/qos.c
··· 122 122 123 123 memset(&param_sq, 0, sizeof(param_sq)); 124 124 memset(&param_cq, 0, sizeof(param_cq)); 125 - mlx5e_build_sq_param(priv->mdev, params, &param_sq); 126 - mlx5e_build_tx_cq_param(priv->mdev, params, &param_cq); 125 + mlx5e_build_sq_param(c->mdev, params, &param_sq); 126 + mlx5e_build_tx_cq_param(c->mdev, params, &param_cq); 127 127 err = mlx5e_open_cq(c->mdev, params->tx_cq_moderation, &param_cq, &ccp, &sq->cq); 128 128 if (err) 129 129 goto err_free_sq; ··· 176 176 */ 177 177 smp_wmb(); 178 178 179 - qos_dbg(priv->mdev, "Activate QoS SQ qid %u\n", node_qid); 179 + qos_dbg(sq->mdev, "Activate QoS SQ qid %u\n", node_qid); 180 180 mlx5e_activate_txqsq(sq); 181 181 182 182 return 0; ··· 190 190 if (!sq) /* Handle the case when the SQ failed to open. */ 191 191 return; 192 192 193 - qos_dbg(priv->mdev, "Deactivate QoS SQ qid %u\n", qid); 193 + qos_dbg(sq->mdev, "Deactivate QoS SQ qid %u\n", qid); 194 194 mlx5e_deactivate_txqsq(sq); 195 195 196 196 priv->txq2sq[mlx5e_qid_from_qos(&priv->channels, qid)] = NULL;
+2 -2
drivers/net/ethernet/mellanox/mlx5/core/en/reporter_rx.c
··· 294 294 295 295 params = &priv->channels.params; 296 296 rq_sz = mlx5e_rqwq_get_size(rq); 297 - real_time = mlx5_is_real_time_rq(priv->mdev); 298 - rq_stride = BIT(mlx5e_mpwqe_get_log_stride_size(priv->mdev, params, NULL)); 297 + real_time = mlx5_is_real_time_rq(rq->mdev); 298 + rq_stride = BIT(mlx5e_mpwqe_get_log_stride_size(rq->mdev, params, NULL)); 299 299 300 300 mlx5e_health_fmsg_named_obj_nest_start(fmsg, "RQ"); 301 301 devlink_fmsg_u8_pair_put(fmsg, "type", params->rq_wq_type);
+1 -2
drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c
··· 219 219 struct mlx5e_txqsq *sq, int tc) 220 220 { 221 221 bool stopped = netif_xmit_stopped(sq->txq); 222 - struct mlx5e_priv *priv = sq->priv; 223 222 u8 state; 224 223 int err; 225 224 ··· 226 227 devlink_fmsg_u32_pair_put(fmsg, "txq ix", sq->txq_ix); 227 228 devlink_fmsg_u32_pair_put(fmsg, "sqn", sq->sqn); 228 229 229 - err = mlx5_core_query_sq_state(priv->mdev, sq->sqn, &state); 230 + err = mlx5_core_query_sq_state(sq->mdev, sq->sqn, &state); 230 231 if (!err) 231 232 devlink_fmsg_u8_pair_put(fmsg, "HW state", state); 232 233
+101 -24
drivers/net/ethernet/mellanox/mlx5/core/en/rqt.c
··· 4 4 #include "rqt.h" 5 5 #include <linux/mlx5/transobj.h> 6 6 7 + static bool verify_num_vhca_ids(struct mlx5_core_dev *mdev, u32 *vhca_ids, 8 + unsigned int size) 9 + { 10 + unsigned int max_num_vhca_id = MLX5_CAP_GEN_2(mdev, max_rqt_vhca_id); 11 + int i; 12 + 13 + /* Verify that all vhca_ids are in range [0, max_num_vhca_ids - 1] */ 14 + for (i = 0; i < size; i++) 15 + if (vhca_ids[i] >= max_num_vhca_id) 16 + return false; 17 + return true; 18 + } 19 + 20 + static bool rqt_verify_vhca_ids(struct mlx5_core_dev *mdev, u32 *vhca_ids, 21 + unsigned int size) 22 + { 23 + if (!vhca_ids) 24 + return true; 25 + 26 + if (!MLX5_CAP_GEN(mdev, cross_vhca_rqt)) 27 + return false; 28 + if (!verify_num_vhca_ids(mdev, vhca_ids, size)) 29 + return false; 30 + 31 + return true; 32 + } 33 + 7 34 void mlx5e_rss_params_indir_init_uniform(struct mlx5e_rss_params_indir *indir, 8 35 unsigned int num_channels) 9 36 { ··· 40 13 indir->table[i] = i % num_channels; 41 14 } 42 15 43 - static int mlx5e_rqt_init(struct mlx5e_rqt *rqt, struct mlx5_core_dev *mdev, 44 - u16 max_size, u32 *init_rqns, u16 init_size) 16 + static void fill_rqn_list(void *rqtc, u32 *rqns, u32 *vhca_ids, unsigned int size) 45 17 { 18 + unsigned int i; 19 + 20 + if (vhca_ids) { 21 + MLX5_SET(rqtc, rqtc, rq_vhca_id_format, 1); 22 + for (i = 0; i < size; i++) { 23 + MLX5_SET(rqtc, rqtc, rq_vhca[i].rq_num, rqns[i]); 24 + MLX5_SET(rqtc, rqtc, rq_vhca[i].rq_vhca_id, vhca_ids[i]); 25 + } 26 + } else { 27 + for (i = 0; i < size; i++) 28 + MLX5_SET(rqtc, rqtc, rq_num[i], rqns[i]); 29 + } 30 + } 31 + static int mlx5e_rqt_init(struct mlx5e_rqt *rqt, struct mlx5_core_dev *mdev, 32 + u16 max_size, u32 *init_rqns, u32 *init_vhca_ids, u16 init_size) 33 + { 34 + int entry_sz; 46 35 void *rqtc; 47 36 int inlen; 48 37 int err; 49 38 u32 *in; 50 - int i; 39 + 40 + if (!rqt_verify_vhca_ids(mdev, init_vhca_ids, init_size)) 41 + return -EOPNOTSUPP; 51 42 52 43 rqt->mdev = mdev; 53 44 rqt->size = max_size; 54 45 55 - inlen = MLX5_ST_SZ_BYTES(create_rqt_in) + sizeof(u32) * init_size; 46 + entry_sz = init_vhca_ids ? MLX5_ST_SZ_BYTES(rq_vhca) : MLX5_ST_SZ_BYTES(rq_num); 47 + inlen = MLX5_ST_SZ_BYTES(create_rqt_in) + entry_sz * init_size; 56 48 in = kvzalloc(inlen, GFP_KERNEL); 57 49 if (!in) 58 50 return -ENOMEM; ··· 79 33 rqtc = MLX5_ADDR_OF(create_rqt_in, in, rqt_context); 80 34 81 35 MLX5_SET(rqtc, rqtc, rqt_max_size, rqt->size); 82 - 83 36 MLX5_SET(rqtc, rqtc, rqt_actual_size, init_size); 84 - for (i = 0; i < init_size; i++) 85 - MLX5_SET(rqtc, rqtc, rq_num[i], init_rqns[i]); 37 + 38 + fill_rqn_list(rqtc, init_rqns, init_vhca_ids, init_size); 86 39 87 40 err = mlx5_core_create_rqt(rqt->mdev, in, inlen, &rqt->rqtn); 88 41 ··· 94 49 { 95 50 u16 max_size = indir_enabled ? indir_table_size : 1; 96 51 97 - return mlx5e_rqt_init(rqt, mdev, max_size, &init_rqn, 1); 52 + return mlx5e_rqt_init(rqt, mdev, max_size, &init_rqn, NULL, 1); 98 53 } 99 54 100 55 static int mlx5e_bits_invert(unsigned long a, int size) ··· 108 63 return inv; 109 64 } 110 65 111 - static int mlx5e_calc_indir_rqns(u32 *rss_rqns, u32 *rqns, unsigned int num_rqns, 66 + static int mlx5e_calc_indir_rqns(u32 *rss_rqns, u32 *rqns, u32 *rss_vhca_ids, u32 *vhca_ids, 67 + unsigned int num_rqns, 112 68 u8 hfunc, struct mlx5e_rss_params_indir *indir) 113 69 { 114 70 unsigned int i; ··· 128 82 */ 129 83 return -EINVAL; 130 84 rss_rqns[i] = rqns[ix]; 85 + if (vhca_ids) 86 + rss_vhca_ids[i] = vhca_ids[ix]; 131 87 } 132 88 133 89 return 0; 134 90 } 135 91 136 92 int mlx5e_rqt_init_indir(struct mlx5e_rqt *rqt, struct mlx5_core_dev *mdev, 137 - u32 *rqns, unsigned int num_rqns, 93 + u32 *rqns, u32 *vhca_ids, unsigned int num_rqns, 138 94 u8 hfunc, struct mlx5e_rss_params_indir *indir) 139 95 { 140 - u32 *rss_rqns; 96 + u32 *rss_rqns, *rss_vhca_ids = NULL; 141 97 int err; 142 98 143 99 rss_rqns = kvmalloc_array(indir->actual_table_size, sizeof(*rss_rqns), GFP_KERNEL); 144 100 if (!rss_rqns) 145 101 return -ENOMEM; 146 102 147 - err = mlx5e_calc_indir_rqns(rss_rqns, rqns, num_rqns, hfunc, indir); 103 + if (vhca_ids) { 104 + rss_vhca_ids = kvmalloc_array(indir->actual_table_size, sizeof(*rss_vhca_ids), 105 + GFP_KERNEL); 106 + if (!rss_vhca_ids) { 107 + kvfree(rss_rqns); 108 + return -ENOMEM; 109 + } 110 + } 111 + 112 + err = mlx5e_calc_indir_rqns(rss_rqns, rqns, rss_vhca_ids, vhca_ids, num_rqns, hfunc, indir); 148 113 if (err) 149 114 goto out; 150 115 151 - err = mlx5e_rqt_init(rqt, mdev, indir->max_table_size, rss_rqns, 116 + err = mlx5e_rqt_init(rqt, mdev, indir->max_table_size, rss_rqns, rss_vhca_ids, 152 117 indir->actual_table_size); 153 118 154 119 out: 120 + kvfree(rss_vhca_ids); 155 121 kvfree(rss_rqns); 156 122 return err; 157 123 } ··· 184 126 mlx5_core_destroy_rqt(rqt->mdev, rqt->rqtn); 185 127 } 186 128 187 - static int mlx5e_rqt_redirect(struct mlx5e_rqt *rqt, u32 *rqns, unsigned int size) 129 + static int mlx5e_rqt_redirect(struct mlx5e_rqt *rqt, u32 *rqns, u32 *vhca_ids, 130 + unsigned int size) 188 131 { 189 - unsigned int i; 132 + int entry_sz; 190 133 void *rqtc; 191 134 int inlen; 192 135 u32 *in; 193 136 int err; 194 137 195 - inlen = MLX5_ST_SZ_BYTES(modify_rqt_in) + sizeof(u32) * size; 138 + if (!rqt_verify_vhca_ids(rqt->mdev, vhca_ids, size)) 139 + return -EINVAL; 140 + 141 + entry_sz = vhca_ids ? MLX5_ST_SZ_BYTES(rq_vhca) : MLX5_ST_SZ_BYTES(rq_num); 142 + inlen = MLX5_ST_SZ_BYTES(modify_rqt_in) + entry_sz * size; 196 143 in = kvzalloc(inlen, GFP_KERNEL); 197 144 if (!in) 198 145 return -ENOMEM; ··· 206 143 207 144 MLX5_SET(modify_rqt_in, in, bitmask.rqn_list, 1); 208 145 MLX5_SET(rqtc, rqtc, rqt_actual_size, size); 209 - for (i = 0; i < size; i++) 210 - MLX5_SET(rqtc, rqtc, rq_num[i], rqns[i]); 146 + 147 + fill_rqn_list(rqtc, rqns, vhca_ids, size); 211 148 212 149 err = mlx5_core_modify_rqt(rqt->mdev, rqt->rqtn, in, inlen); 213 150 ··· 215 152 return err; 216 153 } 217 154 218 - int mlx5e_rqt_redirect_direct(struct mlx5e_rqt *rqt, u32 rqn) 155 + int mlx5e_rqt_redirect_direct(struct mlx5e_rqt *rqt, u32 rqn, u32 *vhca_id) 219 156 { 220 - return mlx5e_rqt_redirect(rqt, &rqn, 1); 157 + return mlx5e_rqt_redirect(rqt, &rqn, vhca_id, 1); 221 158 } 222 159 223 - int mlx5e_rqt_redirect_indir(struct mlx5e_rqt *rqt, u32 *rqns, unsigned int num_rqns, 160 + int mlx5e_rqt_redirect_indir(struct mlx5e_rqt *rqt, u32 *rqns, u32 *vhca_ids, 161 + unsigned int num_rqns, 224 162 u8 hfunc, struct mlx5e_rss_params_indir *indir) 225 163 { 226 - u32 *rss_rqns; 164 + u32 *rss_rqns, *rss_vhca_ids = NULL; 227 165 int err; 166 + 167 + if (!rqt_verify_vhca_ids(rqt->mdev, vhca_ids, num_rqns)) 168 + return -EINVAL; 228 169 229 170 if (WARN_ON(rqt->size != indir->max_table_size)) 230 171 return -EINVAL; ··· 237 170 if (!rss_rqns) 238 171 return -ENOMEM; 239 172 240 - err = mlx5e_calc_indir_rqns(rss_rqns, rqns, num_rqns, hfunc, indir); 173 + if (vhca_ids) { 174 + rss_vhca_ids = kvmalloc_array(indir->actual_table_size, sizeof(*rss_vhca_ids), 175 + GFP_KERNEL); 176 + if (!rss_vhca_ids) { 177 + kvfree(rss_rqns); 178 + return -ENOMEM; 179 + } 180 + } 181 + 182 + err = mlx5e_calc_indir_rqns(rss_rqns, rqns, rss_vhca_ids, vhca_ids, num_rqns, hfunc, indir); 241 183 if (err) 242 184 goto out; 243 185 244 - err = mlx5e_rqt_redirect(rqt, rss_rqns, indir->actual_table_size); 186 + err = mlx5e_rqt_redirect(rqt, rss_rqns, rss_vhca_ids, indir->actual_table_size); 245 187 246 188 out: 189 + kvfree(rss_vhca_ids); 247 190 kvfree(rss_rqns); 248 191 return err; 249 192 }
+5 -4
drivers/net/ethernet/mellanox/mlx5/core/en/rqt.h
··· 20 20 unsigned int num_channels); 21 21 22 22 struct mlx5e_rqt { 23 - struct mlx5_core_dev *mdev; 23 + struct mlx5_core_dev *mdev; /* primary */ 24 24 u32 rqtn; 25 25 u16 size; 26 26 }; ··· 28 28 int mlx5e_rqt_init_direct(struct mlx5e_rqt *rqt, struct mlx5_core_dev *mdev, 29 29 bool indir_enabled, u32 init_rqn, u32 indir_table_size); 30 30 int mlx5e_rqt_init_indir(struct mlx5e_rqt *rqt, struct mlx5_core_dev *mdev, 31 - u32 *rqns, unsigned int num_rqns, 31 + u32 *rqns, u32 *vhca_ids, unsigned int num_rqns, 32 32 u8 hfunc, struct mlx5e_rss_params_indir *indir); 33 33 void mlx5e_rqt_destroy(struct mlx5e_rqt *rqt); 34 34 ··· 38 38 } 39 39 40 40 u32 mlx5e_rqt_size(struct mlx5_core_dev *mdev, unsigned int num_channels); 41 - int mlx5e_rqt_redirect_direct(struct mlx5e_rqt *rqt, u32 rqn); 42 - int mlx5e_rqt_redirect_indir(struct mlx5e_rqt *rqt, u32 *rqns, unsigned int num_rqns, 41 + int mlx5e_rqt_redirect_direct(struct mlx5e_rqt *rqt, u32 rqn, u32 *vhca_id); 42 + int mlx5e_rqt_redirect_indir(struct mlx5e_rqt *rqt, u32 *rqns, u32 *vhca_ids, 43 + unsigned int num_rqns, 43 44 u8 hfunc, struct mlx5e_rss_params_indir *indir); 44 45 45 46 #endif /* __MLX5_EN_RQT_H__ */
+9 -8
drivers/net/ethernet/mellanox/mlx5/core/en/rss.c
··· 74 74 struct mlx5e_tir *tir[MLX5E_NUM_INDIR_TIRS]; 75 75 struct mlx5e_tir *inner_tir[MLX5E_NUM_INDIR_TIRS]; 76 76 struct mlx5e_rqt rqt; 77 - struct mlx5_core_dev *mdev; 77 + struct mlx5_core_dev *mdev; /* primary */ 78 78 u32 drop_rqn; 79 79 bool inner_ft_support; 80 80 bool enabled; ··· 473 473 return 0; 474 474 } 475 475 476 - static int mlx5e_rss_apply(struct mlx5e_rss *rss, u32 *rqns, unsigned int num_rqns) 476 + static int mlx5e_rss_apply(struct mlx5e_rss *rss, u32 *rqns, u32 *vhca_ids, unsigned int num_rqns) 477 477 { 478 478 int err; 479 479 480 - err = mlx5e_rqt_redirect_indir(&rss->rqt, rqns, num_rqns, rss->hash.hfunc, &rss->indir); 480 + err = mlx5e_rqt_redirect_indir(&rss->rqt, rqns, vhca_ids, num_rqns, rss->hash.hfunc, 481 + &rss->indir); 481 482 if (err) 482 483 mlx5e_rss_warn(rss->mdev, "Failed to redirect RQT %#x to channels: err = %d\n", 483 484 mlx5e_rqt_get_rqtn(&rss->rqt), err); 484 485 return err; 485 486 } 486 487 487 - void mlx5e_rss_enable(struct mlx5e_rss *rss, u32 *rqns, unsigned int num_rqns) 488 + void mlx5e_rss_enable(struct mlx5e_rss *rss, u32 *rqns, u32 *vhca_ids, unsigned int num_rqns) 488 489 { 489 490 rss->enabled = true; 490 - mlx5e_rss_apply(rss, rqns, num_rqns); 491 + mlx5e_rss_apply(rss, rqns, vhca_ids, num_rqns); 491 492 } 492 493 493 494 void mlx5e_rss_disable(struct mlx5e_rss *rss) ··· 496 495 int err; 497 496 498 497 rss->enabled = false; 499 - err = mlx5e_rqt_redirect_direct(&rss->rqt, rss->drop_rqn); 498 + err = mlx5e_rqt_redirect_direct(&rss->rqt, rss->drop_rqn, NULL); 500 499 if (err) 501 500 mlx5e_rss_warn(rss->mdev, "Failed to redirect RQT %#x to drop RQ %#x: err = %d\n", 502 501 mlx5e_rqt_get_rqtn(&rss->rqt), rss->drop_rqn, err); ··· 569 568 570 569 int mlx5e_rss_set_rxfh(struct mlx5e_rss *rss, const u32 *indir, 571 570 const u8 *key, const u8 *hfunc, 572 - u32 *rqns, unsigned int num_rqns) 571 + u32 *rqns, u32 *vhca_ids, unsigned int num_rqns) 573 572 { 574 573 bool changed_indir = false; 575 574 bool changed_hash = false; ··· 609 608 } 610 609 611 610 if (changed_indir && rss->enabled) { 612 - err = mlx5e_rss_apply(rss, rqns, num_rqns); 611 + err = mlx5e_rss_apply(rss, rqns, vhca_ids, num_rqns); 613 612 if (err) { 614 613 mlx5e_rss_copy(rss, old_rss); 615 614 goto out;
+2 -2
drivers/net/ethernet/mellanox/mlx5/core/en/rss.h
··· 39 39 const struct mlx5e_packet_merge_param *init_pkt_merge_param, 40 40 bool inner, u32 *tirn); 41 41 42 - void mlx5e_rss_enable(struct mlx5e_rss *rss, u32 *rqns, unsigned int num_rqns); 42 + void mlx5e_rss_enable(struct mlx5e_rss *rss, u32 *rqns, u32 *vhca_ids, unsigned int num_rqns); 43 43 void mlx5e_rss_disable(struct mlx5e_rss *rss); 44 44 45 45 int mlx5e_rss_packet_merge_set_param(struct mlx5e_rss *rss, ··· 47 47 int mlx5e_rss_get_rxfh(struct mlx5e_rss *rss, u32 *indir, u8 *key, u8 *hfunc); 48 48 int mlx5e_rss_set_rxfh(struct mlx5e_rss *rss, const u32 *indir, 49 49 const u8 *key, const u8 *hfunc, 50 - u32 *rqns, unsigned int num_rqns); 50 + u32 *rqns, u32 *vhca_ids, unsigned int num_rqns); 51 51 struct mlx5e_rss_params_hash mlx5e_rss_get_hash(struct mlx5e_rss *rss); 52 52 u8 mlx5e_rss_get_hash_fields(struct mlx5e_rss *rss, enum mlx5_traffic_types tt); 53 53 int mlx5e_rss_set_hash_fields(struct mlx5e_rss *rss, enum mlx5_traffic_types tt,
+47 -15
drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.c
··· 8 8 #define MLX5E_MAX_NUM_RSS 16 9 9 10 10 struct mlx5e_rx_res { 11 - struct mlx5_core_dev *mdev; 11 + struct mlx5_core_dev *mdev; /* primary */ 12 12 enum mlx5e_rx_res_features features; 13 13 unsigned int max_nch; 14 14 u32 drop_rqn; ··· 19 19 struct mlx5e_rss *rss[MLX5E_MAX_NUM_RSS]; 20 20 bool rss_active; 21 21 u32 *rss_rqns; 22 + u32 *rss_vhca_ids; 22 23 unsigned int rss_nch; 23 24 24 25 struct { ··· 34 33 }; 35 34 36 35 /* API for rx_res_rss_* */ 36 + 37 + static u32 *get_vhca_ids(struct mlx5e_rx_res *res, int offset) 38 + { 39 + bool multi_vhca = res->features & MLX5E_RX_RES_FEATURE_MULTI_VHCA; 40 + 41 + return multi_vhca ? res->rss_vhca_ids + offset : NULL; 42 + } 37 43 38 44 void mlx5e_rx_res_rss_update_num_channels(struct mlx5e_rx_res *res, u32 nch) 39 45 { ··· 93 85 return PTR_ERR(rss); 94 86 95 87 mlx5e_rss_set_indir_uniform(rss, init_nch); 96 - if (res->rss_active) 97 - mlx5e_rss_enable(rss, res->rss_rqns, res->rss_nch); 88 + if (res->rss_active) { 89 + u32 *vhca_ids = get_vhca_ids(res, 0); 90 + 91 + mlx5e_rss_enable(rss, res->rss_rqns, vhca_ids, res->rss_nch); 92 + } 98 93 99 94 res->rss[i] = rss; 100 95 *rss_idx = i; ··· 164 153 165 154 for (i = 0; i < MLX5E_MAX_NUM_RSS; i++) { 166 155 struct mlx5e_rss *rss = res->rss[i]; 156 + u32 *vhca_ids; 167 157 168 158 if (!rss) 169 159 continue; 170 - mlx5e_rss_enable(rss, res->rss_rqns, res->rss_nch); 160 + vhca_ids = get_vhca_ids(res, 0); 161 + mlx5e_rss_enable(rss, res->rss_rqns, vhca_ids, res->rss_nch); 171 162 } 172 163 } 173 164 ··· 213 200 int mlx5e_rx_res_rss_set_rxfh(struct mlx5e_rx_res *res, u32 rss_idx, 214 201 const u32 *indir, const u8 *key, const u8 *hfunc) 215 202 { 203 + u32 *vhca_ids = get_vhca_ids(res, 0); 216 204 struct mlx5e_rss *rss; 217 205 218 206 if (rss_idx >= MLX5E_MAX_NUM_RSS) ··· 223 209 if (!rss) 224 210 return -ENOENT; 225 211 226 - return mlx5e_rss_set_rxfh(rss, indir, key, hfunc, res->rss_rqns, res->rss_nch); 212 + return mlx5e_rss_set_rxfh(rss, indir, key, hfunc, res->rss_rqns, vhca_ids, 213 + res->rss_nch); 227 214 } 228 215 229 216 int mlx5e_rx_res_rss_get_hash_fields(struct mlx5e_rx_res *res, u32 rss_idx, ··· 295 280 296 281 static void mlx5e_rx_res_free(struct mlx5e_rx_res *res) 297 282 { 283 + kvfree(res->rss_vhca_ids); 298 284 kvfree(res->rss_rqns); 299 285 kvfree(res); 300 286 } 301 287 302 - static struct mlx5e_rx_res *mlx5e_rx_res_alloc(struct mlx5_core_dev *mdev, unsigned int max_nch) 288 + static struct mlx5e_rx_res *mlx5e_rx_res_alloc(struct mlx5_core_dev *mdev, unsigned int max_nch, 289 + bool multi_vhca) 303 290 { 304 291 struct mlx5e_rx_res *rx_res; 305 292 ··· 313 296 if (!rx_res->rss_rqns) { 314 297 kvfree(rx_res); 315 298 return NULL; 299 + } 300 + 301 + if (multi_vhca) { 302 + rx_res->rss_vhca_ids = kvcalloc(max_nch, sizeof(*rx_res->rss_vhca_ids), GFP_KERNEL); 303 + if (!rx_res->rss_vhca_ids) { 304 + kvfree(rx_res->rss_rqns); 305 + kvfree(rx_res); 306 + return NULL; 307 + } 316 308 } 317 309 318 310 return rx_res; ··· 450 424 const struct mlx5e_packet_merge_param *init_pkt_merge_param, 451 425 unsigned int init_nch) 452 426 { 427 + bool multi_vhca = features & MLX5E_RX_RES_FEATURE_MULTI_VHCA; 453 428 struct mlx5e_rx_res *res; 454 429 int err; 455 430 456 - res = mlx5e_rx_res_alloc(mdev, max_nch); 431 + res = mlx5e_rx_res_alloc(mdev, max_nch, multi_vhca); 457 432 if (!res) 458 433 return ERR_PTR(-ENOMEM); 459 434 ··· 531 504 struct mlx5e_channels *chs, 532 505 unsigned int ix) 533 506 { 507 + u32 *vhca_id = get_vhca_ids(res, ix); 534 508 u32 rqn = res->rss_rqns[ix]; 535 509 int err; 536 510 537 - err = mlx5e_rqt_redirect_direct(&res->channels[ix].direct_rqt, rqn); 511 + err = mlx5e_rqt_redirect_direct(&res->channels[ix].direct_rqt, rqn, vhca_id); 538 512 if (err) 539 513 mlx5_core_warn(res->mdev, "Failed to redirect direct RQT %#x to RQ %#x (channel %u): err = %d\n", 540 514 mlx5e_rqt_get_rqtn(&res->channels[ix].direct_rqt), ··· 547 519 { 548 520 int err; 549 521 550 - err = mlx5e_rqt_redirect_direct(&res->channels[ix].direct_rqt, res->drop_rqn); 522 + err = mlx5e_rqt_redirect_direct(&res->channels[ix].direct_rqt, res->drop_rqn, NULL); 551 523 if (err) 552 524 mlx5_core_warn(res->mdev, "Failed to redirect direct RQT %#x to drop RQ %#x (channel %u): err = %d\n", 553 525 mlx5e_rqt_get_rqtn(&res->channels[ix].direct_rqt), ··· 562 534 nch = mlx5e_channels_get_num(chs); 563 535 564 536 for (ix = 0; ix < chs->num; ix++) { 537 + u32 *vhca_id = get_vhca_ids(res, ix); 538 + 565 539 if (mlx5e_channels_is_xsk(chs, ix)) 566 - mlx5e_channels_get_xsk_rqn(chs, ix, &res->rss_rqns[ix]); 540 + mlx5e_channels_get_xsk_rqn(chs, ix, &res->rss_rqns[ix], vhca_id); 567 541 else 568 - mlx5e_channels_get_regular_rqn(chs, ix, &res->rss_rqns[ix]); 542 + mlx5e_channels_get_regular_rqn(chs, ix, &res->rss_rqns[ix], vhca_id); 569 543 } 570 544 res->rss_nch = chs->num; 571 545 ··· 584 554 if (!mlx5e_channels_get_ptp_rqn(chs, &rqn)) 585 555 rqn = res->drop_rqn; 586 556 587 - err = mlx5e_rqt_redirect_direct(&res->ptp.rqt, rqn); 557 + err = mlx5e_rqt_redirect_direct(&res->ptp.rqt, rqn, NULL); 588 558 if (err) 589 559 mlx5_core_warn(res->mdev, "Failed to redirect direct RQT %#x to RQ %#x (PTP): err = %d\n", 590 560 mlx5e_rqt_get_rqtn(&res->ptp.rqt), ··· 603 573 mlx5e_rx_res_channel_deactivate_direct(res, ix); 604 574 605 575 if (res->features & MLX5E_RX_RES_FEATURE_PTP) { 606 - err = mlx5e_rqt_redirect_direct(&res->ptp.rqt, res->drop_rqn); 576 + err = mlx5e_rqt_redirect_direct(&res->ptp.rqt, res->drop_rqn, NULL); 607 577 if (err) 608 578 mlx5_core_warn(res->mdev, "Failed to redirect direct RQT %#x to drop RQ %#x (PTP): err = %d\n", 609 579 mlx5e_rqt_get_rqtn(&res->ptp.rqt), ··· 614 584 void mlx5e_rx_res_xsk_update(struct mlx5e_rx_res *res, struct mlx5e_channels *chs, 615 585 unsigned int ix, bool xsk) 616 586 { 587 + u32 *vhca_id = get_vhca_ids(res, ix); 588 + 617 589 if (xsk) 618 - mlx5e_channels_get_xsk_rqn(chs, ix, &res->rss_rqns[ix]); 590 + mlx5e_channels_get_xsk_rqn(chs, ix, &res->rss_rqns[ix], vhca_id); 619 591 else 620 - mlx5e_channels_get_regular_rqn(chs, ix, &res->rss_rqns[ix]); 592 + mlx5e_channels_get_regular_rqn(chs, ix, &res->rss_rqns[ix], vhca_id); 621 593 622 594 mlx5e_rx_res_rss_enable(res); 623 595
+1
drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.h
··· 18 18 enum mlx5e_rx_res_features { 19 19 MLX5E_RX_RES_FEATURE_INNER_FT = BIT(0), 20 20 MLX5E_RX_RES_FEATURE_PTP = BIT(1), 21 + MLX5E_RX_RES_FEATURE_MULTI_VHCA = BIT(2), 21 22 }; 22 23 23 24 /* Setup */
+6 -5
drivers/net/ethernet/mellanox/mlx5/core/en/trap.c
··· 63 63 struct mlx5e_create_cq_param ccp = {}; 64 64 struct dim_cq_moder trap_moder = {}; 65 65 struct mlx5e_rq *rq = &t->rq; 66 + u16 q_counter; 66 67 int node; 67 68 int err; 68 69 69 70 node = dev_to_node(mdev->device); 71 + q_counter = priv->q_counter[0]; 70 72 71 73 ccp.netdev = priv->netdev; 72 74 ccp.wq = priv->wq; ··· 81 79 return err; 82 80 83 81 mlx5e_init_trap_rq(t, &t->params, rq); 84 - err = mlx5e_open_rq(&t->params, rq_param, NULL, node, rq); 82 + err = mlx5e_open_rq(&t->params, rq_param, NULL, node, q_counter, rq); 85 83 if (err) 86 84 goto err_destroy_cq; 87 85 ··· 118 116 } 119 117 120 118 static void mlx5e_build_trap_params(struct mlx5_core_dev *mdev, 121 - int max_mtu, u16 q_counter, 122 - struct mlx5e_trap *t) 119 + int max_mtu, struct mlx5e_trap *t) 123 120 { 124 121 struct mlx5e_params *params = &t->params; 125 122 126 123 params->rq_wq_type = MLX5_WQ_TYPE_CYCLIC; 127 124 mlx5e_init_rq_type_params(mdev, params); 128 125 params->sw_mtu = max_mtu; 129 - mlx5e_build_rq_param(mdev, params, NULL, q_counter, &t->rq_param); 126 + mlx5e_build_rq_param(mdev, params, NULL, &t->rq_param); 130 127 } 131 128 132 129 static struct mlx5e_trap *mlx5e_open_trap(struct mlx5e_priv *priv) ··· 139 138 if (!t) 140 139 return ERR_PTR(-ENOMEM); 141 140 142 - mlx5e_build_trap_params(priv->mdev, netdev->max_mtu, priv->q_counter, t); 141 + mlx5e_build_trap_params(priv->mdev, netdev->max_mtu, t); 143 142 144 143 t->priv = priv; 145 144 t->mdev = priv->mdev;
+3 -3
drivers/net/ethernet/mellanox/mlx5/core/en/xsk/pool.c
··· 6 6 #include "setup.h" 7 7 #include "en/params.h" 8 8 9 - static int mlx5e_xsk_map_pool(struct mlx5e_priv *priv, 9 + static int mlx5e_xsk_map_pool(struct mlx5_core_dev *mdev, 10 10 struct xsk_buff_pool *pool) 11 11 { 12 - struct device *dev = mlx5_core_dma_dev(priv->mdev); 12 + struct device *dev = mlx5_core_dma_dev(mdev); 13 13 14 14 return xsk_pool_dma_map(pool, dev, DMA_ATTR_SKIP_CPU_SYNC); 15 15 } ··· 89 89 if (unlikely(!mlx5e_xsk_is_pool_sane(pool))) 90 90 return -EINVAL; 91 91 92 - err = mlx5e_xsk_map_pool(priv, pool); 92 + err = mlx5e_xsk_map_pool(mlx5_sd_ch_ix_get_dev(priv->mdev, ix), pool); 93 93 if (unlikely(err)) 94 94 return err; 95 95
+4 -4
drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c
··· 49 49 static void mlx5e_build_xsk_cparam(struct mlx5_core_dev *mdev, 50 50 struct mlx5e_params *params, 51 51 struct mlx5e_xsk_param *xsk, 52 - u16 q_counter, 53 52 struct mlx5e_channel_param *cparam) 54 53 { 55 - mlx5e_build_rq_param(mdev, params, xsk, q_counter, &cparam->rq); 54 + mlx5e_build_rq_param(mdev, params, xsk, &cparam->rq); 56 55 mlx5e_build_xdpsq_param(mdev, params, xsk, &cparam->xdp_sq); 57 56 } 58 57 ··· 92 93 struct mlx5e_rq_param *rq_params, struct xsk_buff_pool *pool, 93 94 struct mlx5e_xsk_param *xsk) 94 95 { 96 + u16 q_counter = c->priv->q_counter[c->sd_ix]; 95 97 struct mlx5e_rq *xskrq = &c->xskrq; 96 98 int err; 97 99 ··· 100 100 if (err) 101 101 return err; 102 102 103 - err = mlx5e_open_rq(params, rq_params, xsk, cpu_to_node(c->cpu), xskrq); 103 + err = mlx5e_open_rq(params, rq_params, xsk, cpu_to_node(c->cpu), q_counter, xskrq); 104 104 if (err) 105 105 return err; 106 106 ··· 125 125 if (!cparam) 126 126 return -ENOMEM; 127 127 128 - mlx5e_build_xsk_cparam(priv->mdev, params, xsk, priv->q_counter, cparam); 128 + mlx5e_build_xsk_cparam(priv->mdev, params, xsk, cparam); 129 129 130 130 err = mlx5e_open_cq(c->mdev, params->rx_cq_moderation, &cparam->rq.cqp, &ccp, 131 131 &c->xskrq.cq);
+1 -1
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.c
··· 96 96 { 97 97 u8 max_sq_wqebbs = mlx5e_get_max_sq_wqebbs(mdev); 98 98 99 - if (is_kdump_kernel() || !MLX5_CAP_GEN(mdev, tls_rx)) 99 + if (is_kdump_kernel() || !MLX5_CAP_GEN(mdev, tls_rx) || mlx5_get_sd(mdev)) 100 100 return false; 101 101 102 102 /* Check the possibility to post the required ICOSQ WQEs. */
+3 -1
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.h
··· 11 11 12 12 #ifdef CONFIG_MLX5_EN_TLS 13 13 #include "lib/crypto.h" 14 + #include "lib/mlx5.h" 14 15 15 16 struct mlx5_crypto_dek *mlx5_ktls_create_key(struct mlx5_crypto_dek_pool *dek_pool, 16 17 struct tls_crypto_info *crypto_info); ··· 62 61 63 62 static inline bool mlx5e_is_ktls_tx(struct mlx5_core_dev *mdev) 64 63 { 65 - return !is_kdump_kernel() && MLX5_CAP_GEN(mdev, tls_tx); 64 + return !is_kdump_kernel() && MLX5_CAP_GEN(mdev, tls_tx) && 65 + !mlx5_get_sd(mdev); 66 66 } 67 67 68 68 bool mlx5e_is_ktls_rx(struct mlx5_core_dev *mdev);
+2 -4
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c
··· 267 267 goto err_out; 268 268 } 269 269 270 - pdev = mlx5_core_dma_dev(sq->channel->priv->mdev); 270 + pdev = mlx5_core_dma_dev(sq->channel->mdev); 271 271 buf->dma_addr = dma_map_single(pdev, &buf->progress, 272 272 PROGRESS_PARAMS_PADDED_SIZE, DMA_FROM_DEVICE); 273 273 if (unlikely(dma_mapping_error(pdev, buf->dma_addr))) { ··· 425 425 { 426 426 struct mlx5e_ktls_rx_resync_buf *buf = wi->tls_get_params.buf; 427 427 struct mlx5e_ktls_offload_context_rx *priv_rx; 428 - struct mlx5e_ktls_rx_resync_ctx *resync; 429 428 u8 tracker_state, auth_state, *ctx; 430 429 struct device *dev; 431 430 u32 hw_seq; 432 431 433 432 priv_rx = buf->priv_rx; 434 - resync = &priv_rx->resync; 435 - dev = mlx5_core_dma_dev(resync->priv->mdev); 433 + dev = mlx5_core_dma_dev(sq->channel->mdev); 436 434 if (unlikely(test_bit(MLX5E_PRIV_RX_FLAG_DELETING, priv_rx->flags))) 437 435 goto out; 438 436
+135 -45
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
··· 70 70 #include "qos.h" 71 71 #include "en/trap.h" 72 72 #include "lib/devcom.h" 73 + #include "lib/sd.h" 73 74 74 75 bool mlx5e_check_fragmented_striding_rq_cap(struct mlx5_core_dev *mdev, u8 page_shift, 75 76 enum mlx5e_mpwrq_umr_mode umr_mode) ··· 1025 1024 mlx5_wq_destroy(&rq->wq_ctrl); 1026 1025 } 1027 1026 1028 - int mlx5e_create_rq(struct mlx5e_rq *rq, struct mlx5e_rq_param *param) 1027 + int mlx5e_create_rq(struct mlx5e_rq *rq, struct mlx5e_rq_param *param, u16 q_counter) 1029 1028 { 1030 1029 struct mlx5_core_dev *mdev = rq->mdev; 1031 1030 u8 ts_format; ··· 1052 1051 MLX5_SET(rqc, rqc, cqn, rq->cq.mcq.cqn); 1053 1052 MLX5_SET(rqc, rqc, state, MLX5_RQC_STATE_RST); 1054 1053 MLX5_SET(rqc, rqc, ts_format, ts_format); 1054 + MLX5_SET(rqc, rqc, counter_set_id, q_counter); 1055 1055 MLX5_SET(wq, wq, log_wq_pg_sz, rq->wq_ctrl.buf.page_shift - 1056 1056 MLX5_ADAPTER_PAGE_SHIFT); 1057 1057 MLX5_SET64(wq, wq, dbr_addr, rq->wq_ctrl.db.dma); ··· 1276 1274 } 1277 1275 1278 1276 int mlx5e_open_rq(struct mlx5e_params *params, struct mlx5e_rq_param *param, 1279 - struct mlx5e_xsk_param *xsk, int node, 1277 + struct mlx5e_xsk_param *xsk, int node, u16 q_counter, 1280 1278 struct mlx5e_rq *rq) 1281 1279 { 1282 1280 struct mlx5_core_dev *mdev = rq->mdev; ··· 1289 1287 if (err) 1290 1288 return err; 1291 1289 1292 - err = mlx5e_create_rq(rq, param); 1290 + err = mlx5e_create_rq(rq, param, q_counter); 1293 1291 if (err) 1294 1292 goto err_free_rq; 1295 1293 ··· 2337 2335 static int mlx5e_open_rxq_rq(struct mlx5e_channel *c, struct mlx5e_params *params, 2338 2336 struct mlx5e_rq_param *rq_params) 2339 2337 { 2338 + u16 q_counter = c->priv->q_counter[c->sd_ix]; 2340 2339 int err; 2341 2340 2342 2341 err = mlx5e_init_rxq_rq(c, params, rq_params->xdp_frag_size, &c->rq); 2343 2342 if (err) 2344 2343 return err; 2345 2344 2346 - return mlx5e_open_rq(params, rq_params, NULL, cpu_to_node(c->cpu), &c->rq); 2345 + return mlx5e_open_rq(params, rq_params, NULL, cpu_to_node(c->cpu), q_counter, &c->rq); 2347 2346 } 2348 2347 2349 2348 static int mlx5e_open_queues(struct mlx5e_channel *c, ··· 2531 2528 struct xsk_buff_pool *xsk_pool, 2532 2529 struct mlx5e_channel **cp) 2533 2530 { 2534 - int cpu = mlx5_comp_vector_get_cpu(priv->mdev, ix); 2535 2531 struct net_device *netdev = priv->netdev; 2532 + struct mlx5_core_dev *mdev; 2536 2533 struct mlx5e_xsk_param xsk; 2537 2534 struct mlx5e_channel *c; 2538 2535 unsigned int irq; 2536 + int vec_ix; 2537 + int cpu; 2539 2538 int err; 2540 2539 2541 - err = mlx5_comp_irqn_get(priv->mdev, ix, &irq); 2540 + mdev = mlx5_sd_ch_ix_get_dev(priv->mdev, ix); 2541 + vec_ix = mlx5_sd_ch_ix_get_vec_ix(mdev, ix); 2542 + cpu = mlx5_comp_vector_get_cpu(mdev, vec_ix); 2543 + 2544 + err = mlx5_comp_irqn_get(mdev, vec_ix, &irq); 2542 2545 if (err) 2543 2546 return err; 2544 2547 ··· 2557 2548 return -ENOMEM; 2558 2549 2559 2550 c->priv = priv; 2560 - c->mdev = priv->mdev; 2551 + c->mdev = mdev; 2561 2552 c->tstamp = &priv->tstamp; 2562 2553 c->ix = ix; 2554 + c->vec_ix = vec_ix; 2555 + c->sd_ix = mlx5_sd_ch_ix_get_dev_ix(mdev, ix); 2563 2556 c->cpu = cpu; 2564 - c->pdev = mlx5_core_dma_dev(priv->mdev); 2557 + c->pdev = mlx5_core_dma_dev(mdev); 2565 2558 c->netdev = priv->netdev; 2566 - c->mkey_be = cpu_to_be32(priv->mdev->mlx5e_res.hw_objs.mkey); 2559 + c->mkey_be = cpu_to_be32(mdev->mlx5e_res.hw_objs.mkey); 2567 2560 c->num_tc = mlx5e_get_dcb_num_tc(params); 2568 2561 c->xdp = !!params->xdp_prog; 2569 2562 c->stats = &priv->channel_stats[ix]->ch; 2570 2563 c->aff_mask = irq_get_effective_affinity_mask(irq); 2571 - c->lag_port = mlx5e_enumerate_lag_port(priv->mdev, ix); 2564 + c->lag_port = mlx5e_enumerate_lag_port(mdev, ix); 2572 2565 2573 2566 netif_napi_add(netdev, &c->napi, mlx5e_napi_poll); 2574 2567 netif_napi_set_irq(&c->napi, irq); ··· 2665 2654 if (!chs->c || !cparam) 2666 2655 goto err_free; 2667 2656 2668 - err = mlx5e_build_channel_param(priv->mdev, &chs->params, priv->q_counter, cparam); 2657 + err = mlx5e_build_channel_param(priv->mdev, &chs->params, cparam); 2669 2658 if (err) 2670 2659 goto err_free; 2671 2660 ··· 2953 2942 static void mlx5e_set_default_xps_cpumasks(struct mlx5e_priv *priv, 2954 2943 struct mlx5e_params *params) 2955 2944 { 2956 - struct mlx5_core_dev *mdev = priv->mdev; 2957 - int num_comp_vectors, ix, irq; 2958 - 2959 - num_comp_vectors = mlx5_comp_vectors_max(mdev); 2945 + int ix; 2960 2946 2961 2947 for (ix = 0; ix < params->num_channels; ix++) { 2962 - cpumask_clear(priv->scratchpad.cpumask); 2948 + int num_comp_vectors, irq, vec_ix; 2949 + struct mlx5_core_dev *mdev; 2963 2950 2964 - for (irq = ix; irq < num_comp_vectors; irq += params->num_channels) { 2951 + mdev = mlx5_sd_ch_ix_get_dev(priv->mdev, ix); 2952 + num_comp_vectors = mlx5_comp_vectors_max(mdev); 2953 + cpumask_clear(priv->scratchpad.cpumask); 2954 + vec_ix = mlx5_sd_ch_ix_get_vec_ix(mdev, ix); 2955 + 2956 + for (irq = vec_ix; irq < num_comp_vectors; irq += params->num_channels) { 2965 2957 int cpu = mlx5_comp_vector_get_cpu(mdev, irq); 2966 2958 2967 2959 cpumask_set_cpu(cpu, priv->scratchpad.cpumask); ··· 3356 3342 struct mlx5e_cq *cq = &drop_rq->cq; 3357 3343 int err; 3358 3344 3359 - mlx5e_build_drop_rq_param(mdev, priv->drop_rq_q_counter, &rq_param); 3345 + mlx5e_build_drop_rq_param(mdev, &rq_param); 3360 3346 3361 3347 err = mlx5e_alloc_drop_cq(priv, cq, &cq_param); 3362 3348 if (err) ··· 3370 3356 if (err) 3371 3357 goto err_destroy_cq; 3372 3358 3373 - err = mlx5e_create_rq(drop_rq, &rq_param); 3359 + err = mlx5e_create_rq(drop_rq, &rq_param, priv->drop_rq_q_counter); 3374 3360 if (err) 3375 3361 goto err_free_rq; 3376 3362 ··· 5285 5271 u32 out[MLX5_ST_SZ_DW(alloc_q_counter_out)] = {}; 5286 5272 u32 in[MLX5_ST_SZ_DW(alloc_q_counter_in)] = {}; 5287 5273 struct mlx5_core_dev *mdev = priv->mdev; 5288 - int err; 5274 + struct mlx5_core_dev *pos; 5275 + int err, i; 5289 5276 5290 5277 MLX5_SET(alloc_q_counter_in, in, opcode, MLX5_CMD_OP_ALLOC_Q_COUNTER); 5291 - err = mlx5_cmd_exec_inout(mdev, alloc_q_counter, in, out); 5292 - if (!err) 5293 - priv->q_counter = 5294 - MLX5_GET(alloc_q_counter_out, out, counter_set_id); 5278 + 5279 + mlx5_sd_for_each_dev(i, mdev, pos) { 5280 + err = mlx5_cmd_exec_inout(pos, alloc_q_counter, in, out); 5281 + if (!err) 5282 + priv->q_counter[i] = 5283 + MLX5_GET(alloc_q_counter_out, out, counter_set_id); 5284 + } 5295 5285 5296 5286 err = mlx5_cmd_exec_inout(mdev, alloc_q_counter, in, out); 5297 5287 if (!err) ··· 5306 5288 void mlx5e_destroy_q_counters(struct mlx5e_priv *priv) 5307 5289 { 5308 5290 u32 in[MLX5_ST_SZ_DW(dealloc_q_counter_in)] = {}; 5291 + struct mlx5_core_dev *pos; 5292 + int i; 5309 5293 5310 5294 MLX5_SET(dealloc_q_counter_in, in, opcode, 5311 5295 MLX5_CMD_OP_DEALLOC_Q_COUNTER); 5312 - if (priv->q_counter) { 5313 - MLX5_SET(dealloc_q_counter_in, in, counter_set_id, 5314 - priv->q_counter); 5315 - mlx5_cmd_exec_in(priv->mdev, dealloc_q_counter, in); 5296 + mlx5_sd_for_each_dev(i, priv->mdev, pos) { 5297 + if (priv->q_counter[i]) { 5298 + MLX5_SET(dealloc_q_counter_in, in, counter_set_id, 5299 + priv->q_counter[i]); 5300 + mlx5_cmd_exec_in(pos, dealloc_q_counter, in); 5301 + } 5316 5302 } 5317 5303 5318 5304 if (priv->drop_rq_q_counter) { ··· 5400 5378 features = MLX5E_RX_RES_FEATURE_PTP; 5401 5379 if (mlx5_tunnel_inner_ft_supported(mdev)) 5402 5380 features |= MLX5E_RX_RES_FEATURE_INNER_FT; 5381 + if (mlx5_get_sd(priv->mdev)) 5382 + features |= MLX5E_RX_RES_FEATURE_MULTI_VHCA; 5403 5383 5404 5384 priv->rx_res = mlx5e_rx_res_create(priv->mdev, features, priv->max_nch, priv->drop_rq.rqn, 5405 5385 &priv->channels.params.packet_merge, ··· 6011 5987 free_netdev(netdev); 6012 5988 } 6013 5989 6014 - static int mlx5e_resume(struct auxiliary_device *adev) 5990 + static int _mlx5e_resume(struct auxiliary_device *adev) 6015 5991 { 6016 5992 struct mlx5_adev *edev = container_of(adev, struct mlx5_adev, adev); 6017 5993 struct mlx5e_dev *mlx5e_dev = auxiliary_get_drvdata(adev); 6018 5994 struct mlx5e_priv *priv = mlx5e_dev->priv; 6019 5995 struct net_device *netdev = priv->netdev; 6020 5996 struct mlx5_core_dev *mdev = edev->mdev; 6021 - int err; 5997 + struct mlx5_core_dev *pos, *to; 5998 + int err, i; 6022 5999 6023 6000 if (netif_device_present(netdev)) 6024 6001 return 0; 6025 6002 6026 - err = mlx5e_create_mdev_resources(mdev, true); 6003 + mlx5_sd_for_each_dev(i, mdev, pos) { 6004 + err = mlx5e_create_mdev_resources(pos, true); 6005 + if (err) 6006 + goto err_destroy_mdev_res; 6007 + } 6008 + 6009 + err = mlx5e_attach_netdev(priv); 6010 + if (err) 6011 + goto err_destroy_mdev_res; 6012 + 6013 + return 0; 6014 + 6015 + err_destroy_mdev_res: 6016 + to = pos; 6017 + mlx5_sd_for_each_dev_to(i, mdev, to, pos) 6018 + mlx5e_destroy_mdev_resources(pos); 6019 + return err; 6020 + } 6021 + 6022 + static int mlx5e_resume(struct auxiliary_device *adev) 6023 + { 6024 + struct mlx5_adev *edev = container_of(adev, struct mlx5_adev, adev); 6025 + struct mlx5_core_dev *mdev = edev->mdev; 6026 + struct auxiliary_device *actual_adev; 6027 + int err; 6028 + 6029 + err = mlx5_sd_init(mdev); 6027 6030 if (err) 6028 6031 return err; 6029 6032 6030 - err = mlx5e_attach_netdev(priv); 6031 - if (err) { 6032 - mlx5e_destroy_mdev_resources(mdev); 6033 - return err; 6034 - } 6035 - 6033 + actual_adev = mlx5_sd_get_adev(mdev, adev, edev->idx); 6034 + if (actual_adev) 6035 + return _mlx5e_resume(actual_adev); 6036 6036 return 0; 6037 6037 } 6038 6038 ··· 6066 6018 struct mlx5e_priv *priv = mlx5e_dev->priv; 6067 6019 struct net_device *netdev = priv->netdev; 6068 6020 struct mlx5_core_dev *mdev = priv->mdev; 6021 + struct mlx5_core_dev *pos; 6022 + int i; 6069 6023 6070 6024 if (!netif_device_present(netdev)) { 6071 6025 if (test_bit(MLX5E_STATE_DESTROYING, &priv->state)) 6072 - mlx5e_destroy_mdev_resources(mdev); 6026 + mlx5_sd_for_each_dev(i, mdev, pos) 6027 + mlx5e_destroy_mdev_resources(pos); 6073 6028 return -ENODEV; 6074 6029 } 6075 6030 6076 6031 mlx5e_detach_netdev(priv); 6077 - mlx5e_destroy_mdev_resources(mdev); 6032 + mlx5_sd_for_each_dev(i, mdev, pos) 6033 + mlx5e_destroy_mdev_resources(pos); 6034 + 6078 6035 return 0; 6079 6036 } 6080 6037 6081 6038 static int mlx5e_suspend(struct auxiliary_device *adev, pm_message_t state) 6082 6039 { 6083 - return _mlx5e_suspend(adev); 6040 + struct mlx5_adev *edev = container_of(adev, struct mlx5_adev, adev); 6041 + struct mlx5_core_dev *mdev = edev->mdev; 6042 + struct auxiliary_device *actual_adev; 6043 + int err = 0; 6044 + 6045 + actual_adev = mlx5_sd_get_adev(mdev, adev, edev->idx); 6046 + if (actual_adev) 6047 + err = _mlx5e_suspend(actual_adev); 6048 + 6049 + mlx5_sd_cleanup(mdev); 6050 + return err; 6084 6051 } 6085 6052 6086 6053 static int _mlx5e_probe(struct auxiliary_device *adev) ··· 6141 6078 goto err_destroy_netdev; 6142 6079 } 6143 6080 6144 - err = mlx5e_resume(adev); 6081 + err = _mlx5e_resume(adev); 6145 6082 if (err) { 6146 - mlx5_core_err(mdev, "mlx5e_resume failed, %d\n", err); 6083 + mlx5_core_err(mdev, "_mlx5e_resume failed, %d\n", err); 6147 6084 goto err_profile_cleanup; 6148 6085 } 6149 6086 ··· 6174 6111 static int mlx5e_probe(struct auxiliary_device *adev, 6175 6112 const struct auxiliary_device_id *id) 6176 6113 { 6177 - return _mlx5e_probe(adev); 6114 + struct mlx5_adev *edev = container_of(adev, struct mlx5_adev, adev); 6115 + struct mlx5_core_dev *mdev = edev->mdev; 6116 + struct auxiliary_device *actual_adev; 6117 + int err; 6118 + 6119 + err = mlx5_sd_init(mdev); 6120 + if (err) 6121 + return err; 6122 + 6123 + actual_adev = mlx5_sd_get_adev(mdev, adev, edev->idx); 6124 + if (actual_adev) 6125 + return _mlx5e_probe(actual_adev); 6126 + return 0; 6178 6127 } 6179 6128 6180 - static void mlx5e_remove(struct auxiliary_device *adev) 6129 + static void _mlx5e_remove(struct auxiliary_device *adev) 6181 6130 { 6131 + struct mlx5_adev *edev = container_of(adev, struct mlx5_adev, adev); 6182 6132 struct mlx5e_dev *mlx5e_dev = auxiliary_get_drvdata(adev); 6183 6133 struct mlx5e_priv *priv = mlx5e_dev->priv; 6134 + struct mlx5_core_dev *mdev = edev->mdev; 6184 6135 6185 - mlx5_core_uplink_netdev_set(priv->mdev, NULL); 6136 + mlx5_core_uplink_netdev_set(mdev, NULL); 6186 6137 mlx5e_dcbnl_delete_app(priv); 6187 6138 unregister_netdev(priv->netdev); 6188 6139 _mlx5e_suspend(adev); ··· 6204 6127 mlx5e_destroy_netdev(priv); 6205 6128 mlx5e_devlink_port_unregister(mlx5e_dev); 6206 6129 mlx5e_destroy_devlink(mlx5e_dev); 6130 + } 6131 + 6132 + static void mlx5e_remove(struct auxiliary_device *adev) 6133 + { 6134 + struct mlx5_adev *edev = container_of(adev, struct mlx5_adev, adev); 6135 + struct mlx5_core_dev *mdev = edev->mdev; 6136 + struct auxiliary_device *actual_adev; 6137 + 6138 + actual_adev = mlx5_sd_get_adev(mdev, adev, edev->idx); 6139 + if (actual_adev) 6140 + _mlx5e_remove(actual_adev); 6141 + 6142 + mlx5_sd_cleanup(mdev); 6207 6143 } 6208 6144 6209 6145 static const struct auxiliary_device_id mlx5e_id_table[] = {
+28 -11
drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
··· 561 561 #define NUM_Q_COUNTERS ARRAY_SIZE(q_stats_desc) 562 562 #define NUM_DROP_RQ_COUNTERS ARRAY_SIZE(drop_rq_stats_desc) 563 563 564 + static bool q_counter_any(struct mlx5e_priv *priv) 565 + { 566 + struct mlx5_core_dev *pos; 567 + int i; 568 + 569 + mlx5_sd_for_each_dev(i, priv->mdev, pos) 570 + if (priv->q_counter[i++]) 571 + return true; 572 + 573 + return false; 574 + } 575 + 564 576 static MLX5E_DECLARE_STATS_GRP_OP_NUM_STATS(qcnt) 565 577 { 566 578 int num_stats = 0; 567 579 568 - if (priv->q_counter) 580 + if (q_counter_any(priv)) 569 581 num_stats += NUM_Q_COUNTERS; 570 582 571 583 if (priv->drop_rq_q_counter) ··· 590 578 { 591 579 int i; 592 580 593 - for (i = 0; i < NUM_Q_COUNTERS && priv->q_counter; i++) 581 + for (i = 0; i < NUM_Q_COUNTERS && q_counter_any(priv); i++) 594 582 strcpy(data + (idx++) * ETH_GSTRING_LEN, 595 583 q_stats_desc[i].format); 596 584 ··· 605 593 { 606 594 int i; 607 595 608 - for (i = 0; i < NUM_Q_COUNTERS && priv->q_counter; i++) 596 + for (i = 0; i < NUM_Q_COUNTERS && q_counter_any(priv); i++) 609 597 data[idx++] = MLX5E_READ_CTR32_CPU(&priv->stats.qcnt, 610 598 q_stats_desc, i); 611 599 for (i = 0; i < NUM_DROP_RQ_COUNTERS && priv->drop_rq_q_counter; i++) ··· 619 607 struct mlx5e_qcounter_stats *qcnt = &priv->stats.qcnt; 620 608 u32 out[MLX5_ST_SZ_DW(query_q_counter_out)] = {}; 621 609 u32 in[MLX5_ST_SZ_DW(query_q_counter_in)] = {}; 622 - int ret; 610 + struct mlx5_core_dev *pos; 611 + u32 rx_out_of_buffer = 0; 612 + int ret, i; 623 613 624 614 MLX5_SET(query_q_counter_in, in, opcode, MLX5_CMD_OP_QUERY_Q_COUNTER); 625 615 626 - if (priv->q_counter) { 627 - MLX5_SET(query_q_counter_in, in, counter_set_id, 628 - priv->q_counter); 629 - ret = mlx5_cmd_exec_inout(priv->mdev, query_q_counter, in, out); 630 - if (!ret) 631 - qcnt->rx_out_of_buffer = MLX5_GET(query_q_counter_out, 632 - out, out_of_buffer); 616 + mlx5_sd_for_each_dev(i, priv->mdev, pos) { 617 + if (priv->q_counter[i]) { 618 + MLX5_SET(query_q_counter_in, in, counter_set_id, 619 + priv->q_counter[i]); 620 + ret = mlx5_cmd_exec_inout(pos, query_q_counter, in, out); 621 + if (!ret) 622 + rx_out_of_buffer += MLX5_GET(query_q_counter_out, 623 + out, out_of_buffer); 624 + } 633 625 } 626 + qcnt->rx_out_of_buffer = rx_out_of_buffer; 634 627 635 628 if (priv->drop_rq_q_counter) { 636 629 MLX5_SET(query_q_counter_in, in, counter_set_id,
+2 -2
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
··· 766 766 return err; 767 767 768 768 mlx5e_rss_params_indir_init_uniform(&indir, hp->num_channels); 769 - err = mlx5e_rqt_init_indir(&hp->indir_rqt, mdev, hp->pair->rqn, hp->num_channels, 769 + err = mlx5e_rqt_init_indir(&hp->indir_rqt, mdev, hp->pair->rqn, NULL, hp->num_channels, 770 770 mlx5e_rx_res_get_current_hash(priv->rx_res).hfunc, 771 771 &indir); 772 772 ··· 1169 1169 MLX5_CAP_GEN(priv->mdev, log_min_hairpin_wq_data_sz), 1170 1170 MLX5_CAP_GEN(priv->mdev, log_max_hairpin_wq_data_sz)); 1171 1171 1172 - params.q_counter = priv->q_counter; 1172 + params.q_counter = priv->q_counter[0]; 1173 1173 err = devl_param_driverinit_value_get( 1174 1174 devlink, MLX5_DEVLINK_PARAM_ID_HAIRPIN_NUM_QUEUES, &val); 1175 1175 if (err) {
+1
drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h
··· 10 10 MLX5_DEVCOM_ESW_OFFLOADS, 11 11 MLX5_DEVCOM_MPV, 12 12 MLX5_DEVCOM_HCA_PORTS, 13 + MLX5_DEVCOM_SD_GROUP, 13 14 MLX5_DEVCOM_NUM_COMPONENTS, 14 15 }; 15 16
+12
drivers/net/ethernet/mellanox/mlx5/core/lib/mlx5.h
··· 54 54 { 55 55 return mdev->mlx5e_res.uplink_netdev; 56 56 } 57 + 58 + struct mlx5_sd; 59 + 60 + static inline struct mlx5_sd *mlx5_get_sd(struct mlx5_core_dev *dev) 61 + { 62 + return dev->sd; 63 + } 64 + 65 + static inline void mlx5_set_sd(struct mlx5_core_dev *dev, struct mlx5_sd *sd) 66 + { 67 + dev->sd = sd; 68 + } 57 69 #endif
+524
drivers/net/ethernet/mellanox/mlx5/core/lib/sd.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2 + /* Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */ 3 + 4 + #include "lib/sd.h" 5 + #include "mlx5_core.h" 6 + #include "lib/mlx5.h" 7 + #include "fs_cmd.h" 8 + #include <linux/mlx5/vport.h> 9 + #include <linux/debugfs.h> 10 + 11 + #define sd_info(__dev, format, ...) \ 12 + dev_info((__dev)->device, "Socket-Direct: " format, ##__VA_ARGS__) 13 + #define sd_warn(__dev, format, ...) \ 14 + dev_warn((__dev)->device, "Socket-Direct: " format, ##__VA_ARGS__) 15 + 16 + struct mlx5_sd { 17 + u32 group_id; 18 + u8 host_buses; 19 + struct mlx5_devcom_comp_dev *devcom; 20 + struct dentry *dfs; 21 + bool primary; 22 + union { 23 + struct { /* primary */ 24 + struct mlx5_core_dev *secondaries[MLX5_SD_MAX_GROUP_SZ - 1]; 25 + struct mlx5_flow_table *tx_ft; 26 + }; 27 + struct { /* secondary */ 28 + struct mlx5_core_dev *primary_dev; 29 + u32 alias_obj_id; 30 + }; 31 + }; 32 + }; 33 + 34 + static int mlx5_sd_get_host_buses(struct mlx5_core_dev *dev) 35 + { 36 + struct mlx5_sd *sd = mlx5_get_sd(dev); 37 + 38 + if (!sd) 39 + return 1; 40 + 41 + return sd->host_buses; 42 + } 43 + 44 + static struct mlx5_core_dev *mlx5_sd_get_primary(struct mlx5_core_dev *dev) 45 + { 46 + struct mlx5_sd *sd = mlx5_get_sd(dev); 47 + 48 + if (!sd) 49 + return dev; 50 + 51 + return sd->primary ? dev : sd->primary_dev; 52 + } 53 + 54 + struct mlx5_core_dev * 55 + mlx5_sd_primary_get_peer(struct mlx5_core_dev *primary, int idx) 56 + { 57 + struct mlx5_sd *sd; 58 + 59 + if (idx == 0) 60 + return primary; 61 + 62 + if (idx >= mlx5_sd_get_host_buses(primary)) 63 + return NULL; 64 + 65 + sd = mlx5_get_sd(primary); 66 + return sd->secondaries[idx - 1]; 67 + } 68 + 69 + int mlx5_sd_ch_ix_get_dev_ix(struct mlx5_core_dev *dev, int ch_ix) 70 + { 71 + return ch_ix % mlx5_sd_get_host_buses(dev); 72 + } 73 + 74 + int mlx5_sd_ch_ix_get_vec_ix(struct mlx5_core_dev *dev, int ch_ix) 75 + { 76 + return ch_ix / mlx5_sd_get_host_buses(dev); 77 + } 78 + 79 + struct mlx5_core_dev *mlx5_sd_ch_ix_get_dev(struct mlx5_core_dev *primary, int ch_ix) 80 + { 81 + int mdev_idx = mlx5_sd_ch_ix_get_dev_ix(primary, ch_ix); 82 + 83 + return mlx5_sd_primary_get_peer(primary, mdev_idx); 84 + } 85 + 86 + static bool ft_create_alias_supported(struct mlx5_core_dev *dev) 87 + { 88 + u64 obj_allowed = MLX5_CAP_GEN_2_64(dev, allowed_object_for_other_vhca_access); 89 + u32 obj_supp = MLX5_CAP_GEN_2(dev, cross_vhca_object_to_object_supported); 90 + 91 + if (!(obj_supp & 92 + MLX5_CROSS_VHCA_OBJ_TO_OBJ_SUPPORTED_LOCAL_FLOW_TABLE_ROOT_TO_REMOTE_FLOW_TABLE)) 93 + return false; 94 + 95 + if (!(obj_allowed & MLX5_ALLOWED_OBJ_FOR_OTHER_VHCA_ACCESS_FLOW_TABLE)) 96 + return false; 97 + 98 + return true; 99 + } 100 + 101 + static bool mlx5_sd_is_supported(struct mlx5_core_dev *dev, u8 host_buses) 102 + { 103 + /* Feature is currently implemented for PFs only */ 104 + if (!mlx5_core_is_pf(dev)) 105 + return false; 106 + 107 + /* Honor the SW implementation limit */ 108 + if (host_buses > MLX5_SD_MAX_GROUP_SZ) 109 + return false; 110 + 111 + /* Disconnect secondaries from the network */ 112 + if (!MLX5_CAP_GEN(dev, eswitch_manager)) 113 + return false; 114 + if (!MLX5_CAP_GEN(dev, silent_mode)) 115 + return false; 116 + 117 + /* RX steering from primary to secondaries */ 118 + if (!MLX5_CAP_GEN(dev, cross_vhca_rqt)) 119 + return false; 120 + if (host_buses > MLX5_CAP_GEN_2(dev, max_rqt_vhca_id)) 121 + return false; 122 + 123 + /* TX steering from secondaries to primary */ 124 + if (!ft_create_alias_supported(dev)) 125 + return false; 126 + if (!MLX5_CAP_FLOWTABLE_NIC_TX(dev, reset_root_to_default)) 127 + return false; 128 + 129 + return true; 130 + } 131 + 132 + static int mlx5_query_sd(struct mlx5_core_dev *dev, bool *sdm, 133 + u8 *host_buses, u8 *sd_group) 134 + { 135 + u32 out[MLX5_ST_SZ_DW(mpir_reg)]; 136 + int err; 137 + 138 + err = mlx5_query_mpir_reg(dev, out); 139 + if (err) 140 + return err; 141 + 142 + err = mlx5_query_nic_vport_sd_group(dev, sd_group); 143 + if (err) 144 + return err; 145 + 146 + *sdm = MLX5_GET(mpir_reg, out, sdm); 147 + *host_buses = MLX5_GET(mpir_reg, out, host_buses); 148 + 149 + return 0; 150 + } 151 + 152 + static u32 mlx5_sd_group_id(struct mlx5_core_dev *dev, u8 sd_group) 153 + { 154 + return (u32)((MLX5_CAP_GEN(dev, native_port_num) << 8) | sd_group); 155 + } 156 + 157 + static int sd_init(struct mlx5_core_dev *dev) 158 + { 159 + u8 host_buses, sd_group; 160 + struct mlx5_sd *sd; 161 + u32 group_id; 162 + bool sdm; 163 + int err; 164 + 165 + if (!MLX5_CAP_MCAM_REG(dev, mpir)) 166 + return 0; 167 + 168 + err = mlx5_query_sd(dev, &sdm, &host_buses, &sd_group); 169 + if (err) 170 + return err; 171 + 172 + if (!sdm) 173 + return 0; 174 + 175 + if (!sd_group) 176 + return 0; 177 + 178 + group_id = mlx5_sd_group_id(dev, sd_group); 179 + 180 + if (!mlx5_sd_is_supported(dev, host_buses)) { 181 + sd_warn(dev, "can't support requested netdev combining for group id 0x%x), skipping\n", 182 + group_id); 183 + return 0; 184 + } 185 + 186 + sd = kzalloc(sizeof(*sd), GFP_KERNEL); 187 + if (!sd) 188 + return -ENOMEM; 189 + 190 + sd->host_buses = host_buses; 191 + sd->group_id = group_id; 192 + 193 + mlx5_set_sd(dev, sd); 194 + 195 + return 0; 196 + } 197 + 198 + static void sd_cleanup(struct mlx5_core_dev *dev) 199 + { 200 + struct mlx5_sd *sd = mlx5_get_sd(dev); 201 + 202 + mlx5_set_sd(dev, NULL); 203 + kfree(sd); 204 + } 205 + 206 + static int sd_register(struct mlx5_core_dev *dev) 207 + { 208 + struct mlx5_devcom_comp_dev *devcom, *pos; 209 + struct mlx5_core_dev *peer, *primary; 210 + struct mlx5_sd *sd, *primary_sd; 211 + int err, i; 212 + 213 + sd = mlx5_get_sd(dev); 214 + devcom = mlx5_devcom_register_component(dev->priv.devc, MLX5_DEVCOM_SD_GROUP, 215 + sd->group_id, NULL, dev); 216 + if (!devcom) 217 + return -ENOMEM; 218 + 219 + sd->devcom = devcom; 220 + 221 + if (mlx5_devcom_comp_get_size(devcom) != sd->host_buses) 222 + return 0; 223 + 224 + mlx5_devcom_comp_lock(devcom); 225 + mlx5_devcom_comp_set_ready(devcom, true); 226 + mlx5_devcom_comp_unlock(devcom); 227 + 228 + if (!mlx5_devcom_for_each_peer_begin(devcom)) { 229 + err = -ENODEV; 230 + goto err_devcom_unreg; 231 + } 232 + 233 + primary = dev; 234 + mlx5_devcom_for_each_peer_entry(devcom, peer, pos) 235 + if (peer->pdev->bus->number < primary->pdev->bus->number) 236 + primary = peer; 237 + 238 + primary_sd = mlx5_get_sd(primary); 239 + primary_sd->primary = true; 240 + i = 0; 241 + /* loop the secondaries */ 242 + mlx5_devcom_for_each_peer_entry(primary_sd->devcom, peer, pos) { 243 + struct mlx5_sd *peer_sd = mlx5_get_sd(peer); 244 + 245 + primary_sd->secondaries[i++] = peer; 246 + peer_sd->primary = false; 247 + peer_sd->primary_dev = primary; 248 + } 249 + 250 + mlx5_devcom_for_each_peer_end(devcom); 251 + return 0; 252 + 253 + err_devcom_unreg: 254 + mlx5_devcom_comp_lock(sd->devcom); 255 + mlx5_devcom_comp_set_ready(sd->devcom, false); 256 + mlx5_devcom_comp_unlock(sd->devcom); 257 + mlx5_devcom_unregister_component(sd->devcom); 258 + return err; 259 + } 260 + 261 + static void sd_unregister(struct mlx5_core_dev *dev) 262 + { 263 + struct mlx5_sd *sd = mlx5_get_sd(dev); 264 + 265 + mlx5_devcom_comp_lock(sd->devcom); 266 + mlx5_devcom_comp_set_ready(sd->devcom, false); 267 + mlx5_devcom_comp_unlock(sd->devcom); 268 + mlx5_devcom_unregister_component(sd->devcom); 269 + } 270 + 271 + static int sd_cmd_set_primary(struct mlx5_core_dev *primary, u8 *alias_key) 272 + { 273 + struct mlx5_cmd_allow_other_vhca_access_attr allow_attr = {}; 274 + struct mlx5_sd *sd = mlx5_get_sd(primary); 275 + struct mlx5_flow_table_attr ft_attr = {}; 276 + struct mlx5_flow_namespace *nic_ns; 277 + struct mlx5_flow_table *ft; 278 + int err; 279 + 280 + nic_ns = mlx5_get_flow_namespace(primary, MLX5_FLOW_NAMESPACE_EGRESS); 281 + if (!nic_ns) 282 + return -EOPNOTSUPP; 283 + 284 + ft = mlx5_create_flow_table(nic_ns, &ft_attr); 285 + if (IS_ERR(ft)) { 286 + err = PTR_ERR(ft); 287 + return err; 288 + } 289 + sd->tx_ft = ft; 290 + memcpy(allow_attr.access_key, alias_key, ACCESS_KEY_LEN); 291 + allow_attr.obj_type = MLX5_GENERAL_OBJECT_TYPES_FLOW_TABLE_ALIAS; 292 + allow_attr.obj_id = (ft->type << FT_ID_FT_TYPE_OFFSET) | ft->id; 293 + 294 + err = mlx5_cmd_allow_other_vhca_access(primary, &allow_attr); 295 + if (err) { 296 + mlx5_core_err(primary, "Failed to allow other vhca access err=%d\n", 297 + err); 298 + mlx5_destroy_flow_table(ft); 299 + return err; 300 + } 301 + 302 + return 0; 303 + } 304 + 305 + static void sd_cmd_unset_primary(struct mlx5_core_dev *primary) 306 + { 307 + struct mlx5_sd *sd = mlx5_get_sd(primary); 308 + 309 + mlx5_destroy_flow_table(sd->tx_ft); 310 + } 311 + 312 + static int sd_secondary_create_alias_ft(struct mlx5_core_dev *secondary, 313 + struct mlx5_core_dev *primary, 314 + struct mlx5_flow_table *ft, 315 + u32 *obj_id, u8 *alias_key) 316 + { 317 + u32 aliased_object_id = (ft->type << FT_ID_FT_TYPE_OFFSET) | ft->id; 318 + u16 vhca_id_to_be_accessed = MLX5_CAP_GEN(primary, vhca_id); 319 + struct mlx5_cmd_alias_obj_create_attr alias_attr = {}; 320 + int ret; 321 + 322 + memcpy(alias_attr.access_key, alias_key, ACCESS_KEY_LEN); 323 + alias_attr.obj_id = aliased_object_id; 324 + alias_attr.obj_type = MLX5_GENERAL_OBJECT_TYPES_FLOW_TABLE_ALIAS; 325 + alias_attr.vhca_id = vhca_id_to_be_accessed; 326 + ret = mlx5_cmd_alias_obj_create(secondary, &alias_attr, obj_id); 327 + if (ret) { 328 + mlx5_core_err(secondary, "Failed to create alias object err=%d\n", 329 + ret); 330 + return ret; 331 + } 332 + 333 + return 0; 334 + } 335 + 336 + static void sd_secondary_destroy_alias_ft(struct mlx5_core_dev *secondary) 337 + { 338 + struct mlx5_sd *sd = mlx5_get_sd(secondary); 339 + 340 + mlx5_cmd_alias_obj_destroy(secondary, sd->alias_obj_id, 341 + MLX5_GENERAL_OBJECT_TYPES_FLOW_TABLE_ALIAS); 342 + } 343 + 344 + static int sd_cmd_set_secondary(struct mlx5_core_dev *secondary, 345 + struct mlx5_core_dev *primary, 346 + u8 *alias_key) 347 + { 348 + struct mlx5_sd *primary_sd = mlx5_get_sd(primary); 349 + struct mlx5_sd *sd = mlx5_get_sd(secondary); 350 + int err; 351 + 352 + err = mlx5_fs_cmd_set_l2table_entry_silent(secondary, 1); 353 + if (err) 354 + return err; 355 + 356 + err = sd_secondary_create_alias_ft(secondary, primary, primary_sd->tx_ft, 357 + &sd->alias_obj_id, alias_key); 358 + if (err) 359 + goto err_unset_silent; 360 + 361 + err = mlx5_fs_cmd_set_tx_flow_table_root(secondary, sd->alias_obj_id, false); 362 + if (err) 363 + goto err_destroy_alias_ft; 364 + 365 + return 0; 366 + 367 + err_destroy_alias_ft: 368 + sd_secondary_destroy_alias_ft(secondary); 369 + err_unset_silent: 370 + mlx5_fs_cmd_set_l2table_entry_silent(secondary, 0); 371 + return err; 372 + } 373 + 374 + static void sd_cmd_unset_secondary(struct mlx5_core_dev *secondary) 375 + { 376 + mlx5_fs_cmd_set_tx_flow_table_root(secondary, 0, true); 377 + sd_secondary_destroy_alias_ft(secondary); 378 + mlx5_fs_cmd_set_l2table_entry_silent(secondary, 0); 379 + } 380 + 381 + static void sd_print_group(struct mlx5_core_dev *primary) 382 + { 383 + struct mlx5_sd *sd = mlx5_get_sd(primary); 384 + struct mlx5_core_dev *pos; 385 + int i; 386 + 387 + sd_info(primary, "group id %#x, primary %s, vhca %#x\n", 388 + sd->group_id, pci_name(primary->pdev), 389 + MLX5_CAP_GEN(primary, vhca_id)); 390 + mlx5_sd_for_each_secondary(i, primary, pos) 391 + sd_info(primary, "group id %#x, secondary_%d %s, vhca %#x\n", 392 + sd->group_id, i - 1, pci_name(pos->pdev), 393 + MLX5_CAP_GEN(pos, vhca_id)); 394 + } 395 + 396 + static ssize_t dev_read(struct file *filp, char __user *buf, size_t count, 397 + loff_t *pos) 398 + { 399 + struct mlx5_core_dev *dev; 400 + char tbuf[32]; 401 + int ret; 402 + 403 + dev = filp->private_data; 404 + ret = snprintf(tbuf, sizeof(tbuf), "%s vhca %#x\n", pci_name(dev->pdev), 405 + MLX5_CAP_GEN(dev, vhca_id)); 406 + 407 + return simple_read_from_buffer(buf, count, pos, tbuf, ret); 408 + } 409 + 410 + static const struct file_operations dev_fops = { 411 + .owner = THIS_MODULE, 412 + .open = simple_open, 413 + .read = dev_read, 414 + }; 415 + 416 + int mlx5_sd_init(struct mlx5_core_dev *dev) 417 + { 418 + struct mlx5_core_dev *primary, *pos, *to; 419 + struct mlx5_sd *sd = mlx5_get_sd(dev); 420 + u8 alias_key[ACCESS_KEY_LEN]; 421 + int err, i; 422 + 423 + err = sd_init(dev); 424 + if (err) 425 + return err; 426 + 427 + sd = mlx5_get_sd(dev); 428 + if (!sd) 429 + return 0; 430 + 431 + err = sd_register(dev); 432 + if (err) 433 + goto err_sd_cleanup; 434 + 435 + if (!mlx5_devcom_comp_is_ready(sd->devcom)) 436 + return 0; 437 + 438 + primary = mlx5_sd_get_primary(dev); 439 + 440 + for (i = 0; i < ACCESS_KEY_LEN; i++) 441 + alias_key[i] = get_random_u8(); 442 + 443 + err = sd_cmd_set_primary(primary, alias_key); 444 + if (err) 445 + goto err_sd_unregister; 446 + 447 + sd->dfs = debugfs_create_dir("multi-pf", mlx5_debugfs_get_dev_root(primary)); 448 + debugfs_create_x32("group_id", 0400, sd->dfs, &sd->group_id); 449 + debugfs_create_file("primary", 0400, sd->dfs, primary, &dev_fops); 450 + 451 + mlx5_sd_for_each_secondary(i, primary, pos) { 452 + char name[32]; 453 + 454 + err = sd_cmd_set_secondary(pos, primary, alias_key); 455 + if (err) 456 + goto err_unset_secondaries; 457 + 458 + snprintf(name, sizeof(name), "secondary_%d", i - 1); 459 + debugfs_create_file(name, 0400, sd->dfs, pos, &dev_fops); 460 + 461 + } 462 + 463 + sd_info(primary, "group id %#x, size %d, combined\n", 464 + sd->group_id, mlx5_devcom_comp_get_size(sd->devcom)); 465 + sd_print_group(primary); 466 + 467 + return 0; 468 + 469 + err_unset_secondaries: 470 + to = pos; 471 + mlx5_sd_for_each_secondary_to(i, primary, to, pos) 472 + sd_cmd_unset_secondary(pos); 473 + sd_cmd_unset_primary(primary); 474 + debugfs_remove_recursive(sd->dfs); 475 + err_sd_unregister: 476 + sd_unregister(dev); 477 + err_sd_cleanup: 478 + sd_cleanup(dev); 479 + return err; 480 + } 481 + 482 + void mlx5_sd_cleanup(struct mlx5_core_dev *dev) 483 + { 484 + struct mlx5_sd *sd = mlx5_get_sd(dev); 485 + struct mlx5_core_dev *primary, *pos; 486 + int i; 487 + 488 + if (!sd) 489 + return; 490 + 491 + if (!mlx5_devcom_comp_is_ready(sd->devcom)) 492 + goto out; 493 + 494 + primary = mlx5_sd_get_primary(dev); 495 + mlx5_sd_for_each_secondary(i, primary, pos) 496 + sd_cmd_unset_secondary(pos); 497 + sd_cmd_unset_primary(primary); 498 + debugfs_remove_recursive(sd->dfs); 499 + 500 + sd_info(primary, "group id %#x, uncombined\n", sd->group_id); 501 + out: 502 + sd_unregister(dev); 503 + sd_cleanup(dev); 504 + } 505 + 506 + struct auxiliary_device *mlx5_sd_get_adev(struct mlx5_core_dev *dev, 507 + struct auxiliary_device *adev, 508 + int idx) 509 + { 510 + struct mlx5_sd *sd = mlx5_get_sd(dev); 511 + struct mlx5_core_dev *primary; 512 + 513 + if (!sd) 514 + return adev; 515 + 516 + if (!mlx5_devcom_comp_is_ready(sd->devcom)) 517 + return NULL; 518 + 519 + primary = mlx5_sd_get_primary(dev); 520 + if (dev == primary) 521 + return adev; 522 + 523 + return &primary->priv.adev[idx]->adev; 524 + }
+38
drivers/net/ethernet/mellanox/mlx5/core/lib/sd.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ 2 + /* Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */ 3 + 4 + #ifndef __MLX5_LIB_SD_H__ 5 + #define __MLX5_LIB_SD_H__ 6 + 7 + #define MLX5_SD_MAX_GROUP_SZ 2 8 + 9 + struct mlx5_sd; 10 + 11 + struct mlx5_core_dev *mlx5_sd_primary_get_peer(struct mlx5_core_dev *primary, int idx); 12 + int mlx5_sd_ch_ix_get_dev_ix(struct mlx5_core_dev *dev, int ch_ix); 13 + int mlx5_sd_ch_ix_get_vec_ix(struct mlx5_core_dev *dev, int ch_ix); 14 + struct mlx5_core_dev *mlx5_sd_ch_ix_get_dev(struct mlx5_core_dev *primary, int ch_ix); 15 + struct auxiliary_device *mlx5_sd_get_adev(struct mlx5_core_dev *dev, 16 + struct auxiliary_device *adev, 17 + int idx); 18 + 19 + int mlx5_sd_init(struct mlx5_core_dev *dev); 20 + void mlx5_sd_cleanup(struct mlx5_core_dev *dev); 21 + 22 + #define mlx5_sd_for_each_dev_from_to(i, primary, ix_from, to, pos) \ 23 + for (i = ix_from; \ 24 + (pos = mlx5_sd_primary_get_peer(primary, i)) && pos != (to); i++) 25 + 26 + #define mlx5_sd_for_each_dev(i, primary, pos) \ 27 + mlx5_sd_for_each_dev_from_to(i, primary, 0, NULL, pos) 28 + 29 + #define mlx5_sd_for_each_dev_to(i, primary, to, pos) \ 30 + mlx5_sd_for_each_dev_from_to(i, primary, 0, to, pos) 31 + 32 + #define mlx5_sd_for_each_secondary(i, primary, pos) \ 33 + mlx5_sd_for_each_dev_from_to(i, primary, 1, NULL, pos) 34 + 35 + #define mlx5_sd_for_each_secondary_to(i, primary, to, pos) \ 36 + mlx5_sd_for_each_dev_from_to(i, primary, 1, to, pos) 37 + 38 + #endif /* __MLX5_LIB_SD_H__ */
+1
include/linux/mlx5/driver.h
··· 823 823 struct blocking_notifier_head macsec_nh; 824 824 #endif 825 825 u64 num_ipsec_offloads; 826 + struct mlx5_sd *sd; 826 827 }; 827 828 828 829 struct mlx5_db {
+3 -1
include/linux/mlx5/mlx5_ifc.h
··· 10253 10253 u8 mcqi[0x1]; 10254 10254 u8 mcqs[0x1]; 10255 10255 10256 - u8 regs_95_to_87[0x9]; 10256 + u8 regs_95_to_90[0x6]; 10257 + u8 mpir[0x1]; 10258 + u8 regs_88_to_87[0x2]; 10257 10259 u8 mpegc[0x1]; 10258 10260 u8 mtutc[0x1]; 10259 10261 u8 regs_84_to_68[0x11];