From nobody Sun Oct 5 20:01:12 2025 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.13]) (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 A26FF2DFA2E; Wed, 30 Jul 2025 16:08:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.13 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753891727; cv=none; b=cRl+1u+m3+lfQJFAGn7atC+fFQw6sic7PUH8HUBUJZnAtW6L5+iTf7Ue47tpdJ1MRu4CSM8r8oS02WZWAKWq3H0z447iuKHY56/yeHRuhR0FcAviiHVuN02ztBs9XGU9lFX5Ces7NO6Exr8OmRCEIFNH0jr7JAIU2uA0jmSoIHo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753891727; c=relaxed/simple; bh=FFMRYnND+ECyP4uiIkx6z0qhy+lLBOciiVJxoB54vgo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=gsNW7/0hB+k+UlSQbjKC+2JcYRMTubZlIL+lkvhBj/g+epwgWNFSdyCx+jEIyMYIO85c7Gj+Gpp1oVdFtyX7mUH21yw3lUTV77m6pYR1+mxecNrAZryYxhKaDjq+fVU1nVoMSC/MM5mchgDLAemyl0K3SAUh5sTLygQ7ZBWervk= 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=hCCZsEwV; arc=none smtp.client-ip=198.175.65.13 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="hCCZsEwV" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1753891726; x=1785427726; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=FFMRYnND+ECyP4uiIkx6z0qhy+lLBOciiVJxoB54vgo=; b=hCCZsEwVe03LhkLY8z9JgONAPFshcCwp0Gj06VD1awZa62sWlNx9Biz+ r1r42ejTd2DrOiKw1vs1fFqOpwzF1epay/uH3j63QFLGf6seg8ztOlcNs B+d7KCOS9mL9igsof9+syHLm3d1x+FvL1kecV1KzdB0gosf59Ga9EMDJM h/s2/h3sbuwUGVPAvQMetY2RwizFq+3a5c5hg4NSzpg1skN9mjbh8ALil +E90JOliXXATOMmhD41om6me9h/Omn4X4b227SUbPGT7k/OUTRPvk715l XlMfmM8kblf4YCFruAWmFEiUNlrtk5sqyPMT18txxGf/aT1xmcuu/5W+m Q==; X-CSE-ConnectionGUID: /ZDYyZwYT1aRvGwr3fqBeg== X-CSE-MsgGUID: po0iTNp3TryfVU1AI6V1/Q== X-IronPort-AV: E=McAfee;i="6800,10657,11507"; a="67278943" X-IronPort-AV: E=Sophos;i="6.16,350,1744095600"; d="scan'208";a="67278943" Received: from fmviesa010.fm.intel.com ([10.60.135.150]) by orvoesa105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 30 Jul 2025 09:08:45 -0700 X-CSE-ConnectionGUID: 0DSRrxDtSeKFQTGs6rYgiQ== X-CSE-MsgGUID: wQeprawaSaOcsFeF6DxqBw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.16,350,1744095600"; d="scan'208";a="163813017" Received: from newjersey.igk.intel.com ([10.102.20.203]) by fmviesa010.fm.intel.com with ESMTP; 30 Jul 2025 09:08:41 -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 v3 14/18] idpf: implement XDP_SETUP_PROG in ndo_bpf for splitq Date: Wed, 30 Jul 2025 18:07:13 +0200 Message-ID: <20250730160717.28976-15-aleksander.lobakin@intel.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20250730160717.28976-1-aleksander.lobakin@intel.com> References: <20250730160717.28976-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 e0ceb791f5c2..8f2ea790fdf3 100644 --- a/drivers/net/ethernet/intel/idpf/idpf_lib.c +++ b/drivers/net/ethernet/intel/idpf/idpf_lib.c @@ -2521,4 +2521,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 0ef35be0421a..385aa769d85e 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