aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincenzo Maffione <vmaffione@FreeBSD.org>2020-07-20 21:08:56 +0000
committerVincenzo Maffione <vmaffione@FreeBSD.org>2020-07-20 21:08:56 +0000
commitac11d8574093a746fab29c67ce1fbbfb445c449c (patch)
treee7b6d7ed66a2cf6029f3bda5fcc3a937fb8c98be
parent3b41d99d7639f734cdf5d59bcc464a8fb2f1284a (diff)
downloadsrc-ac11d8574093a746fab29c67ce1fbbfb445c449c.tar.gz
src-ac11d8574093a746fab29c67ce1fbbfb445c449c.zip
iflib: initialize netmap with the correct number of descriptors
In case the network device has a RX or TX control queue, the correct number of TX/RX descriptors is contained in the second entry of the isc_ntxd (or isc_nrxd) array, rather than in the first entry. This case is correctly handled by iflib_device_register() and iflib_pseudo_register(), but not by iflib_netmap_attach(). If the first entry is larger than the second, this can result in a panic. This change fixes the bug by introducing two helper functions that also lead to some code simplification. PR: 247647 MFC after: 3 weeks Differential Revision: https://reviews.freebsd.org/D25541
Notes
Notes: svn path=/head/; revision=363378
-rw-r--r--sys/net/iflib.c60
1 files changed, 38 insertions, 22 deletions
diff --git a/sys/net/iflib.c b/sys/net/iflib.c
index e614661ca79a..f87b31251ffe 100644
--- a/sys/net/iflib.c
+++ b/sys/net/iflib.c
@@ -730,6 +730,26 @@ MTX_SYSINIT(iflib_cpu_offset, &cpu_offset_mtx, "iflib_cpu_offset lock",
DEBUGNET_DEFINE(iflib);
+static int
+iflib_num_rx_descs(if_ctx_t ctx)
+{
+ if_softc_ctx_t scctx = &ctx->ifc_softc_ctx;
+ if_shared_ctx_t sctx = ctx->ifc_sctx;
+ uint16_t first_rxq = (sctx->isc_flags & IFLIB_HAS_RXCQ) ? 1 : 0;
+
+ return scctx->isc_nrxd[first_rxq];
+}
+
+static int
+iflib_num_tx_descs(if_ctx_t ctx)
+{
+ if_softc_ctx_t scctx = &ctx->ifc_softc_ctx;
+ if_shared_ctx_t sctx = ctx->ifc_sctx;
+ uint16_t first_txq = (sctx->isc_flags & IFLIB_HAS_TXCQ) ? 1 : 0;
+
+ return scctx->isc_ntxd[first_txq];
+}
+
#ifdef DEV_NETMAP
#include <sys/selinfo.h>
#include <net/netmap.h>
@@ -1165,7 +1185,6 @@ static int
iflib_netmap_attach(if_ctx_t ctx)
{
struct netmap_adapter na;
- if_softc_ctx_t scctx = &ctx->ifc_softc_ctx;
bzero(&na, sizeof(na));
@@ -1174,8 +1193,8 @@ iflib_netmap_attach(if_ctx_t ctx)
MPASS(ctx->ifc_softc_ctx.isc_ntxqsets);
MPASS(ctx->ifc_softc_ctx.isc_nrxqsets);
- na.num_tx_desc = scctx->isc_ntxd[0];
- na.num_rx_desc = scctx->isc_nrxd[0];
+ na.num_tx_desc = iflib_num_tx_descs(ctx);
+ na.num_rx_desc = iflib_num_rx_descs(ctx);
na.nm_txsync = iflib_netmap_txsync;
na.nm_rxsync = iflib_netmap_rxsync;
na.nm_register = iflib_netmap_register;
@@ -4590,7 +4609,7 @@ iflib_device_register(device_t dev, void *sc, if_shared_ctx_t sctx, if_ctx_t *ct
kobjop_desc_t kobj_desc;
kobj_method_t *kobj_method;
int err, msix, rid;
- uint16_t main_rxq, main_txq;
+ int num_txd, num_rxd;
ctx = malloc(sizeof(* ctx), M_IFLIB, M_WAITOK|M_ZERO);
@@ -4640,21 +4659,20 @@ iflib_device_register(device_t dev, void *sc, if_shared_ctx_t sctx, if_ctx_t *ct
if (scctx->isc_nrxqsets == 0 || (scctx->isc_nrxqsets_max && scctx->isc_nrxqsets_max < scctx->isc_nrxqsets))
scctx->isc_nrxqsets = scctx->isc_nrxqsets_max;
- main_txq = (sctx->isc_flags & IFLIB_HAS_TXCQ) ? 1 : 0;
- main_rxq = (sctx->isc_flags & IFLIB_HAS_RXCQ) ? 1 : 0;
+ num_txd = iflib_num_tx_descs(ctx);
+ num_rxd = iflib_num_rx_descs(ctx);
/* XXX change for per-queue sizes */
device_printf(dev, "Using %d TX descriptors and %d RX descriptors\n",
- scctx->isc_ntxd[main_txq], scctx->isc_nrxd[main_rxq]);
+ num_txd, num_rxd);
- if (scctx->isc_tx_nsegments > scctx->isc_ntxd[main_txq] /
- MAX_SINGLE_PACKET_FRACTION)
- scctx->isc_tx_nsegments = max(1, scctx->isc_ntxd[main_txq] /
+ if (scctx->isc_tx_nsegments > num_txd / MAX_SINGLE_PACKET_FRACTION)
+ scctx->isc_tx_nsegments = max(1, num_txd /
MAX_SINGLE_PACKET_FRACTION);
- if (scctx->isc_tx_tso_segments_max > scctx->isc_ntxd[main_txq] /
+ if (scctx->isc_tx_tso_segments_max > num_txd /
MAX_SINGLE_PACKET_FRACTION)
scctx->isc_tx_tso_segments_max = max(1,
- scctx->isc_ntxd[main_txq] / MAX_SINGLE_PACKET_FRACTION);
+ num_txd / MAX_SINGLE_PACKET_FRACTION);
/* TSO parameters - dig these out of the data sheet - simply correspond to tag setup */
if (if_getcapabilities(ifp) & IFCAP_TSO) {
@@ -4831,14 +4849,13 @@ int
iflib_pseudo_register(device_t dev, if_shared_ctx_t sctx, if_ctx_t *ctxp,
struct iflib_cloneattach_ctx *clctx)
{
+ int num_txd, num_rxd;
int err;
if_ctx_t ctx;
if_t ifp;
if_softc_ctx_t scctx;
int i;
void *sc;
- uint16_t main_txq;
- uint16_t main_rxq;
ctx = malloc(sizeof(*ctx), M_IFLIB, M_WAITOK|M_ZERO);
sc = malloc(sctx->isc_driver->size, M_IFLIB, M_WAITOK|M_ZERO);
@@ -4924,21 +4941,20 @@ iflib_pseudo_register(device_t dev, if_shared_ctx_t sctx, if_ctx_t *ctxp,
if (scctx->isc_nrxqsets == 0 || (scctx->isc_nrxqsets_max && scctx->isc_nrxqsets_max < scctx->isc_nrxqsets))
scctx->isc_nrxqsets = scctx->isc_nrxqsets_max;
- main_txq = (sctx->isc_flags & IFLIB_HAS_TXCQ) ? 1 : 0;
- main_rxq = (sctx->isc_flags & IFLIB_HAS_RXCQ) ? 1 : 0;
+ num_txd = iflib_num_tx_descs(ctx);
+ num_rxd = iflib_num_rx_descs(ctx);
/* XXX change for per-queue sizes */
device_printf(dev, "Using %d TX descriptors and %d RX descriptors\n",
- scctx->isc_ntxd[main_txq], scctx->isc_nrxd[main_rxq]);
+ num_txd, num_rxd);
- if (scctx->isc_tx_nsegments > scctx->isc_ntxd[main_txq] /
- MAX_SINGLE_PACKET_FRACTION)
- scctx->isc_tx_nsegments = max(1, scctx->isc_ntxd[main_txq] /
+ if (scctx->isc_tx_nsegments > num_txd / MAX_SINGLE_PACKET_FRACTION)
+ scctx->isc_tx_nsegments = max(1, num_txd /
MAX_SINGLE_PACKET_FRACTION);
- if (scctx->isc_tx_tso_segments_max > scctx->isc_ntxd[main_txq] /
+ if (scctx->isc_tx_tso_segments_max > num_txd /
MAX_SINGLE_PACKET_FRACTION)
scctx->isc_tx_tso_segments_max = max(1,
- scctx->isc_ntxd[main_txq] / MAX_SINGLE_PACKET_FRACTION);
+ num_txd / MAX_SINGLE_PACKET_FRACTION);
/* TSO parameters - dig these out of the data sheet - simply correspond to tag setup */
if (if_getcapabilities(ifp) & IFCAP_TSO) {