Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright 2024 NXP
3 : : */
4 : :
5 : : #include <ethdev_pci.h>
6 : :
7 : : #include "enetc_logs.h"
8 : : #include "enetc.h"
9 : :
10 : : #define NTMP_RSST_ID 3
11 : :
12 : : /* Define NTMP Access Method */
13 : : #define NTMP_AM_ENTRY_ID 0
14 : : #define NTMP_AM_EXACT_KEY 1
15 : : #define NTMP_AM_SEARCH 2
16 : : #define NTMP_AM_TERNARY_KEY 3
17 : :
18 : : /* Define NTMP Header Version */
19 : : #define NTMP_HEADER_VERSION2 2
20 : :
21 : : #define NTMP_REQ_HDR_NPF BIT(15)
22 : :
23 : : #define NTMP_RESP_LEN_MASK GENMASK(19, 0)
24 : : #define NTMP_REQ_LEN_MASK GENMASK(31, 20)
25 : :
26 : : #define ENETC_NTMP_ENTRY_ID_SIZE 4
27 : :
28 : : #define ENETC_RSS_TABLE_ENTRY_NUM 64
29 : : #define ENETC_RSS_CFGEU BIT(0)
30 : : #define ENETC_RSS_STSEU BIT(1)
31 : : #define ENETC_RSS_STSE_DATA_SIZE(n) ((n) * 8)
32 : : #define ENETC_RSS_CFGE_DATA_SIZE(n) (n)
33 : :
34 : : #define NTMP_REQ_RESP_LEN(req, resp) (((req) << 20 & NTMP_REQ_LEN_MASK) | \
35 : : ((resp) & NTMP_RESP_LEN_MASK))
36 : :
37 : : static inline uint32_t
38 : : netc_cbdr_read(void *reg)
39 : : {
40 : : return rte_read32(reg);
41 : : }
42 : :
43 : : static inline void
44 : : netc_cbdr_write(void *reg, uint32_t val)
45 : : {
46 : : rte_write32(val, reg);
47 : : }
48 : :
49 : : static inline void
50 : : ntmp_fill_request_headr(union netc_cbd *cbd, dma_addr_t dma,
51 : : int len, int table_id, int cmd,
52 : : int access_method)
53 : : {
54 : : dma_addr_t dma_align;
55 : :
56 : : memset(cbd, 0, sizeof(*cbd));
57 : : dma_align = dma;
58 : 0 : cbd->ntmp_req_hdr.addr = dma_align;
59 : 0 : cbd->ntmp_req_hdr.len = len;
60 : 0 : cbd->ntmp_req_hdr.cmd = cmd;
61 : : cbd->ntmp_req_hdr.access_method = access_method;
62 : 0 : cbd->ntmp_req_hdr.table_id = table_id;
63 : 0 : cbd->ntmp_req_hdr.hdr_ver = NTMP_HEADER_VERSION2;
64 : : cbd->ntmp_req_hdr.cci = 0;
65 : : cbd->ntmp_req_hdr.rr = 0; /* Must be set to 0 by SW. */
66 : : /* For NTMP version 2.0 or later version */
67 : 0 : cbd->ntmp_req_hdr.npf = NTMP_REQ_HDR_NPF;
68 : 0 : }
69 : :
70 : : static inline int
71 : : netc_get_free_cbd_num(struct netc_cbdr *cbdr)
72 : : {
73 : 0 : return (cbdr->next_to_clean - cbdr->next_to_use - 1 + cbdr->bd_num) %
74 : : cbdr->bd_num;
75 : : }
76 : :
77 : : static inline union
78 : : netc_cbd *netc_get_cbd(struct netc_cbdr *cbdr, int index)
79 : : {
80 : 0 : return &((union netc_cbd *)(cbdr->addr_base_align))[index];
81 : : }
82 : :
83 : : static void
84 : 0 : netc_clean_cbdr(struct netc_cbdr *cbdr)
85 : : {
86 : : union netc_cbd *cbd;
87 : : uint32_t i;
88 : :
89 : 0 : i = cbdr->next_to_clean;
90 [ # # ]: 0 : while (netc_cbdr_read(cbdr->regs.cir) != i) {
91 : 0 : cbd = netc_get_cbd(cbdr, i);
92 : : memset(cbd, 0, sizeof(*cbd));
93 : : dcbf(cbd);
94 : 0 : i = (i + 1) % cbdr->bd_num;
95 : : }
96 : :
97 : 0 : cbdr->next_to_clean = i;
98 : 0 : }
99 : :
100 : : static int
101 : 0 : netc_xmit_ntmp_cmd(struct netc_cbdr *cbdr, union netc_cbd *cbd)
102 : : {
103 : : union netc_cbd *ring_cbd;
104 : : uint32_t i, err = 0;
105 : : uint16_t status;
106 : 0 : uint32_t timeout = cbdr->timeout;
107 : 0 : uint32_t delay = cbdr->delay;
108 : :
109 [ # # ]: 0 : if (unlikely(!cbdr->addr_base))
110 : : return -EFAULT;
111 : :
112 : 0 : rte_spinlock_lock(&cbdr->ring_lock);
113 : :
114 [ # # ]: 0 : if (unlikely(!netc_get_free_cbd_num(cbdr)))
115 : 0 : netc_clean_cbdr(cbdr);
116 : :
117 : 0 : i = cbdr->next_to_use;
118 : : ring_cbd = netc_get_cbd(cbdr, i);
119 : :
120 : : /* Copy command BD to the ring */
121 : 0 : *ring_cbd = *cbd;
122 : : /* Update producer index of both software and hardware */
123 : 0 : i = (i + 1) % cbdr->bd_num;
124 : : dcbf(ring_cbd);
125 : 0 : cbdr->next_to_use = i;
126 : 0 : netc_cbdr_write(cbdr->regs.pir, i);
127 : 0 : ENETC_PMD_DEBUG("Control msg sent PIR = %d, CIR = %d", netc_cbdr_read(cbdr->regs.pir),
128 : : netc_cbdr_read(cbdr->regs.cir));
129 : : do {
130 [ # # ]: 0 : if (netc_cbdr_read(cbdr->regs.cir) == i) {
131 : : dccivac(ring_cbd);
132 : 0 : ENETC_PMD_DEBUG("got response");
133 : 0 : ENETC_PMD_DEBUG("Matched = %d, status = 0x%x",
134 : : ring_cbd->ntmp_resp_hdr.num_matched,
135 : : ring_cbd->ntmp_resp_hdr.error_rr);
136 : 0 : break;
137 : : }
138 : 0 : rte_delay_us(delay);
139 [ # # ]: 0 : } while (timeout--);
140 : :
141 [ # # ]: 0 : if (timeout <= 0)
142 : 0 : ENETC_PMD_ERR("no response of RSS configuration");
143 : :
144 : 0 : ENETC_PMD_DEBUG("CIR after receive = %d, SICBDRSR = 0x%x",
145 : : netc_cbdr_read(cbdr->regs.cir),
146 : : netc_cbdr_read(cbdr->regs.st));
147 : : /* Check the writeback error status */
148 : 0 : status = ring_cbd->ntmp_resp_hdr.error_rr & NTMP_RESP_HDR_ERR;
149 [ # # ]: 0 : if (unlikely(status)) {
150 : 0 : ENETC_PMD_ERR("Command BD error: 0x%04x", status);
151 : : err = -EIO;
152 : : }
153 : :
154 : 0 : netc_clean_cbdr(cbdr);
155 : : rte_spinlock_unlock(&cbdr->ring_lock);
156 : :
157 : 0 : return err;
158 : : }
159 : :
160 : : int
161 : 0 : enetc_ntmp_rsst_query_or_update_entry(struct netc_cbdr *cbdr, uint32_t *table,
162 : : int count, bool query)
163 : : {
164 : : struct rsst_req_update *requ;
165 : : struct rsst_req_query *req;
166 : : union netc_cbd cbd;
167 : : uint32_t len, data_size;
168 : : dma_addr_t dma;
169 : : int err, i;
170 : : void *tmp;
171 : :
172 [ # # ]: 0 : if (count != ENETC_RSS_TABLE_ENTRY_NUM)
173 : : /* HW only takes in a full 64 entry table */
174 : : return -EINVAL;
175 : :
176 [ # # ]: 0 : if (query)
177 : : data_size = ENETC_NTMP_ENTRY_ID_SIZE + ENETC_RSS_STSE_DATA_SIZE(count) +
178 : : ENETC_RSS_CFGE_DATA_SIZE(count);
179 : : else
180 : : data_size = sizeof(*requ) + count * sizeof(uint8_t);
181 : :
182 : 0 : tmp = rte_malloc(NULL, data_size, ENETC_CBDR_ALIGN);
183 [ # # ]: 0 : if (!tmp)
184 : : return -ENOMEM;
185 : :
186 : 0 : dma = rte_mem_virt2iova(tmp);
187 : : req = tmp;
188 : : /* Set the request data buffer */
189 [ # # ]: 0 : if (query) {
190 : 0 : len = NTMP_REQ_RESP_LEN(sizeof(*req), data_size);
191 : : ntmp_fill_request_headr(&cbd, dma, len, NTMP_RSST_ID,
192 : : NTMP_CMD_QUERY, NTMP_AM_ENTRY_ID);
193 : : } else {
194 : : requ = (struct rsst_req_update *)req;
195 : 0 : requ->crd.update_act = (ENETC_RSS_CFGEU | ENETC_RSS_STSEU);
196 [ # # ]: 0 : for (i = 0; i < count; i++)
197 : 0 : requ->groups[i] = (uint8_t)(table[i]);
198 : :
199 : 0 : len = NTMP_REQ_RESP_LEN(data_size, 0);
200 : : ntmp_fill_request_headr(&cbd, dma, len, NTMP_RSST_ID,
201 : : NTMP_CMD_UPDATE, NTMP_AM_ENTRY_ID);
202 : : dcbf(requ);
203 : : }
204 : :
205 : 0 : err = netc_xmit_ntmp_cmd(cbdr, &cbd);
206 [ # # ]: 0 : if (err) {
207 [ # # ]: 0 : ENETC_PMD_ERR("%s RSS table entry failed (%d)!",
208 : : query ? "Query" : "Update", err);
209 : 0 : goto end;
210 : : }
211 : :
212 [ # # ]: 0 : if (query) {
213 : : uint8_t *group = (uint8_t *)req;
214 : :
215 : : group += ENETC_NTMP_ENTRY_ID_SIZE + ENETC_RSS_STSE_DATA_SIZE(count);
216 [ # # ]: 0 : for (i = 0; i < count; i++)
217 : 0 : table[i] = group[i];
218 : : }
219 : 0 : end:
220 : 0 : rte_free(tmp);
221 : :
222 : 0 : return err;
223 : : }
224 : :
225 : : static int
226 : 0 : netc_setup_cbdr(struct rte_eth_dev *dev, int cbd_num,
227 : : struct netc_cbdr_regs *regs,
228 : : struct netc_cbdr *cbdr)
229 : : {
230 : : int size;
231 : :
232 : 0 : size = cbd_num * sizeof(union netc_cbd) +
233 : : NETC_CBDR_BASE_ADDR_ALIGN;
234 : :
235 : 0 : cbdr->addr_base = rte_malloc(NULL, size, ENETC_CBDR_ALIGN);
236 [ # # ]: 0 : if (!cbdr->addr_base)
237 : : return -ENOMEM;
238 : :
239 : 0 : cbdr->dma_base = rte_mem_virt2iova(cbdr->addr_base);
240 : 0 : cbdr->dma_size = size;
241 : 0 : cbdr->bd_num = cbd_num;
242 : 0 : cbdr->regs = *regs;
243 : 0 : cbdr->dma_dev = dev;
244 : 0 : cbdr->timeout = ENETC_CBDR_TIMEOUT;
245 : 0 : cbdr->delay = ENETC_CBDR_DELAY;
246 : :
247 [ # # ]: 0 : if (getenv("ENETC4_CBDR_TIMEOUT"))
248 : 0 : cbdr->timeout = atoi(getenv("ENETC4_CBDR_TIMEOUT"));
249 : :
250 [ # # ]: 0 : if (getenv("ENETC4_CBDR_DELAY"))
251 : 0 : cbdr->delay = atoi(getenv("ENETC4_CBDR_DELAY"));
252 : :
253 : :
254 : 0 : ENETC_PMD_DEBUG("CBDR timeout = %u and delay = %u", cbdr->timeout,
255 : : cbdr->delay);
256 : : /* The base address of the Control BD Ring must be 128 bytes aligned */
257 : 0 : cbdr->dma_base_align = cbdr->dma_base;
258 : 0 : cbdr->addr_base_align = cbdr->addr_base;
259 : :
260 : 0 : cbdr->next_to_clean = 0;
261 : 0 : cbdr->next_to_use = 0;
262 : : rte_spinlock_init(&cbdr->ring_lock);
263 : :
264 : 0 : netc_cbdr_write(cbdr->regs.mr, ~((uint32_t)NETC_CBDRMR_EN));
265 : : /* Step 1: Configure the base address of the Control BD Ring */
266 : 0 : netc_cbdr_write(cbdr->regs.bar0, lower_32_bits(cbdr->dma_base_align));
267 : 0 : netc_cbdr_write(cbdr->regs.bar1, upper_32_bits(cbdr->dma_base_align));
268 : :
269 : : /* Step 2: Configure the producer index register */
270 : 0 : netc_cbdr_write(cbdr->regs.pir, cbdr->next_to_clean);
271 : :
272 : : /* Step 3: Configure the consumer index register */
273 : 0 : netc_cbdr_write(cbdr->regs.cir, cbdr->next_to_use);
274 : : /* Step4: Configure the number of BDs of the Control BD Ring */
275 : 0 : netc_cbdr_write(cbdr->regs.lenr, cbdr->bd_num);
276 : :
277 : : /* Step 5: Enable the Control BD Ring */
278 : 0 : netc_cbdr_write(cbdr->regs.mr, NETC_CBDRMR_EN);
279 : :
280 : 0 : return 0;
281 : : }
282 : :
283 : : void
284 : 0 : enetc_free_cbdr(struct netc_cbdr *cbdr)
285 : : {
286 : : /* Disable the Control BD Ring */
287 [ # # ]: 0 : if (cbdr->regs.mr != NULL) {
288 : : netc_cbdr_write(cbdr->regs.mr, 0);
289 : 0 : rte_free(cbdr->addr_base);
290 : : memset(cbdr, 0, sizeof(*cbdr));
291 : : }
292 : 0 : }
293 : :
294 : : int
295 : 0 : enetc4_setup_cbdr(struct rte_eth_dev *dev, struct enetc_hw *hw,
296 : : int bd_count, struct netc_cbdr *cbdr)
297 : : {
298 : : struct netc_cbdr_regs regs;
299 : :
300 : 0 : regs.pir = (void *)((size_t)hw->reg + ENETC4_SICBDRPIR);
301 : 0 : regs.cir = (void *)((size_t)hw->reg + ENETC4_SICBDRCIR);
302 : 0 : regs.mr = (void *)((size_t)hw->reg + ENETC4_SICBDRMR);
303 : 0 : regs.st = (void *)((size_t)hw->reg + ENETC4_SICBDRSR);
304 : 0 : regs.bar0 = (void *)((size_t)hw->reg + ENETC4_SICBDRBAR0);
305 : 0 : regs.bar1 = (void *)((size_t)hw->reg + ENETC4_SICBDRBAR1);
306 : 0 : regs.lenr = (void *)((size_t)hw->reg + ENETC4_SICBDRLENR);
307 : 0 : regs.sictr0 = (void *)((size_t)hw->reg + ENETC4_SICTR0);
308 : 0 : regs.sictr1 = (void *)((size_t)hw->reg + ENETC4_SICTR1);
309 : :
310 : 0 : return netc_setup_cbdr(dev, bd_count, ®s, cbdr);
311 : : }
|