Branch data Line data Source code
1 : : /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
2 : : *
3 : : * Copyright 2008-2016 Freescale Semiconductor Inc.
4 : : * Copyright 2017 NXP
5 : : *
6 : : */
7 : :
8 : : #include <rte_branch_prediction.h>
9 : :
10 : : #include <fsl_usd.h>
11 : : #include <process.h>
12 : : #include "bman_priv.h"
13 : : #include <sys/ioctl.h>
14 : : #include <err.h>
15 : :
16 : : /*
17 : : * Global variables of the max portal/pool number this bman version supported
18 : : */
19 : : static u16 bman_ip_rev;
20 : : u16 bman_pool_max;
21 : : static void *bman_ccsr_map;
22 : :
23 : : /*****************/
24 : : /* Portal driver */
25 : : /*****************/
26 : :
27 : : static __thread int bmfd = -1;
28 : : static __thread struct bm_portal_config pcfg;
29 : : static __thread struct dpaa_ioctl_portal_map map = {
30 : : .type = dpaa_portal_bman
31 : : };
32 : :
33 : 0 : static int fsl_bman_portal_init(uint32_t idx, int is_shared)
34 : : {
35 : : cpu_set_t cpuset;
36 : : struct bman_portal *portal;
37 : : int loop, ret;
38 : : struct dpaa_ioctl_irq_map irq_map;
39 : :
40 : : /* Verify the thread's cpu-affinity */
41 : 0 : ret = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t),
42 : : &cpuset);
43 [ # # ]: 0 : if (ret) {
44 : 0 : errno = ret;
45 : 0 : err(0, "pthread_getaffinity_np()");
46 : : return ret;
47 : : }
48 : 0 : pcfg.cpu = -1;
49 [ # # ]: 0 : for (loop = 0; loop < CPU_SETSIZE; loop++)
50 [ # # ]: 0 : if (CPU_ISSET(loop, &cpuset)) {
51 [ # # ]: 0 : if (pcfg.cpu != -1) {
52 : 0 : pr_err("Thread is not affine to 1 cpu");
53 : 0 : return -EINVAL;
54 : : }
55 : 0 : pcfg.cpu = loop;
56 : : }
57 [ # # ]: 0 : if (pcfg.cpu == -1) {
58 : 0 : pr_err("Bug in getaffinity handling!");
59 : 0 : return -EINVAL;
60 : : }
61 : : /* Allocate and map a bman portal */
62 : 0 : map.index = idx;
63 : 0 : ret = process_portal_map(&map);
64 [ # # ]: 0 : if (ret) {
65 : 0 : errno = ret;
66 : 0 : err(0, "process_portal_map()");
67 : : return ret;
68 : : }
69 : : /* Make the portal's cache-[enabled|inhibited] regions */
70 : 0 : pcfg.addr_virt[DPAA_PORTAL_CE] = map.addr.cena;
71 : 0 : pcfg.addr_virt[DPAA_PORTAL_CI] = map.addr.cinh;
72 : 0 : pcfg.is_shared = is_shared;
73 : 0 : pcfg.index = map.index;
74 : : bman_depletion_fill(&pcfg.mask);
75 : :
76 : 0 : bmfd = open(BMAN_PORTAL_IRQ_PATH, O_RDONLY);
77 [ # # ]: 0 : if (bmfd == -1) {
78 : 0 : pr_err("BMan irq init failed");
79 : 0 : process_portal_unmap(&map.addr);
80 : 0 : return -EBUSY;
81 : : }
82 : : /* Use the IRQ FD as a unique IRQ number */
83 : 0 : pcfg.irq = bmfd;
84 : :
85 : 0 : portal = bman_create_affine_portal(&pcfg);
86 [ # # ]: 0 : if (!portal) {
87 : 0 : pr_err("Bman portal initialisation failed (%d)",
88 : : pcfg.cpu);
89 : 0 : process_portal_unmap(&map.addr);
90 : 0 : return -EBUSY;
91 : : }
92 : :
93 : : /* Set the IRQ number */
94 : 0 : irq_map.type = dpaa_portal_bman;
95 : 0 : irq_map.portal_cinh = map.addr.cinh;
96 : 0 : process_portal_irq_map(bmfd, &irq_map);
97 : 0 : return 0;
98 : : }
99 : :
100 : 0 : static int fsl_bman_portal_finish(void)
101 : : {
102 : : __maybe_unused const struct bm_portal_config *cfg;
103 : : int ret;
104 : :
105 : 0 : process_portal_irq_unmap(bmfd);
106 : :
107 : 0 : cfg = bman_destroy_affine_portal();
108 : : DPAA_BUG_ON(cfg != &pcfg);
109 : 0 : ret = process_portal_unmap(&map.addr);
110 [ # # ]: 0 : if (ret) {
111 : 0 : errno = ret;
112 : 0 : err(0, "process_portal_unmap()");
113 : : }
114 : 0 : return ret;
115 : : }
116 : :
117 : 0 : int bman_thread_fd(void)
118 : : {
119 : 0 : return bmfd;
120 : : }
121 : :
122 : 0 : int bman_thread_init(void)
123 : : {
124 : : /* Convert from contiguous/virtual cpu numbering to real cpu when
125 : : * calling into the code that is dependent on the device naming.
126 : : */
127 : 0 : return fsl_bman_portal_init(QBMAN_ANY_PORTAL_IDX, 0);
128 : : }
129 : :
130 : 0 : int bman_thread_finish(void)
131 : : {
132 : 0 : return fsl_bman_portal_finish();
133 : : }
134 : :
135 : 0 : void bman_thread_irq(void)
136 : : {
137 : 0 : qbman_invoke_irq(pcfg.irq);
138 : : /* Now we need to uninhibit interrupts. This is the only code outside
139 : : * the regular portal driver that manipulates any portal register, so
140 : : * rather than breaking that encapsulation I am simply hard-coding the
141 : : * offset to the inhibit register here.
142 : : */
143 : 0 : out_be32(pcfg.addr_virt[DPAA_PORTAL_CI] + 0xe0c, 0);
144 : 0 : }
145 : :
146 : 0 : int bman_init_ccsr(const struct device_node *node)
147 : : {
148 : : static int ccsr_map_fd;
149 : : uint64_t phys_addr;
150 : : const uint32_t *bman_addr;
151 : : uint64_t regs_size;
152 : :
153 : 0 : bman_addr = of_get_address(node, 0, ®s_size, NULL);
154 [ # # ]: 0 : if (!bman_addr) {
155 : 0 : pr_err("of_get_address cannot return BMan address");
156 : 0 : return -EINVAL;
157 : : }
158 : 0 : phys_addr = of_translate_address(node, bman_addr);
159 [ # # ]: 0 : if (!phys_addr) {
160 : 0 : pr_err("of_translate_address failed");
161 : 0 : return -EINVAL;
162 : : }
163 : :
164 : 0 : ccsr_map_fd = open(BMAN_CCSR_MAP, O_RDWR);
165 [ # # ]: 0 : if (unlikely(ccsr_map_fd < 0)) {
166 : 0 : pr_err("Can not open /dev/mem for BMan CCSR map");
167 : 0 : return ccsr_map_fd;
168 : : }
169 : :
170 : 0 : bman_ccsr_map = mmap(NULL, regs_size, PROT_READ |
171 : : PROT_WRITE, MAP_SHARED, ccsr_map_fd, phys_addr);
172 [ # # ]: 0 : if (bman_ccsr_map == MAP_FAILED) {
173 : 0 : pr_err("Can not map BMan CCSR base Bman: "
174 : : "0x%x Phys: 0x%" PRIx64 " size 0x%" PRIu64,
175 : : *bman_addr, phys_addr, regs_size);
176 : 0 : return -EINVAL;
177 : : }
178 : :
179 : : return 0;
180 : : }
181 : :
182 : 0 : int bman_global_init(void)
183 : : {
184 : : const struct device_node *dt_node;
185 : : static int done;
186 : :
187 [ # # ]: 0 : if (done)
188 : : return -EBUSY;
189 : : /* Use the device-tree to determine IP revision until something better
190 : : * is devised.
191 : : */
192 : 0 : dt_node = of_find_compatible_node(NULL, NULL, "fsl,bman-portal");
193 [ # # ]: 0 : if (!dt_node) {
194 : 0 : pr_err("No bman portals available for any CPU\n");
195 : 0 : return -ENODEV;
196 : : }
197 [ # # # # ]: 0 : if (of_device_is_compatible(dt_node, "fsl,bman-portal-1.0") ||
198 : 0 : of_device_is_compatible(dt_node, "fsl,bman-portal-1.0.0")) {
199 : 0 : bman_ip_rev = BMAN_REV10;
200 : 0 : bman_pool_max = 64;
201 [ # # # # ]: 0 : } else if (of_device_is_compatible(dt_node, "fsl,bman-portal-2.0") ||
202 : 0 : of_device_is_compatible(dt_node, "fsl,bman-portal-2.0.8")) {
203 : 0 : bman_ip_rev = BMAN_REV20;
204 : 0 : bman_pool_max = 8;
205 [ # # # # ]: 0 : } else if (of_device_is_compatible(dt_node, "fsl,bman-portal-2.1.0") ||
206 [ # # ]: 0 : of_device_is_compatible(dt_node, "fsl,bman-portal-2.1.1") ||
207 [ # # ]: 0 : of_device_is_compatible(dt_node, "fsl,bman-portal-2.1.2") ||
208 : 0 : of_device_is_compatible(dt_node, "fsl,bman-portal-2.1.3")) {
209 : 0 : bman_ip_rev = BMAN_REV21;
210 : 0 : bman_pool_max = 64;
211 : : } else {
212 : 0 : pr_warn("unknown BMan version in portal node,default "
213 : : "to rev1.0");
214 : 0 : bman_ip_rev = BMAN_REV10;
215 : 0 : bman_pool_max = 64;
216 : : }
217 : :
218 [ # # ]: 0 : if (!bman_ip_rev) {
219 : 0 : pr_err("Unknown bman portal version\n");
220 : 0 : return -ENODEV;
221 : : }
222 : : {
223 : 0 : const struct device_node *dn = of_find_compatible_node(NULL,
224 : : NULL, "fsl,bman");
225 [ # # ]: 0 : if (!dn)
226 : 0 : pr_err("No bman device node available");
227 : :
228 [ # # ]: 0 : if (bman_init_ccsr(dn))
229 : 0 : pr_err("BMan CCSR map failed.");
230 : : }
231 : :
232 : 0 : done = 1;
233 : 0 : return 0;
234 : : }
235 : :
236 : : #define BMAN_POOL_CONTENT(n) (0x0600 + ((n) * 0x04))
237 : 0 : u32 bm_pool_free_buffers(u32 bpid)
238 : : {
239 : 0 : return in_be32(bman_ccsr_map + BMAN_POOL_CONTENT(bpid));
240 : : }
241 : :
242 : : static u32 __generate_thresh(u32 val, int roundup)
243 : : {
244 : : u32 e = 0; /* co-efficient, exponent */
245 : : int oddbit = 0;
246 : :
247 [ # # # # : 0 : while (val > 0xff) {
# # # # #
# # # ]
248 : : oddbit = val & 1;
249 : 0 : val >>= 1;
250 : 0 : e++;
251 [ # # # # : 0 : if (roundup && oddbit)
# # ]
252 : 0 : val++;
253 : : }
254 : : DPAA_ASSERT(e < 0x10);
255 : 0 : return (val | (e << 8));
256 : : }
257 : :
258 : : #define POOL_SWDET(n) (0x0000 + ((n) * 0x04))
259 : : #define POOL_HWDET(n) (0x0100 + ((n) * 0x04))
260 : : #define POOL_SWDXT(n) (0x0200 + ((n) * 0x04))
261 : : #define POOL_HWDXT(n) (0x0300 + ((n) * 0x04))
262 : 0 : int bm_pool_set(u32 bpid, const u32 *thresholds)
263 : : {
264 [ # # ]: 0 : if (!bman_ccsr_map)
265 : : return -ENODEV;
266 [ # # ]: 0 : if (bpid >= bman_pool_max)
267 : : return -EINVAL;
268 [ # # ]: 0 : out_be32(bman_ccsr_map + POOL_SWDET(bpid),
269 : : __generate_thresh(thresholds[0], 0));
270 [ # # ]: 0 : out_be32(bman_ccsr_map + POOL_SWDXT(bpid),
271 : : __generate_thresh(thresholds[1], 1));
272 [ # # ]: 0 : out_be32(bman_ccsr_map + POOL_HWDET(bpid),
273 : : __generate_thresh(thresholds[2], 0));
274 [ # # ]: 0 : out_be32(bman_ccsr_map + POOL_HWDXT(bpid),
275 : : __generate_thresh(thresholds[3], 1));
276 : 0 : return 0;
277 : : }
278 : :
279 : : #define BMAN_LOW_DEFAULT_THRESH 0x40
280 : : #define BMAN_HIGH_DEFAULT_THRESH 0x80
281 : 0 : int bm_pool_set_hw_threshold(u32 bpid, const u32 low_thresh,
282 : : const u32 high_thresh)
283 : : {
284 [ # # ]: 0 : if (!bman_ccsr_map)
285 : : return -ENODEV;
286 [ # # ]: 0 : if (bpid >= bman_pool_max)
287 : : return -EINVAL;
288 [ # # ]: 0 : if (low_thresh && high_thresh) {
289 [ # # ]: 0 : out_be32(bman_ccsr_map + POOL_HWDET(bpid),
290 : : __generate_thresh(low_thresh, 0));
291 [ # # ]: 0 : out_be32(bman_ccsr_map + POOL_HWDXT(bpid),
292 : : __generate_thresh(high_thresh, 1));
293 : : } else {
294 : 0 : out_be32(bman_ccsr_map + POOL_HWDET(bpid),
295 : : __generate_thresh(BMAN_LOW_DEFAULT_THRESH, 0));
296 : 0 : out_be32(bman_ccsr_map + POOL_HWDXT(bpid),
297 : : __generate_thresh(BMAN_HIGH_DEFAULT_THRESH, 1));
298 : : }
299 : : return 0;
300 : : }
|