1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
2 /* Copyright (c) 2020 Marvell International Ltd. */
4 #include <linux/dma-mapping.h>
5 #include <linux/qed/qed_chain.h>
6 #include <linux/vmalloc.h>
8 #include "qed_dev_api.h"
10 static void qed_chain_init(struct qed_chain
*chain
,
11 const struct qed_chain_init_params
*params
,
14 memset(chain
, 0, sizeof(*chain
));
16 chain
->elem_size
= params
->elem_size
;
17 chain
->intended_use
= params
->intended_use
;
18 chain
->mode
= params
->mode
;
19 chain
->cnt_type
= params
->cnt_type
;
21 chain
->elem_per_page
= ELEMS_PER_PAGE(params
->elem_size
,
23 chain
->usable_per_page
= USABLE_ELEMS_PER_PAGE(params
->elem_size
,
26 chain
->elem_unusable
= UNUSABLE_ELEMS_PER_PAGE(params
->elem_size
,
29 chain
->elem_per_page_mask
= chain
->elem_per_page
- 1;
30 chain
->next_page_mask
= chain
->usable_per_page
&
31 chain
->elem_per_page_mask
;
33 chain
->page_size
= params
->page_size
;
34 chain
->page_cnt
= page_cnt
;
35 chain
->capacity
= chain
->usable_per_page
* page_cnt
;
36 chain
->size
= chain
->elem_per_page
* page_cnt
;
38 if (params
->ext_pbl_virt
) {
39 chain
->pbl_sp
.table_virt
= params
->ext_pbl_virt
;
40 chain
->pbl_sp
.table_phys
= params
->ext_pbl_phys
;
42 chain
->b_external_pbl
= true;
46 static void qed_chain_init_next_ptr_elem(const struct qed_chain
*chain
,
47 void *virt_curr
, void *virt_next
,
50 struct qed_chain_next
*next
;
53 size
= chain
->elem_size
* chain
->usable_per_page
;
54 next
= virt_curr
+ size
;
56 DMA_REGPAIR_LE(next
->next_phys
, phys_next
);
57 next
->next_virt
= virt_next
;
60 static void qed_chain_init_mem(struct qed_chain
*chain
, void *virt_addr
,
63 chain
->p_virt_addr
= virt_addr
;
64 chain
->p_phys_addr
= phys_addr
;
67 static void qed_chain_free_next_ptr(struct qed_dev
*cdev
,
68 struct qed_chain
*chain
)
70 struct device
*dev
= &cdev
->pdev
->dev
;
71 struct qed_chain_next
*next
;
72 dma_addr_t phys
, phys_next
;
73 void *virt
, *virt_next
;
76 size
= chain
->elem_size
* chain
->usable_per_page
;
77 virt
= chain
->p_virt_addr
;
78 phys
= chain
->p_phys_addr
;
80 for (i
= 0; i
< chain
->page_cnt
; i
++) {
85 virt_next
= next
->next_virt
;
86 phys_next
= HILO_DMA_REGPAIR(next
->next_phys
);
88 dma_free_coherent(dev
, chain
->page_size
, virt
, phys
);
95 static void qed_chain_free_single(struct qed_dev
*cdev
,
96 struct qed_chain
*chain
)
98 if (!chain
->p_virt_addr
)
101 dma_free_coherent(&cdev
->pdev
->dev
, chain
->page_size
,
102 chain
->p_virt_addr
, chain
->p_phys_addr
);
105 static void qed_chain_free_pbl(struct qed_dev
*cdev
, struct qed_chain
*chain
)
107 struct device
*dev
= &cdev
->pdev
->dev
;
108 struct addr_tbl_entry
*entry
;
111 if (!chain
->pbl
.pp_addr_tbl
)
114 for (i
= 0; i
< chain
->page_cnt
; i
++) {
115 entry
= chain
->pbl
.pp_addr_tbl
+ i
;
116 if (!entry
->virt_addr
)
119 dma_free_coherent(dev
, chain
->page_size
, entry
->virt_addr
,
123 if (!chain
->b_external_pbl
)
124 dma_free_coherent(dev
, chain
->pbl_sp
.table_size
,
125 chain
->pbl_sp
.table_virt
,
126 chain
->pbl_sp
.table_phys
);
128 vfree(chain
->pbl
.pp_addr_tbl
);
129 chain
->pbl
.pp_addr_tbl
= NULL
;
133 * qed_chain_free() - Free chain DMA memory.
135 * @cdev: Main device structure.
136 * @chain: Chain to free.
138 void qed_chain_free(struct qed_dev
*cdev
, struct qed_chain
*chain
)
140 switch (chain
->mode
) {
141 case QED_CHAIN_MODE_NEXT_PTR
:
142 qed_chain_free_next_ptr(cdev
, chain
);
144 case QED_CHAIN_MODE_SINGLE
:
145 qed_chain_free_single(cdev
, chain
);
147 case QED_CHAIN_MODE_PBL
:
148 qed_chain_free_pbl(cdev
, chain
);
154 qed_chain_init_mem(chain
, NULL
, 0);
158 qed_chain_alloc_sanity_check(struct qed_dev
*cdev
,
159 const struct qed_chain_init_params
*params
,
164 chain_size
= ELEMS_PER_PAGE(params
->elem_size
, params
->page_size
);
165 chain_size
*= page_cnt
;
170 /* The actual chain size can be larger than the maximal possible value
171 * after rounding up the requested elements number to pages, and after
172 * taking into account the unusuable elements (next-ptr elements).
173 * The size of a "u16" chain can be (U16_MAX + 1) since the chain
174 * size/capacity fields are of u32 type.
176 switch (params
->cnt_type
) {
177 case QED_CHAIN_CNT_TYPE_U16
:
178 if (chain_size
> U16_MAX
+ 1)
182 case QED_CHAIN_CNT_TYPE_U32
:
183 if (chain_size
> U32_MAX
)
192 "The actual chain size (0x%llx) is larger than the maximal possible value\n",
198 static int qed_chain_alloc_next_ptr(struct qed_dev
*cdev
,
199 struct qed_chain
*chain
)
201 struct device
*dev
= &cdev
->pdev
->dev
;
202 void *virt
, *virt_prev
= NULL
;
206 for (i
= 0; i
< chain
->page_cnt
; i
++) {
207 virt
= dma_alloc_coherent(dev
, chain
->page_size
, &phys
,
213 qed_chain_init_mem(chain
, virt
, phys
);
214 qed_chain_reset(chain
);
216 qed_chain_init_next_ptr_elem(chain
, virt_prev
, virt
,
223 /* Last page's next element should point to the beginning of the
226 qed_chain_init_next_ptr_elem(chain
, virt_prev
, chain
->p_virt_addr
,
232 static int qed_chain_alloc_single(struct qed_dev
*cdev
,
233 struct qed_chain
*chain
)
238 virt
= dma_alloc_coherent(&cdev
->pdev
->dev
, chain
->page_size
,
243 qed_chain_init_mem(chain
, virt
, phys
);
244 qed_chain_reset(chain
);
249 static int qed_chain_alloc_pbl(struct qed_dev
*cdev
, struct qed_chain
*chain
)
251 struct device
*dev
= &cdev
->pdev
->dev
;
252 struct addr_tbl_entry
*addr_tbl
;
253 dma_addr_t phys
, pbl_phys
;
259 page_cnt
= chain
->page_cnt
;
261 size
= array_size(page_cnt
, sizeof(*addr_tbl
));
262 if (unlikely(size
== SIZE_MAX
))
265 addr_tbl
= vzalloc(size
);
269 chain
->pbl
.pp_addr_tbl
= addr_tbl
;
271 if (chain
->b_external_pbl
) {
272 pbl_virt
= chain
->pbl_sp
.table_virt
;
276 size
= array_size(page_cnt
, sizeof(*pbl_virt
));
277 if (unlikely(size
== SIZE_MAX
))
280 pbl_virt
= dma_alloc_coherent(dev
, size
, &pbl_phys
, GFP_KERNEL
);
284 chain
->pbl_sp
.table_virt
= pbl_virt
;
285 chain
->pbl_sp
.table_phys
= pbl_phys
;
286 chain
->pbl_sp
.table_size
= size
;
289 for (i
= 0; i
< page_cnt
; i
++) {
290 virt
= dma_alloc_coherent(dev
, chain
->page_size
, &phys
,
296 qed_chain_init_mem(chain
, virt
, phys
);
297 qed_chain_reset(chain
);
300 /* Fill the PBL table with the physical address of the page */
301 pbl_virt
[i
] = cpu_to_le64(phys
);
303 /* Keep the virtual address of the page */
304 addr_tbl
[i
].virt_addr
= virt
;
305 addr_tbl
[i
].dma_map
= phys
;
312 * qed_chain_alloc() - Allocate and initialize a chain.
314 * @cdev: Main device structure.
315 * @chain: Chain to be processed.
316 * @params: Chain initialization parameters.
318 * Return: 0 on success, negative errno otherwise.
320 int qed_chain_alloc(struct qed_dev
*cdev
, struct qed_chain
*chain
,
321 struct qed_chain_init_params
*params
)
326 if (!params
->page_size
)
327 params
->page_size
= QED_CHAIN_PAGE_SIZE
;
329 if (params
->mode
== QED_CHAIN_MODE_SINGLE
)
332 page_cnt
= QED_CHAIN_PAGE_CNT(params
->num_elems
,
337 rc
= qed_chain_alloc_sanity_check(cdev
, params
, page_cnt
);
340 "Cannot allocate a chain with the given arguments:\n");
342 "[use_mode %d, mode %d, cnt_type %d, num_elems %d, elem_size %zu, page_size %u]\n",
343 params
->intended_use
, params
->mode
, params
->cnt_type
,
344 params
->num_elems
, params
->elem_size
,
349 qed_chain_init(chain
, params
, page_cnt
);
351 switch (params
->mode
) {
352 case QED_CHAIN_MODE_NEXT_PTR
:
353 rc
= qed_chain_alloc_next_ptr(cdev
, chain
);
355 case QED_CHAIN_MODE_SINGLE
:
356 rc
= qed_chain_alloc_single(cdev
, chain
);
358 case QED_CHAIN_MODE_PBL
:
359 rc
= qed_chain_alloc_pbl(cdev
, chain
);
368 qed_chain_free(cdev
, chain
);