Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2018-2021 HiSilicon Limited.
3 : : */
4 : :
5 : : #include <ethdev_pci.h>
6 : : #include <rte_io.h>
7 : :
8 : : #include "hns3_common.h"
9 : : #include "hns3_regs.h"
10 : : #include "hns3_intr.h"
11 : : #include "hns3_logs.h"
12 : :
13 : : static int
14 : : hns3_ring_space(struct hns3_cmq_ring *ring)
15 : : {
16 : 0 : int ntu = ring->next_to_use;
17 : 0 : int ntc = ring->next_to_clean;
18 : 0 : int used = (ntu - ntc + ring->desc_num) % ring->desc_num;
19 : :
20 : 0 : return ring->desc_num - used - 1;
21 : : }
22 : :
23 : : static bool
24 : : is_valid_csq_clean_head(struct hns3_cmq_ring *ring, int head)
25 : : {
26 : 0 : int ntu = ring->next_to_use;
27 : 0 : int ntc = ring->next_to_clean;
28 : :
29 : 0 : if (ntu > ntc)
30 : 0 : return head >= ntc && head <= ntu;
31 : :
32 : 0 : return head >= ntc || head <= ntu;
33 : : }
34 : :
35 : : /*
36 : : * hns3_allocate_dma_mem - Specific memory alloc for command function.
37 : : * Malloc a memzone, which is a contiguous portion of physical memory identified
38 : : * by a name.
39 : : * @ring: pointer to the ring structure
40 : : * @size: size of memory requested
41 : : * @alignment: what to align the allocation to
42 : : */
43 : : static int
44 : 0 : hns3_allocate_dma_mem(struct hns3_hw *hw, struct hns3_cmq_ring *ring,
45 : : uint64_t size, uint32_t alignment)
46 : : {
47 : : static RTE_ATOMIC(uint64_t) hns3_dma_memzone_id;
48 : : const struct rte_memzone *mz = NULL;
49 : : char z_name[RTE_MEMZONE_NAMESIZE];
50 : :
51 : 0 : snprintf(z_name, sizeof(z_name), "hns3_dma_%" PRIu64,
52 : : rte_atomic_fetch_add_explicit(&hns3_dma_memzone_id, 1, rte_memory_order_relaxed));
53 : 0 : mz = rte_memzone_reserve_bounded(z_name, size, SOCKET_ID_ANY,
54 : : RTE_MEMZONE_IOVA_CONTIG, alignment,
55 : : RTE_PGSIZE_2M);
56 [ # # ]: 0 : if (mz == NULL)
57 : : return -ENOMEM;
58 : :
59 : 0 : ring->buf_size = size;
60 : 0 : ring->desc = mz->addr;
61 : 0 : ring->desc_dma_addr = mz->iova;
62 : 0 : ring->zone = (const void *)mz;
63 : 0 : hns3_dbg(hw, "cmd ring memzone name: %s", mz->name);
64 : :
65 : 0 : return 0;
66 : : }
67 : :
68 : : static void
69 : : hns3_free_dma_mem(struct hns3_cmq_ring *ring)
70 : : {
71 : 0 : rte_memzone_free((const struct rte_memzone *)ring->zone);
72 : 0 : ring->buf_size = 0;
73 : 0 : ring->desc = NULL;
74 : 0 : ring->desc_dma_addr = 0;
75 : 0 : ring->zone = NULL;
76 : 0 : }
77 : :
78 : : static int
79 : 0 : hns3_alloc_cmd_desc(struct hns3_hw *hw, struct hns3_cmq_ring *ring)
80 : : {
81 : 0 : int size = ring->desc_num * sizeof(struct hns3_cmd_desc);
82 : :
83 [ # # ]: 0 : if (hns3_allocate_dma_mem(hw, ring, size, HNS3_CMD_DESC_ALIGNMENT)) {
84 : 0 : hns3_err(hw, "allocate dma mem failed");
85 : 0 : return -ENOMEM;
86 : : }
87 : :
88 : : return 0;
89 : : }
90 : :
91 : : static void
92 : : hns3_free_cmd_desc(__rte_unused struct hns3_hw *hw, struct hns3_cmq_ring *ring)
93 : : {
94 [ # # ]: 0 : if (ring->desc)
95 : : hns3_free_dma_mem(ring);
96 : : }
97 : :
98 : : static int
99 : 0 : hns3_alloc_cmd_queue(struct hns3_hw *hw, int ring_type)
100 : : {
101 : : struct hns3_cmq_ring *ring =
102 [ # # ]: 0 : (ring_type == HNS3_TYPE_CSQ) ? &hw->cmq.csq : &hw->cmq.crq;
103 : : int ret;
104 : :
105 : 0 : ring->ring_type = ring_type;
106 : 0 : ring->hw = hw;
107 : :
108 : 0 : ret = hns3_alloc_cmd_desc(hw, ring);
109 [ # # ]: 0 : if (ret)
110 [ # # ]: 0 : hns3_err(hw, "descriptor %s alloc error %d",
111 : : (ring_type == HNS3_TYPE_CSQ) ? "CSQ" : "CRQ", ret);
112 : :
113 : 0 : return ret;
114 : : }
115 : :
116 : : void
117 : 0 : hns3_cmd_reuse_desc(struct hns3_cmd_desc *desc, bool is_read)
118 : : {
119 : 0 : desc->flag = rte_cpu_to_le_16(HNS3_CMD_FLAG_NO_INTR | HNS3_CMD_FLAG_IN);
120 [ # # ]: 0 : if (is_read)
121 : 0 : desc->flag |= rte_cpu_to_le_16(HNS3_CMD_FLAG_WR);
122 : : else
123 : : desc->flag &= rte_cpu_to_le_16(~HNS3_CMD_FLAG_WR);
124 : 0 : }
125 : :
126 : : void
127 [ # # ]: 0 : hns3_cmd_setup_basic_desc(struct hns3_cmd_desc *desc,
128 : : enum hns3_opcode_type opcode, bool is_read)
129 : : {
130 : : memset((void *)desc, 0, sizeof(struct hns3_cmd_desc));
131 : 0 : desc->opcode = rte_cpu_to_le_16(opcode);
132 : 0 : desc->flag = rte_cpu_to_le_16(HNS3_CMD_FLAG_NO_INTR | HNS3_CMD_FLAG_IN);
133 : :
134 [ # # ]: 0 : if (is_read)
135 : 0 : desc->flag |= rte_cpu_to_le_16(HNS3_CMD_FLAG_WR);
136 : 0 : }
137 : :
138 : : static void
139 : 0 : hns3_cmd_clear_regs(struct hns3_hw *hw)
140 : : {
141 : 0 : hns3_write_dev(hw, HNS3_CMDQ_TX_ADDR_L_REG, 0);
142 : 0 : hns3_write_dev(hw, HNS3_CMDQ_TX_ADDR_H_REG, 0);
143 : 0 : hns3_write_dev(hw, HNS3_CMDQ_TX_DEPTH_REG, 0);
144 : 0 : hns3_write_dev(hw, HNS3_CMDQ_TX_HEAD_REG, 0);
145 : 0 : hns3_write_dev(hw, HNS3_CMDQ_TX_TAIL_REG, 0);
146 : 0 : hns3_write_dev(hw, HNS3_CMDQ_RX_ADDR_L_REG, 0);
147 : 0 : hns3_write_dev(hw, HNS3_CMDQ_RX_ADDR_H_REG, 0);
148 : 0 : hns3_write_dev(hw, HNS3_CMDQ_RX_DEPTH_REG, 0);
149 : 0 : hns3_write_dev(hw, HNS3_CMDQ_RX_HEAD_REG, 0);
150 : 0 : hns3_write_dev(hw, HNS3_CMDQ_RX_TAIL_REG, 0);
151 : 0 : }
152 : :
153 : : static void
154 : 0 : hns3_cmd_config_regs(struct hns3_cmq_ring *ring)
155 : : {
156 : 0 : uint64_t dma = ring->desc_dma_addr;
157 : :
158 [ # # ]: 0 : if (ring->ring_type == HNS3_TYPE_CSQ) {
159 : 0 : hns3_write_dev(ring->hw, HNS3_CMDQ_TX_ADDR_L_REG,
160 : : lower_32_bits(dma));
161 : 0 : hns3_write_dev(ring->hw, HNS3_CMDQ_TX_ADDR_H_REG,
162 : : upper_32_bits(dma));
163 : 0 : hns3_write_dev(ring->hw, HNS3_CMDQ_TX_DEPTH_REG,
164 : : ring->desc_num >> HNS3_NIC_CMQ_DESC_NUM_S |
165 : : HNS3_NIC_SW_RST_RDY);
166 : 0 : hns3_write_dev(ring->hw, HNS3_CMDQ_TX_HEAD_REG, 0);
167 : 0 : hns3_write_dev(ring->hw, HNS3_CMDQ_TX_TAIL_REG, 0);
168 : : } else {
169 : 0 : hns3_write_dev(ring->hw, HNS3_CMDQ_RX_ADDR_L_REG,
170 : : lower_32_bits(dma));
171 : 0 : hns3_write_dev(ring->hw, HNS3_CMDQ_RX_ADDR_H_REG,
172 : : upper_32_bits(dma));
173 : 0 : hns3_write_dev(ring->hw, HNS3_CMDQ_RX_DEPTH_REG,
174 : : ring->desc_num >> HNS3_NIC_CMQ_DESC_NUM_S);
175 : 0 : hns3_write_dev(ring->hw, HNS3_CMDQ_RX_HEAD_REG, 0);
176 : 0 : hns3_write_dev(ring->hw, HNS3_CMDQ_RX_TAIL_REG, 0);
177 : : }
178 : 0 : }
179 : :
180 : : static void
181 : : hns3_cmd_init_regs(struct hns3_hw *hw)
182 : : {
183 : 0 : hns3_cmd_config_regs(&hw->cmq.csq);
184 : 0 : hns3_cmd_config_regs(&hw->cmq.crq);
185 : : }
186 : :
187 : : static int
188 : 0 : hns3_cmd_csq_clean(struct hns3_hw *hw)
189 : : {
190 : : struct hns3_cmq_ring *csq = &hw->cmq.csq;
191 : : uint32_t head;
192 : : uint32_t addr;
193 : : int clean;
194 : :
195 : 0 : head = hns3_read_dev(hw, HNS3_CMDQ_TX_HEAD_REG);
196 : 0 : addr = hns3_read_dev(hw, HNS3_CMDQ_TX_ADDR_L_REG);
197 [ # # # # : 0 : if (!is_valid_csq_clean_head(csq, head) || addr == 0) {
# # ]
198 : 0 : hns3_err(hw, "wrong cmd addr(%0x) head (%u, %u-%u)", addr, head,
199 : : csq->next_to_use, csq->next_to_clean);
200 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
201 : 0 : rte_atomic_store_explicit(&hw->reset.disable_cmd, 1,
202 : : rte_memory_order_relaxed);
203 : 0 : hns3_schedule_delayed_reset(HNS3_DEV_HW_TO_ADAPTER(hw));
204 : : }
205 : :
206 : 0 : return -EIO;
207 : : }
208 : :
209 : 0 : clean = (head - csq->next_to_clean + csq->desc_num) % csq->desc_num;
210 : 0 : csq->next_to_clean = head;
211 : 0 : return clean;
212 : : }
213 : :
214 : : static int
215 : : hns3_cmd_csq_done(struct hns3_hw *hw)
216 : : {
217 : 0 : uint32_t head = hns3_read_dev(hw, HNS3_CMDQ_TX_HEAD_REG);
218 : :
219 : 0 : return head == hw->cmq.csq.next_to_use;
220 : : }
221 : :
222 : : static bool
223 : 0 : hns3_is_special_opcode(uint16_t opcode)
224 : : {
225 : : /*
226 : : * These commands have several descriptors,
227 : : * and use the first one to save opcode and return value.
228 : : */
229 : 0 : uint16_t spec_opcode[] = {HNS3_OPC_STATS_64_BIT,
230 : : HNS3_OPC_STATS_32_BIT,
231 : : HNS3_OPC_STATS_MAC,
232 : : HNS3_OPC_STATS_MAC_ALL,
233 : : HNS3_OPC_QUERY_32_BIT_REG,
234 : : HNS3_OPC_QUERY_64_BIT_REG,
235 : : HNS3_OPC_QUERY_CLEAR_MPF_RAS_INT,
236 : : HNS3_OPC_QUERY_CLEAR_PF_RAS_INT,
237 : : HNS3_OPC_QUERY_CLEAR_ALL_MPF_MSIX_INT,
238 : : HNS3_OPC_QUERY_CLEAR_ALL_PF_MSIX_INT,
239 : : HNS3_OPC_QUERY_ALL_ERR_INFO,};
240 : : uint32_t i;
241 : :
242 [ # # ]: 0 : for (i = 0; i < RTE_DIM(spec_opcode); i++)
243 [ # # ]: 0 : if (spec_opcode[i] == opcode)
244 : : return true;
245 : :
246 : : return false;
247 : : }
248 : :
249 : : static int
250 : : hns3_cmd_convert_err_code(uint16_t desc_ret)
251 : : {
252 : : static const struct {
253 : : uint16_t imp_errcode;
254 : : int linux_errcode;
255 : : } hns3_cmdq_status[] = {
256 : : {HNS3_CMD_EXEC_SUCCESS, 0},
257 : : {HNS3_CMD_NO_AUTH, -EPERM},
258 : : {HNS3_CMD_NOT_SUPPORTED, -EOPNOTSUPP},
259 : : {HNS3_CMD_QUEUE_FULL, -EXFULL},
260 : : {HNS3_CMD_NEXT_ERR, -ENOSR},
261 : : {HNS3_CMD_UNEXE_ERR, -ENOTBLK},
262 : : {HNS3_CMD_PARA_ERR, -EINVAL},
263 : : {HNS3_CMD_RESULT_ERR, -ERANGE},
264 : : {HNS3_CMD_TIMEOUT, -ETIME},
265 : : {HNS3_CMD_HILINK_ERR, -ENOLINK},
266 : : {HNS3_CMD_QUEUE_ILLEGAL, -ENXIO},
267 : : {HNS3_CMD_INVALID, -EBADR},
268 : : {HNS3_CMD_ROH_CHECK_FAIL, -EINVAL}
269 : : };
270 : :
271 : : uint32_t i;
272 : :
273 [ # # ]: 0 : for (i = 0; i < RTE_DIM(hns3_cmdq_status); i++)
274 [ # # ]: 0 : if (hns3_cmdq_status[i].imp_errcode == desc_ret)
275 : 0 : return hns3_cmdq_status[i].linux_errcode;
276 : :
277 : : return -EREMOTEIO;
278 : : }
279 : :
280 : : static int
281 : 0 : hns3_cmd_get_hardware_reply(struct hns3_hw *hw,
282 : : struct hns3_cmd_desc *desc, int num, int ntc)
283 : : {
284 : : uint16_t opcode, desc_ret;
285 : : int current_ntc = ntc;
286 : : int handle;
287 : :
288 : 0 : opcode = rte_le_to_cpu_16(desc[0].opcode);
289 [ # # ]: 0 : for (handle = 0; handle < num; handle++) {
290 : : /* Get the result of hardware write back */
291 : 0 : desc[handle] = hw->cmq.csq.desc[current_ntc];
292 : :
293 : 0 : current_ntc++;
294 [ # # ]: 0 : if (current_ntc == hw->cmq.csq.desc_num)
295 : : current_ntc = 0;
296 : : }
297 : :
298 [ # # ]: 0 : if (likely(!hns3_is_special_opcode(opcode)))
299 : 0 : desc_ret = rte_le_to_cpu_16(desc[num - 1].retval);
300 : : else
301 : 0 : desc_ret = rte_le_to_cpu_16(desc[0].retval);
302 : :
303 : 0 : hw->cmq.last_status = desc_ret;
304 : 0 : return hns3_cmd_convert_err_code(desc_ret);
305 : : }
306 : :
307 : : static uint32_t hns3_get_cmd_tx_timeout(uint16_t opcode)
308 : : {
309 : 0 : if (opcode == HNS3_OPC_CFG_RST_TRIGGER)
310 : 0 : return HNS3_COMQ_CFG_RST_TIMEOUT;
311 : :
312 : : return HNS3_CMDQ_TX_TIMEOUT_DEFAULT;
313 : : }
314 : :
315 [ # # ]: 0 : static int hns3_cmd_poll_reply(struct hns3_hw *hw, uint16_t opcode)
316 : : {
317 : : uint32_t cmdq_tx_timeout = hns3_get_cmd_tx_timeout(opcode);
318 : : struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
319 : : uint32_t timeout = 0;
320 : :
321 : : do {
322 [ # # ]: 0 : if (hns3_cmd_csq_done(hw))
323 : : return 0;
324 : :
325 [ # # ]: 0 : if (rte_atomic_load_explicit(&hw->reset.disable_cmd, rte_memory_order_relaxed)) {
326 : 0 : hns3_err(hw,
327 : : "Don't wait for reply because of disable_cmd");
328 : 0 : return -EBUSY;
329 : : }
330 : :
331 [ # # ]: 0 : if (is_reset_pending(hns)) {
332 : 0 : hns3_err(hw, "Don't wait for reply because of reset pending");
333 : 0 : return -EIO;
334 : : }
335 : :
336 : 0 : rte_delay_us(1);
337 : 0 : timeout++;
338 [ # # ]: 0 : } while (timeout < cmdq_tx_timeout);
339 : 0 : hns3_err(hw, "Wait for reply timeout");
340 : 0 : return -ETIME;
341 : : }
342 : :
343 : : /*
344 : : * hns3_cmd_send - send command to command queue
345 : : *
346 : : * @param hw
347 : : * pointer to the hw struct
348 : : * @param desc
349 : : * prefilled descriptor for describing the command
350 : : * @param num
351 : : * the number of descriptors to be sent
352 : : * @return
353 : : * - -EBUSY if detect device is in resetting
354 : : * - -EIO if detect cmd csq corrupted (due to reset) or
355 : : * there is reset pending
356 : : * - -ENOMEM/-ETIME/...(Non-Zero) if other error case
357 : : * - Zero if operation completed successfully
358 : : *
359 : : * Note -BUSY/-EIO only used in reset case
360 : : *
361 : : * Note this is the main send command for command queue, it
362 : : * sends the queue, cleans the queue, etc
363 : : */
364 : : int
365 : 0 : hns3_cmd_send(struct hns3_hw *hw, struct hns3_cmd_desc *desc, int num)
366 : : {
367 : : struct hns3_cmd_desc *desc_to_use;
368 : : int handle = 0;
369 : : int retval;
370 : : uint32_t ntc;
371 : :
372 [ # # ]: 0 : if (rte_atomic_load_explicit(&hw->reset.disable_cmd, rte_memory_order_relaxed))
373 : : return -EBUSY;
374 : :
375 : 0 : rte_spinlock_lock(&hw->cmq.csq.lock);
376 : :
377 : : /* Clean the command send queue */
378 : 0 : retval = hns3_cmd_csq_clean(hw);
379 [ # # ]: 0 : if (retval < 0) {
380 : : rte_spinlock_unlock(&hw->cmq.csq.lock);
381 : 0 : return retval;
382 : : }
383 : :
384 [ # # ]: 0 : if (num > hns3_ring_space(&hw->cmq.csq)) {
385 : : rte_spinlock_unlock(&hw->cmq.csq.lock);
386 : 0 : return -ENOMEM;
387 : : }
388 : :
389 : : /*
390 : : * Record the location of desc in the ring for this time
391 : : * which will be use for hardware to write back
392 : : */
393 : : ntc = hw->cmq.csq.next_to_use;
394 : :
395 [ # # ]: 0 : while (handle < num) {
396 : 0 : desc_to_use = &hw->cmq.csq.desc[hw->cmq.csq.next_to_use];
397 : 0 : *desc_to_use = desc[handle];
398 : 0 : (hw->cmq.csq.next_to_use)++;
399 [ # # ]: 0 : if (hw->cmq.csq.next_to_use == hw->cmq.csq.desc_num)
400 : 0 : hw->cmq.csq.next_to_use = 0;
401 : 0 : handle++;
402 : : }
403 : :
404 : : /* Write to hardware */
405 : 0 : hns3_write_dev(hw, HNS3_CMDQ_TX_TAIL_REG, hw->cmq.csq.next_to_use);
406 : :
407 : : /*
408 : : * If the command is sync, wait for the firmware to write back,
409 : : * if multi descriptors to be sent, use the first one to check.
410 : : */
411 [ # # ]: 0 : if (HNS3_CMD_SEND_SYNC(rte_le_to_cpu_16(desc->flag))) {
412 : 0 : retval = hns3_cmd_poll_reply(hw, desc->opcode);
413 [ # # ]: 0 : if (!retval)
414 : 0 : retval = hns3_cmd_get_hardware_reply(hw, desc, num,
415 : : ntc);
416 : : }
417 : :
418 : : rte_spinlock_unlock(&hw->cmq.csq.lock);
419 : 0 : return retval;
420 : : }
421 : :
422 : : static const char *
423 : 0 : hns3_get_caps_name(uint32_t caps_id)
424 : : {
425 : : const struct {
426 : : enum HNS3_CAPS_BITS caps;
427 : : const char *name;
428 : 0 : } dev_caps[] = {
429 : : { HNS3_CAPS_FD_QUEUE_REGION_B, "fd_queue_region" },
430 : : { HNS3_CAPS_PTP_B, "ptp" },
431 : : { HNS3_CAPS_SIMPLE_BD_B, "simple_bd" },
432 : : { HNS3_CAPS_TX_PUSH_B, "tx_push" },
433 : : { HNS3_CAPS_PHY_IMP_B, "phy_imp" },
434 : : { HNS3_CAPS_TQP_TXRX_INDEP_B, "tqp_txrx_indep" },
435 : : { HNS3_CAPS_HW_PAD_B, "hw_pad" },
436 : : { HNS3_CAPS_STASH_B, "stash" },
437 : : { HNS3_CAPS_UDP_TUNNEL_CSUM_B, "udp_tunnel_csum" },
438 : : { HNS3_CAPS_RAS_IMP_B, "ras_imp" },
439 : : { HNS3_CAPS_RXD_ADV_LAYOUT_B, "rxd_adv_layout" },
440 : : { HNS3_CAPS_TM_B, "tm_capability" },
441 : : { HNS3_CAPS_FC_AUTO_B, "fc_autoneg" }
442 : : };
443 : : uint32_t i;
444 : :
445 [ # # ]: 0 : for (i = 0; i < RTE_DIM(dev_caps); i++) {
446 [ # # ]: 0 : if (dev_caps[i].caps == caps_id)
447 : 0 : return dev_caps[i].name;
448 : : }
449 : :
450 : : return "unknown";
451 : : }
452 : :
453 : : static void
454 : 0 : hns3_mask_capability(struct hns3_hw *hw,
455 : : struct hns3_query_version_cmd *cmd)
456 : : {
457 : : #define MAX_CAPS_BIT 64
458 : :
459 : : struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
460 : : uint64_t caps_org, caps_new, caps_masked;
461 : : uint32_t i;
462 : :
463 [ # # ]: 0 : if (hns->dev_caps_mask == 0)
464 : 0 : return;
465 : :
466 : : memcpy(&caps_org, &cmd->caps[0], sizeof(caps_org));
467 : : caps_org = rte_le_to_cpu_64(caps_org);
468 : 0 : caps_new = caps_org ^ (caps_org & hns->dev_caps_mask);
469 : 0 : caps_masked = caps_org ^ caps_new;
470 : : caps_new = rte_cpu_to_le_64(caps_new);
471 : 0 : memcpy(&cmd->caps[0], &caps_new, sizeof(caps_new));
472 : :
473 [ # # ]: 0 : for (i = 0; i < MAX_CAPS_BIT; i++) {
474 [ # # ]: 0 : if (!(caps_masked & BIT_ULL(i)))
475 : 0 : continue;
476 : 0 : hns3_info(hw, "mask capability: id-%u, name-%s.",
477 : : i, hns3_get_caps_name(i));
478 : : }
479 : : }
480 : :
481 : : static void
482 : 0 : hns3_parse_capability(struct hns3_hw *hw,
483 : : struct hns3_query_version_cmd *cmd)
484 : : {
485 : 0 : uint64_t caps = ((uint64_t)rte_le_to_cpu_32(cmd->caps[1]) << 32) |
486 : 0 : rte_le_to_cpu_32(cmd->caps[0]);
487 : :
488 [ # # ]: 0 : if (hns3_get_bit(caps, HNS3_CAPS_FD_QUEUE_REGION_B))
489 : 0 : hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_FD_QUEUE_REGION_B,
490 : : 1);
491 [ # # ]: 0 : if (hns3_get_bit(caps, HNS3_CAPS_PTP_B)) {
492 : : /*
493 : : * PTP depends on special packet type reported by hardware which
494 : : * enabled rxd advanced layout, so if the hardware doesn't
495 : : * support rxd advanced layout, driver should ignore the PTP
496 : : * capability.
497 : : */
498 [ # # ]: 0 : if (hns3_get_bit(caps, HNS3_CAPS_RXD_ADV_LAYOUT_B))
499 : 0 : hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_PTP_B, 1);
500 : : else
501 : 0 : hns3_warn(hw, "ignore PTP capability due to lack of "
502 : : "rxd advanced layout capability.");
503 : : }
504 [ # # ]: 0 : if (hns3_get_bit(caps, HNS3_CAPS_SIMPLE_BD_B))
505 : 0 : hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_SIMPLE_BD_B, 1);
506 [ # # ]: 0 : if (hns3_get_bit(caps, HNS3_CAPS_TX_PUSH_B))
507 : 0 : hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_TX_PUSH_B, 1);
508 [ # # ]: 0 : if (hns3_get_bit(caps, HNS3_CAPS_PHY_IMP_B))
509 : 0 : hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_COPPER_B, 1);
510 [ # # ]: 0 : if (hns3_get_bit(caps, HNS3_CAPS_TQP_TXRX_INDEP_B))
511 : 0 : hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_INDEP_TXRX_B, 1);
512 [ # # ]: 0 : if (hns3_get_bit(caps, HNS3_CAPS_STASH_B))
513 : 0 : hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_STASH_B, 1);
514 [ # # ]: 0 : if (hns3_get_bit(caps, HNS3_CAPS_RXD_ADV_LAYOUT_B))
515 : 0 : hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_RXD_ADV_LAYOUT_B,
516 : : 1);
517 [ # # ]: 0 : if (hns3_get_bit(caps, HNS3_CAPS_UDP_TUNNEL_CSUM_B))
518 : 0 : hns3_set_bit(hw->capability,
519 : : HNS3_DEV_SUPPORT_OUTER_UDP_CKSUM_B, 1);
520 [ # # ]: 0 : if (hns3_get_bit(caps, HNS3_CAPS_RAS_IMP_B))
521 : 0 : hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_RAS_IMP_B, 1);
522 [ # # ]: 0 : if (hns3_get_bit(caps, HNS3_CAPS_TM_B))
523 : 0 : hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_TM_B, 1);
524 [ # # ]: 0 : if (hns3_get_bit(caps, HNS3_CAPS_FC_AUTO_B))
525 : 0 : hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_FC_AUTO_B, 1);
526 [ # # ]: 0 : if (hns3_get_bit(caps, HNS3_CAPS_GRO_B))
527 : 0 : hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_GRO_B, 1);
528 [ # # ]: 0 : if (hns3_get_bit(caps, HNS3_CAPS_VF_MULTI_TCS_B))
529 : 0 : hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_VF_MULTI_TCS_B, 1);
530 : 0 : }
531 : :
532 : : static uint32_t
533 : : hns3_build_api_caps(void)
534 : : {
535 : : uint32_t api_caps = 0;
536 : :
537 : : hns3_set_bit(api_caps, HNS3_API_CAP_FLEX_RSS_TBL_B, 1);
538 : :
539 : : return rte_cpu_to_le_32(api_caps);
540 : : }
541 : :
542 : : static void
543 : 0 : hns3_set_dcb_capability(struct hns3_hw *hw)
544 : : {
545 : : struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
546 : : struct rte_pci_device *pci_dev;
547 : : struct rte_eth_dev *eth_dev;
548 : : uint16_t device_id;
549 : :
550 [ # # ]: 0 : if (hns->is_vf)
551 : : return;
552 : :
553 : 0 : eth_dev = &rte_eth_devices[hw->data->port_id];
554 : 0 : pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
555 : 0 : device_id = pci_dev->id.device_id;
556 : :
557 : 0 : if (device_id == HNS3_DEV_ID_25GE_RDMA ||
558 [ # # ]: 0 : device_id == HNS3_DEV_ID_50GE_RDMA ||
559 : 0 : device_id == HNS3_DEV_ID_100G_RDMA_MACSEC ||
560 [ # # ]: 0 : device_id == HNS3_DEV_ID_200G_RDMA)
561 : 0 : hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_DCB_B, 1);
562 : : }
563 : :
564 : : static void
565 : : hns3_set_default_capability(struct hns3_hw *hw)
566 : : {
567 : 0 : hns3_set_dcb_capability(hw);
568 : :
569 : : /*
570 : : * The firmware of the network engines with HIP08 do not report some
571 : : * capabilities, like GRO. Set default capabilities for it.
572 : : */
573 [ # # ]: 0 : if (hw->revision < PCI_REVISION_ID_HIP09_A)
574 : 0 : hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_GRO_B, 1);
575 : : }
576 : :
577 : : static int
578 : 0 : hns3_cmd_query_firmware_version_and_capability(struct hns3_hw *hw)
579 : : {
580 : : struct hns3_query_version_cmd *resp;
581 : : struct hns3_cmd_desc desc;
582 : : int ret;
583 : :
584 : 0 : hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_QUERY_FW_VER, 1);
585 : : resp = (struct hns3_query_version_cmd *)desc.data;
586 : 0 : resp->api_caps = hns3_build_api_caps();
587 : :
588 : : /* Initialize the cmd function */
589 : 0 : ret = hns3_cmd_send(hw, &desc, 1);
590 [ # # ]: 0 : if (ret)
591 : : return ret;
592 : :
593 : 0 : hw->fw_version = rte_le_to_cpu_32(resp->firmware);
594 : :
595 : : hns3_set_default_capability(hw);
596 : :
597 : : /*
598 : : * Make sure mask the capability before parse capability because it
599 : : * may overwrite resp's data.
600 : : */
601 : 0 : hns3_mask_capability(hw, resp);
602 : 0 : hns3_parse_capability(hw, resp);
603 : :
604 : 0 : return 0;
605 : : }
606 : :
607 : : int
608 : 0 : hns3_cmd_init_queue(struct hns3_hw *hw)
609 : : {
610 : : int ret;
611 : :
612 : : /* Setup the lock for command queue */
613 : : rte_spinlock_init(&hw->cmq.csq.lock);
614 : : rte_spinlock_init(&hw->cmq.crq.lock);
615 : :
616 : : /*
617 : : * Clear up all command register,
618 : : * in case there are some residual values
619 : : */
620 : 0 : hns3_cmd_clear_regs(hw);
621 : :
622 : : /* Setup the queue entries for use cmd queue */
623 : 0 : hw->cmq.csq.desc_num = HNS3_NIC_CMQ_DESC_NUM;
624 : 0 : hw->cmq.crq.desc_num = HNS3_NIC_CMQ_DESC_NUM;
625 : :
626 : : /* Setup queue rings */
627 : 0 : ret = hns3_alloc_cmd_queue(hw, HNS3_TYPE_CSQ);
628 [ # # ]: 0 : if (ret) {
629 : 0 : PMD_INIT_LOG(ERR, "CSQ ring setup error %d", ret);
630 : 0 : return ret;
631 : : }
632 : :
633 : 0 : ret = hns3_alloc_cmd_queue(hw, HNS3_TYPE_CRQ);
634 [ # # ]: 0 : if (ret) {
635 : 0 : PMD_INIT_LOG(ERR, "CRQ ring setup error %d", ret);
636 [ # # ]: 0 : goto err_crq;
637 : : }
638 : :
639 : : return 0;
640 : :
641 : : err_crq:
642 : : hns3_free_cmd_desc(hw, &hw->cmq.csq);
643 : :
644 : : return ret;
645 : : }
646 : :
647 : : static void
648 : : hns3_update_dev_lsc_cap(struct hns3_hw *hw, int fw_compact_cmd_result)
649 : : {
650 : 0 : struct rte_eth_dev *dev = &rte_eth_devices[hw->data->port_id];
651 : :
652 [ # # ]: 0 : if (hw->adapter_state != HNS3_NIC_UNINITIALIZED)
653 : : return;
654 : :
655 [ # # ]: 0 : if (fw_compact_cmd_result != 0) {
656 : : /*
657 : : * If fw_compact_cmd_result is not zero, it means firmware don't
658 : : * support link status change interrupt.
659 : : * Framework already set RTE_ETH_DEV_INTR_LSC bit because driver
660 : : * declared RTE_PCI_DRV_INTR_LSC in drv_flags. It need to clear
661 : : * the RTE_ETH_DEV_INTR_LSC capability when detect firmware
662 : : * don't support link status change interrupt.
663 : : */
664 : 0 : dev->data->dev_flags &= ~RTE_ETH_DEV_INTR_LSC;
665 : : }
666 : : }
667 : :
668 : : static void
669 : : hns3_set_fc_autoneg_cap(struct hns3_adapter *hns, int fw_compact_cmd_result)
670 : : {
671 : : struct hns3_hw *hw = &hns->hw;
672 : : struct hns3_mac *mac = &hw->mac;
673 : :
674 [ # # ]: 0 : if (mac->media_type == HNS3_MEDIA_TYPE_COPPER) {
675 : 0 : hns->pf.support_fc_autoneg = true;
676 : 0 : return;
677 : : }
678 : :
679 : : /*
680 : : * Flow control auto-negotiation requires the cooperation of the driver
681 : : * and firmware.
682 : : */
683 : 0 : hns->pf.support_fc_autoneg = (hns3_dev_get_support(hw, FC_AUTO) &&
684 : : fw_compact_cmd_result == 0) ?
685 [ # # # # ]: 0 : true : false;
686 : : }
687 : :
688 : : static int
689 : 0 : hns3_apply_fw_compat_cmd_result(struct hns3_hw *hw, int result)
690 : : {
691 : : struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
692 : :
693 [ # # # # ]: 0 : if (result != 0 && hns3_dev_get_support(hw, COPPER)) {
694 : 0 : hns3_err(hw, "firmware fails to initialize the PHY, ret = %d.",
695 : : result);
696 : 0 : return result;
697 : : }
698 : :
699 : : hns3_update_dev_lsc_cap(hw, result);
700 : : hns3_set_fc_autoneg_cap(hns, result);
701 : :
702 : : return 0;
703 : : }
704 : :
705 : : static int
706 : 0 : hns3_firmware_compat_config(struct hns3_hw *hw, bool is_init)
707 : : {
708 : : struct hns3_firmware_compat_cmd *req;
709 : : struct hns3_cmd_desc desc;
710 : : uint32_t compat = 0;
711 : :
712 : 0 : hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_FIRMWARE_COMPAT_CFG, false);
713 : : req = (struct hns3_firmware_compat_cmd *)desc.data;
714 : :
715 [ # # ]: 0 : if (is_init) {
716 : : hns3_set_bit(compat, HNS3_LINK_EVENT_REPORT_EN_B, 1);
717 : : hns3_set_bit(compat, HNS3_NCSI_ERROR_REPORT_EN_B, 0);
718 : : hns3_set_bit(compat, HNS3_LLRS_FEC_EN_B, 1);
719 [ # # ]: 0 : if (hns3_dev_get_support(hw, COPPER))
720 : : hns3_set_bit(compat, HNS3_FIRMWARE_PHY_DRIVER_EN_B, 1);
721 [ # # ]: 0 : if (hns3_dev_get_support(hw, FC_AUTO))
722 : 0 : hns3_set_bit(compat, HNS3_MAC_FC_AUTONEG_EN_B, 1);
723 : : }
724 : 0 : req->compat = rte_cpu_to_le_32(compat);
725 : :
726 : 0 : return hns3_cmd_send(hw, &desc, 1);
727 : : }
728 : :
729 : : int
730 : 0 : hns3_cmd_init(struct hns3_hw *hw)
731 : : {
732 : : struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
733 : : uint32_t version;
734 : : int ret;
735 : :
736 : 0 : rte_spinlock_lock(&hw->cmq.csq.lock);
737 : 0 : rte_spinlock_lock(&hw->cmq.crq.lock);
738 : :
739 : 0 : hw->cmq.csq.next_to_clean = 0;
740 : 0 : hw->cmq.csq.next_to_use = 0;
741 : 0 : hw->cmq.crq.next_to_clean = 0;
742 : 0 : hw->cmq.crq.next_to_use = 0;
743 : : hns3_cmd_init_regs(hw);
744 : :
745 : : rte_spinlock_unlock(&hw->cmq.crq.lock);
746 : : rte_spinlock_unlock(&hw->cmq.csq.lock);
747 : :
748 : : /*
749 : : * Check if there is new reset pending, because the higher level
750 : : * reset may happen when lower level reset is being processed.
751 : : */
752 [ # # ]: 0 : if (is_reset_pending(HNS3_DEV_HW_TO_ADAPTER(hw))) {
753 : 0 : PMD_INIT_LOG(ERR, "New reset pending, keep disable cmd");
754 : : ret = -EBUSY;
755 : 0 : goto err_cmd_init;
756 : : }
757 : 0 : rte_atomic_store_explicit(&hw->reset.disable_cmd, 0, rte_memory_order_relaxed);
758 : :
759 : 0 : ret = hns3_cmd_query_firmware_version_and_capability(hw);
760 [ # # ]: 0 : if (ret) {
761 : 0 : PMD_INIT_LOG(ERR, "firmware version query failed %d", ret);
762 : 0 : goto err_cmd_init;
763 : : }
764 : :
765 : 0 : version = hw->fw_version;
766 : 0 : PMD_INIT_LOG(INFO, "The firmware version is %lu.%lu.%lu.%lu",
767 : : hns3_get_field(version, HNS3_FW_VERSION_BYTE3_M,
768 : : HNS3_FW_VERSION_BYTE3_S),
769 : : hns3_get_field(version, HNS3_FW_VERSION_BYTE2_M,
770 : : HNS3_FW_VERSION_BYTE2_S),
771 : : hns3_get_field(version, HNS3_FW_VERSION_BYTE1_M,
772 : : HNS3_FW_VERSION_BYTE1_S),
773 : : hns3_get_field(version, HNS3_FW_VERSION_BYTE0_M,
774 : : HNS3_FW_VERSION_BYTE0_S));
775 : :
776 [ # # ]: 0 : if (hns->is_vf)
777 : : return 0;
778 : :
779 : : /*
780 : : * Requiring firmware to enable some features, fiber port can still
781 : : * work without it, but copper port can't work because the firmware
782 : : * fails to take over the PHY.
783 : : */
784 : 0 : ret = hns3_firmware_compat_config(hw, true);
785 [ # # ]: 0 : if (ret)
786 : 0 : PMD_INIT_LOG(WARNING, "firmware compatible features not "
787 : : "supported, ret = %d.", ret);
788 : :
789 : : /*
790 : : * Perform some corresponding operations based on the firmware
791 : : * compatibility configuration result.
792 : : */
793 : 0 : ret = hns3_apply_fw_compat_cmd_result(hw, ret);
794 [ # # ]: 0 : if (ret)
795 : 0 : goto err_cmd_init;
796 : :
797 : : return 0;
798 : :
799 : 0 : err_cmd_init:
800 : 0 : rte_atomic_store_explicit(&hw->reset.disable_cmd, 1, rte_memory_order_relaxed);
801 : 0 : return ret;
802 : : }
803 : :
804 : : static void
805 : 0 : hns3_destroy_queue(struct hns3_hw *hw, struct hns3_cmq_ring *ring)
806 : : {
807 : 0 : rte_spinlock_lock(&ring->lock);
808 : :
809 : : hns3_free_cmd_desc(hw, ring);
810 : :
811 : : rte_spinlock_unlock(&ring->lock);
812 : 0 : }
813 : :
814 : : void
815 : 0 : hns3_cmd_destroy_queue(struct hns3_hw *hw)
816 : : {
817 : 0 : hns3_destroy_queue(hw, &hw->cmq.csq);
818 : 0 : hns3_destroy_queue(hw, &hw->cmq.crq);
819 : 0 : }
820 : :
821 : : void
822 : 0 : hns3_cmd_uninit(struct hns3_hw *hw)
823 : : {
824 : : struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
825 : :
826 [ # # ]: 0 : if (!hns->is_vf)
827 : 0 : (void)hns3_firmware_compat_config(hw, false);
828 : :
829 : 0 : rte_atomic_store_explicit(&hw->reset.disable_cmd, 1, rte_memory_order_relaxed);
830 : :
831 : : /*
832 : : * A delay is added to ensure that the register cleanup operations
833 : : * will not be performed concurrently with the firmware command and
834 : : * ensure that all the reserved commands are executed.
835 : : * Concurrency may occur in two scenarios: asynchronous command and
836 : : * timeout command. If the command fails to be executed due to busy
837 : : * scheduling, the command will be processed in the next scheduling
838 : : * of the firmware.
839 : : */
840 : : rte_delay_ms(HNS3_CMDQ_CLEAR_WAIT_TIME);
841 : :
842 : 0 : rte_spinlock_lock(&hw->cmq.csq.lock);
843 : 0 : rte_spinlock_lock(&hw->cmq.crq.lock);
844 : 0 : hns3_cmd_clear_regs(hw);
845 : : rte_spinlock_unlock(&hw->cmq.crq.lock);
846 : : rte_spinlock_unlock(&hw->cmq.csq.lock);
847 : 0 : }
|