Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2021 HiSilicon Limited
3 : : */
4 : :
5 : : #include <inttypes.h>
6 : : #include <string.h>
7 : :
8 : : #include <bus_pci_driver.h>
9 : : #include <rte_cycles.h>
10 : : #include <rte_eal.h>
11 : : #include <rte_io.h>
12 : : #include <rte_log.h>
13 : : #include <rte_malloc.h>
14 : : #include <rte_memzone.h>
15 : : #include <rte_pci.h>
16 : : #include <rte_dmadev_pmd.h>
17 : :
18 : : #include "hisi_dmadev.h"
19 : :
20 [ - + ]: 238 : RTE_LOG_REGISTER_DEFAULT(hisi_dma_logtype, INFO);
21 : : #define HISI_DMA_LOG(level, fmt, args...) \
22 : : rte_log(RTE_LOG_ ## level, hisi_dma_logtype, \
23 : : "%s(): " fmt "\n", __func__, ##args)
24 : : #define HISI_DMA_LOG_RAW(hw, level, fmt, args...) \
25 : : rte_log(RTE_LOG_ ## level, hisi_dma_logtype, \
26 : : "%s %s(): " fmt "\n", (hw)->data->dev_name, \
27 : : __func__, ##args)
28 : : #define HISI_DMA_DEBUG(hw, fmt, args...) \
29 : : HISI_DMA_LOG_RAW(hw, DEBUG, fmt, ## args)
30 : : #define HISI_DMA_INFO(hw, fmt, args...) \
31 : : HISI_DMA_LOG_RAW(hw, INFO, fmt, ## args)
32 : : #define HISI_DMA_WARN(hw, fmt, args...) \
33 : : HISI_DMA_LOG_RAW(hw, WARNING, fmt, ## args)
34 : : #define HISI_DMA_ERR(hw, fmt, args...) \
35 : : HISI_DMA_LOG_RAW(hw, ERR, fmt, ## args)
36 : :
37 : : static uint32_t
38 : : hisi_dma_queue_base(struct hisi_dma_dev *hw)
39 : : {
40 [ # # # # : 0 : if (hw->reg_layout == HISI_DMA_REG_LAYOUT_HIP08)
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
41 : : return HISI_DMA_HIP08_QUEUE_BASE;
42 [ # # # # : 0 : else if (hw->reg_layout == HISI_DMA_REG_LAYOUT_HIP09)
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # ]
43 : : return HISI_DMA_HIP09_QUEUE_BASE;
44 : : else
45 : 0 : return 0;
46 : : }
47 : :
48 : : static volatile void *
49 : : hisi_dma_queue_regaddr(struct hisi_dma_dev *hw, uint32_t qoff)
50 : : {
51 : 0 : uint32_t off = hisi_dma_queue_base(hw) +
52 : 0 : hw->queue_id * HISI_DMA_QUEUE_REGION_SIZE + qoff;
53 : 0 : return (volatile void *)((char *)hw->io_base + off);
54 : : }
55 : :
56 : : static void
57 : : hisi_dma_write_reg(void *base, uint32_t off, uint32_t val)
58 : : {
59 : 0 : rte_write32(rte_cpu_to_le_32(val),
60 : : (volatile void *)((char *)base + off));
61 : : }
62 : :
63 : : static void
64 : : hisi_dma_write_dev(struct hisi_dma_dev *hw, uint32_t off, uint32_t val)
65 : : {
66 : 0 : hisi_dma_write_reg(hw->io_base, off, val);
67 : : }
68 : :
69 : : static void
70 : : hisi_dma_write_queue(struct hisi_dma_dev *hw, uint32_t qoff, uint32_t val)
71 : : {
72 : 0 : uint32_t off = hisi_dma_queue_base(hw) +
73 : 0 : hw->queue_id * HISI_DMA_QUEUE_REGION_SIZE + qoff;
74 : : hisi_dma_write_dev(hw, off, val);
75 : : }
76 : :
77 : : static uint32_t
78 : : hisi_dma_read_reg(void *base, uint32_t off)
79 : : {
80 : 0 : uint32_t val = rte_read32((volatile void *)((char *)base + off));
81 : : return rte_le_to_cpu_32(val);
82 : : }
83 : :
84 : : static uint32_t
85 : : hisi_dma_read_dev(struct hisi_dma_dev *hw, uint32_t off)
86 : : {
87 : 0 : return hisi_dma_read_reg(hw->io_base, off);
88 : : }
89 : :
90 : : static uint32_t
91 : : hisi_dma_read_queue(struct hisi_dma_dev *hw, uint32_t qoff)
92 : : {
93 : 0 : uint32_t off = hisi_dma_queue_base(hw) +
94 : 0 : hw->queue_id * HISI_DMA_QUEUE_REGION_SIZE + qoff;
95 : : return hisi_dma_read_dev(hw, off);
96 : : }
97 : :
98 : : static void
99 : : hisi_dma_update_bit(struct hisi_dma_dev *hw, uint32_t off, uint32_t pos,
100 : : bool set)
101 : : {
102 : : uint32_t tmp = hisi_dma_read_dev(hw, off);
103 : : uint32_t mask = 1u << pos;
104 : 0 : tmp = set ? tmp | mask : tmp & ~mask;
105 : : hisi_dma_write_dev(hw, off, tmp);
106 : 0 : }
107 : :
108 : : static void
109 [ # # ]: 0 : hisi_dma_update_queue_bit(struct hisi_dma_dev *hw, uint32_t qoff, uint32_t pos,
110 : : bool set)
111 : : {
112 : : uint32_t tmp = hisi_dma_read_queue(hw, qoff);
113 : 0 : uint32_t mask = 1u << pos;
114 [ # # ]: 0 : tmp = set ? tmp | mask : tmp & ~mask;
115 : : hisi_dma_write_queue(hw, qoff, tmp);
116 : 0 : }
117 : :
118 : : static void
119 [ # # ]: 0 : hisi_dma_update_queue_mbit(struct hisi_dma_dev *hw, uint32_t qoff,
120 : : uint32_t mask, bool set)
121 : : {
122 : : uint32_t tmp = hisi_dma_read_queue(hw, qoff);
123 [ # # ]: 0 : tmp = set ? tmp | mask : tmp & ~mask;
124 : : hisi_dma_write_queue(hw, qoff, tmp);
125 : 0 : }
126 : :
127 : : #define hisi_dma_poll_hw_state(hw, val, cond, sleep_us, timeout_us) __extension__ ({ \
128 : : uint32_t timeout = 0; \
129 : : while (timeout++ <= (timeout_us)) { \
130 : : (val) = hisi_dma_read_queue(hw, HISI_DMA_QUEUE_FSM_REG); \
131 : : if (cond) \
132 : : break; \
133 : : rte_delay_us(sleep_us); \
134 : : } \
135 : : (cond) ? 0 : -ETIME; \
136 : : })
137 : :
138 : : static int
139 : 0 : hisi_dma_reset_hw(struct hisi_dma_dev *hw)
140 : : {
141 : : #define POLL_SLEEP_US 100
142 : : #define POLL_TIMEOUT_US 10000
143 : :
144 : : uint32_t tmp;
145 : : int ret;
146 : :
147 : 0 : hisi_dma_update_queue_bit(hw, HISI_DMA_QUEUE_CTRL0_REG,
148 : : HISI_DMA_QUEUE_CTRL0_PAUSE_B, true);
149 : 0 : hisi_dma_update_queue_bit(hw, HISI_DMA_QUEUE_CTRL0_REG,
150 : : HISI_DMA_QUEUE_CTRL0_EN_B, false);
151 : :
152 [ # # # # : 0 : ret = hisi_dma_poll_hw_state(hw, tmp,
# # ]
153 : : FIELD_GET(HISI_DMA_QUEUE_FSM_STS_M, tmp) != HISI_DMA_STATE_RUN,
154 : : POLL_SLEEP_US, POLL_TIMEOUT_US);
155 : : if (ret) {
156 : 0 : HISI_DMA_ERR(hw, "disable dma timeout!");
157 : 0 : return ret;
158 : : }
159 : :
160 : 0 : hisi_dma_update_queue_bit(hw, HISI_DMA_QUEUE_CTRL1_REG,
161 : : HISI_DMA_QUEUE_CTRL1_RESET_B, true);
162 : : hisi_dma_write_queue(hw, HISI_DMA_QUEUE_SQ_TAIL_REG, 0);
163 : : hisi_dma_write_queue(hw, HISI_DMA_QUEUE_CQ_HEAD_REG, 0);
164 : 0 : hisi_dma_update_queue_bit(hw, HISI_DMA_QUEUE_CTRL0_REG,
165 : : HISI_DMA_QUEUE_CTRL0_PAUSE_B, false);
166 : :
167 [ # # # # : 0 : ret = hisi_dma_poll_hw_state(hw, tmp,
# # ]
168 : : FIELD_GET(HISI_DMA_QUEUE_FSM_STS_M, tmp) == HISI_DMA_STATE_IDLE,
169 : : POLL_SLEEP_US, POLL_TIMEOUT_US);
170 : : if (ret) {
171 : 0 : HISI_DMA_ERR(hw, "reset dma timeout!");
172 : 0 : return ret;
173 : : }
174 : :
175 : : return 0;
176 : : }
177 : :
178 : : static void
179 : 0 : hisi_dma_init_common(struct hisi_dma_dev *hw)
180 : : {
181 : 0 : hisi_dma_write_queue(hw, HISI_DMA_QUEUE_SQ_BASE_L_REG,
182 [ # # ]: 0 : lower_32_bits(hw->sqe_iova));
183 : 0 : hisi_dma_write_queue(hw, HISI_DMA_QUEUE_SQ_BASE_H_REG,
184 [ # # ]: 0 : upper_32_bits(hw->sqe_iova));
185 : 0 : hisi_dma_write_queue(hw, HISI_DMA_QUEUE_CQ_BASE_L_REG,
186 [ # # ]: 0 : lower_32_bits(hw->cqe_iova));
187 : 0 : hisi_dma_write_queue(hw, HISI_DMA_QUEUE_CQ_BASE_H_REG,
188 [ # # ]: 0 : upper_32_bits(hw->cqe_iova));
189 : 0 : hisi_dma_write_queue(hw, HISI_DMA_QUEUE_SQ_DEPTH_REG,
190 [ # # ]: 0 : hw->sq_depth_mask);
191 [ # # ]: 0 : hisi_dma_write_queue(hw, HISI_DMA_QUEUE_CQ_DEPTH_REG, hw->cq_depth - 1);
192 : : hisi_dma_write_queue(hw, HISI_DMA_QUEUE_SQ_TAIL_REG, 0);
193 : : hisi_dma_write_queue(hw, HISI_DMA_QUEUE_CQ_HEAD_REG, 0);
194 : : hisi_dma_write_queue(hw, HISI_DMA_QUEUE_ERR_INT_NUM0_REG, 0);
195 : : hisi_dma_write_queue(hw, HISI_DMA_QUEUE_ERR_INT_NUM1_REG, 0);
196 : : hisi_dma_write_queue(hw, HISI_DMA_QUEUE_ERR_INT_NUM2_REG, 0);
197 : 0 : }
198 : :
199 : : static void
200 : 0 : hisi_dma_init_hw(struct hisi_dma_dev *hw)
201 : : {
202 : 0 : hisi_dma_init_common(hw);
203 : :
204 [ # # ]: 0 : if (hw->reg_layout == HISI_DMA_REG_LAYOUT_HIP08) {
205 : : hisi_dma_write_queue(hw, HISI_DMA_HIP08_QUEUE_ERR_INT_NUM3_REG,
206 : : 0);
207 : : hisi_dma_write_queue(hw, HISI_DMA_HIP08_QUEUE_ERR_INT_NUM4_REG,
208 : : 0);
209 : : hisi_dma_write_queue(hw, HISI_DMA_HIP08_QUEUE_ERR_INT_NUM5_REG,
210 : : 0);
211 : : hisi_dma_write_queue(hw, HISI_DMA_HIP08_QUEUE_ERR_INT_NUM6_REG,
212 : : 0);
213 : 0 : hisi_dma_update_queue_bit(hw, HISI_DMA_QUEUE_CTRL0_REG,
214 : : HISI_DMA_HIP08_QUEUE_CTRL0_ERR_ABORT_B, false);
215 : 0 : hisi_dma_update_queue_mbit(hw, HISI_DMA_QUEUE_INT_STATUS_REG,
216 : : HISI_DMA_HIP08_QUEUE_INT_MASK_M, true);
217 : 0 : hisi_dma_update_queue_mbit(hw, HISI_DMA_QUEUE_INT_MASK_REG,
218 : : HISI_DMA_HIP08_QUEUE_INT_MASK_M, true);
219 [ # # ]: 0 : } else if (hw->reg_layout == HISI_DMA_REG_LAYOUT_HIP09) {
220 : 0 : hisi_dma_update_queue_mbit(hw, HISI_DMA_QUEUE_CTRL0_REG,
221 : : HISI_DMA_HIP09_QUEUE_CTRL0_ERR_ABORT_M, false);
222 : 0 : hisi_dma_update_queue_mbit(hw, HISI_DMA_QUEUE_INT_STATUS_REG,
223 : : HISI_DMA_HIP09_QUEUE_INT_MASK_M, true);
224 : 0 : hisi_dma_update_queue_mbit(hw, HISI_DMA_QUEUE_INT_MASK_REG,
225 : : HISI_DMA_HIP09_QUEUE_INT_MASK_M, true);
226 : 0 : hisi_dma_update_queue_mbit(hw,
227 : : HISI_DMA_HIP09_QUEUE_ERR_INT_STATUS_REG,
228 : : HISI_DMA_HIP09_QUEUE_ERR_INT_MASK_M, true);
229 : 0 : hisi_dma_update_queue_mbit(hw,
230 : : HISI_DMA_HIP09_QUEUE_ERR_INT_MASK_REG,
231 : : HISI_DMA_HIP09_QUEUE_ERR_INT_MASK_M, true);
232 : 0 : hisi_dma_update_queue_bit(hw, HISI_DMA_QUEUE_CTRL1_REG,
233 : : HISI_DMA_HIP09_QUEUE_CTRL1_VA_ENABLE_B, true);
234 : : hisi_dma_update_bit(hw,
235 : 0 : HISI_DMA_HIP09_QUEUE_CFG_REG(hw->queue_id),
236 : : HISI_DMA_HIP09_QUEUE_CFG_LINK_DOWN_MASK_B,
237 : : true);
238 : : }
239 : 0 : }
240 : :
241 : : static void
242 [ # # ]: 0 : hisi_dma_init_gbl(void *pci_bar, uint8_t revision)
243 : : {
244 : : struct hisi_dma_dev hw;
245 : :
246 : : memset(&hw, 0, sizeof(hw));
247 : 0 : hw.io_base = pci_bar;
248 : :
249 [ # # ]: 0 : if (revision == HISI_DMA_REVISION_HIP08B)
250 : : hisi_dma_update_bit(&hw, HISI_DMA_HIP08_MODE_REG,
251 : : HISI_DMA_HIP08_MODE_SEL_B, true);
252 : 0 : }
253 : :
254 : : static uint8_t
255 : : hisi_dma_reg_layout(uint8_t revision)
256 : : {
257 : 0 : if (revision == HISI_DMA_REVISION_HIP08B)
258 : : return HISI_DMA_REG_LAYOUT_HIP08;
259 [ # # # # ]: 0 : else if (revision >= HISI_DMA_REVISION_HIP09A)
260 : : return HISI_DMA_REG_LAYOUT_HIP09;
261 : : else
262 : 0 : return HISI_DMA_REG_LAYOUT_INVALID;
263 : : }
264 : :
265 : : static void
266 : : hisi_dma_zero_iomem(struct hisi_dma_dev *hw)
267 : : {
268 : 0 : memset(hw->iomz->addr, 0, hw->iomz_sz);
269 : : }
270 : :
271 : : static int
272 : 0 : hisi_dma_alloc_iomem(struct hisi_dma_dev *hw, uint16_t ring_size,
273 : : const char *dev_name)
274 : : {
275 : 0 : uint32_t sq_size = sizeof(struct hisi_dma_sqe) * ring_size;
276 : 0 : uint32_t cq_size = sizeof(struct hisi_dma_cqe) *
277 : 0 : (ring_size + HISI_DMA_CQ_RESERVED);
278 : 0 : uint32_t status_size = sizeof(uint16_t) * ring_size;
279 : : char mz_name[RTE_MEMZONE_NAMESIZE];
280 : : const struct rte_memzone *iomz;
281 : : uint32_t total_size;
282 : :
283 : 0 : sq_size = RTE_CACHE_LINE_ROUNDUP(sq_size);
284 : 0 : cq_size = RTE_CACHE_LINE_ROUNDUP(cq_size);
285 : 0 : status_size = RTE_CACHE_LINE_ROUNDUP(status_size);
286 : 0 : total_size = sq_size + cq_size + status_size;
287 : :
288 : : (void)snprintf(mz_name, sizeof(mz_name), "hisi_dma:%s", dev_name);
289 : 0 : iomz = rte_memzone_reserve(mz_name, total_size, hw->data->numa_node,
290 : : RTE_MEMZONE_IOVA_CONTIG);
291 [ # # ]: 0 : if (iomz == NULL) {
292 : 0 : HISI_DMA_ERR(hw, "malloc %s iomem fail!", mz_name);
293 : 0 : return -ENOMEM;
294 : : }
295 : :
296 : 0 : hw->iomz = iomz;
297 : 0 : hw->iomz_sz = total_size;
298 : 0 : hw->sqe = iomz->addr;
299 : 0 : hw->cqe = (void *)((char *)iomz->addr + sq_size);
300 : 0 : hw->status = (void *)((char *)iomz->addr + sq_size + cq_size);
301 : 0 : hw->sqe_iova = iomz->iova;
302 : 0 : hw->cqe_iova = iomz->iova + sq_size;
303 : 0 : hw->sq_depth_mask = ring_size - 1;
304 : 0 : hw->cq_depth = ring_size + HISI_DMA_CQ_RESERVED;
305 : : hisi_dma_zero_iomem(hw);
306 : :
307 : 0 : return 0;
308 : : }
309 : :
310 : : static void
311 : : hisi_dma_free_iomem(struct hisi_dma_dev *hw)
312 : : {
313 [ # # ]: 0 : if (hw->iomz != NULL)
314 : 0 : rte_memzone_free(hw->iomz);
315 : :
316 : 0 : hw->iomz = NULL;
317 : 0 : hw->sqe = NULL;
318 : 0 : hw->cqe = NULL;
319 : 0 : hw->status = NULL;
320 : 0 : hw->sqe_iova = 0;
321 : 0 : hw->cqe_iova = 0;
322 : 0 : hw->sq_depth_mask = 0;
323 : 0 : hw->cq_depth = 0;
324 : 0 : }
325 : :
326 : : static int
327 : 0 : hisi_dma_info_get(const struct rte_dma_dev *dev,
328 : : struct rte_dma_info *dev_info,
329 : : uint32_t info_sz)
330 : : {
331 : 0 : struct hisi_dma_dev *hw = dev->data->dev_private;
332 : : RTE_SET_USED(info_sz);
333 : :
334 : 0 : dev_info->dev_capa = RTE_DMA_CAPA_MEM_TO_MEM |
335 : : RTE_DMA_CAPA_OPS_COPY;
336 [ # # ]: 0 : if (hw->reg_layout == HISI_DMA_REG_LAYOUT_HIP09)
337 : 0 : dev_info->dev_capa |= RTE_DMA_CAPA_HANDLES_ERRORS;
338 : :
339 : 0 : dev_info->max_vchans = 1;
340 : 0 : dev_info->max_desc = HISI_DMA_MAX_DESC_NUM;
341 : 0 : dev_info->min_desc = HISI_DMA_MIN_DESC_NUM;
342 : :
343 : 0 : return 0;
344 : : }
345 : :
346 : : static int
347 : 0 : hisi_dma_configure(struct rte_dma_dev *dev,
348 : : const struct rte_dma_conf *conf,
349 : : uint32_t conf_sz)
350 : : {
351 : : RTE_SET_USED(dev);
352 : : RTE_SET_USED(conf);
353 : : RTE_SET_USED(conf_sz);
354 : 0 : return 0;
355 : : }
356 : :
357 : : static int
358 : 0 : hisi_dma_vchan_setup(struct rte_dma_dev *dev, uint16_t vchan,
359 : : const struct rte_dma_vchan_conf *conf,
360 : : uint32_t conf_sz)
361 : : {
362 : 0 : struct hisi_dma_dev *hw = dev->data->dev_private;
363 : : int ret;
364 : :
365 : : RTE_SET_USED(vchan);
366 : : RTE_SET_USED(conf_sz);
367 : :
368 [ # # ]: 0 : if (!rte_is_power_of_2(conf->nb_desc)) {
369 : 0 : HISI_DMA_ERR(hw, "Number of desc must be power of 2!");
370 : 0 : return -EINVAL;
371 : : }
372 : :
373 : : hisi_dma_free_iomem(hw);
374 : 0 : ret = hisi_dma_alloc_iomem(hw, conf->nb_desc, dev->data->dev_name);
375 [ # # ]: 0 : if (ret)
376 : 0 : return ret;
377 : :
378 : : return 0;
379 : : }
380 : :
381 : : static int
382 : 0 : hisi_dma_start(struct rte_dma_dev *dev)
383 : : {
384 : 0 : struct hisi_dma_dev *hw = dev->data->dev_private;
385 : :
386 [ # # ]: 0 : if (hw->iomz == NULL) {
387 : 0 : HISI_DMA_ERR(hw, "Vchan was not setup, start fail!\n");
388 : 0 : return -EINVAL;
389 : : }
390 : :
391 : : /* Reset the dmadev to a known state, include:
392 : : * 1) zero iomem, also include status fields.
393 : : * 2) init hardware register.
394 : : * 3) init index values to zero.
395 : : * 4) init running statistics.
396 : : */
397 : : hisi_dma_zero_iomem(hw);
398 : 0 : hisi_dma_init_hw(hw);
399 : 0 : hw->ridx = 0;
400 : 0 : hw->cridx = 0;
401 : 0 : hw->sq_head = 0;
402 : 0 : hw->sq_tail = 0;
403 : 0 : hw->cq_sq_head = 0;
404 : 0 : hw->cq_head = 0;
405 : 0 : hw->cqs_completed = 0;
406 : 0 : hw->cqe_vld = 1;
407 : 0 : hw->submitted = 0;
408 : 0 : hw->completed = 0;
409 : 0 : hw->errors = 0;
410 : 0 : hw->qfulls = 0;
411 : :
412 : 0 : hisi_dma_update_queue_bit(hw, HISI_DMA_QUEUE_CTRL0_REG,
413 : : HISI_DMA_QUEUE_CTRL0_EN_B, true);
414 : :
415 : 0 : return 0;
416 : : }
417 : :
418 : : static int
419 : 0 : hisi_dma_stop(struct rte_dma_dev *dev)
420 : : {
421 : 0 : return hisi_dma_reset_hw(dev->data->dev_private);
422 : : }
423 : :
424 : : static int
425 : 0 : hisi_dma_close(struct rte_dma_dev *dev)
426 : : {
427 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
428 : : /* The dmadev already stopped */
429 [ # # ]: 0 : hisi_dma_free_iomem(dev->data->dev_private);
430 : : }
431 : 0 : return 0;
432 : : }
433 : :
434 : : static int
435 : 0 : hisi_dma_stats_get(const struct rte_dma_dev *dev, uint16_t vchan,
436 : : struct rte_dma_stats *stats,
437 : : uint32_t stats_sz)
438 : : {
439 : 0 : struct hisi_dma_dev *hw = dev->data->dev_private;
440 : :
441 : : RTE_SET_USED(vchan);
442 : : RTE_SET_USED(stats_sz);
443 : 0 : stats->submitted = hw->submitted;
444 : 0 : stats->completed = hw->completed;
445 : 0 : stats->errors = hw->errors;
446 : :
447 : 0 : return 0;
448 : : }
449 : :
450 : : static int
451 : 0 : hisi_dma_stats_reset(struct rte_dma_dev *dev, uint16_t vchan)
452 : : {
453 : 0 : struct hisi_dma_dev *hw = dev->data->dev_private;
454 : :
455 : : RTE_SET_USED(vchan);
456 : 0 : hw->submitted = 0;
457 : 0 : hw->completed = 0;
458 : 0 : hw->errors = 0;
459 : 0 : hw->qfulls = 0;
460 : :
461 : 0 : return 0;
462 : : }
463 : :
464 : : static int
465 : 0 : hisi_dma_vchan_status(const struct rte_dma_dev *dev, uint16_t vchan,
466 : : enum rte_dma_vchan_status *status)
467 : : {
468 [ # # ]: 0 : struct hisi_dma_dev *hw = dev->data->dev_private;
469 : : uint32_t val;
470 : :
471 : : RTE_SET_USED(vchan);
472 : :
473 : : val = hisi_dma_read_queue(hw, HISI_DMA_QUEUE_FSM_REG);
474 : 0 : val = FIELD_GET(HISI_DMA_QUEUE_FSM_STS_M, val);
475 [ # # ]: 0 : if (val == HISI_DMA_STATE_RUN)
476 : 0 : *status = RTE_DMA_VCHAN_ACTIVE;
477 [ # # ]: 0 : else if (val == HISI_DMA_STATE_CPL)
478 : 0 : *status = RTE_DMA_VCHAN_IDLE;
479 : : else
480 : 0 : *status = RTE_DMA_VCHAN_HALTED_ERROR;
481 : :
482 : 0 : return 0;
483 : : }
484 : :
485 : : static void
486 : 0 : hisi_dma_dump_range(struct hisi_dma_dev *hw, FILE *f, uint32_t start,
487 : : uint32_t end)
488 : : {
489 : : #define DUMP_REGNUM_PER_LINE 4
490 : :
491 : : uint32_t cnt, i;
492 : :
493 : : cnt = 0;
494 [ # # ]: 0 : for (i = start; i <= end; i += sizeof(uint32_t)) {
495 [ # # ]: 0 : if (cnt % DUMP_REGNUM_PER_LINE == 0)
496 : : (void)fprintf(f, " [%4x]:", i);
497 : : (void)fprintf(f, " 0x%08x", hisi_dma_read_dev(hw, i));
498 : 0 : cnt++;
499 [ # # ]: 0 : if (cnt % DUMP_REGNUM_PER_LINE == 0)
500 : : (void)fprintf(f, "\n");
501 : : }
502 [ # # ]: 0 : if (cnt % DUMP_REGNUM_PER_LINE)
503 : : (void)fprintf(f, "\n");
504 : 0 : }
505 : :
506 : : static void
507 : 0 : hisi_dma_dump_common(struct hisi_dma_dev *hw, FILE *f)
508 : : {
509 : : struct {
510 : : uint8_t reg_layout;
511 : : uint32_t start;
512 : : uint32_t end;
513 : 0 : } reg_info[] = {
514 : : { HISI_DMA_REG_LAYOUT_HIP08,
515 : : HISI_DMA_HIP08_DUMP_START_REG,
516 : : HISI_DMA_HIP08_DUMP_END_REG },
517 : : { HISI_DMA_REG_LAYOUT_HIP09,
518 : : HISI_DMA_HIP09_DUMP_REGION_A_START_REG,
519 : : HISI_DMA_HIP09_DUMP_REGION_A_END_REG },
520 : : { HISI_DMA_REG_LAYOUT_HIP09,
521 : : HISI_DMA_HIP09_DUMP_REGION_B_START_REG,
522 : : HISI_DMA_HIP09_DUMP_REGION_B_END_REG },
523 : : { HISI_DMA_REG_LAYOUT_HIP09,
524 : : HISI_DMA_HIP09_DUMP_REGION_C_START_REG,
525 : : HISI_DMA_HIP09_DUMP_REGION_C_END_REG },
526 : : { HISI_DMA_REG_LAYOUT_HIP09,
527 : : HISI_DMA_HIP09_DUMP_REGION_D_START_REG,
528 : : HISI_DMA_HIP09_DUMP_REGION_D_END_REG },
529 : : };
530 : : uint32_t i;
531 : :
532 : : (void)fprintf(f, " common-register:\n");
533 [ # # ]: 0 : for (i = 0; i < RTE_DIM(reg_info); i++) {
534 [ # # ]: 0 : if (hw->reg_layout != reg_info[i].reg_layout)
535 : 0 : continue;
536 : 0 : hisi_dma_dump_range(hw, f, reg_info[i].start, reg_info[i].end);
537 : : }
538 : 0 : }
539 : :
540 : : static void
541 : 0 : hisi_dma_dump_read_queue(struct hisi_dma_dev *hw, uint32_t qoff,
542 : : char *buffer, int max_sz)
543 : : {
544 [ # # ]: 0 : memset(buffer, 0, max_sz);
545 : :
546 : : /* Address-related registers are not printed for security reasons. */
547 : 0 : if (qoff == HISI_DMA_QUEUE_SQ_BASE_L_REG ||
548 [ # # ]: 0 : qoff == HISI_DMA_QUEUE_SQ_BASE_H_REG ||
549 : 0 : qoff == HISI_DMA_QUEUE_CQ_BASE_L_REG ||
550 [ # # ]: 0 : qoff == HISI_DMA_QUEUE_CQ_BASE_H_REG) {
551 : : (void)snprintf(buffer, max_sz, "**********");
552 : 0 : return;
553 : : }
554 : :
555 : : (void)snprintf(buffer, max_sz, "0x%08x", hisi_dma_read_queue(hw, qoff));
556 : : }
557 : :
558 : : static void
559 : 0 : hisi_dma_dump_queue(struct hisi_dma_dev *hw, FILE *f)
560 : : {
561 : : #define REG_FMT_LEN 32
562 : 0 : char buf[REG_FMT_LEN] = { 0 };
563 : : uint32_t i;
564 : :
565 : : (void)fprintf(f, " queue-register:\n");
566 [ # # ]: 0 : for (i = 0; i < HISI_DMA_QUEUE_REGION_SIZE; ) {
567 : 0 : hisi_dma_dump_read_queue(hw, i, buf, sizeof(buf));
568 : : (void)fprintf(f, " [%2x]: %s", i, buf);
569 : 0 : i += sizeof(uint32_t);
570 : 0 : hisi_dma_dump_read_queue(hw, i, buf, sizeof(buf));
571 : : (void)fprintf(f, " %s", buf);
572 : 0 : i += sizeof(uint32_t);
573 : 0 : hisi_dma_dump_read_queue(hw, i, buf, sizeof(buf));
574 : : (void)fprintf(f, " %s", buf);
575 : 0 : i += sizeof(uint32_t);
576 : 0 : hisi_dma_dump_read_queue(hw, i, buf, sizeof(buf));
577 : : (void)fprintf(f, " %s\n", buf);
578 : 0 : i += sizeof(uint32_t);
579 : : }
580 : 0 : }
581 : :
582 : : static int
583 : 0 : hisi_dma_dump(const struct rte_dma_dev *dev, FILE *f)
584 : : {
585 : 0 : struct hisi_dma_dev *hw = dev->data->dev_private;
586 : :
587 : 0 : (void)fprintf(f,
588 : : " revision: 0x%x queue_id: %u ring_size: %u\n"
589 : : " ridx: %u cridx: %u\n"
590 : : " sq_head: %u sq_tail: %u cq_sq_head: %u\n"
591 : : " cq_head: %u cqs_completed: %u cqe_vld: %u\n"
592 : : " submitted: %" PRIu64 " completed: %" PRIu64 " errors: %"
593 : : PRIu64 " qfulls: %" PRIu64 "\n",
594 : 0 : hw->revision, hw->queue_id,
595 : 0 : hw->sq_depth_mask > 0 ? hw->sq_depth_mask + 1 : 0,
596 : 0 : hw->ridx, hw->cridx,
597 : 0 : hw->sq_head, hw->sq_tail, hw->cq_sq_head,
598 [ # # ]: 0 : hw->cq_head, hw->cqs_completed, hw->cqe_vld,
599 : : hw->submitted, hw->completed, hw->errors, hw->qfulls);
600 : 0 : hisi_dma_dump_queue(hw, f);
601 : 0 : hisi_dma_dump_common(hw, f);
602 : :
603 : 0 : return 0;
604 : : }
605 : :
606 : : static int
607 : 0 : hisi_dma_copy(void *dev_private, uint16_t vchan,
608 : : rte_iova_t src, rte_iova_t dst,
609 : : uint32_t length, uint64_t flags)
610 : : {
611 : : struct hisi_dma_dev *hw = dev_private;
612 : 0 : struct hisi_dma_sqe *sqe = &hw->sqe[hw->sq_tail];
613 : :
614 : : RTE_SET_USED(vchan);
615 : :
616 [ # # ]: 0 : if (((hw->sq_tail + 1) & hw->sq_depth_mask) == hw->sq_head) {
617 : 0 : hw->qfulls++;
618 : 0 : return -ENOSPC;
619 : : }
620 : :
621 : 0 : sqe->dw0 = rte_cpu_to_le_32(SQE_OPCODE_M2M);
622 : 0 : sqe->dw1 = 0;
623 : 0 : sqe->dw2 = 0;
624 : 0 : sqe->length = rte_cpu_to_le_32(length);
625 : 0 : sqe->src_addr = rte_cpu_to_le_64(src);
626 : 0 : sqe->dst_addr = rte_cpu_to_le_64(dst);
627 : 0 : hw->sq_tail = (hw->sq_tail + 1) & hw->sq_depth_mask;
628 : 0 : hw->submitted++;
629 : :
630 [ # # ]: 0 : if (flags & RTE_DMA_OP_FLAG_FENCE)
631 : 0 : sqe->dw0 |= rte_cpu_to_le_32(SQE_FENCE_FLAG);
632 [ # # ]: 0 : if (flags & RTE_DMA_OP_FLAG_SUBMIT)
633 : 0 : rte_write32(rte_cpu_to_le_32(hw->sq_tail), hw->sq_tail_reg);
634 : :
635 : 0 : return hw->ridx++;
636 : : }
637 : :
638 : : static int
639 : 0 : hisi_dma_submit(void *dev_private, uint16_t vchan)
640 : : {
641 : : struct hisi_dma_dev *hw = dev_private;
642 : :
643 : : RTE_SET_USED(vchan);
644 : 0 : rte_write32(rte_cpu_to_le_32(hw->sq_tail), hw->sq_tail_reg);
645 : :
646 : 0 : return 0;
647 : : }
648 : :
649 : : static inline void
650 : 0 : hisi_dma_scan_cq(struct hisi_dma_dev *hw)
651 : : {
652 : : volatile struct hisi_dma_cqe *cqe;
653 : 0 : uint16_t csq_head = hw->cq_sq_head;
654 : 0 : uint16_t cq_head = hw->cq_head;
655 : : uint16_t count = 0;
656 : : uint64_t misc;
657 : :
658 [ # # ]: 0 : while (count < hw->cq_depth) {
659 : 0 : cqe = &hw->cqe[cq_head];
660 : 0 : misc = cqe->misc;
661 : : misc = rte_le_to_cpu_64(misc);
662 [ # # ]: 0 : if (FIELD_GET(CQE_VALID_B, misc) != hw->cqe_vld)
663 : : break;
664 : :
665 : 0 : csq_head = FIELD_GET(CQE_SQ_HEAD_MASK, misc);
666 [ # # ]: 0 : if (unlikely(csq_head > hw->sq_depth_mask)) {
667 : : /**
668 : : * Defensive programming to prevent overflow of the
669 : : * status array indexed by csq_head. Only error logs
670 : : * are used for prompting.
671 : : */
672 : 0 : HISI_DMA_ERR(hw, "invalid csq_head:%u!\n", csq_head);
673 : : count = 0;
674 : : break;
675 : : }
676 [ # # ]: 0 : if (unlikely(misc & CQE_STATUS_MASK))
677 : 0 : hw->status[csq_head] = FIELD_GET(CQE_STATUS_MASK,
678 : : misc);
679 : :
680 : 0 : count++;
681 : 0 : cq_head++;
682 [ # # ]: 0 : if (cq_head == hw->cq_depth) {
683 : 0 : hw->cqe_vld = !hw->cqe_vld;
684 : : cq_head = 0;
685 : : }
686 : : }
687 : :
688 [ # # ]: 0 : if (count == 0)
689 : 0 : return;
690 : :
691 : 0 : hw->cq_head = cq_head;
692 : 0 : hw->cq_sq_head = (csq_head + 1) & hw->sq_depth_mask;
693 : 0 : hw->cqs_completed += count;
694 [ # # ]: 0 : if (hw->cqs_completed >= HISI_DMA_CQ_RESERVED) {
695 : 0 : rte_write32(rte_cpu_to_le_32(cq_head), hw->cq_head_reg);
696 : 0 : hw->cqs_completed = 0;
697 : : }
698 : : }
699 : :
700 : : static inline uint16_t
701 : : hisi_dma_calc_cpls(struct hisi_dma_dev *hw, const uint16_t nb_cpls)
702 : : {
703 : : uint16_t cpl_num;
704 : :
705 [ # # # # ]: 0 : if (hw->cq_sq_head >= hw->sq_head)
706 : 0 : cpl_num = hw->cq_sq_head - hw->sq_head;
707 : : else
708 : 0 : cpl_num = hw->sq_depth_mask + 1 - hw->sq_head + hw->cq_sq_head;
709 : :
710 : : if (cpl_num > nb_cpls)
711 : : cpl_num = nb_cpls;
712 : :
713 : : return cpl_num;
714 : : }
715 : :
716 : : static uint16_t
717 : 0 : hisi_dma_completed(void *dev_private,
718 : : uint16_t vchan, const uint16_t nb_cpls,
719 : : uint16_t *last_idx, bool *has_error)
720 : : {
721 : : struct hisi_dma_dev *hw = dev_private;
722 : 0 : uint16_t sq_head = hw->sq_head;
723 : : uint16_t cpl_num, i;
724 : :
725 : : RTE_SET_USED(vchan);
726 : 0 : hisi_dma_scan_cq(hw);
727 : :
728 : : cpl_num = hisi_dma_calc_cpls(hw, nb_cpls);
729 [ # # ]: 0 : for (i = 0; i < cpl_num; i++) {
730 [ # # ]: 0 : if (hw->status[sq_head]) {
731 : 0 : *has_error = true;
732 : 0 : break;
733 : : }
734 : 0 : sq_head = (sq_head + 1) & hw->sq_depth_mask;
735 : : }
736 : 0 : *last_idx = hw->cridx + i - 1;
737 [ # # ]: 0 : if (i > 0) {
738 : 0 : hw->cridx += i;
739 : 0 : hw->sq_head = sq_head;
740 : 0 : hw->completed += i;
741 : : }
742 : :
743 : 0 : return i;
744 : : }
745 : :
746 : : static enum rte_dma_status_code
747 : 0 : hisi_dma_convert_status(uint16_t status)
748 : : {
749 [ # # # # : 0 : switch (status) {
# # # # #
# ]
750 : : case HISI_DMA_STATUS_SUCCESS:
751 : : return RTE_DMA_STATUS_SUCCESSFUL;
752 : 0 : case HISI_DMA_STATUS_INVALID_OPCODE:
753 : 0 : return RTE_DMA_STATUS_INVALID_OPCODE;
754 : 0 : case HISI_DMA_STATUS_INVALID_LENGTH:
755 : 0 : return RTE_DMA_STATUS_INVALID_LENGTH;
756 : 0 : case HISI_DMA_STATUS_USER_ABORT:
757 : 0 : return RTE_DMA_STATUS_USER_ABORT;
758 : 0 : case HISI_DMA_STATUS_REMOTE_READ_ERROR:
759 : : case HISI_DMA_STATUS_AXI_READ_ERROR:
760 : 0 : return RTE_DMA_STATUS_BUS_READ_ERROR;
761 : 0 : case HISI_DMA_STATUS_AXI_WRITE_ERROR:
762 : 0 : return RTE_DMA_STATUS_BUS_WRITE_ERROR;
763 : 0 : case HISI_DMA_STATUS_DATA_POISON:
764 : : case HISI_DMA_STATUS_REMOTE_DATA_POISION:
765 : 0 : return RTE_DMA_STATUS_DATA_POISION;
766 : 0 : case HISI_DMA_STATUS_SQE_READ_ERROR:
767 : : case HISI_DMA_STATUS_SQE_READ_POISION:
768 : 0 : return RTE_DMA_STATUS_DESCRIPTOR_READ_ERROR;
769 : 0 : case HISI_DMA_STATUS_LINK_DOWN_ERROR:
770 : 0 : return RTE_DMA_STATUS_DEV_LINK_ERROR;
771 : 0 : default:
772 : 0 : return RTE_DMA_STATUS_ERROR_UNKNOWN;
773 : : }
774 : : }
775 : :
776 : : static uint16_t
777 : 0 : hisi_dma_completed_status(void *dev_private,
778 : : uint16_t vchan, const uint16_t nb_cpls,
779 : : uint16_t *last_idx, enum rte_dma_status_code *status)
780 : : {
781 : : struct hisi_dma_dev *hw = dev_private;
782 : 0 : uint16_t sq_head = hw->sq_head;
783 : : uint16_t cpl_num, i;
784 : :
785 : : RTE_SET_USED(vchan);
786 : 0 : hisi_dma_scan_cq(hw);
787 : :
788 : : cpl_num = hisi_dma_calc_cpls(hw, nb_cpls);
789 [ # # ]: 0 : for (i = 0; i < cpl_num; i++) {
790 : 0 : status[i] = hisi_dma_convert_status(hw->status[sq_head]);
791 : 0 : hw->errors += !!status[i];
792 : 0 : hw->status[sq_head] = HISI_DMA_STATUS_SUCCESS;
793 : 0 : sq_head = (sq_head + 1) & hw->sq_depth_mask;
794 : : }
795 : 0 : *last_idx = hw->cridx + cpl_num - 1;
796 [ # # ]: 0 : if (likely(cpl_num > 0)) {
797 : 0 : hw->cridx += cpl_num;
798 : 0 : hw->sq_head = sq_head;
799 : 0 : hw->completed += cpl_num;
800 : : }
801 : :
802 : 0 : return cpl_num;
803 : : }
804 : :
805 : : static uint16_t
806 : 0 : hisi_dma_burst_capacity(const void *dev_private, uint16_t vchan)
807 : : {
808 : : const struct hisi_dma_dev *hw = dev_private;
809 : 0 : uint16_t sq_head = hw->sq_head;
810 : 0 : uint16_t sq_tail = hw->sq_tail;
811 : :
812 : : RTE_SET_USED(vchan);
813 : :
814 [ # # ]: 0 : return (sq_tail >= sq_head) ? hw->sq_depth_mask - sq_tail + sq_head :
815 : 0 : sq_head - 1 - sq_tail;
816 : : }
817 : :
818 : : static void
819 : 0 : hisi_dma_gen_dev_name(const struct rte_pci_device *pci_dev,
820 : : uint8_t queue_id, char *dev_name, size_t size)
821 : : {
822 : 0 : char name[RTE_DEV_NAME_MAX_LEN] = { 0 };
823 : :
824 : : memset(dev_name, 0, size);
825 : 0 : rte_pci_device_name(&pci_dev->addr, name, sizeof(name));
826 : 0 : (void)snprintf(dev_name, size, "%s-ch%u", name, queue_id);
827 : 0 : }
828 : :
829 : : /**
830 : : * Hardware queue state machine:
831 : : *
832 : : * ----------- dmadev_create ------------------
833 : : * | Unknown | ---------------> | IDLE |
834 : : * ----------- ------------------
835 : : * ^ |
836 : : * | |dev_start
837 : : * dev_stop| |
838 : : * | v
839 : : * ------------------
840 : : * | CPL |
841 : : * ------------------
842 : : * ^ |
843 : : * hardware | |
844 : : * completed all| |dev_submit
845 : : * descriptors | |
846 : : * | |
847 : : * ------------------
848 : : * | RUN |
849 : : * ------------------
850 : : *
851 : : */
852 : : static const struct rte_dma_dev_ops hisi_dmadev_ops = {
853 : : .dev_info_get = hisi_dma_info_get,
854 : : .dev_configure = hisi_dma_configure,
855 : : .dev_start = hisi_dma_start,
856 : : .dev_stop = hisi_dma_stop,
857 : : .dev_close = hisi_dma_close,
858 : : .vchan_setup = hisi_dma_vchan_setup,
859 : : .stats_get = hisi_dma_stats_get,
860 : : .stats_reset = hisi_dma_stats_reset,
861 : : .vchan_status = hisi_dma_vchan_status,
862 : : .dev_dump = hisi_dma_dump,
863 : : };
864 : :
865 : : static int
866 : 0 : hisi_dma_create(struct rte_pci_device *pci_dev, uint8_t queue_id,
867 : : uint8_t revision)
868 : : {
869 : : #define REG_PCI_BAR_INDEX 2
870 : :
871 : : char name[RTE_DEV_NAME_MAX_LEN];
872 : : struct rte_dma_dev *dev;
873 : : struct hisi_dma_dev *hw;
874 : : int ret;
875 : :
876 : 0 : hisi_dma_gen_dev_name(pci_dev, queue_id, name, sizeof(name));
877 : 0 : dev = rte_dma_pmd_allocate(name, pci_dev->device.numa_node,
878 : : sizeof(*hw));
879 [ # # ]: 0 : if (dev == NULL) {
880 : 0 : HISI_DMA_LOG(ERR, "%s allocate dmadev fail!", name);
881 : 0 : return -EINVAL;
882 : : }
883 : :
884 : 0 : dev->device = &pci_dev->device;
885 : 0 : dev->dev_ops = &hisi_dmadev_ops;
886 : 0 : dev->fp_obj->dev_private = dev->data->dev_private;
887 : 0 : dev->fp_obj->copy = hisi_dma_copy;
888 : 0 : dev->fp_obj->submit = hisi_dma_submit;
889 : 0 : dev->fp_obj->completed = hisi_dma_completed;
890 : 0 : dev->fp_obj->completed_status = hisi_dma_completed_status;
891 : 0 : dev->fp_obj->burst_capacity = hisi_dma_burst_capacity;
892 : :
893 : : hw = dev->data->dev_private;
894 : 0 : hw->data = dev->data;
895 [ # # ]: 0 : hw->revision = revision;
896 : 0 : hw->reg_layout = hisi_dma_reg_layout(revision);
897 : 0 : hw->io_base = pci_dev->mem_resource[REG_PCI_BAR_INDEX].addr;
898 [ # # ]: 0 : hw->queue_id = queue_id;
899 [ # # ]: 0 : hw->sq_tail_reg = hisi_dma_queue_regaddr(hw,
900 : : HISI_DMA_QUEUE_SQ_TAIL_REG);
901 : 0 : hw->cq_head_reg = hisi_dma_queue_regaddr(hw,
902 : : HISI_DMA_QUEUE_CQ_HEAD_REG);
903 : :
904 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
905 : 0 : ret = hisi_dma_reset_hw(hw);
906 [ # # ]: 0 : if (ret) {
907 : 0 : HISI_DMA_LOG(ERR, "%s init device fail!", name);
908 : 0 : (void)rte_dma_pmd_release(name);
909 : 0 : return -EIO;
910 : : }
911 : : }
912 : :
913 : 0 : dev->state = RTE_DMA_DEV_READY;
914 : 0 : HISI_DMA_LOG(DEBUG, "%s create dmadev success!", name);
915 : :
916 : 0 : return 0;
917 : : }
918 : :
919 : : static int
920 : 0 : hisi_dma_check_revision(struct rte_pci_device *pci_dev, const char *name,
921 : : uint8_t *out_revision)
922 : : {
923 : : uint8_t revision;
924 : : int ret;
925 : :
926 : 0 : ret = rte_pci_read_config(pci_dev, &revision, 1,
927 : : HISI_DMA_PCI_REVISION_ID_REG);
928 [ # # ]: 0 : if (ret != 1) {
929 : 0 : HISI_DMA_LOG(ERR, "%s read PCI revision failed!", name);
930 : 0 : return -EINVAL;
931 : : }
932 [ # # ]: 0 : if (hisi_dma_reg_layout(revision) == HISI_DMA_REG_LAYOUT_INVALID) {
933 : 0 : HISI_DMA_LOG(ERR, "%s revision: 0x%x not supported!",
934 : : name, revision);
935 : 0 : return -EINVAL;
936 : : }
937 : :
938 : 0 : *out_revision = revision;
939 : 0 : return 0;
940 : : }
941 : :
942 : : static int
943 : 0 : hisi_dma_probe(struct rte_pci_driver *pci_drv __rte_unused,
944 : : struct rte_pci_device *pci_dev)
945 : : {
946 : 0 : char name[RTE_DEV_NAME_MAX_LEN] = { 0 };
947 : : uint8_t revision;
948 : : uint8_t i;
949 : : int ret;
950 : :
951 : 0 : rte_pci_device_name(&pci_dev->addr, name, sizeof(name));
952 : :
953 [ # # ]: 0 : if (pci_dev->mem_resource[2].addr == NULL) {
954 : 0 : HISI_DMA_LOG(ERR, "%s BAR2 is NULL!\n", name);
955 : 0 : return -ENODEV;
956 : : }
957 : :
958 : 0 : ret = hisi_dma_check_revision(pci_dev, name, &revision);
959 [ # # ]: 0 : if (ret)
960 : : return ret;
961 : 0 : HISI_DMA_LOG(DEBUG, "%s read PCI revision: 0x%x", name, revision);
962 : :
963 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_PRIMARY)
964 : 0 : hisi_dma_init_gbl(pci_dev->mem_resource[2].addr, revision);
965 : :
966 [ # # ]: 0 : for (i = 0; i < HISI_DMA_MAX_HW_QUEUES; i++) {
967 : 0 : ret = hisi_dma_create(pci_dev, i, revision);
968 [ # # ]: 0 : if (ret) {
969 : 0 : HISI_DMA_LOG(ERR, "%s create dmadev %u failed!",
970 : : name, i);
971 : 0 : break;
972 : : }
973 : : }
974 : :
975 : : return ret;
976 : : }
977 : :
978 : : static int
979 : 0 : hisi_dma_remove(struct rte_pci_device *pci_dev)
980 : : {
981 : : char name[RTE_DEV_NAME_MAX_LEN];
982 : : uint8_t i;
983 : : int ret;
984 : :
985 [ # # ]: 0 : for (i = 0; i < HISI_DMA_MAX_HW_QUEUES; i++) {
986 : 0 : hisi_dma_gen_dev_name(pci_dev, i, name, sizeof(name));
987 : 0 : ret = rte_dma_pmd_release(name);
988 [ # # ]: 0 : if (ret)
989 : 0 : return ret;
990 : : }
991 : :
992 : : return 0;
993 : : }
994 : :
995 : : static const struct rte_pci_id pci_id_hisi_dma_map[] = {
996 : : { RTE_PCI_DEVICE(PCI_VENDOR_ID_HUAWEI, HISI_DMA_DEVICE_ID) },
997 : : { .vendor_id = 0, }, /* sentinel */
998 : : };
999 : :
1000 : : static struct rte_pci_driver hisi_dma_pmd_drv = {
1001 : : .id_table = pci_id_hisi_dma_map,
1002 : : .drv_flags = RTE_PCI_DRV_NEED_MAPPING,
1003 : : .probe = hisi_dma_probe,
1004 : : .remove = hisi_dma_remove,
1005 : : };
1006 : :
1007 : 238 : RTE_PMD_REGISTER_PCI(dma_hisilicon, hisi_dma_pmd_drv);
1008 : : RTE_PMD_REGISTER_PCI_TABLE(dma_hisilicon, pci_id_hisi_dma_map);
1009 : : RTE_PMD_REGISTER_KMOD_DEP(dma_hisilicon, "vfio-pci");
|