Skip to content

Commit 3990a8f

Browse files
cmclachl-xilinxdavem330
authored andcommitted
sfc: allocate channels for XDP tx queues
Each CPU needs access to its own queue to allow uncontested transmission of XDP_TX packets. This means we need to allocate (up front) enough channels ("xdp transmit channels") to provide at least one extra tx queue per CPU. These tx queues should not do TSO. Signed-off-by: Charles McLachlan <cmclachlan@solarflare.com> Acked-by: Jesper Dangaard Brouer <brouer@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent e45a4fe commit 3990a8f

File tree

4 files changed

+190
-40
lines changed

4 files changed

+190
-40
lines changed

drivers/net/ethernet/sfc/ef10.c

+9-5
Original file line numberDiff line numberDiff line change
@@ -946,8 +946,10 @@ static int efx_ef10_link_piobufs(struct efx_nic *efx)
946946
/* Extra channels, even those with TXQs (PTP), do not require
947947
* PIO resources.
948948
*/
949-
if (!channel->type->want_pio)
949+
if (!channel->type->want_pio ||
950+
channel->channel >= efx->xdp_channel_offset)
950951
continue;
952+
951953
efx_for_each_channel_tx_queue(tx_queue, channel) {
952954
/* We assign the PIO buffers to queues in
953955
* reverse order to allow for the following
@@ -1296,8 +1298,9 @@ static int efx_ef10_dimension_resources(struct efx_nic *efx)
12961298
int rc;
12971299

12981300
channel_vis = max(efx->n_channels,
1299-
(efx->n_tx_channels + efx->n_extra_tx_channels) *
1300-
EFX_TXQ_TYPES);
1301+
((efx->n_tx_channels + efx->n_extra_tx_channels) *
1302+
EFX_TXQ_TYPES) +
1303+
efx->n_xdp_channels * efx->xdp_tx_per_channel);
13011304

13021305
#ifdef EFX_USE_PIO
13031306
/* Try to allocate PIO buffers if wanted and if the full
@@ -2434,11 +2437,12 @@ static void efx_ef10_tx_init(struct efx_tx_queue *tx_queue)
24342437
/* TSOv2 is a limited resource that can only be configured on a limited
24352438
* number of queues. TSO without checksum offload is not really a thing,
24362439
* so we only enable it for those queues.
2437-
* TSOv2 cannot be used with Hardware timestamping.
2440+
* TSOv2 cannot be used with Hardware timestamping, and is never needed
2441+
* for XDP tx.
24382442
*/
24392443
if (csum_offload && (nic_data->datapath_caps2 &
24402444
(1 << MC_CMD_GET_CAPABILITIES_V2_OUT_TX_TSO_V2_LBN)) &&
2441-
!tx_queue->timestamping) {
2445+
!tx_queue->timestamping && !tx_queue->xdp_tx) {
24422446
tso_v2 = true;
24432447
netif_dbg(efx, hw, efx->net_dev, "Using TSOv2 for channel %u\n",
24442448
channel->channel);

drivers/net/ethernet/sfc/efx.c

+148-32
Original file line numberDiff line numberDiff line change
@@ -583,9 +583,14 @@ efx_get_channel_name(struct efx_channel *channel, char *buf, size_t len)
583583
int number;
584584

585585
number = channel->channel;
586-
if (efx->tx_channel_offset == 0) {
586+
587+
if (number >= efx->xdp_channel_offset &&
588+
!WARN_ON_ONCE(!efx->n_xdp_channels)) {
589+
type = "-xdp";
590+
number -= efx->xdp_channel_offset;
591+
} else if (efx->tx_channel_offset == 0) {
587592
type = "";
588-
} else if (channel->channel < efx->tx_channel_offset) {
593+
} else if (number < efx->tx_channel_offset) {
589594
type = "-rx";
590595
} else {
591596
type = "-tx";
@@ -803,6 +808,8 @@ static void efx_remove_channels(struct efx_nic *efx)
803808

804809
efx_for_each_channel(channel, efx)
805810
efx_remove_channel(channel);
811+
812+
kfree(efx->xdp_tx_queues);
806813
}
807814

808815
int
@@ -1440,6 +1447,101 @@ static unsigned int efx_wanted_parallelism(struct efx_nic *efx)
14401447
return count;
14411448
}
14421449

1450+
static int efx_allocate_msix_channels(struct efx_nic *efx,
1451+
unsigned int max_channels,
1452+
unsigned int extra_channels,
1453+
unsigned int parallelism)
1454+
{
1455+
unsigned int n_channels = parallelism;
1456+
int vec_count;
1457+
int n_xdp_tx;
1458+
int n_xdp_ev;
1459+
1460+
if (efx_separate_tx_channels)
1461+
n_channels *= 2;
1462+
n_channels += extra_channels;
1463+
1464+
/* To allow XDP transmit to happen from arbitrary NAPI contexts
1465+
* we allocate a TX queue per CPU. We share event queues across
1466+
* multiple tx queues, assuming tx and ev queues are both
1467+
* maximum size.
1468+
*/
1469+
1470+
n_xdp_tx = num_possible_cpus();
1471+
n_xdp_ev = DIV_ROUND_UP(n_xdp_tx, EFX_TXQ_TYPES);
1472+
1473+
/* Check resources.
1474+
* We need a channel per event queue, plus a VI per tx queue.
1475+
* This may be more pessimistic than it needs to be.
1476+
*/
1477+
if (n_channels + n_xdp_ev > max_channels) {
1478+
netif_err(efx, drv, efx->net_dev,
1479+
"Insufficient resources for %d XDP event queues (%d other channels, max %d)\n",
1480+
n_xdp_ev, n_channels, max_channels);
1481+
efx->n_xdp_channels = 0;
1482+
efx->xdp_tx_per_channel = 0;
1483+
efx->xdp_tx_queue_count = 0;
1484+
} else {
1485+
efx->n_xdp_channels = n_xdp_ev;
1486+
efx->xdp_tx_per_channel = EFX_TXQ_TYPES;
1487+
efx->xdp_tx_queue_count = n_xdp_tx;
1488+
n_channels += n_xdp_ev;
1489+
netif_dbg(efx, drv, efx->net_dev,
1490+
"Allocating %d TX and %d event queues for XDP\n",
1491+
n_xdp_tx, n_xdp_ev);
1492+
}
1493+
1494+
n_channels = min(n_channels, max_channels);
1495+
1496+
vec_count = pci_msix_vec_count(efx->pci_dev);
1497+
if (vec_count < 0)
1498+
return vec_count;
1499+
if (vec_count < n_channels) {
1500+
netif_err(efx, drv, efx->net_dev,
1501+
"WARNING: Insufficient MSI-X vectors available (%d < %u).\n",
1502+
vec_count, n_channels);
1503+
netif_err(efx, drv, efx->net_dev,
1504+
"WARNING: Performance may be reduced.\n");
1505+
n_channels = vec_count;
1506+
}
1507+
1508+
efx->n_channels = n_channels;
1509+
1510+
/* Do not create the PTP TX queue(s) if PTP uses the MC directly. */
1511+
if (extra_channels && !efx_ptp_use_mac_tx_timestamps(efx))
1512+
n_channels--;
1513+
1514+
/* Ignore XDP tx channels when creating rx channels. */
1515+
n_channels -= efx->n_xdp_channels;
1516+
1517+
if (efx_separate_tx_channels) {
1518+
efx->n_tx_channels =
1519+
min(max(n_channels / 2, 1U),
1520+
efx->max_tx_channels);
1521+
efx->tx_channel_offset =
1522+
n_channels - efx->n_tx_channels;
1523+
efx->n_rx_channels =
1524+
max(n_channels -
1525+
efx->n_tx_channels, 1U);
1526+
} else {
1527+
efx->n_tx_channels = min(n_channels, efx->max_tx_channels);
1528+
efx->tx_channel_offset = 0;
1529+
efx->n_rx_channels = n_channels;
1530+
}
1531+
1532+
if (efx->n_xdp_channels)
1533+
efx->xdp_channel_offset = efx->tx_channel_offset +
1534+
efx->n_tx_channels;
1535+
else
1536+
efx->xdp_channel_offset = efx->n_channels;
1537+
1538+
netif_dbg(efx, drv, efx->net_dev,
1539+
"Allocating %u RX channels\n",
1540+
efx->n_rx_channels);
1541+
1542+
return efx->n_channels;
1543+
}
1544+
14431545
/* Probe the number and type of interrupts we are able to obtain, and
14441546
* the resulting numbers of channels and RX queues.
14451547
*/
@@ -1454,19 +1556,19 @@ static int efx_probe_interrupts(struct efx_nic *efx)
14541556
++extra_channels;
14551557

14561558
if (efx->interrupt_mode == EFX_INT_MODE_MSIX) {
1559+
unsigned int parallelism = efx_wanted_parallelism(efx);
14571560
struct msix_entry xentries[EFX_MAX_CHANNELS];
14581561
unsigned int n_channels;
14591562

1460-
n_channels = efx_wanted_parallelism(efx);
1461-
if (efx_separate_tx_channels)
1462-
n_channels *= 2;
1463-
n_channels += extra_channels;
1464-
n_channels = min(n_channels, efx->max_channels);
1465-
1466-
for (i = 0; i < n_channels; i++)
1467-
xentries[i].entry = i;
1468-
rc = pci_enable_msix_range(efx->pci_dev,
1469-
xentries, 1, n_channels);
1563+
rc = efx_allocate_msix_channels(efx, efx->max_channels,
1564+
extra_channels, parallelism);
1565+
if (rc >= 0) {
1566+
n_channels = rc;
1567+
for (i = 0; i < n_channels; i++)
1568+
xentries[i].entry = i;
1569+
rc = pci_enable_msix_range(efx->pci_dev, xentries, 1,
1570+
n_channels);
1571+
}
14701572
if (rc < 0) {
14711573
/* Fall back to single channel MSI */
14721574
netif_err(efx, drv, efx->net_dev,
@@ -1485,21 +1587,6 @@ static int efx_probe_interrupts(struct efx_nic *efx)
14851587
}
14861588

14871589
if (rc > 0) {
1488-
efx->n_channels = n_channels;
1489-
if (n_channels > extra_channels)
1490-
n_channels -= extra_channels;
1491-
if (efx_separate_tx_channels) {
1492-
efx->n_tx_channels = min(max(n_channels / 2,
1493-
1U),
1494-
efx->max_tx_channels);
1495-
efx->n_rx_channels = max(n_channels -
1496-
efx->n_tx_channels,
1497-
1U);
1498-
} else {
1499-
efx->n_tx_channels = min(n_channels,
1500-
efx->max_tx_channels);
1501-
efx->n_rx_channels = n_channels;
1502-
}
15031590
for (i = 0; i < efx->n_channels; i++)
15041591
efx_get_channel(efx, i)->irq =
15051592
xentries[i].vector;
@@ -1511,6 +1598,8 @@ static int efx_probe_interrupts(struct efx_nic *efx)
15111598
efx->n_channels = 1;
15121599
efx->n_rx_channels = 1;
15131600
efx->n_tx_channels = 1;
1601+
efx->n_xdp_channels = 0;
1602+
efx->xdp_channel_offset = efx->n_channels;
15141603
rc = pci_enable_msi(efx->pci_dev);
15151604
if (rc == 0) {
15161605
efx_get_channel(efx, 0)->irq = efx->pci_dev->irq;
@@ -1529,12 +1618,14 @@ static int efx_probe_interrupts(struct efx_nic *efx)
15291618
efx->n_channels = 1 + (efx_separate_tx_channels ? 1 : 0);
15301619
efx->n_rx_channels = 1;
15311620
efx->n_tx_channels = 1;
1621+
efx->n_xdp_channels = 0;
1622+
efx->xdp_channel_offset = efx->n_channels;
15321623
efx->legacy_irq = efx->pci_dev->irq;
15331624
}
15341625

1535-
/* Assign extra channels if possible */
1626+
/* Assign extra channels if possible, before XDP channels */
15361627
efx->n_extra_tx_channels = 0;
1537-
j = efx->n_channels;
1628+
j = efx->xdp_channel_offset;
15381629
for (i = 0; i < EFX_MAX_EXTRA_CHANNELS; i++) {
15391630
if (!efx->extra_channel_type[i])
15401631
continue;
@@ -1729,29 +1820,50 @@ static void efx_remove_interrupts(struct efx_nic *efx)
17291820
efx->legacy_irq = 0;
17301821
}
17311822

1732-
static void efx_set_channels(struct efx_nic *efx)
1823+
static int efx_set_channels(struct efx_nic *efx)
17331824
{
17341825
struct efx_channel *channel;
17351826
struct efx_tx_queue *tx_queue;
1827+
int xdp_queue_number;
17361828

17371829
efx->tx_channel_offset =
17381830
efx_separate_tx_channels ?
17391831
efx->n_channels - efx->n_tx_channels : 0;
17401832

1833+
if (efx->xdp_tx_queue_count) {
1834+
EFX_WARN_ON_PARANOID(efx->xdp_tx_queues);
1835+
1836+
/* Allocate array for XDP TX queue lookup. */
1837+
efx->xdp_tx_queues = kcalloc(efx->xdp_tx_queue_count,
1838+
sizeof(*efx->xdp_tx_queues),
1839+
GFP_KERNEL);
1840+
if (!efx->xdp_tx_queues)
1841+
return -ENOMEM;
1842+
}
1843+
17411844
/* We need to mark which channels really have RX and TX
17421845
* queues, and adjust the TX queue numbers if we have separate
17431846
* RX-only and TX-only channels.
17441847
*/
1848+
xdp_queue_number = 0;
17451849
efx_for_each_channel(channel, efx) {
17461850
if (channel->channel < efx->n_rx_channels)
17471851
channel->rx_queue.core_index = channel->channel;
17481852
else
17491853
channel->rx_queue.core_index = -1;
17501854

1751-
efx_for_each_channel_tx_queue(tx_queue, channel)
1855+
efx_for_each_channel_tx_queue(tx_queue, channel) {
17521856
tx_queue->queue -= (efx->tx_channel_offset *
17531857
EFX_TXQ_TYPES);
1858+
1859+
if (efx_channel_is_xdp_tx(channel) &&
1860+
xdp_queue_number < efx->xdp_tx_queue_count) {
1861+
efx->xdp_tx_queues[xdp_queue_number] = tx_queue;
1862+
xdp_queue_number++;
1863+
}
1864+
}
17541865
}
1866+
return 0;
17551867
}
17561868

17571869
static int efx_probe_nic(struct efx_nic *efx)
@@ -1781,7 +1893,9 @@ static int efx_probe_nic(struct efx_nic *efx)
17811893
if (rc)
17821894
goto fail1;
17831895

1784-
efx_set_channels(efx);
1896+
rc = efx_set_channels(efx);
1897+
if (rc)
1898+
goto fail1;
17851899

17861900
/* dimension_resources can fail with EAGAIN */
17871901
rc = efx->type->dimension_resources(efx);
@@ -2091,6 +2205,8 @@ int efx_init_irq_moderation(struct efx_nic *efx, unsigned int tx_usecs,
20912205
channel->irq_moderation_us = rx_usecs;
20922206
else if (efx_channel_has_tx_queues(channel))
20932207
channel->irq_moderation_us = tx_usecs;
2208+
else if (efx_channel_is_xdp_tx(channel))
2209+
channel->irq_moderation_us = tx_usecs;
20942210
}
20952211

20962212
return 0;

0 commit comments

Comments
 (0)