Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/2165660/?format=api
{ "id": 2165660, "url": "http://patchwork.ozlabs.org/api/patches/2165660/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20251117134912.18566-6-larysa.zaremba@intel.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": "<20251117134912.18566-6-larysa.zaremba@intel.com>", "list_archive_url": null, "date": "2025-11-17T13:48:45", "name": "[iwl-next,v5,05/15] libie: add control queue support", "commit_ref": null, "pull_url": null, "state": "under-review", "archived": false, "hash": "fd7a5073d6d566aa46d6df55dd734b81e09b90d0", "submitter": { "id": 84900, "url": "http://patchwork.ozlabs.org/api/people/84900/?format=api", "name": "Larysa Zaremba", "email": "larysa.zaremba@intel.com" }, "delegate": { "id": 109701, "url": "http://patchwork.ozlabs.org/api/users/109701/?format=api", "username": "anguy11", "first_name": "Anthony", "last_name": "Nguyen", "email": "anthony.l.nguyen@intel.com" }, "mbox": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20251117134912.18566-6-larysa.zaremba@intel.com/mbox/", "series": [ { "id": 482391, "url": "http://patchwork.ozlabs.org/api/series/482391/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/list/?series=482391", "date": "2025-11-17T13:48:40", "name": "Introduce iXD driver", "version": 5, "mbox": "http://patchwork.ozlabs.org/series/482391/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2165660/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2165660/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<intel-wired-lan-bounces@osuosl.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "intel-wired-lan@lists.osuosl.org" ], "Delivered-To": [ "patchwork-incoming@legolas.ozlabs.org", "intel-wired-lan@lists.osuosl.org" ], "Authentication-Results": [ "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=osuosl.org header.i=@osuosl.org header.a=rsa-sha256\n header.s=default header.b=3bgCC5Ae;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=osuosl.org\n (client-ip=2605:bc80:3010::136; helo=smtp3.osuosl.org;\n envelope-from=intel-wired-lan-bounces@osuosl.org;\n receiver=patchwork.ozlabs.org)" ], "Received": [ "from smtp3.osuosl.org (smtp3.osuosl.org [IPv6:2605:bc80:3010::136])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4d98Hh56njz1yHt\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 18 Nov 2025 00:49:36 +1100 (AEDT)", "from localhost (localhost [127.0.0.1])\n\tby smtp3.osuosl.org (Postfix) with ESMTP id 466726086F;\n\tMon, 17 Nov 2025 13:49:35 +0000 (UTC)", "from smtp3.osuosl.org ([127.0.0.1])\n by localhost (smtp3.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id 8ZZlOsxuGHIl; Mon, 17 Nov 2025 13:49:33 +0000 (UTC)", "from lists1.osuosl.org (lists1.osuosl.org [140.211.166.142])\n\tby smtp3.osuosl.org (Postfix) with ESMTP id BF9D060DA1;\n\tMon, 17 Nov 2025 13:49:33 +0000 (UTC)", "from smtp3.osuosl.org (smtp3.osuosl.org [IPv6:2605:bc80:3010::136])\n by lists1.osuosl.org (Postfix) with ESMTP id 549AFD5\n for <intel-wired-lan@lists.osuosl.org>; Mon, 17 Nov 2025 13:49:32 +0000 (UTC)", "from localhost (localhost [127.0.0.1])\n by smtp3.osuosl.org (Postfix) with ESMTP id 3B1BD60DB0\n for <intel-wired-lan@lists.osuosl.org>; Mon, 17 Nov 2025 13:49:32 +0000 (UTC)", "from smtp3.osuosl.org ([127.0.0.1])\n by localhost (smtp3.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id L92QLl1yHztm for <intel-wired-lan@lists.osuosl.org>;\n Mon, 17 Nov 2025 13:49:31 +0000 (UTC)", "from mgamail.intel.com (mgamail.intel.com [198.175.65.12])\n by smtp3.osuosl.org (Postfix) with ESMTPS id CA34460DA3\n for <intel-wired-lan@lists.osuosl.org>; Mon, 17 Nov 2025 13:49:30 +0000 (UTC)", "from fmviesa007.fm.intel.com ([10.60.135.147])\n by orvoesa104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 17 Nov 2025 05:49:30 -0800", "from irvmail002.ir.intel.com ([10.43.11.120])\n by fmviesa007.fm.intel.com with ESMTP; 17 Nov 2025 05:49:24 -0800", "from mglak.igk.intel.com (mglak.igk.intel.com [10.237.112.146])\n by irvmail002.ir.intel.com (Postfix) with ESMTP id B1CAB37E27;\n Mon, 17 Nov 2025 13:49:21 +0000 (GMT)" ], "X-Virus-Scanned": [ "amavis at osuosl.org", "amavis at osuosl.org" ], "X-Comment": "SPF check N/A for local connections - client-ip=140.211.166.142;\n helo=lists1.osuosl.org; envelope-from=intel-wired-lan-bounces@osuosl.org;\n receiver=<UNKNOWN> ", "DKIM-Filter": [ "OpenDKIM Filter v2.11.0 smtp3.osuosl.org BF9D060DA1", "OpenDKIM Filter v2.11.0 smtp3.osuosl.org CA34460DA3" ], "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=osuosl.org;\n\ts=default; t=1763387373;\n\tbh=olLCLoM3SLCXiNZpxpzHOcj2RCqKmaacruEw10sona8=;\n\th=From:To:Cc:Date:In-Reply-To:References:Subject:List-Id:\n\t List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe:\n\t From;\n\tb=3bgCC5Ae1TK8vBYsUssCPIsNmojumB5SnLgeRFs/5DK2Rf6aDg0UuMGauImt+oWFP\n\t cBTY+QJhDr+vkCWLpjrlJbrfXe2p1bM6uckbulwTUM9ZqmGo8ePi8hDz1ONrpCFf7o\n\t px4ilTVbQnENi0iltTFF+6icImF3HWJUPp3aX5kR4Zqfs7fU6EPLF14kDkpzqCoJG1\n\t r0q1xpq98AFi7n/V8nHPj7Zi1Qf0xSLoL/+TKhKnuuD98CkCdw6cWPKolN0QROe59w\n\t ph9DFYm1fCqhYlADvTaZ2JHZSPTYgF3mY7NM+SwnEWyc+ERFPQIFGtCshA3giZ44VB\n\t zoLoIFfeWHykQ==", "Received-SPF": "Pass (mailfrom) identity=mailfrom; client-ip=198.175.65.12;\n helo=mgamail.intel.com; envelope-from=larysa.zaremba@intel.com;\n receiver=<UNKNOWN>", "DMARC-Filter": "OpenDMARC Filter v1.4.2 smtp3.osuosl.org CA34460DA3", "X-CSE-ConnectionGUID": [ "ZofhRGDnTNudt5jSIZ6fwQ==", "wrgJ59puSCm/gsDGSpuo4g==" ], "X-CSE-MsgGUID": [ "TTtlBUbNSeSI4/MCPCkMUA==", "zu278t4WQ66B0AE9/dT7oQ==" ], "X-IronPort-AV": [ "E=McAfee;i=\"6800,10657,11616\"; a=\"76846087\"", "E=Sophos;i=\"6.19,311,1754982000\"; d=\"scan'208\";a=\"76846087\"", "E=Sophos;i=\"6.19,311,1754982000\"; d=\"scan'208\";a=\"190115713\"" ], "X-ExtLoop1": "1", "From": "Larysa Zaremba <larysa.zaremba@intel.com>", "To": "intel-wired-lan@lists.osuosl.org, Tony Nguyen <anthony.l.nguyen@intel.com>", "Cc": "aleksander.lobakin@intel.com, sridhar.samudrala@intel.com,\n \"Singhai, Anjali\" <anjali.singhai@intel.com>,\n Michal Swiatkowski <michal.swiatkowski@linux.intel.com>,\n Larysa Zaremba <larysa.zaremba@intel.com>,\n \"Fijalkowski, Maciej\" <maciej.fijalkowski@intel.com>,\n Emil Tantilov <emil.s.tantilov@intel.com>,\n Madhu Chittim <madhu.chittim@intel.com>, Josh Hay <joshua.a.hay@intel.com>,\n \"Keller, Jacob E\" <jacob.e.keller@intel.com>,\n jayaprakash.shanmugam@intel.com, natalia.wochtman@intel.com,\n Jiri Pirko <jiri@resnulli.us>, \"David S. Miller\" <davem@davemloft.net>,\n Eric Dumazet <edumazet@google.com>, Jakub Kicinski <kuba@kernel.org>,\n Paolo Abeni <pabeni@redhat.com>, Simon Horman <horms@kernel.org>,\n Jonathan Corbet <corbet@lwn.net>,\n Richard Cochran <richardcochran@gmail.com>,\n Przemek Kitszel <przemyslaw.kitszel@intel.com>,\n Andrew Lunn <andrew+netdev@lunn.ch>, netdev@vger.kernel.org,\n linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,\n Phani R Burra <phani.r.burra@intel.com>", "Date": "Mon, 17 Nov 2025 14:48:45 +0100", "Message-ID": "<20251117134912.18566-6-larysa.zaremba@intel.com>", "X-Mailer": "git-send-email 2.47.0", "In-Reply-To": "<20251117134912.18566-1-larysa.zaremba@intel.com>", "References": "<20251117134912.18566-1-larysa.zaremba@intel.com>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "X-Mailman-Original-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple;\n d=intel.com; i=@intel.com; q=dns/txt; s=Intel;\n t=1763387371; x=1794923371;\n h=from:to:cc:subject:date:message-id:in-reply-to:\n references:mime-version:content-transfer-encoding;\n bh=rARkSauCbX7Bg6h+t/v2Z6tk0sBP5nE+2SO88Aw5ftg=;\n b=FK68WPD5Mg7VUJF0OtG9nkOUKl1uZGR5TFXTKkHhAmvWoz+rOrHDf+8a\n tE+YTen/7bh8nqKC1KNSsgHbyAwBd0MRDUbILPl6NkaDq4HJ9E7Sw0EWm\n nfPp2UjK22+O1U0vdTiVPfA54L3aJb9SDVsJwvlYOZHrRA8bPDpECRUsI\n ZH/54KJHa9vO1ff/a9PDElSDscQjc1UMgmtjXsB1eEWg6Nh5rFXJxPmbF\n 5RvJIMufIqI6Ajs5XTehIWq+VAaHrEQ95famOFpxc74UmLyrxOQKWH2ik\n yEvM6OWcA/i3XvEo5QfKzkeJRIhSMWEokMw7uQ7HuIYO1kZTONjetg4ur\n A==;", "X-Mailman-Original-Authentication-Results": [ "smtp3.osuosl.org;\n dmarc=pass (p=none dis=none)\n header.from=intel.com", "smtp3.osuosl.org;\n dkim=pass (2048-bit key,\n unprotected) header.d=intel.com header.i=@intel.com header.a=rsa-sha256\n header.s=Intel header.b=FK68WPD5" ], "Subject": "[Intel-wired-lan] [PATCH iwl-next v5 05/15] libie: add control\n queue support", "X-BeenThere": "intel-wired-lan@osuosl.org", "X-Mailman-Version": "2.1.30", "Precedence": "list", "List-Id": "Intel Wired Ethernet Linux Kernel Driver Development\n <intel-wired-lan.osuosl.org>", "List-Unsubscribe": "<https://lists.osuosl.org/mailman/options/intel-wired-lan>,\n <mailto:intel-wired-lan-request@osuosl.org?subject=unsubscribe>", "List-Archive": "<http://lists.osuosl.org/pipermail/intel-wired-lan/>", "List-Post": "<mailto:intel-wired-lan@osuosl.org>", "List-Help": "<mailto:intel-wired-lan-request@osuosl.org?subject=help>", "List-Subscribe": "<https://lists.osuosl.org/mailman/listinfo/intel-wired-lan>,\n <mailto:intel-wired-lan-request@osuosl.org?subject=subscribe>", "Errors-To": "intel-wired-lan-bounces@osuosl.org", "Sender": "\"Intel-wired-lan\" <intel-wired-lan-bounces@osuosl.org>" }, "content": "From: Phani R Burra <phani.r.burra@intel.com>\n\nLibie will now support control queue setup and configuration APIs. These\nare mainly used for mailbox communication between drivers and control\nplane.\n\nMake use of the libeth_rx page pool support for managing controlq buffers.\n\nReviewed-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>\nSigned-off-by: Phani R Burra <phani.r.burra@intel.com>\nCo-developed-by: Victor Raj <victor.raj@intel.com>\nSigned-off-by: Victor Raj <victor.raj@intel.com>\nCo-developed-by: Sridhar Samudrala <sridhar.samudrala@intel.com>\nSigned-off-by: Sridhar Samudrala <sridhar.samudrala@intel.com>\nCo-developed-by: Pavan Kumar Linga <pavan.kumar.linga@intel.com>\nSigned-off-by: Pavan Kumar Linga <pavan.kumar.linga@intel.com>\nCo-developed-by: Larysa Zaremba <larysa.zaremba@intel.com>\nSigned-off-by: Larysa Zaremba <larysa.zaremba@intel.com>\n---\n drivers/net/ethernet/intel/libie/Kconfig | 8 +\n drivers/net/ethernet/intel/libie/Makefile | 4 +\n drivers/net/ethernet/intel/libie/controlq.c | 607 ++++++++++++++++++++\n include/linux/intel/libie/controlq.h | 249 ++++++++\n 4 files changed, 868 insertions(+)\n create mode 100644 drivers/net/ethernet/intel/libie/controlq.c\n create mode 100644 include/linux/intel/libie/controlq.h", "diff": "diff --git a/drivers/net/ethernet/intel/libie/Kconfig b/drivers/net/ethernet/intel/libie/Kconfig\nindex 500a95c944a8..9c5fdebb6766 100644\n--- a/drivers/net/ethernet/intel/libie/Kconfig\n+++ b/drivers/net/ethernet/intel/libie/Kconfig\n@@ -15,6 +15,14 @@ config LIBIE_ADMINQ\n \t Helper functions used by Intel Ethernet drivers for administration\n \t queue command interface (aka adminq).\n \n+config LIBIE_CP\n+\ttristate\n+\tselect LIBETH\n+\tselect LIBIE_PCI\n+\thelp\n+\t Common helper routines to communicate with the device Control Plane\n+\t using virtchnl2 or related mailbox protocols.\n+\n config LIBIE_FWLOG\n \ttristate\n \tselect LIBIE_ADMINQ\ndiff --git a/drivers/net/ethernet/intel/libie/Makefile b/drivers/net/ethernet/intel/libie/Makefile\nindex a28509cb9086..3065aa057798 100644\n--- a/drivers/net/ethernet/intel/libie/Makefile\n+++ b/drivers/net/ethernet/intel/libie/Makefile\n@@ -9,6 +9,10 @@ obj-$(CONFIG_LIBIE_ADMINQ) \t+= libie_adminq.o\n \n libie_adminq-y\t\t\t:= adminq.o\n \n+obj-$(CONFIG_LIBIE_CP)\t\t+= libie_cp.o\n+\n+libie_cp-y\t\t\t:= controlq.o\n+\n obj-$(CONFIG_LIBIE_FWLOG) \t+= libie_fwlog.o\n \n libie_fwlog-y\t\t\t:= fwlog.o\ndiff --git a/drivers/net/ethernet/intel/libie/controlq.c b/drivers/net/ethernet/intel/libie/controlq.c\nnew file mode 100644\nindex 000000000000..80b0f1c2cc0a\n--- /dev/null\n+++ b/drivers/net/ethernet/intel/libie/controlq.c\n@@ -0,0 +1,607 @@\n+// SPDX-License-Identifier: GPL-2.0-only\n+/* Copyright (C) 2025 Intel Corporation */\n+\n+#include <linux/bitfield.h>\n+#include <net/libeth/rx.h>\n+\n+#include <linux/intel/libie/controlq.h>\n+\n+#define LIBIE_CTLQ_DESC_QWORD0(sz)\t\t\t\\\n+\t(LIBIE_CTLQ_DESC_FLAG_BUF |\t\t\t\\\n+\t LIBIE_CTLQ_DESC_FLAG_RD |\t\t\t\\\n+\t FIELD_PREP(LIBIE_CTLQ_DESC_DATA_LEN, sz))\n+\n+/**\n+ * libie_ctlq_free_fq - free fill queue resources, including buffers\n+ * @ctlq: Rx control queue whose resources need to be freed\n+ */\n+static void libie_ctlq_free_fq(struct libie_ctlq_info *ctlq)\n+{\n+\tstruct libeth_fq fq = {\n+\t\t.fqes\t\t= ctlq->rx_fqes,\n+\t\t.pp\t\t= ctlq->pp,\n+\t};\n+\n+\tfor (u32 ntc = ctlq->next_to_clean; ntc != ctlq->next_to_post; ) {\n+\t\tpage_pool_put_full_netmem(fq.pp, fq.fqes[ntc].netmem, false);\n+\n+\t\tif (++ntc >= ctlq->ring_len)\n+\t\t\tntc = 0;\n+\t}\n+\n+\tlibeth_rx_fq_destroy(&fq);\n+}\n+\n+/**\n+ * libie_ctlq_init_fq - initialize fill queue for an Rx controlq\n+ * @ctlq: control queue that needs a Rx buffer allocation\n+ *\n+ * Return: %0 on success, -%errno on failure\n+ */\n+static int libie_ctlq_init_fq(struct libie_ctlq_info *ctlq)\n+{\n+\tstruct libeth_fq fq = {\n+\t\t.count\t\t= ctlq->ring_len,\n+\t\t.truesize\t= LIBIE_CTLQ_MAX_BUF_LEN,\n+\t\t.nid\t\t= NUMA_NO_NODE,\n+\t\t.type\t\t= LIBETH_FQE_SHORT,\n+\t\t.hsplit\t\t= true,\n+\t\t.no_napi\t= true,\n+\t};\n+\tint err;\n+\n+\terr = libeth_rx_fq_create(&fq, ctlq->dev);\n+\tif (err)\n+\t\treturn err;\n+\n+\tctlq->pp = fq.pp;\n+\tctlq->rx_fqes = fq.fqes;\n+\tctlq->truesize = fq.truesize;\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * libie_ctlq_reset_rx_desc - reset the descriptor with a new address\n+ * @desc: descriptor to (re)initialize\n+ * @addr: physical address to put into descriptor\n+ * @mem_truesize: size of the accessible memory\n+ */\n+static void libie_ctlq_reset_rx_desc(struct libie_ctlq_desc *desc,\n+\t\t\t\t dma_addr_t addr, u32 mem_truesize)\n+{\n+\tu64 qword;\n+\n+\t*desc = (struct libie_ctlq_desc) {};\n+\tqword = LIBIE_CTLQ_DESC_QWORD0(mem_truesize);\n+\tdesc->qword0 = cpu_to_le64(qword);\n+\n+\tqword = FIELD_PREP(LIBIE_CTLQ_DESC_DATA_ADDR_HIGH,\n+\t\t\t upper_32_bits(addr)) |\n+\t\tFIELD_PREP(LIBIE_CTLQ_DESC_DATA_ADDR_LOW,\n+\t\t\t lower_32_bits(addr));\n+\tdesc->qword3 = cpu_to_le64(qword);\n+}\n+\n+/**\n+ * libie_ctlq_post_rx_buffs - post buffers to descriptor ring\n+ * @ctlq: control queue that requires Rx descriptor ring to be initialized with\n+ *\t new Rx buffers\n+ *\n+ * The caller must make sure that calls to libie_ctlq_post_rx_buffs()\n+ * and libie_ctlq_recv() for separate queues are either serialized\n+ * or used under ctlq->lock.\n+ *\n+ * Return: %0 on success, -%ENOMEM if any buffer could not be allocated\n+ */\n+int libie_ctlq_post_rx_buffs(struct libie_ctlq_info *ctlq)\n+{\n+\tu32 ntp = ctlq->next_to_post, ntc = ctlq->next_to_clean, num_to_post;\n+\tconst struct libeth_fq_fp fq = {\n+\t\t.pp\t\t= ctlq->pp,\n+\t\t.fqes\t\t= ctlq->rx_fqes,\n+\t\t.truesize\t= ctlq->truesize,\n+\t\t.count\t\t= ctlq->ring_len,\n+\t};\n+\tint ret = 0;\n+\n+\tnum_to_post = (ntc > ntp ? 0 : ctlq->ring_len) + ntc - ntp - 1;\n+\n+\twhile (num_to_post--) {\n+\t\tdma_addr_t addr;\n+\n+\t\taddr = libeth_rx_alloc(&fq, ntp);\n+\t\tif (unlikely(addr == DMA_MAPPING_ERROR)) {\n+\t\t\tret = -ENOMEM;\n+\t\t\tgoto post_bufs;\n+\t\t}\n+\n+\t\tlibie_ctlq_reset_rx_desc(&ctlq->descs[ntp], addr, fq.truesize);\n+\n+\t\tif (unlikely(++ntp == ctlq->ring_len))\n+\t\t\tntp = 0;\n+\t}\n+\n+post_bufs:\n+\tif (likely(ctlq->next_to_post != ntp)) {\n+\t\tctlq->next_to_post = ntp;\n+\n+\t\twritel(ntp, ctlq->reg.tail);\n+\t}\n+\n+\treturn ret;\n+}\n+EXPORT_SYMBOL_NS_GPL(libie_ctlq_post_rx_buffs, \"LIBIE_CP\");\n+\n+/**\n+ * libie_ctlq_free_tx_msgs - Free Tx control queue messages\n+ * @ctlq: Tx control queue being destroyed\n+ * @num_msgs: number of messages allocated so far\n+ */\n+static void libie_ctlq_free_tx_msgs(struct libie_ctlq_info *ctlq,\n+\t\t\t\t u32 num_msgs)\n+{\n+\tfor (u32 i = 0; i < num_msgs; i++)\n+\t\tkfree(ctlq->tx_msg[i]);\n+\n+\tkvfree(ctlq->tx_msg);\n+}\n+\n+/**\n+ * libie_ctlq_alloc_tx_msgs - Allocate Tx control queue messages\n+ * @ctlq: Tx control queue being created\n+ *\n+ * Return: %0 on success, -%ENOMEM on allocation error\n+ */\n+static int libie_ctlq_alloc_tx_msgs(struct libie_ctlq_info *ctlq)\n+{\n+\tctlq->tx_msg = kvcalloc(ctlq->ring_len,\n+\t\t\t\tsizeof(*ctlq->tx_msg), GFP_KERNEL);\n+\tif (!ctlq->tx_msg)\n+\t\treturn -ENOMEM;\n+\n+\tfor (u32 i = 0; i < ctlq->ring_len; i++) {\n+\t\tctlq->tx_msg[i] = kzalloc(sizeof(*ctlq->tx_msg[i]), GFP_KERNEL);\n+\n+\t\tif (!ctlq->tx_msg[i]) {\n+\t\t\tlibie_ctlq_free_tx_msgs(ctlq, i);\n+\t\t\treturn -ENOMEM;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * libie_cp_free_dma_mem - Free the previously allocated DMA memory\n+ * @dev: device information\n+ * @mem: DMA memory information\n+ */\n+static void libie_cp_free_dma_mem(struct device *dev,\n+\t\t\t\t struct libie_cp_dma_mem *mem)\n+{\n+\tdma_free_coherent(dev, mem->size, mem->va, mem->pa);\n+\tmem->va = NULL;\n+}\n+\n+/**\n+ * libie_ctlq_dealloc_ring_res - Free memory allocated for control queue\n+ * @ctlq: control queue that requires its ring memory to be freed\n+ *\n+ * Free the memory used by the ring, buffers and other related structures.\n+ */\n+static void libie_ctlq_dealloc_ring_res(struct libie_ctlq_info *ctlq)\n+{\n+\tstruct libie_cp_dma_mem *dma = &ctlq->ring_mem;\n+\n+\tif (ctlq->type == LIBIE_CTLQ_TYPE_TX)\n+\t\tlibie_ctlq_free_tx_msgs(ctlq, ctlq->ring_len);\n+\telse\n+\t\tlibie_ctlq_free_fq(ctlq);\n+\n+\tlibie_cp_free_dma_mem(ctlq->dev, dma);\n+}\n+\n+/**\n+ * libie_cp_alloc_dma_mem - Allocate a DMA memory\n+ * @dev: device information\n+ * @mem: memory for DMA information to be stored\n+ * @size: size of the memory to allocate\n+ *\n+ * Return: virtual address of DMA memory or NULL.\n+ */\n+static void *libie_cp_alloc_dma_mem(struct device *dev,\n+\t\t\t\t struct libie_cp_dma_mem *mem, u32 size)\n+{\n+\tsize = ALIGN(size, SZ_4K);\n+\n+\tmem->va = dma_alloc_coherent(dev, size, &mem->pa, GFP_KERNEL);\n+\tmem->size = size;\n+\n+\treturn mem->va;\n+}\n+\n+/**\n+ * libie_ctlq_alloc_queue_res - allocate memory for descriptor ring and bufs\n+ * @ctlq: control queue that requires its ring resources to be allocated\n+ *\n+ * Return: %0 on success, -%errno on failure\n+ */\n+static int libie_ctlq_alloc_queue_res(struct libie_ctlq_info *ctlq)\n+{\n+\tsize_t size = array_size(ctlq->ring_len, sizeof(*ctlq->descs));\n+\tstruct libie_cp_dma_mem *dma = &ctlq->ring_mem;\n+\tint err = -ENOMEM;\n+\n+\tif (!libie_cp_alloc_dma_mem(ctlq->dev, dma, size))\n+\t\treturn -ENOMEM;\n+\n+\tctlq->descs = dma->va;\n+\n+\tif (ctlq->type == LIBIE_CTLQ_TYPE_TX) {\n+\t\tif (libie_ctlq_alloc_tx_msgs(ctlq))\n+\t\t\tgoto free_dma_mem;\n+\t} else {\n+\t\terr = libie_ctlq_init_fq(ctlq);\n+\t\tif (err)\n+\t\t\tgoto free_dma_mem;\n+\n+\t\terr = libie_ctlq_post_rx_buffs(ctlq);\n+\t\tif (err) {\n+\t\t\tlibie_ctlq_free_fq(ctlq);\n+\t\t\tgoto free_dma_mem;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+\n+free_dma_mem:\n+\tlibie_cp_free_dma_mem(ctlq->dev, dma);\n+\n+\treturn err;\n+}\n+\n+/**\n+ * libie_ctlq_init_regs - Initialize control queue registers\n+ * @ctlq: control queue that needs to be initialized\n+ *\n+ * Initialize registers. The caller is expected to have already initialized the\n+ * descriptor ring memory and buffer memory.\n+ */\n+static void libie_ctlq_init_regs(struct libie_ctlq_info *ctlq)\n+{\n+\tu32 dword;\n+\n+\tif (ctlq->type == VIRTCHNL2_QUEUE_TYPE_RX)\n+\t\twritel(ctlq->ring_len - 1, ctlq->reg.tail);\n+\n+\twritel(0, ctlq->reg.head);\n+\twritel(lower_32_bits(ctlq->ring_mem.pa), ctlq->reg.addr_low);\n+\twritel(upper_32_bits(ctlq->ring_mem.pa), ctlq->reg.addr_high);\n+\n+\tdword = FIELD_PREP(LIBIE_CTLQ_MBX_ATQ_LEN, ctlq->ring_len) |\n+\t\tctlq->reg.len_ena_mask;\n+\twritel(dword, ctlq->reg.len);\n+}\n+\n+/**\n+ * libie_find_ctlq - find the controlq for the given id and type\n+ * @ctx: controlq context structure\n+ * @type: type of controlq to find\n+ * @id: controlq id to find\n+ *\n+ * Return: control queue info pointer on success, NULL on failure\n+ */\n+struct libie_ctlq_info *libie_find_ctlq(struct libie_ctlq_ctx *ctx,\n+\t\t\t\t\tenum virtchnl2_queue_type type,\n+\t\t\t\t\t int id)\n+{\n+\tstruct libie_ctlq_info *cq;\n+\n+\tguard(spinlock)(&ctx->ctlqs_lock);\n+\n+\tlist_for_each_entry(cq, &ctx->ctlqs, list)\n+\t\tif (cq->qid == id && cq->type == type)\n+\t\t\treturn cq;\n+\n+\treturn NULL;\n+}\n+EXPORT_SYMBOL_NS_GPL(libie_find_ctlq, \"LIBIE_CP\");\n+\n+/**\n+ * libie_ctlq_add - add one control queue\n+ * @ctx: controlq context information\n+ * @qinfo: information that requires for queue creation\n+ *\n+ * Allocate and initialize a control queue and add it to the control queue list.\n+ * The ctlq parameter will be allocated/initialized and passed back to the\n+ * caller if no errors occur.\n+ *\n+ * Note: libie_ctlq_init must be called prior to any calls to libie_ctlq_add.\n+ *\n+ * Return: added control queue info pointer on success, error pointer on failure\n+ */\n+static struct libie_ctlq_info *\n+libie_ctlq_add(struct libie_ctlq_ctx *ctx,\n+\t const struct libie_ctlq_create_info *qinfo)\n+{\n+\tstruct libie_ctlq_info *ctlq;\n+\n+\tif (qinfo->id != LIBIE_CTLQ_MBX_ID)\n+\t\treturn ERR_PTR(-EOPNOTSUPP);\n+\n+\t/* libie_ctlq_init was not called */\n+\tscoped_guard(spinlock, &ctx->ctlqs_lock)\n+\t\tif (!ctx->ctlqs.next)\n+\t\t\treturn ERR_PTR(-EINVAL);\n+\n+\tctlq = kvzalloc(sizeof(*ctlq), GFP_KERNEL);\n+\tif (!ctlq)\n+\t\treturn ERR_PTR(-ENOMEM);\n+\n+\tctlq->type = qinfo->type;\n+\tctlq->qid = qinfo->id;\n+\tctlq->ring_len = qinfo->len;\n+\tctlq->dev = &ctx->mmio_info.pdev->dev;\n+\tctlq->reg = qinfo->reg;\n+\n+\tif (libie_ctlq_alloc_queue_res(ctlq)) {\n+\t\tkvfree(ctlq);\n+\t\treturn ERR_PTR(-ENOMEM);\n+\t}\n+\n+\tlibie_ctlq_init_regs(ctlq);\n+\n+\tspin_lock_init(&ctlq->lock);\n+\n+\tscoped_guard(spinlock, &ctx->ctlqs_lock)\n+\t\tlist_add(&ctlq->list, &ctx->ctlqs);\n+\n+\treturn ctlq;\n+}\n+\n+/**\n+ * libie_ctlq_remove - deallocate and remove specified control queue\n+ * @ctx: libie context information\n+ * @ctlq: specific control queue that needs to be removed\n+ */\n+static void libie_ctlq_remove(struct libie_ctlq_ctx *ctx,\n+\t\t\t struct libie_ctlq_info *ctlq)\n+{\n+\tscoped_guard(spinlock, &ctx->ctlqs_lock)\n+\t\tlist_del(&ctlq->list);\n+\n+\tlibie_ctlq_dealloc_ring_res(ctlq);\n+\tkvfree(ctlq);\n+}\n+\n+/**\n+ * libie_ctlq_init - main initialization routine for all control queues\n+ * @ctx: libie context information\n+ * @qinfo: array of structs containing info for each queue to be initialized\n+ * @numq: number of queues to initialize\n+ *\n+ * This initializes queue list and adds any number and any type of control\n+ * queues. This is an all or nothing routine; if one fails, all previously\n+ * allocated queues will be destroyed. This must be called prior to using\n+ * the individual add/remove APIs.\n+ *\n+ * Return: %0 on success, -%errno on failure\n+ */\n+int libie_ctlq_init(struct libie_ctlq_ctx *ctx,\n+\t\t const struct libie_ctlq_create_info *qinfo,\n+\t\t u32 numq)\n+{\n+\tINIT_LIST_HEAD(&ctx->ctlqs);\n+\tspin_lock_init(&ctx->ctlqs_lock);\n+\n+\tfor (u32 i = 0; i < numq; i++) {\n+\t\tstruct libie_ctlq_info *ctlq;\n+\n+\t\tctlq = libie_ctlq_add(ctx, &qinfo[i]);\n+\t\tif (IS_ERR(ctlq)) {\n+\t\t\tlibie_ctlq_deinit(ctx);\n+\t\t\treturn PTR_ERR(ctlq);\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+EXPORT_SYMBOL_NS_GPL(libie_ctlq_init, \"LIBIE_CP\");\n+\n+/**\n+ * libie_ctlq_deinit - destroy all control queues\n+ * @ctx: libie CP context information\n+ */\n+void libie_ctlq_deinit(struct libie_ctlq_ctx *ctx)\n+{\n+\tstruct libie_ctlq_info *ctlq, *tmp;\n+\n+\tlist_for_each_entry_safe(ctlq, tmp, &ctx->ctlqs, list)\n+\t\tlibie_ctlq_remove(ctx, ctlq);\n+}\n+EXPORT_SYMBOL_NS_GPL(libie_ctlq_deinit, \"LIBIE_CP\");\n+\n+/**\n+ * libie_ctlq_tx_desc_from_msg - initialize a Tx descriptor from a message\n+ * @desc: descriptor to be initialized\n+ * @msg: filled control queue message\n+ */\n+static void libie_ctlq_tx_desc_from_msg(struct libie_ctlq_desc *desc,\n+\t\t\t\t\tconst struct libie_ctlq_msg *msg)\n+{\n+\tconst struct libie_cp_dma_mem *dma = &msg->send_mem;\n+\tu64 qword;\n+\n+\tqword = FIELD_PREP(LIBIE_CTLQ_DESC_FLAGS, msg->flags) |\n+\t\tFIELD_PREP(LIBIE_CTLQ_DESC_INFRA_OPCODE, msg->opcode) |\n+\t\tFIELD_PREP(LIBIE_CTLQ_DESC_PFID_VFID, msg->func_id);\n+\tdesc->qword0 = cpu_to_le64(qword);\n+\n+\tqword = FIELD_PREP(LIBIE_CTLQ_DESC_VIRTCHNL_OPCODE,\n+\t\t\t msg->chnl_opcode) |\n+\t\tFIELD_PREP(LIBIE_CTLQ_DESC_VIRTCHNL_MSG_RET_VAL,\n+\t\t\t msg->chnl_retval);\n+\tdesc->qword1 = cpu_to_le64(qword);\n+\n+\tqword = FIELD_PREP(LIBIE_CTLQ_DESC_MSG_PARAM0, msg->param0) |\n+\t\tFIELD_PREP(LIBIE_CTLQ_DESC_SW_COOKIE,\n+\t\t\t msg->sw_cookie) |\n+\t\tFIELD_PREP(LIBIE_CTLQ_DESC_VIRTCHNL_FLAGS,\n+\t\t\t msg->virt_flags);\n+\tdesc->qword2 = cpu_to_le64(qword);\n+\n+\tif (likely(msg->data_len)) {\n+\t\tdesc->qword0 |=\n+\t\t\tcpu_to_le64(LIBIE_CTLQ_DESC_QWORD0(msg->data_len));\n+\t\tqword = FIELD_PREP(LIBIE_CTLQ_DESC_DATA_ADDR_HIGH,\n+\t\t\t\t upper_32_bits(dma->pa)) |\n+\t\t\tFIELD_PREP(LIBIE_CTLQ_DESC_DATA_ADDR_LOW,\n+\t\t\t\t lower_32_bits(dma->pa));\n+\t} else {\n+\t\tqword = msg->addr_param;\n+\t}\n+\n+\tdesc->qword3 = cpu_to_le64(qword);\n+}\n+\n+/**\n+ * libie_ctlq_send - send a message to Control Plane or Peer\n+ * @ctlq: specific control queue which is used for sending a message\n+ * @q_msg: array of queue messages to be sent\n+ * @num_q_msg: number of messages to send on control queue\n+ *\n+ * The control queue will hold a reference to each send message until\n+ * the completion for that message has been cleaned.\n+ *\n+ * The caller must hold ctlq->lock.\n+ *\n+ * Return: %0 on success, -%errno on failure.\n+ */\n+int libie_ctlq_send(struct libie_ctlq_info *ctlq,\n+\t\t struct libie_ctlq_msg *q_msg, u32 num_q_msg)\n+{\n+\tu32 num_desc_avail, ntu;\n+\n+\tntu = ctlq->next_to_use;\n+\n+\tnum_desc_avail = (ctlq->next_to_clean > ntu ? 0 : ctlq->ring_len) +\n+\t\t\t ctlq->next_to_clean - ntu - 1;\n+\n+\tif (num_desc_avail < num_q_msg)\n+\t\treturn -EBUSY;\n+\n+\tfor (int i = 0; i < num_q_msg; i++) {\n+\t\tstruct libie_ctlq_msg *msg = &q_msg[i];\n+\t\tstruct libie_ctlq_desc *desc;\n+\n+\t\tdesc = &ctlq->descs[ntu];\n+\t\tlibie_ctlq_tx_desc_from_msg(desc, msg);\n+\n+\t\tif (unlikely(++ntu == ctlq->ring_len))\n+\t\t\tntu = 0;\n+\t}\n+\twritel(ntu, ctlq->reg.tail);\n+\tctlq->next_to_use = ntu;\n+\n+\treturn 0;\n+}\n+EXPORT_SYMBOL_NS_GPL(libie_ctlq_send, \"LIBIE_CP\");\n+\n+/**\n+ * libie_ctlq_fill_rx_msg - fill in a message from Rx descriptor and buffer\n+ * @msg: message to be filled in\n+ * @desc: received descriptor\n+ * @rx_buf: fill queue buffer associated with the descriptor\n+ */\n+static void libie_ctlq_fill_rx_msg(struct libie_ctlq_msg *msg,\n+\t\t\t\t const struct libie_ctlq_desc *desc,\n+\t\t\t\t struct libeth_fqe *rx_buf)\n+{\n+\tu64 qword = le64_to_cpu(desc->qword0);\n+\n+\tmsg->flags = FIELD_GET(LIBIE_CTLQ_DESC_FLAGS, qword);\n+\tmsg->opcode = FIELD_GET(LIBIE_CTLQ_DESC_INFRA_OPCODE, qword);\n+\tmsg->data_len = FIELD_GET(LIBIE_CTLQ_DESC_DATA_LEN, qword);\n+\tmsg->hw_retval = FIELD_GET(LIBIE_CTLQ_DESC_HW_RETVAL, qword);\n+\n+\tqword = le64_to_cpu(desc->qword1);\n+\tmsg->chnl_opcode =\n+\t\tFIELD_GET(LIBIE_CTLQ_DESC_VIRTCHNL_OPCODE, qword);\n+\tmsg->chnl_retval =\n+\t\tFIELD_GET(LIBIE_CTLQ_DESC_VIRTCHNL_MSG_RET_VAL, qword);\n+\n+\tqword = le64_to_cpu(desc->qword2);\n+\tmsg->param0 =\n+\t\tFIELD_GET(LIBIE_CTLQ_DESC_MSG_PARAM0, qword);\n+\tmsg->sw_cookie =\n+\t\tFIELD_GET(LIBIE_CTLQ_DESC_SW_COOKIE, qword);\n+\tmsg->virt_flags =\n+\t\tFIELD_GET(LIBIE_CTLQ_DESC_VIRTCHNL_FLAGS, qword);\n+\n+\tif (likely(msg->data_len)) {\n+\t\tmsg->recv_mem = (struct kvec) {\n+\t\t\t.iov_base = netmem_address(rx_buf->netmem),\n+\t\t\t.iov_len = msg->data_len,\n+\t\t};\n+\t\tlibeth_rx_sync_for_cpu(rx_buf, msg->data_len);\n+\t} else {\n+\t\tmsg->recv_mem = (struct kvec) {};\n+\t\tmsg->addr_param = le64_to_cpu(desc->qword3);\n+\t\tpage_pool_put_full_netmem(netmem_get_pp(rx_buf->netmem),\n+\t\t\t\t\t rx_buf->netmem, false);\n+\t}\n+}\n+\n+/**\n+ * libie_ctlq_recv - receive control queue message call back\n+ * @ctlq: control queue that needs to processed for receive\n+ * @msg: array of received control queue messages on this q;\n+ * needs to be pre-allocated by caller for as many messages as requested\n+ * @num_q_msg: number of messages that can be stored in msg buffer\n+ *\n+ * Called by interrupt handler or polling mechanism. Caller is expected\n+ * to free buffers.\n+ *\n+ * The caller must make sure that calls to libie_ctlq_post_rx_buffs()\n+ * and libie_ctlq_recv() for separate queues are either serialized\n+ * or used under ctlq->lock.\n+ *\n+ * Return: number of messages received\n+ */\n+u32 libie_ctlq_recv(struct libie_ctlq_info *ctlq, struct libie_ctlq_msg *msg,\n+\t\t u32 num_q_msg)\n+{\n+\tu32 ntc, i;\n+\n+\tntc = ctlq->next_to_clean;\n+\n+\tfor (i = 0; i < num_q_msg; i++) {\n+\t\tconst struct libie_ctlq_desc *desc = &ctlq->descs[ntc];\n+\t\tstruct libeth_fqe *rx_buf = &ctlq->rx_fqes[ntc];\n+\t\tu64 qword;\n+\n+\t\tqword = le64_to_cpu(desc->qword0);\n+\t\tif (!FIELD_GET(LIBIE_CTLQ_DESC_FLAG_DD, qword))\n+\t\t\tbreak;\n+\n+\t\tdma_rmb();\n+\n+\t\tif (unlikely(FIELD_GET(LIBIE_CTLQ_DESC_FLAG_ERR, qword)))\n+\t\t\tbreak;\n+\n+\t\tlibie_ctlq_fill_rx_msg(&msg[i], desc, rx_buf);\n+\n+\t\tif (unlikely(++ntc == ctlq->ring_len))\n+\t\t\tntc = 0;\n+\t}\n+\n+\tctlq->next_to_clean = ntc;\n+\n+\treturn i;\n+}\n+EXPORT_SYMBOL_NS_GPL(libie_ctlq_recv, \"LIBIE_CP\");\n+\n+MODULE_DESCRIPTION(\"Control Plane communication API\");\n+MODULE_IMPORT_NS(\"LIBETH\");\n+MODULE_LICENSE(\"GPL\");\ndiff --git a/include/linux/intel/libie/controlq.h b/include/linux/intel/libie/controlq.h\nnew file mode 100644\nindex 000000000000..534508fbb405\n--- /dev/null\n+++ b/include/linux/intel/libie/controlq.h\n@@ -0,0 +1,249 @@\n+/* SPDX-License-Identifier: GPL-2.0-only */\n+/* Copyright (C) 2025 Intel Corporation */\n+\n+#ifndef __LIBIE_CONTROLQ_H\n+#define __LIBIE_CONTROLQ_H\n+\n+#include <net/libeth/rx.h>\n+\n+#include <linux/intel/libie/pci.h>\n+#include <linux/intel/virtchnl2.h>\n+\n+/* Default mailbox control queue */\n+#define LIBIE_CTLQ_MBX_ID\t\t\t-1\n+#define LIBIE_CTLQ_MAX_BUF_LEN\t\t\tSZ_4K\n+\n+#define LIBIE_CTLQ_TYPE_TX\t\t\t0\n+#define LIBIE_CTLQ_TYPE_RX\t\t\t1\n+\n+/* Opcode used to send controlq message to the control plane */\n+#define LIBIE_CTLQ_SEND_MSG_TO_CP\t\t0x801\n+#define LIBIE_CTLQ_SEND_MSG_TO_PEER\t\t0x804\n+\n+/**\n+ * struct libie_ctlq_ctx - contains controlq info and MMIO region info\n+ * @mmio_info: MMIO region info structure\n+ * @ctlqs: list that stores all the control queues\n+ * @ctlqs_lock: lock for control queue list\n+ */\n+struct libie_ctlq_ctx {\n+\tstruct libie_mmio_info\tmmio_info;\n+\tstruct list_head\tctlqs;\n+\tspinlock_t\t\tctlqs_lock;\t/* protects the ctlqs list */\n+};\n+\n+/**\n+ * struct libie_ctlq_reg - structure representing virtual addresses of the\n+ *\t\t\t controlq registers and masks\n+ * @head: controlq head register address\n+ * @tail: controlq tail register address\n+ * @len: register address to write controlq length and enable bit\n+ * @addr_high: register address to write the upper 32b of ring physical address\n+ * @addr_low: register address to write the lower 32b of ring physical address\n+ * @len_mask: mask to read the controlq length\n+ * @len_ena_mask: mask to write the controlq enable bit\n+ * @head_mask: mask to read the head value\n+ */\n+struct libie_ctlq_reg {\n+\tvoid __iomem\t*head;\n+\tvoid __iomem\t*tail;\n+\tvoid __iomem\t*len;\n+\tvoid __iomem\t*addr_high;\n+\tvoid __iomem\t*addr_low;\n+\tu32\t\tlen_mask;\n+\tu32\t\tlen_ena_mask;\n+\tu32\t\thead_mask;\n+};\n+\n+/**\n+ * struct libie_cp_dma_mem - structure for DMA memory\n+ * @va: virtual address\n+ * @pa: physical address\n+ * @size: memory size\n+ */\n+struct libie_cp_dma_mem {\n+\tvoid\t\t*va;\n+\tdma_addr_t\tpa;\n+\tsize_t\t\tsize;\n+};\n+\n+/**\n+ * struct libie_ctlq_msg - control queue message data\n+ * @flags: refer to 'Flags sub-structure' definitions\n+ * @opcode: infrastructure message opcode\n+ * @data_len: size of the payload\n+ * @func_id: queue id for the secondary mailbox queue, 0 for default mailbox\n+ * @hw_retval: execution status from the HW\n+ * @chnl_opcode: virtchnl message opcode\n+ * @chnl_retval: virtchnl return value\n+ * @param0: indirect message raw parameter0\n+ * @sw_cookie: used to verify the response of the sent virtchnl message\n+ * @virt_flags: virtchnl capability flags\n+ * @addr_param: additional parameters in place of the address, given no buffer\n+ * @recv_mem: virtual address and size of the buffer that contains\n+ *\t the indirect response\n+ * @send_mem: physical and virtual address of the DMA buffer,\n+ *\t used for sending\n+ */\n+struct libie_ctlq_msg {\n+\tu16\t\t\tflags;\n+\tu16\t\t\topcode;\n+\tu16\t\t\tdata_len;\n+\tunion {\n+\t\tu16\t\tfunc_id;\n+\t\tu16\t\thw_retval;\n+\t};\n+\tu32\t\t\tchnl_opcode;\n+\tu32\t\t\tchnl_retval;\n+\tu32\t\t\tparam0;\n+\tu16\t\t\tsw_cookie;\n+\tu16\t\t\tvirt_flags;\n+\tu64\t\t\taddr_param;\n+\tunion {\n+\t\tstruct kvec\trecv_mem;\n+\t\tstruct\tlibie_cp_dma_mem send_mem;\n+\t};\n+};\n+\n+/**\n+ * struct libie_ctlq_create_info - control queue create information\n+ * @type: control queue type (Rx or Tx)\n+ * @id: queue offset passed as input, -1 for default mailbox\n+ * @reg: registers accessed by control queue\n+ * @len: controlq length\n+ */\n+struct libie_ctlq_create_info {\n+\tenum virtchnl2_queue_type\ttype;\n+\tint\t\t\t\tid;\n+\tstruct libie_ctlq_reg\t\treg;\n+\tu16\t\t\t\tlen;\n+};\n+\n+/**\n+ * struct libie_ctlq_info - control queue information\n+ * @list: used to add a controlq to the list of queues in libie_ctlq_ctx\n+ * @type: control queue type\n+ * @qid: queue identifier\n+ * @lock: control queue lock\n+ * @ring_mem: descrtiptor ring DMA memory\n+ * @descs: array of descrtiptors\n+ * @rx_fqes: array of controlq Rx buffers\n+ * @tx_msg: Tx messages sent to hardware\n+ * @reg: registers used by control queue\n+ * @dev: device that owns this control queue\n+ * @pp: page pool for controlq Rx buffers\n+ * @truesize: size to allocate per buffer\n+ * @next_to_use: next available slot to send buffer\n+ * @next_to_clean: next descrtiptor to be cleaned\n+ * @next_to_post: next available slot to post buffers to after receive\n+ * @ring_len: length of the descriptor ring\n+ */\n+struct libie_ctlq_info {\n+\tstruct list_head\t\tlist;\n+\tenum virtchnl2_queue_type\ttype;\n+\tint\t\t\t\tqid;\n+\tspinlock_t\t\t\tlock;\t/* for concurrent processing */\n+\tstruct libie_cp_dma_mem\tring_mem;\n+\tstruct libie_ctlq_desc\t\t*descs;\n+\tunion {\n+\t\tstruct libeth_fqe\t\t*rx_fqes;\n+\t\tstruct libie_ctlq_msg\t\t**tx_msg;\n+\t};\n+\tstruct libie_ctlq_reg\t\treg;\n+\tstruct device\t\t\t*dev;\n+\tstruct page_pool\t\t*pp;\n+\tu32\t\t\t\ttruesize;\n+\tu32\t\t\t\tnext_to_clean;\n+\tunion {\n+\t\tu32\t\t\tnext_to_use;\n+\t\tu32\t\t\tnext_to_post;\n+\t};\n+\tu32\t\t\t\tring_len;\n+};\n+\n+#define LIBIE_CTLQ_MBX_ATQ_LEN\t\t\tGENMASK(9, 0)\n+\n+/* Flags sub-structure\n+ * |0 |1 |2 |3 |4 |5 |6 |7 |8 |9 |10 |11 |12 |13 |14 |15 |\n+ * |DD |CMP|ERR| * RSV * |FTYPE | *RSV* |RD |VFC|BUF| HOST_ID |\n+ */\n+ /* libie controlq descriptor qword0 details */\n+#define LIBIE_CTLQ_DESC_FLAG_DD\t\tBIT(0)\n+#define LIBIE_CTLQ_DESC_FLAG_CMP\t\tBIT(1)\n+#define LIBIE_CTLQ_DESC_FLAG_ERR\t\tBIT(2)\n+#define LIBIE_CTLQ_DESC_FLAG_FTYPE_VM\t\tBIT(6)\n+#define LIBIE_CTLQ_DESC_FLAG_FTYPE_PF\t\tBIT(7)\n+#define LIBIE_CTLQ_DESC_FLAG_FTYPE\t\tGENMASK(7, 6)\n+#define LIBIE_CTLQ_DESC_FLAG_RD\t\tBIT(10)\n+#define LIBIE_CTLQ_DESC_FLAG_VFC\t\tBIT(11)\n+#define LIBIE_CTLQ_DESC_FLAG_BUF\t\tBIT(12)\n+#define LIBIE_CTLQ_DESC_FLAG_HOST_ID\t\tGENMASK(15, 13)\n+\n+#define LIBIE_CTLQ_DESC_FLAGS\t\t\tGENMASK(15, 0)\n+#define LIBIE_CTLQ_DESC_INFRA_OPCODE\t\tGENMASK_ULL(31, 16)\n+#define LIBIE_CTLQ_DESC_DATA_LEN\t\tGENMASK_ULL(47, 32)\n+#define LIBIE_CTLQ_DESC_HW_RETVAL\t\tGENMASK_ULL(63, 48)\n+\n+#define LIBIE_CTLQ_DESC_PFID_VFID\t\tGENMASK_ULL(63, 48)\n+\n+/* libie controlq descriptor qword1 details */\n+#define LIBIE_CTLQ_DESC_VIRTCHNL_OPCODE\tGENMASK(27, 0)\n+#define LIBIE_CTLQ_DESC_VIRTCHNL_DESC_TYPE\tGENMASK_ULL(31, 28)\n+#define LIBIE_CTLQ_DESC_VIRTCHNL_MSG_RET_VAL\tGENMASK_ULL(63, 32)\n+\n+/* libie controlq descriptor qword2 details */\n+#define LIBIE_CTLQ_DESC_MSG_PARAM0\t\tGENMASK_ULL(31, 0)\n+#define LIBIE_CTLQ_DESC_SW_COOKIE\t\tGENMASK_ULL(47, 32)\n+#define LIBIE_CTLQ_DESC_VIRTCHNL_FLAGS\t\tGENMASK_ULL(63, 48)\n+\n+/* libie controlq descriptor qword3 details */\n+#define LIBIE_CTLQ_DESC_DATA_ADDR_HIGH\t\tGENMASK_ULL(31, 0)\n+#define LIBIE_CTLQ_DESC_DATA_ADDR_LOW\t\tGENMASK_ULL(63, 32)\n+\n+/**\n+ * struct libie_ctlq_desc - control queue descriptor format\n+ * @qword0: flags, message opcode, data length etc\n+ * @qword1: virtchnl opcode, descriptor type and return value\n+ * @qword2: indirect message parameters\n+ * @qword3: indirect message buffer address\n+ */\n+struct libie_ctlq_desc {\n+\t__le64\t\t\tqword0;\n+\t__le64\t\t\tqword1;\n+\t__le64\t\t\tqword2;\n+\t__le64\t\t\tqword3;\n+};\n+\n+/**\n+ * libie_ctlq_release_rx_buf - Release Rx buffer for a specific control queue\n+ * @rx_buf: Rx buffer to be freed\n+ *\n+ * Driver uses this function to post back the Rx buffer after the usage.\n+ */\n+static inline void libie_ctlq_release_rx_buf(struct kvec *rx_buf)\n+{\n+\tnetmem_ref netmem;\n+\n+\tif (!rx_buf->iov_base)\n+\t\treturn;\n+\n+\tnetmem = virt_to_netmem(rx_buf->iov_base);\n+\tpage_pool_put_full_netmem(netmem_get_pp(netmem), netmem, false);\n+}\n+\n+int libie_ctlq_init(struct libie_ctlq_ctx *ctx,\n+\t\t const struct libie_ctlq_create_info *qinfo, u32 numq);\n+void libie_ctlq_deinit(struct libie_ctlq_ctx *ctx);\n+\n+struct libie_ctlq_info *libie_find_ctlq(struct libie_ctlq_ctx *ctx,\n+\t\t\t\t\tenum virtchnl2_queue_type type,\n+\t\t\t\t\t int id);\n+\n+int libie_ctlq_send(struct libie_ctlq_info *ctlq,\n+\t\t struct libie_ctlq_msg *q_msg, u32 num_q_msg);\n+u32 libie_ctlq_recv(struct libie_ctlq_info *ctlq, struct libie_ctlq_msg *msg,\n+\t\t u32 num_q_msg);\n+\n+int libie_ctlq_post_rx_buffs(struct libie_ctlq_info *ctlq);\n+\n+#endif /* __LIBIE_CONTROLQ_H */\n", "prefixes": [ "iwl-next", "v5", "05/15" ] }