Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/40931/?format=api
https://patches.dpdk.org/api/patches/40931/?format=api", "web_url": "https://patches.dpdk.org/project/dpdk/patch/cac38d5add2eda08f19c4f124b2849013dd89b53.1528469677.git.rahul.lakkireddy@chelsio.com/", "project": { "id": 1, "url": "https://patches.dpdk.org/api/projects/1/?format=api", "name": "DPDK", "link_name": "dpdk", "list_id": "dev.dpdk.org", "list_email": "dev@dpdk.org", "web_url": "http://core.dpdk.org", "scm_url": "git://dpdk.org/dpdk", "webscm_url": "http://git.dpdk.org/dpdk", "list_archive_url": "https://inbox.dpdk.org/dev", "list_archive_url_format": "https://inbox.dpdk.org/dev/{}", "commit_url_format": "" }, "msgid": "<cac38d5add2eda08f19c4f124b2849013dd89b53.1528469677.git.rahul.lakkireddy@chelsio.com>", "list_archive_url": "https://inbox.dpdk.org/dev/cac38d5add2eda08f19c4f124b2849013dd89b53.1528469677.git.rahul.lakkireddy@chelsio.com", "date": "2018-06-08T17:58:16", "name": "[dpdk-dev,6/7] net/cxgbe: implement flow query operation", "commit_ref": null, "pull_url": null, "state": "accepted", "archived": true, "hash": "05f581cc25a9727ff7d69e6330733d5e3f69dc51", "submitter": { "id": 241, "url": "https://patches.dpdk.org/api/people/241/?format=api", "name": "Rahul Lakkireddy", "email": "rahul.lakkireddy@chelsio.com" }, "delegate": { "id": 319, "url": "https://patches.dpdk.org/api/users/319/?format=api", "username": "fyigit", "first_name": "Ferruh", "last_name": "Yigit", "email": "ferruh.yigit@amd.com" }, "mbox": "https://patches.dpdk.org/project/dpdk/patch/cac38d5add2eda08f19c4f124b2849013dd89b53.1528469677.git.rahul.lakkireddy@chelsio.com/mbox/", "series": [ { "id": 63, "url": "https://patches.dpdk.org/api/series/63/?format=api", "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=63", "date": "2018-06-08T17:58:10", "name": "cxgbe: add support to offload flows via rte_flow", "version": 1, "mbox": "https://patches.dpdk.org/series/63/mbox/" } ], "comments": "https://patches.dpdk.org/api/patches/40931/comments/", "check": "success", "checks": "https://patches.dpdk.org/api/patches/40931/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<dev-bounces@dpdk.org>", "X-Original-To": "patchwork@dpdk.org", "Delivered-To": "patchwork@dpdk.org", "Received": [ "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 60F0C1D013;\n\tFri, 8 Jun 2018 19:59:38 +0200 (CEST)", "from stargate.chelsio.com (stargate.chelsio.com [12.32.117.8])\n\tby dpdk.org (Postfix) with ESMTP id 7840E1BB89\n\tfor <dev@dpdk.org>; Fri, 8 Jun 2018 19:59:36 +0200 (CEST)", "from localhost (scalar.blr.asicdesigners.com [10.193.185.94])\n\tby stargate.chelsio.com (8.13.8/8.13.8) with ESMTP id w58HxXwU017303; \n\tFri, 8 Jun 2018 10:59:34 -0700" ], "From": "Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>", "To": "dev@dpdk.org", "Cc": "shaguna@chelsio.com, kumaras@chelsio.com, indranil@chelsio.com,\n\tnirranjan@chelsio.com", "Date": "Fri, 8 Jun 2018 23:28:16 +0530", "Message-Id": "<cac38d5add2eda08f19c4f124b2849013dd89b53.1528469677.git.rahul.lakkireddy@chelsio.com>", "X-Mailer": "git-send-email 2.5.3", "In-Reply-To": [ "<cover.1528469677.git.rahul.lakkireddy@chelsio.com>", "<cover.1528469677.git.rahul.lakkireddy@chelsio.com>" ], "References": [ "<cover.1528469677.git.rahul.lakkireddy@chelsio.com>", "<cover.1528469677.git.rahul.lakkireddy@chelsio.com>" ], "Subject": "[dpdk-dev] [PATCH 6/7] net/cxgbe: implement flow query operation", "X-BeenThere": "dev@dpdk.org", "X-Mailman-Version": "2.1.15", "Precedence": "list", "List-Id": "DPDK patches and discussions <dev.dpdk.org>", "List-Unsubscribe": "<https://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>", "List-Archive": "<http://dpdk.org/ml/archives/dev/>", "List-Post": "<mailto:dev@dpdk.org>", "List-Help": "<mailto:dev-request@dpdk.org?subject=help>", "List-Subscribe": "<https://dpdk.org/ml/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>", "Errors-To": "dev-bounces@dpdk.org", "Sender": "\"dev\" <dev-bounces@dpdk.org>" }, "content": "From: Shagun Agrawal <shaguna@chelsio.com>\n\nAdd API to query filter hit and byte counts from hardware.\n\nSigned-off-by: Shagun Agrawal <shaguna@chelsio.com>\nSigned-off-by: Kumar Sanghvi <kumaras@chelsio.com>\nSigned-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>\n---\n drivers/net/cxgbe/base/adapter.h | 1 +\n drivers/net/cxgbe/base/common.h | 15 +++\n drivers/net/cxgbe/base/t4_hw.c | 209 +++++++++++++++++++++++++++++++++++++++\n drivers/net/cxgbe/base/t4_hw.h | 4 +\n drivers/net/cxgbe/base/t4_regs.h | 16 +++\n drivers/net/cxgbe/cxgbe_filter.c | 62 ++++++++++++\n drivers/net/cxgbe/cxgbe_filter.h | 2 +\n drivers/net/cxgbe/cxgbe_flow.c | 62 +++++++++++-\n drivers/net/cxgbe/cxgbe_main.c | 1 +\n 9 files changed, 371 insertions(+), 1 deletion(-)", "diff": "diff --git a/drivers/net/cxgbe/base/adapter.h b/drivers/net/cxgbe/base/adapter.h\nindex 7f9ddae01..de46ecfe3 100644\n--- a/drivers/net/cxgbe/base/adapter.h\n+++ b/drivers/net/cxgbe/base/adapter.h\n@@ -319,6 +319,7 @@ struct adapter {\n \tunsigned int vpd_flag;\n \n \tint use_unpacked_mode; /* unpacked rx mode state */\n+\trte_spinlock_t win0_lock;\n \n \tstruct tid_info tids; /* Info used to access TID related tables */\n };\ndiff --git a/drivers/net/cxgbe/base/common.h b/drivers/net/cxgbe/base/common.h\nindex c80304b24..e524f7931 100644\n--- a/drivers/net/cxgbe/base/common.h\n+++ b/drivers/net/cxgbe/base/common.h\n@@ -18,6 +18,9 @@ extern \"C\" {\n \n #define CXGBE_PAGE_SIZE RTE_PGSIZE_4K\n \n+#define T4_MEMORY_WRITE 0\n+#define T4_MEMORY_READ 1\n+\n enum {\n \tMAX_NPORTS = 4, /* max # of ports */\n };\n@@ -47,6 +50,8 @@ enum cc_fec {\n \tFEC_BASER_RS = 1 << 2, /* BaseR/Reed-Solomon */\n };\n \n+enum { MEM_EDC0, MEM_EDC1, MEM_MC, MEM_MC0 = MEM_MC, MEM_MC1 };\n+\n struct port_stats {\n \tu64 tx_octets; /* total # of octets in good frames */\n \tu64 tx_frames; /* all good frames */\n@@ -502,5 +507,15 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size);\n int t4_seeprom_read(struct adapter *adapter, u32 addr, u32 *data);\n int t4_seeprom_write(struct adapter *adapter, u32 addr, u32 data);\n int t4_seeprom_wp(struct adapter *adapter, int enable);\n+int t4_memory_rw_addr(struct adapter *adap, int win,\n+\t\t u32 addr, u32 len, void *hbuf, int dir);\n+int t4_memory_rw_mtype(struct adapter *adap, int win, int mtype, u32 maddr,\n+\t\t u32 len, void *hbuf, int dir);\n+static inline int t4_memory_rw(struct adapter *adap, int win,\n+\t\t\t int mtype, u32 maddr, u32 len,\n+\t\t\t void *hbuf, int dir)\n+{\n+\treturn t4_memory_rw_mtype(adap, win, mtype, maddr, len, hbuf, dir);\n+}\n fw_port_cap32_t fwcaps16_to_caps32(fw_port_cap16_t caps16);\n #endif /* __CHELSIO_COMMON_H */\ndiff --git a/drivers/net/cxgbe/base/t4_hw.c b/drivers/net/cxgbe/base/t4_hw.c\nindex c146c911e..66d080476 100644\n--- a/drivers/net/cxgbe/base/t4_hw.c\n+++ b/drivers/net/cxgbe/base/t4_hw.c\n@@ -5215,3 +5215,212 @@ int t4_port_init(struct adapter *adap, int mbox, int pf, int vf)\n \t}\n \treturn 0;\n }\n+\n+/**\n+ * t4_memory_rw_addr - read/write adapter memory via PCIE memory window\n+ * @adap: the adapter\n+ * @win: PCI-E Memory Window to use\n+ * @addr: address within adapter memory\n+ * @len: amount of memory to transfer\n+ * @hbuf: host memory buffer\n+ * @dir: direction of transfer T4_MEMORY_READ (1) or T4_MEMORY_WRITE (0)\n+ *\n+ * Reads/writes an [almost] arbitrary memory region in the firmware: the\n+ * firmware memory address and host buffer must be aligned on 32-bit\n+ * boudaries; the length may be arbitrary.\n+ *\n+ * NOTES:\n+ * 1. The memory is transferred as a raw byte sequence from/to the\n+ * firmware's memory. If this memory contains data structures which\n+ * contain multi-byte integers, it's the caller's responsibility to\n+ * perform appropriate byte order conversions.\n+ *\n+ * 2. It is the Caller's responsibility to ensure that no other code\n+ * uses the specified PCI-E Memory Window while this routine is\n+ * using it. This is typically done via the use of OS-specific\n+ * locks, etc.\n+ */\n+int t4_memory_rw_addr(struct adapter *adap, int win, u32 addr,\n+\t\t u32 len, void *hbuf, int dir)\n+{\n+\tu32 pos, offset, resid;\n+\tu32 win_pf, mem_reg, mem_aperture, mem_base;\n+\tu32 *buf;\n+\n+\t/* Argument sanity checks ...*/\n+\tif (addr & 0x3 || (uintptr_t)hbuf & 0x3)\n+\t\treturn -EINVAL;\n+\tbuf = (u32 *)hbuf;\n+\n+\t/* It's convenient to be able to handle lengths which aren't a\n+\t * multiple of 32-bits because we often end up transferring files to\n+\t * the firmware. So we'll handle that by normalizing the length here\n+\t * and then handling any residual transfer at the end.\n+\t */\n+\tresid = len & 0x3;\n+\tlen -= resid;\n+\n+\t/* Each PCI-E Memory Window is programmed with a window size -- or\n+\t * \"aperture\" -- which controls the granularity of its mapping onto\n+\t * adapter memory. We need to grab that aperture in order to know\n+\t * how to use the specified window. The window is also programmed\n+\t * with the base address of the Memory Window in BAR0's address\n+\t * space. For T4 this is an absolute PCI-E Bus Address. For T5\n+\t * the address is relative to BAR0.\n+\t */\n+\tmem_reg = t4_read_reg(adap,\n+\t\t\t PCIE_MEM_ACCESS_REG(A_PCIE_MEM_ACCESS_BASE_WIN,\n+\t\t\t\t\t\t win));\n+\tmem_aperture = 1 << (G_WINDOW(mem_reg) + X_WINDOW_SHIFT);\n+\tmem_base = G_PCIEOFST(mem_reg) << X_PCIEOFST_SHIFT;\n+\n+\twin_pf = is_t4(adap->params.chip) ? 0 : V_PFNUM(adap->pf);\n+\n+\t/* Calculate our initial PCI-E Memory Window Position and Offset into\n+\t * that Window.\n+\t */\n+\tpos = addr & ~(mem_aperture - 1);\n+\toffset = addr - pos;\n+\n+\t/* Set up initial PCI-E Memory Window to cover the start of our\n+\t * transfer. (Read it back to ensure that changes propagate before we\n+\t * attempt to use the new value.)\n+\t */\n+\tt4_write_reg(adap,\n+\t\t PCIE_MEM_ACCESS_REG(A_PCIE_MEM_ACCESS_OFFSET, win),\n+\t\t pos | win_pf);\n+\tt4_read_reg(adap,\n+\t\t PCIE_MEM_ACCESS_REG(A_PCIE_MEM_ACCESS_OFFSET, win));\n+\n+\t/* Transfer data to/from the adapter as long as there's an integral\n+\t * number of 32-bit transfers to complete.\n+\t *\n+\t * A note on Endianness issues:\n+\t *\n+\t * The \"register\" reads and writes below from/to the PCI-E Memory\n+\t * Window invoke the standard adapter Big-Endian to PCI-E Link\n+\t * Little-Endian \"swizzel.\" As a result, if we have the following\n+\t * data in adapter memory:\n+\t *\n+\t * Memory: ... | b0 | b1 | b2 | b3 | ...\n+\t * Address: i+0 i+1 i+2 i+3\n+\t *\n+\t * Then a read of the adapter memory via the PCI-E Memory Window\n+\t * will yield:\n+\t *\n+\t * x = readl(i)\n+\t * 31 0\n+\t * [ b3 | b2 | b1 | b0 ]\n+\t *\n+\t * If this value is stored into local memory on a Little-Endian system\n+\t * it will show up correctly in local memory as:\n+\t *\n+\t * ( ..., b0, b1, b2, b3, ... )\n+\t *\n+\t * But on a Big-Endian system, the store will show up in memory\n+\t * incorrectly swizzled as:\n+\t *\n+\t * ( ..., b3, b2, b1, b0, ... )\n+\t *\n+\t * So we need to account for this in the reads and writes to the\n+\t * PCI-E Memory Window below by undoing the register read/write\n+\t * swizzels.\n+\t */\n+\twhile (len > 0) {\n+\t\tif (dir == T4_MEMORY_READ)\n+\t\t\t*buf++ = le32_to_cpu((__le32)t4_read_reg(adap,\n+\t\t\t\t\t\t\t\t mem_base +\n+\t\t\t\t\t\t\t\t offset));\n+\t\telse\n+\t\t\tt4_write_reg(adap, mem_base + offset,\n+\t\t\t\t (u32)cpu_to_le32(*buf++));\n+\t\toffset += sizeof(__be32);\n+\t\tlen -= sizeof(__be32);\n+\n+\t\t/* If we've reached the end of our current window aperture,\n+\t\t * move the PCI-E Memory Window on to the next. Note that\n+\t\t * doing this here after \"len\" may be 0 allows us to set up\n+\t\t * the PCI-E Memory Window for a possible final residual\n+\t\t * transfer below ...\n+\t\t */\n+\t\tif (offset == mem_aperture) {\n+\t\t\tpos += mem_aperture;\n+\t\t\toffset = 0;\n+\t\t\tt4_write_reg(adap,\n+\t\t\t\tPCIE_MEM_ACCESS_REG(A_PCIE_MEM_ACCESS_OFFSET,\n+\t\t\t\t\t\t win), pos | win_pf);\n+\t\t\tt4_read_reg(adap,\n+\t\t\t\tPCIE_MEM_ACCESS_REG(A_PCIE_MEM_ACCESS_OFFSET,\n+\t\t\t\t\t\t win));\n+\t\t}\n+\t}\n+\n+\t/* If the original transfer had a length which wasn't a multiple of\n+\t * 32-bits, now's where we need to finish off the transfer of the\n+\t * residual amount. The PCI-E Memory Window has already been moved\n+\t * above (if necessary) to cover this final transfer.\n+\t */\n+\tif (resid) {\n+\t\tunion {\n+\t\t\tu32 word;\n+\t\t\tchar byte[4];\n+\t\t} last;\n+\t\tunsigned char *bp;\n+\t\tint i;\n+\n+\t\tif (dir == T4_MEMORY_READ) {\n+\t\t\tlast.word = le32_to_cpu((__le32)t4_read_reg(adap,\n+\t\t\t\t\t\t\t\t mem_base +\n+\t\t\t\t\t\t\t\t offset));\n+\t\t\tfor (bp = (unsigned char *)buf, i = resid; i < 4; i++)\n+\t\t\t\tbp[i] = last.byte[i];\n+\t\t} else {\n+\t\t\tlast.word = *buf;\n+\t\t\tfor (i = resid; i < 4; i++)\n+\t\t\t\tlast.byte[i] = 0;\n+\t\t\tt4_write_reg(adap, mem_base + offset,\n+\t\t\t\t (u32)cpu_to_le32(last.word));\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * t4_memory_rw_mtype -read/write EDC 0, EDC 1 or MC via PCIE memory window\n+ * @adap: the adapter\n+ * @win: PCI-E Memory Window to use\n+ * @mtype: memory type: MEM_EDC0, MEM_EDC1 or MEM_MC\n+ * @maddr: address within indicated memory type\n+ * @len: amount of memory to transfer\n+ * @hbuf: host memory buffer\n+ * @dir: direction of transfer T4_MEMORY_READ (1) or T4_MEMORY_WRITE (0)\n+ *\n+ * Reads/writes adapter memory using t4_memory_rw_addr(). This routine\n+ * provides an (memory type, address within memory type) interface.\n+ */\n+int t4_memory_rw_mtype(struct adapter *adap, int win, int mtype, u32 maddr,\n+\t\t u32 len, void *hbuf, int dir)\n+{\n+\tu32 mtype_offset;\n+\tu32 edc_size, mc_size;\n+\n+\t/* Offset into the region of memory which is being accessed\n+\t * MEM_EDC0 = 0\n+\t * MEM_EDC1 = 1\n+\t * MEM_MC = 2 -- MEM_MC for chips with only 1 memory controller\n+\t * MEM_MC1 = 3 -- for chips with 2 memory controllers (e.g. T5)\n+\t */\n+\tedc_size = G_EDRAM0_SIZE(t4_read_reg(adap, A_MA_EDRAM0_BAR));\n+\tif (mtype != MEM_MC1) {\n+\t\tmtype_offset = (mtype * (edc_size * 1024 * 1024));\n+\t} else {\n+\t\tmc_size = G_EXT_MEM0_SIZE(t4_read_reg(adap,\n+\t\t\t\t\t\t A_MA_EXT_MEMORY0_BAR));\n+\t\tmtype_offset = (MEM_MC0 * edc_size + mc_size) * 1024 * 1024;\n+\t}\n+\n+\treturn t4_memory_rw_addr(adap, win,\n+\t\t\t\t mtype_offset + maddr, len,\n+\t\t\t\t hbuf, dir);\n+}\ndiff --git a/drivers/net/cxgbe/base/t4_hw.h b/drivers/net/cxgbe/base/t4_hw.h\nindex ac12afc04..e77563dfa 100644\n--- a/drivers/net/cxgbe/base/t4_hw.h\n+++ b/drivers/net/cxgbe/base/t4_hw.h\n@@ -42,6 +42,10 @@ enum {\n \tSGE_MAX_WR_NDESC = SGE_MAX_WR_LEN / SGE_EQ_IDXSIZE,\n };\n \n+enum {\n+\tTCB_SIZE = 128, /* TCB size */\n+};\n+\n struct sge_qstat { /* data written to SGE queue status entries */\n \t__be32 qid;\n \t__be16 cidx;\ndiff --git a/drivers/net/cxgbe/base/t4_regs.h b/drivers/net/cxgbe/base/t4_regs.h\nindex c0d6ddcac..fd8f9cf27 100644\n--- a/drivers/net/cxgbe/base/t4_regs.h\n+++ b/drivers/net/cxgbe/base/t4_regs.h\n@@ -458,6 +458,7 @@\n #define F_CRXPKTENC V_CRXPKTENC(1U)\n \n #define TP_BASE_ADDR 0x7d00\n+#define A_TP_CMM_TCB_BASE 0x7d10\n \n #define A_TP_TIMER_RESOLUTION 0x7d90\n \n@@ -574,6 +575,21 @@\n #define S_RM_OVLAN\t9\n #define V_RM_OVLAN(x)\t((x) << S_RM_OVLAN)\n \n+/* registers for module MA */\n+#define A_MA_EDRAM0_BAR 0x77c0\n+\n+#define S_EDRAM0_SIZE 0\n+#define M_EDRAM0_SIZE 0xfffU\n+#define V_EDRAM0_SIZE(x) ((x) << S_EDRAM0_SIZE)\n+#define G_EDRAM0_SIZE(x) (((x) >> S_EDRAM0_SIZE) & M_EDRAM0_SIZE)\n+\n+#define A_MA_EXT_MEMORY0_BAR 0x77c8\n+\n+#define S_EXT_MEM0_SIZE 0\n+#define M_EXT_MEM0_SIZE 0xfffU\n+#define V_EXT_MEM0_SIZE(x) ((x) << S_EXT_MEM0_SIZE)\n+#define G_EXT_MEM0_SIZE(x) (((x) >> S_EXT_MEM0_SIZE) & M_EXT_MEM0_SIZE)\n+\n /* registers for module MPS */\n #define MPS_BASE_ADDR 0x9000\n #define T4VF_MPS_BASE_ADDR 0x0100\ndiff --git a/drivers/net/cxgbe/cxgbe_filter.c b/drivers/net/cxgbe/cxgbe_filter.c\nindex 8129ed01f..2fc580e61 100644\n--- a/drivers/net/cxgbe/cxgbe_filter.c\n+++ b/drivers/net/cxgbe/cxgbe_filter.c\n@@ -545,3 +545,65 @@ void filter_rpl(struct adapter *adap, const struct cpl_set_tcb_rpl *rpl)\n \t\t\tt4_complete(&ctx->completion);\n \t}\n }\n+\n+/*\n+ * Retrieve the packet count for the specified filter.\n+ */\n+int cxgbe_get_filter_count(struct adapter *adapter, unsigned int fidx,\n+\t\t\t u64 *c, bool get_byte)\n+{\n+\tstruct filter_entry *f;\n+\tunsigned int tcb_base, tcbaddr;\n+\tint ret;\n+\n+\ttcb_base = t4_read_reg(adapter, A_TP_CMM_TCB_BASE);\n+\tif (fidx >= adapter->tids.nftids)\n+\t\treturn -ERANGE;\n+\n+\tf = &adapter->tids.ftid_tab[fidx];\n+\tif (!f->valid)\n+\t\treturn -EINVAL;\n+\n+\ttcbaddr = tcb_base + f->tid * TCB_SIZE;\n+\n+\tif (is_t5(adapter->params.chip) || is_t6(adapter->params.chip)) {\n+\t\t/*\n+\t\t * For T5, the Filter Packet Hit Count is maintained as a\n+\t\t * 32-bit Big Endian value in the TCB field {timestamp}.\n+\t\t * Similar to the craziness above, instead of the filter hit\n+\t\t * count showing up at offset 20 ((W_TCB_TIMESTAMP == 5) *\n+\t\t * sizeof(u32)), it actually shows up at offset 24. Whacky.\n+\t\t */\n+\t\tif (get_byte) {\n+\t\t\tunsigned int word_offset = 4;\n+\t\t\t__be64 be64_byte_count;\n+\n+\t\t\tt4_os_lock(&adapter->win0_lock);\n+\t\t\tret = t4_memory_rw(adapter, MEMWIN_NIC, MEM_EDC0,\n+\t\t\t\t\t tcbaddr +\n+\t\t\t\t\t (word_offset * sizeof(__be32)),\n+\t\t\t\t\t sizeof(be64_byte_count),\n+\t\t\t\t\t &be64_byte_count,\n+\t\t\t\t\t T4_MEMORY_READ);\n+\t\t\tt4_os_unlock(&adapter->win0_lock);\n+\t\t\tif (ret < 0)\n+\t\t\t\treturn ret;\n+\t\t\t*c = be64_to_cpu(be64_byte_count);\n+\t\t} else {\n+\t\t\tunsigned int word_offset = 6;\n+\t\t\t__be32 be32_count;\n+\n+\t\t\tt4_os_lock(&adapter->win0_lock);\n+\t\t\tret = t4_memory_rw(adapter, MEMWIN_NIC, MEM_EDC0,\n+\t\t\t\t\t tcbaddr +\n+\t\t\t\t\t (word_offset * sizeof(__be32)),\n+\t\t\t\t\t sizeof(be32_count), &be32_count,\n+\t\t\t\t\t T4_MEMORY_READ);\n+\t\t\tt4_os_unlock(&adapter->win0_lock);\n+\t\t\tif (ret < 0)\n+\t\t\t\treturn ret;\n+\t\t\t*c = (u64)be32_to_cpu(be32_count);\n+\t\t}\n+\t}\n+\treturn 0;\n+}\ndiff --git a/drivers/net/cxgbe/cxgbe_filter.h b/drivers/net/cxgbe/cxgbe_filter.h\nindex e0ba6a4d3..3c81c1a64 100644\n--- a/drivers/net/cxgbe/cxgbe_filter.h\n+++ b/drivers/net/cxgbe/cxgbe_filter.h\n@@ -220,4 +220,6 @@ int cxgbe_del_filter(struct rte_eth_dev *dev, unsigned int filter_id,\n \t\t struct filter_ctx *ctx);\n int cxgbe_alloc_ftid(struct adapter *adap, unsigned int family);\n int validate_filter(struct adapter *adap, struct ch_filter_specification *fs);\n+int cxgbe_get_filter_count(struct adapter *adapter, unsigned int fidx,\n+\t\t\t u64 *c, bool get_byte);\n #endif /* _CXGBE_FILTER_H_ */\ndiff --git a/drivers/net/cxgbe/cxgbe_flow.c b/drivers/net/cxgbe/cxgbe_flow.c\nindex 1584df392..89490ecc2 100644\n--- a/drivers/net/cxgbe/cxgbe_flow.c\n+++ b/drivers/net/cxgbe/cxgbe_flow.c\n@@ -522,6 +522,66 @@ cxgbe_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *flow,\n \treturn 0;\n }\n \n+static int __cxgbe_flow_query(struct rte_flow *flow, u64 *count,\n+\t\t\t u64 *byte_count)\n+{\n+\tstruct adapter *adap = ethdev2adap(flow->dev);\n+\tunsigned int fidx = flow->fidx;\n+\tint ret = 0;\n+\n+\tret = cxgbe_get_filter_count(adap, fidx, count, 0);\n+\tif (ret)\n+\t\treturn ret;\n+\treturn cxgbe_get_filter_count(adap, fidx, byte_count, 1);\n+}\n+\n+static int\n+cxgbe_flow_query(struct rte_eth_dev *dev, struct rte_flow *flow,\n+\t\t const struct rte_flow_action *action, void *data,\n+\t\t struct rte_flow_error *e)\n+{\n+\tstruct ch_filter_specification fs;\n+\tstruct rte_flow_query_count *c;\n+\tstruct filter_entry *f;\n+\tint ret;\n+\n+\tRTE_SET_USED(dev);\n+\n+\tf = flow->f;\n+\tfs = f->fs;\n+\n+\tif (action->type != RTE_FLOW_ACTION_TYPE_COUNT)\n+\t\treturn rte_flow_error_set(e, ENOTSUP,\n+\t\t\t\t\t RTE_FLOW_ERROR_TYPE_ACTION, NULL,\n+\t\t\t\t\t \"only count supported for query\");\n+\n+\t/*\n+\t * This is a valid operation, Since we are allowed to do chelsio\n+\t * specific operations in rte side of our code but not vise-versa\n+\t *\n+\t * So, fs can be queried/modified here BUT rte_flow_query_count\n+\t * cannot be worked on by the lower layer since we want to maintain\n+\t * it as rte_flow agnostic.\n+\t */\n+\tif (!fs.hitcnts)\n+\t\treturn rte_flow_error_set(e, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,\n+\t\t\t\t\t &fs, \"filter hit counters were not\"\n+\t\t\t\t\t \" enabled during filter creation\");\n+\n+\tc = (struct rte_flow_query_count *)data;\n+\tret = __cxgbe_flow_query(flow, &c->hits, &c->bytes);\n+\tif (ret)\n+\t\treturn rte_flow_error_set(e, -ret, RTE_FLOW_ERROR_TYPE_ACTION,\n+\t\t\t\t\t f, \"cxgbe pmd failed to\"\n+\t\t\t\t\t \" perform query\");\n+\n+\t/* Query was successful */\n+\tc->bytes_set = 1;\n+\tc->hits_set = 1;\n+\n+\treturn 0; /* success / partial_success */\n+}\n+\n static int\n cxgbe_flow_validate(struct rte_eth_dev *dev,\n \t\t const struct rte_flow_attr *attr,\n@@ -577,7 +637,7 @@ static const struct rte_flow_ops cxgbe_flow_ops = {\n \t.create\t\t= cxgbe_flow_create,\n \t.destroy\t= cxgbe_flow_destroy,\n \t.flush\t\t= NULL,\n-\t.query\t\t= NULL,\n+\t.query\t\t= cxgbe_flow_query,\n \t.isolate\t= NULL,\n };\n \ndiff --git a/drivers/net/cxgbe/cxgbe_main.c b/drivers/net/cxgbe/cxgbe_main.c\nindex a00e0700d..21ad380ae 100644\n--- a/drivers/net/cxgbe/cxgbe_main.c\n+++ b/drivers/net/cxgbe/cxgbe_main.c\n@@ -1527,6 +1527,7 @@ int cxgbe_probe(struct adapter *adapter)\n \n \tt4_os_lock_init(&adapter->mbox_lock);\n \tTAILQ_INIT(&adapter->mbox_list);\n+\tt4_os_lock_init(&adapter->win0_lock);\n \n \terr = t4_prep_adapter(adapter);\n \tif (err)\n", "prefixes": [ "dpdk-dev", "6/7" ] }{ "id": 40931, "url": "