]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | /* SPDX-License-Identifier: BSD-3-Clause |
2 | * | |
3 | * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. | |
f67539c2 | 4 | * Copyright 2018-2019 NXP |
11fdf7f2 TL |
5 | * |
6 | */ | |
7 | ||
9f95a23c TL |
8 | #ifndef _QBMAN_PORTAL_H_ |
9 | #define _QBMAN_PORTAL_H_ | |
10 | ||
11fdf7f2 TL |
11 | #include "qbman_sys.h" |
12 | #include <fsl_qbman_portal.h> | |
13 | ||
f67539c2 | 14 | extern uint32_t qman_version; |
11fdf7f2 TL |
15 | #define QMAN_REV_4000 0x04000000 |
16 | #define QMAN_REV_4100 0x04010000 | |
17 | #define QMAN_REV_4101 0x04010001 | |
18 | ||
19 | /* All QBMan command and result structures use this "valid bit" encoding */ | |
20 | #define QB_VALID_BIT ((uint32_t)0x80) | |
21 | ||
9f95a23c TL |
22 | /* All QBMan command use this "Read trigger bit" encoding */ |
23 | #define QB_RT_BIT ((uint32_t)0x100) | |
24 | ||
11fdf7f2 TL |
25 | /* Management command result codes */ |
26 | #define QBMAN_MC_RSLT_OK 0xf0 | |
27 | ||
28 | /* QBMan DQRR size is set at runtime in qbman_portal.c */ | |
29 | ||
11fdf7f2 TL |
30 | static inline uint8_t qm_cyc_diff(uint8_t ringsize, uint8_t first, |
31 | uint8_t last) | |
32 | { | |
33 | /* 'first' is included, 'last' is excluded */ | |
34 | if (first <= last) | |
35 | return last - first; | |
36 | return (2 * ringsize) + last - first; | |
37 | } | |
38 | ||
39 | /* --------------------- */ | |
40 | /* portal data structure */ | |
41 | /* --------------------- */ | |
42 | ||
43 | struct qbman_swp { | |
44 | struct qbman_swp_desc desc; | |
45 | /* The qbman_sys (ie. arch/OS-specific) support code can put anything it | |
46 | * needs in here. | |
47 | */ | |
48 | struct qbman_swp_sys sys; | |
49 | /* Management commands */ | |
50 | struct { | |
51 | #ifdef QBMAN_CHECKING | |
52 | enum swp_mc_check { | |
53 | swp_mc_can_start, /* call __qbman_swp_mc_start() */ | |
54 | swp_mc_can_submit, /* call __qbman_swp_mc_submit() */ | |
55 | swp_mc_can_poll, /* call __qbman_swp_mc_result() */ | |
56 | } check; | |
57 | #endif | |
58 | uint32_t valid_bit; /* 0x00 or 0x80 */ | |
59 | } mc; | |
9f95a23c TL |
60 | /* Management response */ |
61 | struct { | |
62 | uint32_t valid_bit; /* 0x00 or 0x80 */ | |
63 | } mr; | |
11fdf7f2 TL |
64 | /* Push dequeues */ |
65 | uint32_t sdq; | |
66 | /* Volatile dequeues */ | |
67 | struct { | |
68 | /* VDQCR supports a "1 deep pipeline", meaning that if you know | |
69 | * the last-submitted command is already executing in the | |
70 | * hardware (as evidenced by at least 1 valid dequeue result), | |
71 | * you can write another dequeue command to the register, the | |
72 | * hardware will start executing it as soon as the | |
73 | * already-executing command terminates. (This minimises latency | |
74 | * and stalls.) With that in mind, this "busy" variable refers | |
75 | * to whether or not a command can be submitted, not whether or | |
76 | * not a previously-submitted command is still executing. In | |
77 | * other words, once proof is seen that the previously-submitted | |
78 | * command is executing, "vdq" is no longer "busy". | |
79 | */ | |
80 | atomic_t busy; | |
81 | uint32_t valid_bit; /* 0x00 or 0x80 */ | |
82 | /* We need to determine when vdq is no longer busy. This depends | |
83 | * on whether the "busy" (last-submitted) dequeue command is | |
84 | * targeting DQRR or main-memory, and detected is based on the | |
85 | * presence of the dequeue command's "token" showing up in | |
86 | * dequeue entries in DQRR or main-memory (respectively). | |
87 | */ | |
88 | struct qbman_result *storage; /* NULL if DQRR */ | |
89 | } vdq; | |
90 | /* DQRR */ | |
91 | struct { | |
92 | uint32_t next_idx; | |
93 | uint32_t valid_bit; | |
94 | uint8_t dqrr_size; | |
95 | int reset_bug; | |
96 | } dqrr; | |
97 | struct { | |
98 | uint32_t pi; | |
99 | uint32_t pi_vb; | |
9f95a23c TL |
100 | uint32_t pi_ring_size; |
101 | uint32_t pi_ci_mask; | |
11fdf7f2 TL |
102 | uint32_t ci; |
103 | int available; | |
104 | } eqcr; | |
105 | }; | |
106 | ||
107 | /* -------------------------- */ | |
108 | /* portal management commands */ | |
109 | /* -------------------------- */ | |
110 | ||
111 | /* Different management commands all use this common base layer of code to issue | |
112 | * commands and poll for results. The first function returns a pointer to where | |
113 | * the caller should fill in their MC command (though they should ignore the | |
114 | * verb byte), the second function commits merges in the caller-supplied command | |
115 | * verb (which should not include the valid-bit) and submits the command to | |
116 | * hardware, and the third function checks for a completed response (returns | |
117 | * non-NULL if only if the response is complete). | |
118 | */ | |
119 | void *qbman_swp_mc_start(struct qbman_swp *p); | |
120 | void qbman_swp_mc_submit(struct qbman_swp *p, void *cmd, uint8_t cmd_verb); | |
121 | void *qbman_swp_mc_result(struct qbman_swp *p); | |
122 | ||
123 | /* Wraps up submit + poll-for-result */ | |
124 | static inline void *qbman_swp_mc_complete(struct qbman_swp *swp, void *cmd, | |
125 | uint8_t cmd_verb) | |
126 | { | |
127 | int loopvar = 1000; | |
128 | ||
129 | qbman_swp_mc_submit(swp, cmd, cmd_verb); | |
130 | do { | |
131 | cmd = qbman_swp_mc_result(swp); | |
132 | } while (!cmd && loopvar--); | |
133 | QBMAN_BUG_ON(!loopvar); | |
134 | ||
135 | return cmd; | |
136 | } | |
137 | ||
138 | /* ---------------------- */ | |
139 | /* Descriptors/cachelines */ | |
140 | /* ---------------------- */ | |
141 | ||
142 | /* To avoid needless dynamic allocation, the driver API often gives the caller | |
143 | * a "descriptor" type that the caller can instantiate however they like. | |
144 | * Ultimately though, it is just a cacheline of binary storage (or something | |
145 | * smaller when it is known that the descriptor doesn't need all 64 bytes) for | |
146 | * holding pre-formatted pieces of hardware commands. The performance-critical | |
147 | * code can then copy these descriptors directly into hardware command | |
148 | * registers more efficiently than trying to construct/format commands | |
149 | * on-the-fly. The API user sees the descriptor as an array of 32-bit words in | |
150 | * order for the compiler to know its size, but the internal details are not | |
151 | * exposed. The following macro is used within the driver for converting *any* | |
152 | * descriptor pointer to a usable array pointer. The use of a macro (instead of | |
153 | * an inline) is necessary to work with different descriptor types and to work | |
154 | * correctly with const and non-const inputs (and similarly-qualified outputs). | |
155 | */ | |
9f95a23c TL |
156 | #define qb_cl(d) (&(d)->dont_manipulate_directly[0]) |
157 | ||
158 | #ifdef RTE_ARCH_ARM64 | |
159 | #define clean(p) \ | |
160 | { asm volatile("dc cvac, %0;" : : "r" (p) : "memory"); } | |
161 | #define invalidate(p) \ | |
162 | { asm volatile("dc ivac, %0" : : "r"(p) : "memory"); } | |
163 | #else | |
164 | #define clean(p) | |
165 | #define invalidate(p) | |
166 | #endif | |
167 | ||
168 | #endif |