get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/706702/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 706702,
    "url": "http://patchwork.ozlabs.org/api/patches/706702/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20161217134000.31640-3-bjorn.topel@gmail.com/",
    "project": {
        "id": 46,
        "url": "http://patchwork.ozlabs.org/api/projects/46/?format=api",
        "name": "Intel Wired Ethernet development",
        "link_name": "intel-wired-lan",
        "list_id": "intel-wired-lan.osuosl.org",
        "list_email": "intel-wired-lan@osuosl.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": "",
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<20161217134000.31640-3-bjorn.topel@gmail.com>",
    "list_archive_url": null,
    "date": "2016-12-17T13:39:58",
    "name": "[v4,2/4] i40e: Initial support for XDP",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": false,
    "hash": "e790820a438ca520c1601daa6539a238acc36189",
    "submitter": {
        "id": 70569,
        "url": "http://patchwork.ozlabs.org/api/people/70569/?format=api",
        "name": "Björn Töpel",
        "email": "bjorn.topel@gmail.com"
    },
    "delegate": {
        "id": 68,
        "url": "http://patchwork.ozlabs.org/api/users/68/?format=api",
        "username": "jtkirshe",
        "first_name": "Jeff",
        "last_name": "Kirsher",
        "email": "jeffrey.t.kirsher@intel.com"
    },
    "mbox": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20161217134000.31640-3-bjorn.topel@gmail.com/mbox/",
    "series": [],
    "comments": "http://patchwork.ozlabs.org/api/patches/706702/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/706702/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<intel-wired-lan-bounces@lists.osuosl.org>",
        "X-Original-To": [
            "incoming@patchwork.ozlabs.org",
            "intel-wired-lan@lists.osuosl.org"
        ],
        "Delivered-To": [
            "patchwork-incoming@bilbo.ozlabs.org",
            "intel-wired-lan@lists.osuosl.org"
        ],
        "Received": [
            "from whitealder.osuosl.org (smtp1.osuosl.org [140.211.166.138])\n\t(using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits))\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3tgpGL5z00z9t25\n\tfor <incoming@patchwork.ozlabs.org>;\n\tSun, 18 Dec 2016 00:40:26 +1100 (AEDT)",
            "from localhost (localhost [127.0.0.1])\n\tby whitealder.osuosl.org (Postfix) with ESMTP id 125C984D4A;\n\tSat, 17 Dec 2016 13:40:25 +0000 (UTC)",
            "from whitealder.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id h3OZfaKGFcMO; Sat, 17 Dec 2016 13:40:19 +0000 (UTC)",
            "from ash.osuosl.org (ash.osuosl.org [140.211.166.34])\n\tby whitealder.osuosl.org (Postfix) with ESMTP id CDD0684BF8;\n\tSat, 17 Dec 2016 13:40:18 +0000 (UTC)",
            "from fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137])\n\tby ash.osuosl.org (Postfix) with ESMTP id 190FD1C0F9B\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tSat, 17 Dec 2016 13:40:17 +0000 (UTC)",
            "from localhost (localhost [127.0.0.1])\n\tby fraxinus.osuosl.org (Postfix) with ESMTP id 1479B85BF0\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tSat, 17 Dec 2016 13:40:17 +0000 (UTC)",
            "from fraxinus.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id bBe1pkpQgqIq for <intel-wired-lan@lists.osuosl.org>;\n\tSat, 17 Dec 2016 13:40:16 +0000 (UTC)",
            "from mga04.intel.com (mga04.intel.com [192.55.52.120])\n\tby fraxinus.osuosl.org (Postfix) with ESMTPS id 49A5585A7C\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tSat, 17 Dec 2016 13:40:16 +0000 (UTC)",
            "from fmsmga001.fm.intel.com ([10.253.24.23])\n\tby fmsmga104.fm.intel.com with ESMTP; 17 Dec 2016 05:40:16 -0800",
            "from jabolger-mobl1.ger.corp.intel.com (HELO\n\tbtopel-mobl1.intel.com) ([10.252.31.3])\n\tby fmsmga001.fm.intel.com with ESMTP; 17 Dec 2016 05:40:13 -0800"
        ],
        "X-Virus-Scanned": [
            "amavisd-new at osuosl.org",
            "amavisd-new at osuosl.org"
        ],
        "X-Greylist": "from auto-whitelisted by SQLgrey-1.7.6",
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos; i=\"5.33,363,1477983600\"; d=\"scan'208\";\n\ta=\"1083168123\"",
        "From": "=?UTF-8?q?Bj=C3=B6rn=20T=C3=B6pel?= <bjorn.topel@gmail.com>",
        "To": "jeffrey.t.kirsher@intel.com,\n\tintel-wired-lan@lists.osuosl.org",
        "Date": "Sat, 17 Dec 2016 14:39:58 +0100",
        "Message-Id": "<20161217134000.31640-3-bjorn.topel@gmail.com>",
        "X-Mailer": "git-send-email 2.9.3",
        "In-Reply-To": "<20161217134000.31640-1-bjorn.topel@gmail.com>",
        "References": "<20161217134000.31640-1-bjorn.topel@gmail.com>",
        "MIME-Version": "1.0",
        "Cc": "daniel@iogearbox.net,\n\t=?UTF-8?q?Bj=C3=B6rn=20T=C3=B6pel?= <bjorn.topel@intel.com>,\n\tmagnus.karlsson@intel.com",
        "Subject": "[Intel-wired-lan] [PATCH v4 2/4] i40e: Initial support for XDP",
        "X-BeenThere": "intel-wired-lan@lists.osuosl.org",
        "X-Mailman-Version": "2.1.18-1",
        "Precedence": "list",
        "List-Id": "Intel Wired Ethernet Linux Kernel Driver Development\n\t<intel-wired-lan.lists.osuosl.org>",
        "List-Unsubscribe": "<http://lists.osuosl.org/mailman/options/intel-wired-lan>, \n\t<mailto:intel-wired-lan-request@lists.osuosl.org?subject=unsubscribe>",
        "List-Archive": "<http://lists.osuosl.org/pipermail/intel-wired-lan/>",
        "List-Post": "<mailto:intel-wired-lan@lists.osuosl.org>",
        "List-Help": "<mailto:intel-wired-lan-request@lists.osuosl.org?subject=help>",
        "List-Subscribe": "<http://lists.osuosl.org/mailman/listinfo/intel-wired-lan>, \n\t<mailto:intel-wired-lan-request@lists.osuosl.org?subject=subscribe>",
        "Content-Type": "text/plain; charset=\"utf-8\"",
        "Content-Transfer-Encoding": "base64",
        "Errors-To": "intel-wired-lan-bounces@lists.osuosl.org",
        "Sender": "\"Intel-wired-lan\" <intel-wired-lan-bounces@lists.osuosl.org>"
    },
    "content": "From: Björn Töpel <bjorn.topel@intel.com>\n\nThis commit adds basic XDP support for i40e derived NICs. All XDP\nactions will end up in XDP_DROP.\n\nOnly the default/main VSI has support for enabling XDP.\n\nSigned-off-by: Björn Töpel <bjorn.topel@intel.com>\n---\n drivers/net/ethernet/intel/i40e/i40e.h         |  13 +++\n drivers/net/ethernet/intel/i40e/i40e_ethtool.c |   4 +\n drivers/net/ethernet/intel/i40e/i40e_main.c    |  83 +++++++++++++++++\n drivers/net/ethernet/intel/i40e/i40e_txrx.c    | 124 +++++++++++++++++++++++--\n drivers/net/ethernet/intel/i40e/i40e_txrx.h    |   2 +\n 5 files changed, 220 insertions(+), 6 deletions(-)",
    "diff": "diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h\nindex 19a296d46023..5382d4782396 100644\n--- a/drivers/net/ethernet/intel/i40e/i40e.h\n+++ b/drivers/net/ethernet/intel/i40e/i40e.h\n@@ -589,6 +589,8 @@ struct i40e_vsi {\n \tstruct i40e_ring **rx_rings;\n \tstruct i40e_ring **tx_rings;\n \n+\tbool xdp_enabled;\n+\n \tu32  active_filters;\n \tu32  promisc_threshold;\n \n@@ -948,4 +950,15 @@ i40e_status i40e_get_npar_bw_setting(struct i40e_pf *pf);\n i40e_status i40e_set_npar_bw_setting(struct i40e_pf *pf);\n i40e_status i40e_commit_npar_bw_setting(struct i40e_pf *pf);\n void i40e_print_link_message(struct i40e_vsi *vsi, bool isup);\n+\n+/**\n+ * i40e_enabled_xdp_vsi - Check if VSI has XDP enabled\n+ * @vsi: pointer to a vsi\n+ *\n+ * Returns true if the VSI has XDP enabled.\n+ **/\n+static inline bool i40e_enabled_xdp_vsi(const struct i40e_vsi *vsi)\n+{\n+\treturn !!vsi->xdp_enabled;\n+}\n #endif /* _I40E_H_ */\ndiff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c\nindex dece0d676482..ccb3b77405d7 100644\n--- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c\n+++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c\n@@ -1257,6 +1257,10 @@ static int i40e_set_ringparam(struct net_device *netdev,\n \tif ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))\n \t\treturn -EINVAL;\n \n+\t/* Don't allow any change while XDP is enabled. */\n+\tif (i40e_enabled_xdp_vsi(vsi))\n+\t\treturn -EINVAL;\n+\n \tif (ring->tx_pending > I40E_MAX_NUM_DESCRIPTORS ||\n \t    ring->tx_pending < I40E_MIN_NUM_DESCRIPTORS ||\n \t    ring->rx_pending > I40E_MAX_NUM_DESCRIPTORS ||\ndiff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c\nindex 3f81a8503165..86bd2131d2bc 100644\n--- a/drivers/net/ethernet/intel/i40e/i40e_main.c\n+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c\n@@ -24,6 +24,7 @@\n  *\n  ******************************************************************************/\n \n+#include <linux/bpf.h>\n #include <linux/etherdevice.h>\n #include <linux/of_net.h>\n #include <linux/pci.h>\n@@ -2483,6 +2484,13 @@ static int i40e_change_mtu(struct net_device *netdev, int new_mtu)\n \tstruct i40e_netdev_priv *np = netdev_priv(netdev);\n \tstruct i40e_vsi *vsi = np->vsi;\n \n+\tif (i40e_enabled_xdp_vsi(vsi)) {\n+\t\tint max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;\n+\n+\t\tif (max_frame > I40E_RXBUFFER_2048)\n+\t\t\treturn -EINVAL;\n+\t}\n+\n \tnetdev_info(netdev, \"changing MTU from %d to %d\\n\",\n \t\t    netdev->mtu, new_mtu);\n \tnetdev->mtu = new_mtu;\n@@ -9341,6 +9349,78 @@ static netdev_features_t i40e_features_check(struct sk_buff *skb,\n \treturn features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);\n }\n \n+/**\n+ * i40e_xdp_setup - Add/remove an XDP program to a VSI\n+ * @vsi: the VSI to add the program\n+ * @prog: the XDP program\n+ **/\n+static int i40e_xdp_setup(struct i40e_vsi *vsi,\n+\t\t\t  struct bpf_prog *prog)\n+{\n+\tstruct i40e_pf *pf = vsi->back;\n+\tstruct net_device *netdev = vsi->netdev;\n+\tint i, frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;\n+\tbool need_reset;\n+\tstruct bpf_prog *old_prog;\n+\n+\t/* The Rx frame has to fit in 2k */\n+\tif (frame_size > I40E_RXBUFFER_2048)\n+\t\treturn -EINVAL;\n+\n+\tif (!i40e_enabled_xdp_vsi(vsi) && !prog)\n+\t\treturn 0;\n+\n+\tif (prog) {\n+\t\tprog = bpf_prog_add(prog, vsi->num_queue_pairs - 1);\n+\t\tif (IS_ERR(prog))\n+\t\t\treturn PTR_ERR(prog);\n+\t}\n+\n+\t/* When turning XDP on->off/off->on we reset and rebuild the rings. */\n+\tneed_reset = (i40e_enabled_xdp_vsi(vsi) != !!prog);\n+\n+\tif (need_reset)\n+\t\ti40e_prep_for_reset(pf);\n+\n+\tvsi->xdp_enabled = !!prog;\n+\n+\tif (need_reset)\n+\t\ti40e_reset_and_rebuild(pf, true);\n+\n+\tfor (i = 0; i < vsi->num_queue_pairs; i++) {\n+\t\told_prog = rtnl_dereference(vsi->rx_rings[i]->xdp_prog);\n+\t\trcu_assign_pointer(vsi->rx_rings[i]->xdp_prog, prog);\n+\t\tif (old_prog)\n+\t\t\tbpf_prog_put(old_prog);\n+\t}\n+\treturn 0;\n+}\n+\n+/**\n+ * i40e_xdp - NDO for enabled/query\n+ * @dev: the netdev\n+ * @xdp: XDP program\n+ **/\n+static int i40e_xdp(struct net_device *dev,\n+\t\t    struct netdev_xdp *xdp)\n+{\n+\tstruct i40e_netdev_priv *np = netdev_priv(dev);\n+\tstruct i40e_vsi *vsi = np->vsi;\n+\n+\tif (vsi->type != I40E_VSI_MAIN)\n+\t\treturn -EINVAL;\n+\n+\tswitch (xdp->command) {\n+\tcase XDP_SETUP_PROG:\n+\t\treturn i40e_xdp_setup(vsi, xdp->prog);\n+\tcase XDP_QUERY_PROG:\n+\t\txdp->prog_attached = i40e_enabled_xdp_vsi(vsi);\n+\t\treturn 0;\n+\tdefault:\n+\t\treturn -EINVAL;\n+\t}\n+}\n+\n static const struct net_device_ops i40e_netdev_ops = {\n \t.ndo_open\t\t= i40e_open,\n \t.ndo_stop\t\t= i40e_close,\n@@ -9377,6 +9457,7 @@ static const struct net_device_ops i40e_netdev_ops = {\n \t.ndo_features_check\t= i40e_features_check,\n \t.ndo_bridge_getlink\t= i40e_ndo_bridge_getlink,\n \t.ndo_bridge_setlink\t= i40e_ndo_bridge_setlink,\n+\t.ndo_xdp                = i40e_xdp,\n };\n \n /**\n@@ -11600,7 +11681,9 @@ static void i40e_remove(struct pci_dev *pdev)\n \t\tpf->flags &= ~I40E_FLAG_SRIOV_ENABLED;\n \t}\n \n+\trtnl_lock();\n \ti40e_fdir_teardown(pf);\n+\trtnl_unlock();\n \n \t/* If there is a switch structure or any orphans, remove them.\n \t * This will leave only the PF's VSI remaining.\ndiff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c\nindex 8bdc95c9e9b7..ad57c406c5f7 100644\n--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c\n+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c\n@@ -24,6 +24,7 @@\n  *\n  ******************************************************************************/\n \n+#include <linux/bpf.h>\n #include <linux/prefetch.h>\n #include <net/busy_poll.h>\n #include \"i40e.h\"\n@@ -1013,6 +1014,7 @@ void i40e_clean_rx_ring(struct i40e_ring *rx_ring)\n \tstruct device *dev = rx_ring->dev;\n \tunsigned long bi_size;\n \tu16 i;\n+\tstruct bpf_prog *old_prog;\n \n \t/* ring already cleared, nothing to do */\n \tif (!rx_ring->rx_bi)\n@@ -1046,6 +1048,11 @@ void i40e_clean_rx_ring(struct i40e_ring *rx_ring)\n \trx_ring->next_to_alloc = 0;\n \trx_ring->next_to_clean = 0;\n \trx_ring->next_to_use = 0;\n+\n+\told_prog = rtnl_dereference(rx_ring->xdp_prog);\n+\tRCU_INIT_POINTER(rx_ring->xdp_prog, NULL);\n+\tif (old_prog)\n+\t\tbpf_prog_put(old_prog);\n }\n \n /**\n@@ -1620,19 +1627,84 @@ static bool i40e_add_rx_frag(struct i40e_ring *rx_ring,\n }\n \n /**\n+ * i40e_run_xdp - Runs an XDP program for an Rx ring\n+ * @rx_ring: Rx ring used for XDP\n+ * @rx_buffer: current Rx buffer\n+ * @rx_desc: current Rx descriptor\n+ * @size: buffer size\n+ * @xdp_prog: the XDP program to run\n+ *\n+ * Returns true if the XDP program consumed the incoming frame. False\n+ * means pass the frame to the good old stack.\n+ **/\n+static bool i40e_run_xdp(struct i40e_ring *rx_ring,\n+\t\t\t struct i40e_rx_buffer *rx_buffer,\n+\t\t\t union i40e_rx_desc *rx_desc,\n+\t\t\t unsigned int size,\n+\t\t\t struct bpf_prog *xdp_prog)\n+{\n+\tstruct xdp_buff xdp;\n+\tu32 xdp_action;\n+\n+\tif (unlikely(!i40e_test_staterr(rx_desc,\n+\t\t\t\t\tBIT(I40E_RX_DESC_STATUS_EOF_SHIFT)))) {\n+\t\tdev_warn_once(&rx_ring->vsi->back->pdev->dev,\n+\t\t\t      \"Received unexpected RXD_EOF!\\n\");\n+\t\tgoto do_drop;\n+\t}\n+\n+\txdp.data = page_address(rx_buffer->page) + rx_buffer->page_offset;\n+\txdp.data_end = xdp.data + size;\n+\txdp.data_hard_start = xdp.data;\n+\txdp_action = bpf_prog_run_xdp(xdp_prog, &xdp);\n+\n+\tswitch (xdp_action) {\n+\tcase XDP_PASS:\n+\t\treturn false;\n+\tdefault:\n+\t\tbpf_warn_invalid_xdp_action(xdp_action);\n+\tcase XDP_ABORTED:\n+\tcase XDP_TX:\n+\tcase XDP_DROP:\n+do_drop:\n+\t\tif (likely(i40e_page_is_reusable(rx_buffer->page))) {\n+\t\t\ti40e_reuse_rx_page(rx_ring, rx_buffer);\n+\t\t\trx_ring->rx_stats.page_reuse_count++;\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\t/* we are not reusing the buffer so unmap it */\n+\t\tdma_unmap_page(rx_ring->dev, rx_buffer->dma, PAGE_SIZE,\n+\t\t\t       DMA_FROM_DEVICE);\n+\t\t__free_pages(rx_buffer->page, 0);\n+\t}\n+\n+\t/* clear contents of buffer_info */\n+\trx_buffer->page = NULL;\n+\treturn true; /* Swallowed by XDP */\n+}\n+\n+/**\n  * i40e_fetch_rx_buffer - Allocate skb and populate it\n  * @rx_ring: rx descriptor ring to transact packets on\n  * @rx_desc: descriptor containing info written by hardware\n+ * @skb: The allocated skb, if any\n+ * @xdp_consumed_bytes: The size of the frame consumed by XDP\n  *\n- * This function allocates an skb on the fly, and populates it with the page\n- * data from the current receive descriptor, taking care to set up the skb\n- * correctly, as well as handling calling the page recycle function if\n- * necessary.\n+ * Unless XDP is enabled, this function allocates an skb on the fly,\n+ * and populates it with the page data from the current receive\n+ * descriptor, taking care to set up the skb correctly, as well as\n+ * handling calling the page recycle function if necessary.\n+ *\n+ * If the received frame was handled by XDP, true is\n+ * returned. Otherwise, the skb is returned to the caller via the skb\n+ * parameter.\n  */\n static inline\n struct sk_buff *i40e_fetch_rx_buffer(struct i40e_ring *rx_ring,\n \t\t\t\t     union i40e_rx_desc *rx_desc,\n-\t\t\t\t     struct sk_buff *skb)\n+\t\t\t\t     struct sk_buff *skb,\n+\t\t\t\t     unsigned int *xdp_consumed_bytes)\n {\n \tu64 local_status_error_len =\n \t\tle64_to_cpu(rx_desc->wb.qword1.status_error_len);\n@@ -1641,6 +1713,7 @@ struct sk_buff *i40e_fetch_rx_buffer(struct i40e_ring *rx_ring,\n \t\tI40E_RXD_QW1_LENGTH_PBUF_SHIFT;\n \tstruct i40e_rx_buffer *rx_buffer;\n \tstruct page *page;\n+\tstruct bpf_prog *xdp_prog;\n \n \trx_buffer = &rx_ring->rx_bi[rx_ring->next_to_clean];\n \tpage = rx_buffer->page;\n@@ -1653,6 +1726,19 @@ struct sk_buff *i40e_fetch_rx_buffer(struct i40e_ring *rx_ring,\n \t\t\t\t      size,\n \t\t\t\t      DMA_FROM_DEVICE);\n \n+\trcu_read_lock();\n+\txdp_prog = rcu_dereference(rx_ring->xdp_prog);\n+\tif (xdp_prog) {\n+\t\tbool xdp_consumed = i40e_run_xdp(rx_ring, rx_buffer, rx_desc,\n+\t\t\t\t\t\t size, xdp_prog);\n+\t\tif (xdp_consumed) {\n+\t\t\trcu_read_unlock();\n+\t\t\t*xdp_consumed_bytes = size;\n+\t\t\treturn NULL;\n+\t\t}\n+\t}\n+\trcu_read_unlock();\n+\n \tif (likely(!skb)) {\n \t\tvoid *page_addr = page_address(page) + rx_buffer->page_offset;\n \n@@ -1734,6 +1820,20 @@ static bool i40e_is_non_eop(struct i40e_ring *rx_ring,\n }\n \n /**\n+ * i40e_update_rx_next_to_clean - Bumps the next-to-clean for an Rx ing\n+ * @rx_ring: Rx ring to bump\n+ **/\n+static void i40e_update_rx_next_to_clean(struct i40e_ring *rx_ring)\n+{\n+\tu32 ntc = rx_ring->next_to_clean + 1;\n+\n+\tntc = (ntc < rx_ring->count) ? ntc : 0;\n+\trx_ring->next_to_clean = ntc;\n+\n+\tprefetch(I40E_RX_DESC(rx_ring, ntc));\n+}\n+\n+/**\n  * i40e_clean_rx_irq - Clean completed descriptors from Rx ring - bounce buf\n  * @rx_ring: rx descriptor ring to transact packets on\n  * @budget: Total limit on number of packets to process\n@@ -1757,6 +1857,7 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)\n \t\tu16 vlan_tag;\n \t\tu8 rx_ptype;\n \t\tu64 qword;\n+\t\tunsigned int xdp_consumed_bytes = 0;\n \n \t\t/* return some buffers to hardware, one at a time is too slow */\n \t\tif (cleaned_count >= I40E_RX_BUFFER_WRITE) {\n@@ -1782,7 +1883,18 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)\n \t\t */\n \t\tdma_rmb();\n \n-\t\tskb = i40e_fetch_rx_buffer(rx_ring, rx_desc, skb);\n+\t\tskb = i40e_fetch_rx_buffer(rx_ring, rx_desc, skb,\n+\t\t\t\t\t   &xdp_consumed_bytes);\n+\t\tif (xdp_consumed_bytes) {\n+\t\t\tcleaned_count++;\n+\n+\t\t\ti40e_update_rx_next_to_clean(rx_ring);\n+\n+\t\t\ttotal_rx_bytes += xdp_consumed_bytes;\n+\t\t\ttotal_rx_packets++;\n+\t\t\tcontinue;\n+\t\t}\n+\n \t\tif (!skb)\n \t\t\tbreak;\n \ndiff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.h b/drivers/net/ethernet/intel/i40e/i40e_txrx.h\nindex f80979025c01..78d0aa0468f1 100644\n--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.h\n+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.h\n@@ -361,6 +361,8 @@ struct i40e_ring {\n \t\t\t\t\t * i40e_clean_rx_ring_irq() is called\n \t\t\t\t\t * for this ring.\n \t\t\t\t\t */\n+\n+\tstruct bpf_prog __rcu *xdp_prog;\n } ____cacheline_internodealigned_in_smp;\n \n enum i40e_latency_range {\n",
    "prefixes": [
        "v4",
        "2/4"
    ]
}