Skip to content

Commit 6831582

Browse files
Nick ChildPaolo Abeni
authored andcommitted
ibmvnic: Toggle between queue types in affinity mapping
Previously, ibmvnic IRQs were assigned to CPU numbers by assigning all the IRQs for transmit queues then assigning all the IRQs for receive queues. With multi-threaded processors, in a heavy RX or TX environment, physical cores would either be overloaded or underutilized (due to the IRQ assignment algorithm). This approach is sub-optimal because IRQs for the same subprocess (RX or TX) would be bound to adjacent CPU numbers, meaning they were more likely to be contending for the same core. For example, in a system with 64 CPU's and 32 queues, the IRQs would be bound to CPU in the following pattern: IRQ type | CPU number ----------------------- TX0 | 0-1 TX1 | 2-3 <etc> RX0 | 32-33 RX1 | 34-35 <etc> Observe that in SMT-8, the first 4 tx queues would be sharing the same core. A more optimal algorithm would balance the number RX and TX IRQ's across the physical cores. Therefore, to increase performance, distribute RX and TX IRQs across cores by alternating between assigning IRQs for RX and TX queues to CPUs. With a system with 64 CPUs and 32 queues, this results in the following pattern: IRQ type | CPU number ----------------------- TX0 | 0-1 RX0 | 2-3 TX1 | 4-5 RX1 | 6-7 <etc> Observe that in SMT-8, there is equal distribution of RX and TX IRQs per core. In the above case, each core handles 2 TX and 2 RX IRQ's. Signed-off-by: Nick Child <nnac123@linux.ibm.com> Reviewed-by: Haren Myneni <haren@linux.ibm.com> Link: https://lore.kernel.org/r/20230127214358.318152-1-nnac123@linux.ibm.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
1 parent 6a8ab43 commit 6831582

File tree

1 file changed

+16
-13
lines changed

1 file changed

+16
-13
lines changed

drivers/net/ethernet/ibm/ibmvnic.c

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -250,10 +250,11 @@ static void ibmvnic_set_affinity(struct ibmvnic_adapter *adapter)
250250
struct ibmvnic_sub_crq_queue **rxqs = adapter->rx_scrq;
251251
struct ibmvnic_sub_crq_queue **txqs = adapter->tx_scrq;
252252
struct ibmvnic_sub_crq_queue *queue;
253-
int num_rxqs = adapter->num_active_rx_scrqs;
254-
int num_txqs = adapter->num_active_tx_scrqs;
253+
int num_rxqs = adapter->num_active_rx_scrqs, i_rxqs = 0;
254+
int num_txqs = adapter->num_active_tx_scrqs, i_txqs = 0;
255255
int total_queues, stride, stragglers, i;
256256
unsigned int num_cpu, cpu;
257+
bool is_rx_queue;
257258
int rc = 0;
258259

259260
netdev_dbg(adapter->netdev, "%s: Setting irq affinity hints", __func__);
@@ -273,14 +274,24 @@ static void ibmvnic_set_affinity(struct ibmvnic_adapter *adapter)
273274
/* next available cpu to assign irq to */
274275
cpu = cpumask_next(-1, cpu_online_mask);
275276

276-
for (i = 0; i < num_txqs; i++) {
277-
queue = txqs[i];
277+
for (i = 0; i < total_queues; i++) {
278+
is_rx_queue = false;
279+
/* balance core load by alternating rx and tx assignments
280+
* ex: TX0 -> RX0 -> TX1 -> RX1 etc.
281+
*/
282+
if ((i % 2 == 1 && i_rxqs < num_rxqs) || i_txqs == num_txqs) {
283+
queue = rxqs[i_rxqs++];
284+
is_rx_queue = true;
285+
} else {
286+
queue = txqs[i_txqs++];
287+
}
288+
278289
rc = ibmvnic_set_queue_affinity(queue, &cpu, &stragglers,
279290
stride);
280291
if (rc)
281292
goto out;
282293

283-
if (!queue)
294+
if (!queue || is_rx_queue)
284295
continue;
285296

286297
rc = __netif_set_xps_queue(adapter->netdev,
@@ -291,14 +302,6 @@ static void ibmvnic_set_affinity(struct ibmvnic_adapter *adapter)
291302
__func__, i, rc);
292303
}
293304

294-
for (i = 0; i < num_rxqs; i++) {
295-
queue = rxqs[i];
296-
rc = ibmvnic_set_queue_affinity(queue, &cpu, &stragglers,
297-
stride);
298-
if (rc)
299-
goto out;
300-
}
301-
302305
out:
303306
if (rc) {
304307
netdev_warn(adapter->netdev,

0 commit comments

Comments
 (0)