From nobody Sun Oct 5 01:50:01 2025 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.20]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5B46F2E542E; Mon, 11 Aug 2025 16:13:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.20 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754928806; cv=none; b=utbyfNfVlIXpbLt3CofO+8+k3+RX/nhSO0Ga+gEunIMKUzIv1IRSvaiBNHN5R9GyIWsclVI54241n+wyjlFn6hZ9uNeS1Ck+hNKkOj//KwhOr5NTkIQ9+9HRddNlzw5s/YDB7CC2Y60pSaWWQPwsP893xWZHPstThQW/6DXM4Zs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754928806; c=relaxed/simple; bh=xVYNzZQUgGtpidHLut5Kd6E2GSiGftOsGyMSS7Hmb9Y=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=cH8CY3gGhsB9sAEF+sBM1TASDP0QLqg3O4B+cRi6uXVtB//ld/XCfBVJUUituAe5DwtlxARQNe8MWBjD2/6cicOIIywfuxHhIqCTM/vDRNh1ATunFtp0SoAYph+4lK1L2eA5t628xhB4DyeYf7YGtcnmp21jMIvC61B+G2hCclE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=OhSSlEvq; arc=none smtp.client-ip=198.175.65.20 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="OhSSlEvq" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1754928804; x=1786464804; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=xVYNzZQUgGtpidHLut5Kd6E2GSiGftOsGyMSS7Hmb9Y=; b=OhSSlEvqIqtvdIVlMO0LnNQepsWexcU5ebmefActpbcm4i7nWXFZ1W4u Bg6/dNFnyhY4fo6yEk5VHrU/lm8fNCumecnQOUndVHUtO5/NGoQgIHWaV IrQ2JhjYm3BWBu3tSs7dl7MaKPQvFlD2Z3aCf/opVqXflScQ+XASsctk3 otoIPMABiIskyzxjg4mncyAWc4MKqSEPpSM3vq8dMQ4mgFy2T9YNwlzVD kSnpgiZ9p0XL76ER0CptXyAUWA4Y7hX03GP86f/yMQNNjGjvxapRvQpqZ UsQsi4xyB6SBAIl/5FLELrWXSE+/6vcQMS3RK0i66n20Dtnv4E+aBa+G+ Q==; X-CSE-ConnectionGUID: h96ayaeMTKORryfIMELS+A== X-CSE-MsgGUID: GeIBqUqlSd6RI8NOnhH3iw== X-IronPort-AV: E=McAfee;i="6800,10657,11518"; a="56899673" X-IronPort-AV: E=Sophos;i="6.17,278,1747724400"; d="scan'208";a="56899673" Received: from orviesa006.jf.intel.com ([10.64.159.146]) by orvoesa112.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Aug 2025 09:13:24 -0700 X-CSE-ConnectionGUID: 4jq12l6eSRKHOejAVZ4J3g== X-CSE-MsgGUID: FVOHSsH+QOiYE6TfBMcJug== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.17,278,1747724400"; d="scan'208";a="165163228" Received: from newjersey.igk.intel.com ([10.102.20.203]) by orviesa006.jf.intel.com with ESMTP; 11 Aug 2025 09:13:20 -0700 From: Alexander Lobakin To: intel-wired-lan@lists.osuosl.org Cc: Alexander Lobakin , Michal Kubiak , Maciej Fijalkowski , Tony Nguyen , Przemek Kitszel , Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Alexei Starovoitov , Daniel Borkmann , Simon Horman , nxne.cnse.osdt.itp.upstreaming@intel.com, bpf@vger.kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH iwl-next v4 09/13] idpf: implement XDP_SETUP_PROG in ndo_bpf for splitq Date: Mon, 11 Aug 2025 18:10:40 +0200 Message-ID: <20250811161044.32329-10-aleksander.lobakin@intel.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20250811161044.32329-1-aleksander.lobakin@intel.com> References: <20250811161044.32329-1-aleksander.lobakin@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Michal Kubiak Implement loading/removing XDP program using .ndo_bpf callback in the split queue mode. Reconfigure and restart the queues if needed (!!old_prog !=3D !!new_prog), otherwise, just update the pointers. Signed-off-by: Michal Kubiak Signed-off-by: Alexander Lobakin --- drivers/net/ethernet/intel/idpf/idpf_txrx.h | 4 +- drivers/net/ethernet/intel/idpf/xdp.h | 7 ++ drivers/net/ethernet/intel/idpf/idpf_lib.c | 1 + drivers/net/ethernet/intel/idpf/idpf_txrx.c | 4 + drivers/net/ethernet/intel/idpf/xdp.c | 98 +++++++++++++++++++++ 5 files changed, 113 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/idpf/idpf_txrx.h b/drivers/net/ethe= rnet/intel/idpf/idpf_txrx.h index 6bc204b68d9e..f898a9c8de1d 100644 --- a/drivers/net/ethernet/intel/idpf/idpf_txrx.h +++ b/drivers/net/ethernet/intel/idpf/idpf_txrx.h @@ -467,6 +467,7 @@ struct idpf_tx_queue_stats { * @desc_ring: virtual descriptor ring address * @bufq_sets: Pointer to the array of buffer queues in splitq mode * @napi: NAPI instance corresponding to this queue (splitq) + * @xdp_prog: attached XDP program * @rx_buf: See struct &libeth_fqe * @pp: Page pool pointer in singleq mode * @tail: Tail offset. Used for both queue models single and split. @@ -508,13 +509,14 @@ struct idpf_rx_queue { struct { struct idpf_bufq_set *bufq_sets; struct napi_struct *napi; + struct bpf_prog __rcu *xdp_prog; }; struct { struct libeth_fqe *rx_buf; struct page_pool *pp; + void __iomem *tail; }; }; - void __iomem *tail; =20 DECLARE_BITMAP(flags, __IDPF_Q_FLAGS_NBITS); u16 idx; diff --git a/drivers/net/ethernet/intel/idpf/xdp.h b/drivers/net/ethernet/i= ntel/idpf/xdp.h index cf6823b24ba5..47553ce5f81a 100644 --- a/drivers/net/ethernet/intel/idpf/xdp.h +++ b/drivers/net/ethernet/intel/idpf/xdp.h @@ -6,12 +6,19 @@ =20 #include =20 +struct bpf_prog; struct idpf_vport; +struct net_device; +struct netdev_bpf; =20 int idpf_xdp_rxq_info_init_all(const struct idpf_vport *vport); void idpf_xdp_rxq_info_deinit_all(const struct idpf_vport *vport); +void idpf_xdp_copy_prog_to_rqs(const struct idpf_vport *vport, + struct bpf_prog *xdp_prog); =20 int idpf_xdpsqs_get(const struct idpf_vport *vport); void idpf_xdpsqs_put(const struct idpf_vport *vport); =20 +int idpf_xdp(struct net_device *dev, struct netdev_bpf *xdp); + #endif /* _IDPF_XDP_H_ */ diff --git a/drivers/net/ethernet/intel/idpf/idpf_lib.c b/drivers/net/ether= net/intel/idpf/idpf_lib.c index 21caa3e2ce6f..1d96947e4091 100644 --- a/drivers/net/ethernet/intel/idpf/idpf_lib.c +++ b/drivers/net/ethernet/intel/idpf/idpf_lib.c @@ -2519,4 +2519,5 @@ static const struct net_device_ops idpf_netdev_ops = =3D { .ndo_tx_timeout =3D idpf_tx_timeout, .ndo_hwtstamp_get =3D idpf_hwtstamp_get, .ndo_hwtstamp_set =3D idpf_hwtstamp_set, + .ndo_bpf =3D idpf_xdp, }; diff --git a/drivers/net/ethernet/intel/idpf/idpf_txrx.c b/drivers/net/ethe= rnet/intel/idpf/idpf_txrx.c index 18294fc93176..7224f92624cb 100644 --- a/drivers/net/ethernet/intel/idpf/idpf_txrx.c +++ b/drivers/net/ethernet/intel/idpf/idpf_txrx.c @@ -741,6 +741,8 @@ int idpf_rx_bufs_init_all(struct idpf_vport *vport) bool split =3D idpf_is_queue_model_split(vport->rxq_model); int i, j, err; =20 + idpf_xdp_copy_prog_to_rqs(vport, vport->xdp_prog); + for (i =3D 0; i < vport->num_rxq_grp; i++) { struct idpf_rxq_group *rx_qgrp =3D &vport->rxq_grps[i]; u32 truesize =3D 0; @@ -1019,6 +1021,8 @@ static void idpf_vport_queue_grp_rel_all(struct idpf_= vport *vport) */ void idpf_vport_queues_rel(struct idpf_vport *vport) { + idpf_xdp_copy_prog_to_rqs(vport, NULL); + idpf_tx_desc_rel_all(vport); idpf_rx_desc_rel_all(vport); =20 diff --git a/drivers/net/ethernet/intel/idpf/xdp.c b/drivers/net/ethernet/i= ntel/idpf/xdp.c index 08d63462dca4..09e84fe80d4e 100644 --- a/drivers/net/ethernet/intel/idpf/xdp.c +++ b/drivers/net/ethernet/intel/idpf/xdp.c @@ -4,6 +4,7 @@ #include =20 #include "idpf.h" +#include "idpf_virtchnl.h" #include "xdp.h" =20 static int idpf_rxq_for_each(const struct idpf_vport *vport, @@ -91,6 +92,28 @@ void idpf_xdp_rxq_info_deinit_all(const struct idpf_vpor= t *vport) (void *)(size_t)vport->rxq_model); } =20 +static int idpf_xdp_rxq_assign_prog(struct idpf_rx_queue *rxq, void *arg) +{ + struct mutex *lock =3D &rxq->q_vector->vport->adapter->vport_ctrl_lock; + struct bpf_prog *prog =3D arg; + struct bpf_prog *old; + + if (prog) + bpf_prog_inc(prog); + + old =3D rcu_replace_pointer(rxq->xdp_prog, prog, lockdep_is_held(lock)); + if (old) + bpf_prog_put(old); + + return 0; +} + +void idpf_xdp_copy_prog_to_rqs(const struct idpf_vport *vport, + struct bpf_prog *xdp_prog) +{ + idpf_rxq_for_each(vport, idpf_xdp_rxq_assign_prog, xdp_prog); +} + int idpf_xdpsqs_get(const struct idpf_vport *vport) { struct libeth_xdpsq_timer **timers __free(kvfree) =3D NULL; @@ -163,3 +186,78 @@ void idpf_xdpsqs_put(const struct idpf_vport *vport) idpf_queue_clear(NOIRQ, xdpsq); } } + +static int idpf_xdp_setup_prog(struct idpf_vport *vport, + const struct netdev_bpf *xdp) +{ + const struct idpf_netdev_priv *np =3D netdev_priv(vport->netdev); + struct bpf_prog *old, *prog =3D xdp->prog; + struct idpf_vport_config *cfg; + int ret; + + cfg =3D vport->adapter->vport_config[vport->idx]; + + if (test_bit(IDPF_REMOVE_IN_PROG, vport->adapter->flags) || + !test_bit(IDPF_VPORT_REG_NETDEV, cfg->flags) || + !!vport->xdp_prog =3D=3D !!prog) { + if (np->state =3D=3D __IDPF_VPORT_UP) + idpf_xdp_copy_prog_to_rqs(vport, prog); + + old =3D xchg(&vport->xdp_prog, prog); + if (old) + bpf_prog_put(old); + + cfg->user_config.xdp_prog =3D prog; + + return 0; + } + + if (!vport->num_xdp_txq && vport->num_txq =3D=3D cfg->max_q.max_txq) { + NL_SET_ERR_MSG_MOD(xdp->extack, + "No Tx queues available for XDP, please decrease the number of regu= lar SQs"); + return -ENOSPC; + } + + old =3D cfg->user_config.xdp_prog; + cfg->user_config.xdp_prog =3D prog; + + ret =3D idpf_initiate_soft_reset(vport, IDPF_SR_Q_CHANGE); + if (ret) { + NL_SET_ERR_MSG_MOD(xdp->extack, + "Could not reopen the vport after XDP setup"); + + cfg->user_config.xdp_prog =3D old; + old =3D prog; + } + + if (old) + bpf_prog_put(old); + + return ret; +} + +int idpf_xdp(struct net_device *dev, struct netdev_bpf *xdp) +{ + struct idpf_vport *vport; + int ret; + + idpf_vport_ctrl_lock(dev); + vport =3D idpf_netdev_to_vport(dev); + + if (!idpf_is_queue_model_split(vport->txq_model)) + goto notsupp; + + switch (xdp->command) { + case XDP_SETUP_PROG: + ret =3D idpf_xdp_setup_prog(vport, xdp); + break; + default: +notsupp: + ret =3D -EOPNOTSUPP; + break; + } + + idpf_vport_ctrl_unlock(dev); + + return ret; +} --=20 2.50.1