1*4882a593Smuzhiyun /* Copyright 2008 - 2016 Freescale Semiconductor, Inc.
2*4882a593Smuzhiyun *
3*4882a593Smuzhiyun * Redistribution and use in source and binary forms, with or without
4*4882a593Smuzhiyun * modification, are permitted provided that the following conditions are met:
5*4882a593Smuzhiyun * * Redistributions of source code must retain the above copyright
6*4882a593Smuzhiyun * notice, this list of conditions and the following disclaimer.
7*4882a593Smuzhiyun * * Redistributions in binary form must reproduce the above copyright
8*4882a593Smuzhiyun * notice, this list of conditions and the following disclaimer in the
9*4882a593Smuzhiyun * documentation and/or other materials provided with the distribution.
10*4882a593Smuzhiyun * * Neither the name of Freescale Semiconductor nor the
11*4882a593Smuzhiyun * names of its contributors may be used to endorse or promote products
12*4882a593Smuzhiyun * derived from this software without specific prior written permission.
13*4882a593Smuzhiyun *
14*4882a593Smuzhiyun * ALTERNATIVELY, this software may be distributed under the terms of the
15*4882a593Smuzhiyun * GNU General Public License ("GPL") as published by the Free Software
16*4882a593Smuzhiyun * Foundation, either version 2 of that License or (at your option) any
17*4882a593Smuzhiyun * later version.
18*4882a593Smuzhiyun *
19*4882a593Smuzhiyun * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
20*4882a593Smuzhiyun * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21*4882a593Smuzhiyun * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22*4882a593Smuzhiyun * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
23*4882a593Smuzhiyun * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24*4882a593Smuzhiyun * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25*4882a593Smuzhiyun * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26*4882a593Smuzhiyun * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27*4882a593Smuzhiyun * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28*4882a593Smuzhiyun * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29*4882a593Smuzhiyun */
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun #ifndef __FSL_QMAN_H
32*4882a593Smuzhiyun #define __FSL_QMAN_H
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun #include <linux/bitops.h>
35*4882a593Smuzhiyun #include <linux/device.h>
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun /* Hardware constants */
38*4882a593Smuzhiyun #define QM_CHANNEL_SWPORTAL0 0
39*4882a593Smuzhiyun #define QMAN_CHANNEL_POOL1 0x21
40*4882a593Smuzhiyun #define QMAN_CHANNEL_CAAM 0x80
41*4882a593Smuzhiyun #define QMAN_CHANNEL_POOL1_REV3 0x401
42*4882a593Smuzhiyun #define QMAN_CHANNEL_CAAM_REV3 0x840
43*4882a593Smuzhiyun extern u16 qm_channel_pool1;
44*4882a593Smuzhiyun extern u16 qm_channel_caam;
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun /* Portal processing (interrupt) sources */
47*4882a593Smuzhiyun #define QM_PIRQ_CSCI 0x00100000 /* Congestion State Change */
48*4882a593Smuzhiyun #define QM_PIRQ_EQCI 0x00080000 /* Enqueue Command Committed */
49*4882a593Smuzhiyun #define QM_PIRQ_EQRI 0x00040000 /* EQCR Ring (below threshold) */
50*4882a593Smuzhiyun #define QM_PIRQ_DQRI 0x00020000 /* DQRR Ring (non-empty) */
51*4882a593Smuzhiyun #define QM_PIRQ_MRI 0x00010000 /* MR Ring (non-empty) */
52*4882a593Smuzhiyun /*
53*4882a593Smuzhiyun * This mask contains all the interrupt sources that need handling except DQRI,
54*4882a593Smuzhiyun * ie. that if present should trigger slow-path processing.
55*4882a593Smuzhiyun */
56*4882a593Smuzhiyun #define QM_PIRQ_SLOW (QM_PIRQ_CSCI | QM_PIRQ_EQCI | QM_PIRQ_EQRI | \
57*4882a593Smuzhiyun QM_PIRQ_MRI)
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun /* For qman_static_dequeue_*** APIs */
60*4882a593Smuzhiyun #define QM_SDQCR_CHANNELS_POOL_MASK 0x00007fff
61*4882a593Smuzhiyun /* for n in [1,15] */
62*4882a593Smuzhiyun #define QM_SDQCR_CHANNELS_POOL(n) (0x00008000 >> (n))
63*4882a593Smuzhiyun /* for conversion from n of qm_channel */
QM_SDQCR_CHANNELS_POOL_CONV(u16 channel)64*4882a593Smuzhiyun static inline u32 QM_SDQCR_CHANNELS_POOL_CONV(u16 channel)
65*4882a593Smuzhiyun {
66*4882a593Smuzhiyun return QM_SDQCR_CHANNELS_POOL(channel + 1 - qm_channel_pool1);
67*4882a593Smuzhiyun }
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun /* --- QMan data structures (and associated constants) --- */
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun /* "Frame Descriptor (FD)" */
72*4882a593Smuzhiyun struct qm_fd {
73*4882a593Smuzhiyun union {
74*4882a593Smuzhiyun struct {
75*4882a593Smuzhiyun u8 cfg8b_w1;
76*4882a593Smuzhiyun u8 bpid; /* Buffer Pool ID */
77*4882a593Smuzhiyun u8 cfg8b_w3;
78*4882a593Smuzhiyun u8 addr_hi; /* high 8-bits of 40-bit address */
79*4882a593Smuzhiyun __be32 addr_lo; /* low 32-bits of 40-bit address */
80*4882a593Smuzhiyun } __packed;
81*4882a593Smuzhiyun __be64 data;
82*4882a593Smuzhiyun };
83*4882a593Smuzhiyun __be32 cfg; /* format, offset, length / congestion */
84*4882a593Smuzhiyun union {
85*4882a593Smuzhiyun __be32 cmd;
86*4882a593Smuzhiyun __be32 status;
87*4882a593Smuzhiyun };
88*4882a593Smuzhiyun } __aligned(8);
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun #define QM_FD_FORMAT_SG BIT(31)
91*4882a593Smuzhiyun #define QM_FD_FORMAT_LONG BIT(30)
92*4882a593Smuzhiyun #define QM_FD_FORMAT_COMPOUND BIT(29)
93*4882a593Smuzhiyun #define QM_FD_FORMAT_MASK GENMASK(31, 29)
94*4882a593Smuzhiyun #define QM_FD_OFF_SHIFT 20
95*4882a593Smuzhiyun #define QM_FD_OFF_MASK GENMASK(28, 20)
96*4882a593Smuzhiyun #define QM_FD_LEN_MASK GENMASK(19, 0)
97*4882a593Smuzhiyun #define QM_FD_LEN_BIG_MASK GENMASK(28, 0)
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun enum qm_fd_format {
100*4882a593Smuzhiyun /*
101*4882a593Smuzhiyun * 'contig' implies a contiguous buffer, whereas 'sg' implies a
102*4882a593Smuzhiyun * scatter-gather table. 'big' implies a 29-bit length with no offset
103*4882a593Smuzhiyun * field, otherwise length is 20-bit and offset is 9-bit. 'compound'
104*4882a593Smuzhiyun * implies a s/g-like table, where each entry itself represents a frame
105*4882a593Smuzhiyun * (contiguous or scatter-gather) and the 29-bit "length" is
106*4882a593Smuzhiyun * interpreted purely for congestion calculations, ie. a "congestion
107*4882a593Smuzhiyun * weight".
108*4882a593Smuzhiyun */
109*4882a593Smuzhiyun qm_fd_contig = 0,
110*4882a593Smuzhiyun qm_fd_contig_big = QM_FD_FORMAT_LONG,
111*4882a593Smuzhiyun qm_fd_sg = QM_FD_FORMAT_SG,
112*4882a593Smuzhiyun qm_fd_sg_big = QM_FD_FORMAT_SG | QM_FD_FORMAT_LONG,
113*4882a593Smuzhiyun qm_fd_compound = QM_FD_FORMAT_COMPOUND
114*4882a593Smuzhiyun };
115*4882a593Smuzhiyun
qm_fd_addr(const struct qm_fd * fd)116*4882a593Smuzhiyun static inline dma_addr_t qm_fd_addr(const struct qm_fd *fd)
117*4882a593Smuzhiyun {
118*4882a593Smuzhiyun return be64_to_cpu(fd->data) & 0xffffffffffLLU;
119*4882a593Smuzhiyun }
120*4882a593Smuzhiyun
qm_fd_addr_get64(const struct qm_fd * fd)121*4882a593Smuzhiyun static inline u64 qm_fd_addr_get64(const struct qm_fd *fd)
122*4882a593Smuzhiyun {
123*4882a593Smuzhiyun return be64_to_cpu(fd->data) & 0xffffffffffLLU;
124*4882a593Smuzhiyun }
125*4882a593Smuzhiyun
qm_fd_addr_set64(struct qm_fd * fd,u64 addr)126*4882a593Smuzhiyun static inline void qm_fd_addr_set64(struct qm_fd *fd, u64 addr)
127*4882a593Smuzhiyun {
128*4882a593Smuzhiyun fd->addr_hi = upper_32_bits(addr);
129*4882a593Smuzhiyun fd->addr_lo = cpu_to_be32(lower_32_bits(addr));
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun /*
133*4882a593Smuzhiyun * The 'format' field indicates the interpretation of the remaining
134*4882a593Smuzhiyun * 29 bits of the 32-bit word.
135*4882a593Smuzhiyun * If 'format' is _contig or _sg, 20b length and 9b offset.
136*4882a593Smuzhiyun * If 'format' is _contig_big or _sg_big, 29b length.
137*4882a593Smuzhiyun * If 'format' is _compound, 29b "congestion weight".
138*4882a593Smuzhiyun */
qm_fd_get_format(const struct qm_fd * fd)139*4882a593Smuzhiyun static inline enum qm_fd_format qm_fd_get_format(const struct qm_fd *fd)
140*4882a593Smuzhiyun {
141*4882a593Smuzhiyun return be32_to_cpu(fd->cfg) & QM_FD_FORMAT_MASK;
142*4882a593Smuzhiyun }
143*4882a593Smuzhiyun
qm_fd_get_offset(const struct qm_fd * fd)144*4882a593Smuzhiyun static inline int qm_fd_get_offset(const struct qm_fd *fd)
145*4882a593Smuzhiyun {
146*4882a593Smuzhiyun return (be32_to_cpu(fd->cfg) & QM_FD_OFF_MASK) >> QM_FD_OFF_SHIFT;
147*4882a593Smuzhiyun }
148*4882a593Smuzhiyun
qm_fd_get_length(const struct qm_fd * fd)149*4882a593Smuzhiyun static inline int qm_fd_get_length(const struct qm_fd *fd)
150*4882a593Smuzhiyun {
151*4882a593Smuzhiyun return be32_to_cpu(fd->cfg) & QM_FD_LEN_MASK;
152*4882a593Smuzhiyun }
153*4882a593Smuzhiyun
qm_fd_get_len_big(const struct qm_fd * fd)154*4882a593Smuzhiyun static inline int qm_fd_get_len_big(const struct qm_fd *fd)
155*4882a593Smuzhiyun {
156*4882a593Smuzhiyun return be32_to_cpu(fd->cfg) & QM_FD_LEN_BIG_MASK;
157*4882a593Smuzhiyun }
158*4882a593Smuzhiyun
qm_fd_set_param(struct qm_fd * fd,enum qm_fd_format fmt,int off,int len)159*4882a593Smuzhiyun static inline void qm_fd_set_param(struct qm_fd *fd, enum qm_fd_format fmt,
160*4882a593Smuzhiyun int off, int len)
161*4882a593Smuzhiyun {
162*4882a593Smuzhiyun fd->cfg = cpu_to_be32(fmt | (len & QM_FD_LEN_BIG_MASK) |
163*4882a593Smuzhiyun ((off << QM_FD_OFF_SHIFT) & QM_FD_OFF_MASK));
164*4882a593Smuzhiyun }
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun #define qm_fd_set_contig(fd, off, len) \
167*4882a593Smuzhiyun qm_fd_set_param(fd, qm_fd_contig, off, len)
168*4882a593Smuzhiyun #define qm_fd_set_sg(fd, off, len) qm_fd_set_param(fd, qm_fd_sg, off, len)
169*4882a593Smuzhiyun #define qm_fd_set_contig_big(fd, len) \
170*4882a593Smuzhiyun qm_fd_set_param(fd, qm_fd_contig_big, 0, len)
171*4882a593Smuzhiyun #define qm_fd_set_sg_big(fd, len) qm_fd_set_param(fd, qm_fd_sg_big, 0, len)
172*4882a593Smuzhiyun #define qm_fd_set_compound(fd, len) qm_fd_set_param(fd, qm_fd_compound, 0, len)
173*4882a593Smuzhiyun
qm_fd_clear_fd(struct qm_fd * fd)174*4882a593Smuzhiyun static inline void qm_fd_clear_fd(struct qm_fd *fd)
175*4882a593Smuzhiyun {
176*4882a593Smuzhiyun fd->data = 0;
177*4882a593Smuzhiyun fd->cfg = 0;
178*4882a593Smuzhiyun fd->cmd = 0;
179*4882a593Smuzhiyun }
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun /* Scatter/Gather table entry */
182*4882a593Smuzhiyun struct qm_sg_entry {
183*4882a593Smuzhiyun union {
184*4882a593Smuzhiyun struct {
185*4882a593Smuzhiyun u8 __reserved1[3];
186*4882a593Smuzhiyun u8 addr_hi; /* high 8-bits of 40-bit address */
187*4882a593Smuzhiyun __be32 addr_lo; /* low 32-bits of 40-bit address */
188*4882a593Smuzhiyun };
189*4882a593Smuzhiyun __be64 data;
190*4882a593Smuzhiyun };
191*4882a593Smuzhiyun __be32 cfg; /* E bit, F bit, length */
192*4882a593Smuzhiyun u8 __reserved2;
193*4882a593Smuzhiyun u8 bpid;
194*4882a593Smuzhiyun __be16 offset; /* 13-bit, _res[13-15]*/
195*4882a593Smuzhiyun } __packed;
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun #define QM_SG_LEN_MASK GENMASK(29, 0)
198*4882a593Smuzhiyun #define QM_SG_OFF_MASK GENMASK(12, 0)
199*4882a593Smuzhiyun #define QM_SG_FIN BIT(30)
200*4882a593Smuzhiyun #define QM_SG_EXT BIT(31)
201*4882a593Smuzhiyun
qm_sg_addr(const struct qm_sg_entry * sg)202*4882a593Smuzhiyun static inline dma_addr_t qm_sg_addr(const struct qm_sg_entry *sg)
203*4882a593Smuzhiyun {
204*4882a593Smuzhiyun return be64_to_cpu(sg->data) & 0xffffffffffLLU;
205*4882a593Smuzhiyun }
206*4882a593Smuzhiyun
qm_sg_entry_get64(const struct qm_sg_entry * sg)207*4882a593Smuzhiyun static inline u64 qm_sg_entry_get64(const struct qm_sg_entry *sg)
208*4882a593Smuzhiyun {
209*4882a593Smuzhiyun return be64_to_cpu(sg->data) & 0xffffffffffLLU;
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun
qm_sg_entry_set64(struct qm_sg_entry * sg,u64 addr)212*4882a593Smuzhiyun static inline void qm_sg_entry_set64(struct qm_sg_entry *sg, u64 addr)
213*4882a593Smuzhiyun {
214*4882a593Smuzhiyun sg->addr_hi = upper_32_bits(addr);
215*4882a593Smuzhiyun sg->addr_lo = cpu_to_be32(lower_32_bits(addr));
216*4882a593Smuzhiyun }
217*4882a593Smuzhiyun
qm_sg_entry_is_final(const struct qm_sg_entry * sg)218*4882a593Smuzhiyun static inline bool qm_sg_entry_is_final(const struct qm_sg_entry *sg)
219*4882a593Smuzhiyun {
220*4882a593Smuzhiyun return be32_to_cpu(sg->cfg) & QM_SG_FIN;
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun
qm_sg_entry_is_ext(const struct qm_sg_entry * sg)223*4882a593Smuzhiyun static inline bool qm_sg_entry_is_ext(const struct qm_sg_entry *sg)
224*4882a593Smuzhiyun {
225*4882a593Smuzhiyun return be32_to_cpu(sg->cfg) & QM_SG_EXT;
226*4882a593Smuzhiyun }
227*4882a593Smuzhiyun
qm_sg_entry_get_len(const struct qm_sg_entry * sg)228*4882a593Smuzhiyun static inline int qm_sg_entry_get_len(const struct qm_sg_entry *sg)
229*4882a593Smuzhiyun {
230*4882a593Smuzhiyun return be32_to_cpu(sg->cfg) & QM_SG_LEN_MASK;
231*4882a593Smuzhiyun }
232*4882a593Smuzhiyun
qm_sg_entry_set_len(struct qm_sg_entry * sg,int len)233*4882a593Smuzhiyun static inline void qm_sg_entry_set_len(struct qm_sg_entry *sg, int len)
234*4882a593Smuzhiyun {
235*4882a593Smuzhiyun sg->cfg = cpu_to_be32(len & QM_SG_LEN_MASK);
236*4882a593Smuzhiyun }
237*4882a593Smuzhiyun
qm_sg_entry_set_f(struct qm_sg_entry * sg,int len)238*4882a593Smuzhiyun static inline void qm_sg_entry_set_f(struct qm_sg_entry *sg, int len)
239*4882a593Smuzhiyun {
240*4882a593Smuzhiyun sg->cfg = cpu_to_be32(QM_SG_FIN | (len & QM_SG_LEN_MASK));
241*4882a593Smuzhiyun }
242*4882a593Smuzhiyun
qm_sg_entry_get_off(const struct qm_sg_entry * sg)243*4882a593Smuzhiyun static inline int qm_sg_entry_get_off(const struct qm_sg_entry *sg)
244*4882a593Smuzhiyun {
245*4882a593Smuzhiyun return be32_to_cpu(sg->offset) & QM_SG_OFF_MASK;
246*4882a593Smuzhiyun }
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun /* "Frame Dequeue Response" */
249*4882a593Smuzhiyun struct qm_dqrr_entry {
250*4882a593Smuzhiyun u8 verb;
251*4882a593Smuzhiyun u8 stat;
252*4882a593Smuzhiyun __be16 seqnum; /* 15-bit */
253*4882a593Smuzhiyun u8 tok;
254*4882a593Smuzhiyun u8 __reserved2[3];
255*4882a593Smuzhiyun __be32 fqid; /* 24-bit */
256*4882a593Smuzhiyun __be32 context_b;
257*4882a593Smuzhiyun struct qm_fd fd;
258*4882a593Smuzhiyun u8 __reserved4[32];
259*4882a593Smuzhiyun } __packed __aligned(64);
260*4882a593Smuzhiyun #define QM_DQRR_VERB_VBIT 0x80
261*4882a593Smuzhiyun #define QM_DQRR_VERB_MASK 0x7f /* where the verb contains; */
262*4882a593Smuzhiyun #define QM_DQRR_VERB_FRAME_DEQUEUE 0x60 /* "this format" */
263*4882a593Smuzhiyun #define QM_DQRR_STAT_FQ_EMPTY 0x80 /* FQ empty */
264*4882a593Smuzhiyun #define QM_DQRR_STAT_FQ_HELDACTIVE 0x40 /* FQ held active */
265*4882a593Smuzhiyun #define QM_DQRR_STAT_FQ_FORCEELIGIBLE 0x20 /* FQ was force-eligible'd */
266*4882a593Smuzhiyun #define QM_DQRR_STAT_FD_VALID 0x10 /* has a non-NULL FD */
267*4882a593Smuzhiyun #define QM_DQRR_STAT_UNSCHEDULED 0x02 /* Unscheduled dequeue */
268*4882a593Smuzhiyun #define QM_DQRR_STAT_DQCR_EXPIRED 0x01 /* VDQCR or PDQCR expired*/
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun /* 'fqid' is a 24-bit field in every h/w descriptor */
271*4882a593Smuzhiyun #define QM_FQID_MASK GENMASK(23, 0)
272*4882a593Smuzhiyun #define qm_fqid_set(p, v) ((p)->fqid = cpu_to_be32((v) & QM_FQID_MASK))
273*4882a593Smuzhiyun #define qm_fqid_get(p) (be32_to_cpu((p)->fqid) & QM_FQID_MASK)
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun /* "ERN Message Response" */
276*4882a593Smuzhiyun /* "FQ State Change Notification" */
277*4882a593Smuzhiyun union qm_mr_entry {
278*4882a593Smuzhiyun struct {
279*4882a593Smuzhiyun u8 verb;
280*4882a593Smuzhiyun u8 __reserved[63];
281*4882a593Smuzhiyun };
282*4882a593Smuzhiyun struct {
283*4882a593Smuzhiyun u8 verb;
284*4882a593Smuzhiyun u8 dca;
285*4882a593Smuzhiyun __be16 seqnum;
286*4882a593Smuzhiyun u8 rc; /* Rej Code: 8-bit */
287*4882a593Smuzhiyun u8 __reserved[3];
288*4882a593Smuzhiyun __be32 fqid; /* 24-bit */
289*4882a593Smuzhiyun __be32 tag;
290*4882a593Smuzhiyun struct qm_fd fd;
291*4882a593Smuzhiyun u8 __reserved1[32];
292*4882a593Smuzhiyun } __packed __aligned(64) ern;
293*4882a593Smuzhiyun struct {
294*4882a593Smuzhiyun u8 verb;
295*4882a593Smuzhiyun u8 fqs; /* Frame Queue Status */
296*4882a593Smuzhiyun u8 __reserved1[6];
297*4882a593Smuzhiyun __be32 fqid; /* 24-bit */
298*4882a593Smuzhiyun __be32 context_b;
299*4882a593Smuzhiyun u8 __reserved2[48];
300*4882a593Smuzhiyun } __packed fq; /* FQRN/FQRNI/FQRL/FQPN */
301*4882a593Smuzhiyun };
302*4882a593Smuzhiyun #define QM_MR_VERB_VBIT 0x80
303*4882a593Smuzhiyun /*
304*4882a593Smuzhiyun * ERNs originating from direct-connect portals ("dcern") use 0x20 as a verb
305*4882a593Smuzhiyun * which would be invalid as a s/w enqueue verb. A s/w ERN can be distinguished
306*4882a593Smuzhiyun * from the other MR types by noting if the 0x20 bit is unset.
307*4882a593Smuzhiyun */
308*4882a593Smuzhiyun #define QM_MR_VERB_TYPE_MASK 0x27
309*4882a593Smuzhiyun #define QM_MR_VERB_DC_ERN 0x20
310*4882a593Smuzhiyun #define QM_MR_VERB_FQRN 0x21
311*4882a593Smuzhiyun #define QM_MR_VERB_FQRNI 0x22
312*4882a593Smuzhiyun #define QM_MR_VERB_FQRL 0x23
313*4882a593Smuzhiyun #define QM_MR_VERB_FQPN 0x24
314*4882a593Smuzhiyun #define QM_MR_RC_MASK 0xf0 /* contains one of; */
315*4882a593Smuzhiyun #define QM_MR_RC_CGR_TAILDROP 0x00
316*4882a593Smuzhiyun #define QM_MR_RC_WRED 0x10
317*4882a593Smuzhiyun #define QM_MR_RC_ERROR 0x20
318*4882a593Smuzhiyun #define QM_MR_RC_ORPWINDOW_EARLY 0x30
319*4882a593Smuzhiyun #define QM_MR_RC_ORPWINDOW_LATE 0x40
320*4882a593Smuzhiyun #define QM_MR_RC_FQ_TAILDROP 0x50
321*4882a593Smuzhiyun #define QM_MR_RC_ORPWINDOW_RETIRED 0x60
322*4882a593Smuzhiyun #define QM_MR_RC_ORP_ZERO 0x70
323*4882a593Smuzhiyun #define QM_MR_FQS_ORLPRESENT 0x02 /* ORL fragments to come */
324*4882a593Smuzhiyun #define QM_MR_FQS_NOTEMPTY 0x01 /* FQ has enqueued frames */
325*4882a593Smuzhiyun
326*4882a593Smuzhiyun /*
327*4882a593Smuzhiyun * An identical structure of FQD fields is present in the "Init FQ" command and
328*4882a593Smuzhiyun * the "Query FQ" result, it's suctioned out into the "struct qm_fqd" type.
329*4882a593Smuzhiyun * Within that, the 'stashing' and 'taildrop' pieces are also factored out, the
330*4882a593Smuzhiyun * latter has two inlines to assist with converting to/from the mant+exp
331*4882a593Smuzhiyun * representation.
332*4882a593Smuzhiyun */
333*4882a593Smuzhiyun struct qm_fqd_stashing {
334*4882a593Smuzhiyun /* See QM_STASHING_EXCL_<...> */
335*4882a593Smuzhiyun u8 exclusive;
336*4882a593Smuzhiyun /* Numbers of cachelines */
337*4882a593Smuzhiyun u8 cl; /* _res[6-7], as[4-5], ds[2-3], cs[0-1] */
338*4882a593Smuzhiyun };
339*4882a593Smuzhiyun
340*4882a593Smuzhiyun struct qm_fqd_oac {
341*4882a593Smuzhiyun /* "Overhead Accounting Control", see QM_OAC_<...> */
342*4882a593Smuzhiyun u8 oac; /* oac[6-7], _res[0-5] */
343*4882a593Smuzhiyun /* Two's-complement value (-128 to +127) */
344*4882a593Smuzhiyun s8 oal; /* "Overhead Accounting Length" */
345*4882a593Smuzhiyun };
346*4882a593Smuzhiyun
347*4882a593Smuzhiyun struct qm_fqd {
348*4882a593Smuzhiyun /* _res[6-7], orprws[3-5], oa[2], olws[0-1] */
349*4882a593Smuzhiyun u8 orpc;
350*4882a593Smuzhiyun u8 cgid;
351*4882a593Smuzhiyun __be16 fq_ctrl; /* See QM_FQCTRL_<...> */
352*4882a593Smuzhiyun __be16 dest_wq; /* channel[3-15], wq[0-2] */
353*4882a593Smuzhiyun __be16 ics_cred; /* 15-bit */
354*4882a593Smuzhiyun /*
355*4882a593Smuzhiyun * For "Initialize Frame Queue" commands, the write-enable mask
356*4882a593Smuzhiyun * determines whether 'td' or 'oac_init' is observed. For query
357*4882a593Smuzhiyun * commands, this field is always 'td', and 'oac_query' (below) reflects
358*4882a593Smuzhiyun * the Overhead ACcounting values.
359*4882a593Smuzhiyun */
360*4882a593Smuzhiyun union {
361*4882a593Smuzhiyun __be16 td; /* "Taildrop": _res[13-15], mant[5-12], exp[0-4] */
362*4882a593Smuzhiyun struct qm_fqd_oac oac_init;
363*4882a593Smuzhiyun };
364*4882a593Smuzhiyun __be32 context_b;
365*4882a593Smuzhiyun union {
366*4882a593Smuzhiyun /* Treat it as 64-bit opaque */
367*4882a593Smuzhiyun __be64 opaque;
368*4882a593Smuzhiyun struct {
369*4882a593Smuzhiyun __be32 hi;
370*4882a593Smuzhiyun __be32 lo;
371*4882a593Smuzhiyun };
372*4882a593Smuzhiyun /* Treat it as s/w portal stashing config */
373*4882a593Smuzhiyun /* see "FQD Context_A field used for [...]" */
374*4882a593Smuzhiyun struct {
375*4882a593Smuzhiyun struct qm_fqd_stashing stashing;
376*4882a593Smuzhiyun /*
377*4882a593Smuzhiyun * 48-bit address of FQ context to
378*4882a593Smuzhiyun * stash, must be cacheline-aligned
379*4882a593Smuzhiyun */
380*4882a593Smuzhiyun __be16 context_hi;
381*4882a593Smuzhiyun __be32 context_lo;
382*4882a593Smuzhiyun } __packed;
383*4882a593Smuzhiyun } context_a;
384*4882a593Smuzhiyun struct qm_fqd_oac oac_query;
385*4882a593Smuzhiyun } __packed;
386*4882a593Smuzhiyun
387*4882a593Smuzhiyun #define QM_FQD_CHAN_OFF 3
388*4882a593Smuzhiyun #define QM_FQD_WQ_MASK GENMASK(2, 0)
389*4882a593Smuzhiyun #define QM_FQD_TD_EXP_MASK GENMASK(4, 0)
390*4882a593Smuzhiyun #define QM_FQD_TD_MANT_OFF 5
391*4882a593Smuzhiyun #define QM_FQD_TD_MANT_MASK GENMASK(12, 5)
392*4882a593Smuzhiyun #define QM_FQD_TD_MAX 0xe0000000
393*4882a593Smuzhiyun #define QM_FQD_TD_MANT_MAX 0xff
394*4882a593Smuzhiyun #define QM_FQD_OAC_OFF 6
395*4882a593Smuzhiyun #define QM_FQD_AS_OFF 4
396*4882a593Smuzhiyun #define QM_FQD_DS_OFF 2
397*4882a593Smuzhiyun #define QM_FQD_XS_MASK 0x3
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun /* 64-bit converters for context_hi/lo */
qm_fqd_stashing_get64(const struct qm_fqd * fqd)400*4882a593Smuzhiyun static inline u64 qm_fqd_stashing_get64(const struct qm_fqd *fqd)
401*4882a593Smuzhiyun {
402*4882a593Smuzhiyun return be64_to_cpu(fqd->context_a.opaque) & 0xffffffffffffULL;
403*4882a593Smuzhiyun }
404*4882a593Smuzhiyun
qm_fqd_stashing_addr(const struct qm_fqd * fqd)405*4882a593Smuzhiyun static inline dma_addr_t qm_fqd_stashing_addr(const struct qm_fqd *fqd)
406*4882a593Smuzhiyun {
407*4882a593Smuzhiyun return be64_to_cpu(fqd->context_a.opaque) & 0xffffffffffffULL;
408*4882a593Smuzhiyun }
409*4882a593Smuzhiyun
qm_fqd_context_a_get64(const struct qm_fqd * fqd)410*4882a593Smuzhiyun static inline u64 qm_fqd_context_a_get64(const struct qm_fqd *fqd)
411*4882a593Smuzhiyun {
412*4882a593Smuzhiyun return qm_fqd_stashing_get64(fqd);
413*4882a593Smuzhiyun }
414*4882a593Smuzhiyun
qm_fqd_stashing_set64(struct qm_fqd * fqd,u64 addr)415*4882a593Smuzhiyun static inline void qm_fqd_stashing_set64(struct qm_fqd *fqd, u64 addr)
416*4882a593Smuzhiyun {
417*4882a593Smuzhiyun fqd->context_a.context_hi = cpu_to_be16(upper_32_bits(addr));
418*4882a593Smuzhiyun fqd->context_a.context_lo = cpu_to_be32(lower_32_bits(addr));
419*4882a593Smuzhiyun }
420*4882a593Smuzhiyun
qm_fqd_context_a_set64(struct qm_fqd * fqd,u64 addr)421*4882a593Smuzhiyun static inline void qm_fqd_context_a_set64(struct qm_fqd *fqd, u64 addr)
422*4882a593Smuzhiyun {
423*4882a593Smuzhiyun fqd->context_a.hi = cpu_to_be32(upper_32_bits(addr));
424*4882a593Smuzhiyun fqd->context_a.lo = cpu_to_be32(lower_32_bits(addr));
425*4882a593Smuzhiyun }
426*4882a593Smuzhiyun
427*4882a593Smuzhiyun /* convert a threshold value into mant+exp representation */
qm_fqd_set_taildrop(struct qm_fqd * fqd,u32 val,int roundup)428*4882a593Smuzhiyun static inline int qm_fqd_set_taildrop(struct qm_fqd *fqd, u32 val,
429*4882a593Smuzhiyun int roundup)
430*4882a593Smuzhiyun {
431*4882a593Smuzhiyun u32 e = 0;
432*4882a593Smuzhiyun int td, oddbit = 0;
433*4882a593Smuzhiyun
434*4882a593Smuzhiyun if (val > QM_FQD_TD_MAX)
435*4882a593Smuzhiyun return -ERANGE;
436*4882a593Smuzhiyun
437*4882a593Smuzhiyun while (val > QM_FQD_TD_MANT_MAX) {
438*4882a593Smuzhiyun oddbit = val & 1;
439*4882a593Smuzhiyun val >>= 1;
440*4882a593Smuzhiyun e++;
441*4882a593Smuzhiyun if (roundup && oddbit)
442*4882a593Smuzhiyun val++;
443*4882a593Smuzhiyun }
444*4882a593Smuzhiyun
445*4882a593Smuzhiyun td = (val << QM_FQD_TD_MANT_OFF) & QM_FQD_TD_MANT_MASK;
446*4882a593Smuzhiyun td |= (e & QM_FQD_TD_EXP_MASK);
447*4882a593Smuzhiyun fqd->td = cpu_to_be16(td);
448*4882a593Smuzhiyun return 0;
449*4882a593Smuzhiyun }
450*4882a593Smuzhiyun /* and the other direction */
qm_fqd_get_taildrop(const struct qm_fqd * fqd)451*4882a593Smuzhiyun static inline int qm_fqd_get_taildrop(const struct qm_fqd *fqd)
452*4882a593Smuzhiyun {
453*4882a593Smuzhiyun int td = be16_to_cpu(fqd->td);
454*4882a593Smuzhiyun
455*4882a593Smuzhiyun return ((td & QM_FQD_TD_MANT_MASK) >> QM_FQD_TD_MANT_OFF)
456*4882a593Smuzhiyun << (td & QM_FQD_TD_EXP_MASK);
457*4882a593Smuzhiyun }
458*4882a593Smuzhiyun
qm_fqd_set_stashing(struct qm_fqd * fqd,u8 as,u8 ds,u8 cs)459*4882a593Smuzhiyun static inline void qm_fqd_set_stashing(struct qm_fqd *fqd, u8 as, u8 ds, u8 cs)
460*4882a593Smuzhiyun {
461*4882a593Smuzhiyun struct qm_fqd_stashing *st = &fqd->context_a.stashing;
462*4882a593Smuzhiyun
463*4882a593Smuzhiyun st->cl = ((as & QM_FQD_XS_MASK) << QM_FQD_AS_OFF) |
464*4882a593Smuzhiyun ((ds & QM_FQD_XS_MASK) << QM_FQD_DS_OFF) |
465*4882a593Smuzhiyun (cs & QM_FQD_XS_MASK);
466*4882a593Smuzhiyun }
467*4882a593Smuzhiyun
qm_fqd_get_stashing(const struct qm_fqd * fqd)468*4882a593Smuzhiyun static inline u8 qm_fqd_get_stashing(const struct qm_fqd *fqd)
469*4882a593Smuzhiyun {
470*4882a593Smuzhiyun return fqd->context_a.stashing.cl;
471*4882a593Smuzhiyun }
472*4882a593Smuzhiyun
qm_fqd_set_oac(struct qm_fqd * fqd,u8 val)473*4882a593Smuzhiyun static inline void qm_fqd_set_oac(struct qm_fqd *fqd, u8 val)
474*4882a593Smuzhiyun {
475*4882a593Smuzhiyun fqd->oac_init.oac = val << QM_FQD_OAC_OFF;
476*4882a593Smuzhiyun }
477*4882a593Smuzhiyun
qm_fqd_set_oal(struct qm_fqd * fqd,s8 val)478*4882a593Smuzhiyun static inline void qm_fqd_set_oal(struct qm_fqd *fqd, s8 val)
479*4882a593Smuzhiyun {
480*4882a593Smuzhiyun fqd->oac_init.oal = val;
481*4882a593Smuzhiyun }
482*4882a593Smuzhiyun
qm_fqd_set_destwq(struct qm_fqd * fqd,int ch,int wq)483*4882a593Smuzhiyun static inline void qm_fqd_set_destwq(struct qm_fqd *fqd, int ch, int wq)
484*4882a593Smuzhiyun {
485*4882a593Smuzhiyun fqd->dest_wq = cpu_to_be16((ch << QM_FQD_CHAN_OFF) |
486*4882a593Smuzhiyun (wq & QM_FQD_WQ_MASK));
487*4882a593Smuzhiyun }
488*4882a593Smuzhiyun
qm_fqd_get_chan(const struct qm_fqd * fqd)489*4882a593Smuzhiyun static inline int qm_fqd_get_chan(const struct qm_fqd *fqd)
490*4882a593Smuzhiyun {
491*4882a593Smuzhiyun return be16_to_cpu(fqd->dest_wq) >> QM_FQD_CHAN_OFF;
492*4882a593Smuzhiyun }
493*4882a593Smuzhiyun
qm_fqd_get_wq(const struct qm_fqd * fqd)494*4882a593Smuzhiyun static inline int qm_fqd_get_wq(const struct qm_fqd *fqd)
495*4882a593Smuzhiyun {
496*4882a593Smuzhiyun return be16_to_cpu(fqd->dest_wq) & QM_FQD_WQ_MASK;
497*4882a593Smuzhiyun }
498*4882a593Smuzhiyun
499*4882a593Smuzhiyun /* See "Frame Queue Descriptor (FQD)" */
500*4882a593Smuzhiyun /* Frame Queue Descriptor (FQD) field 'fq_ctrl' uses these constants */
501*4882a593Smuzhiyun #define QM_FQCTRL_MASK 0x07ff /* 'fq_ctrl' flags; */
502*4882a593Smuzhiyun #define QM_FQCTRL_CGE 0x0400 /* Congestion Group Enable */
503*4882a593Smuzhiyun #define QM_FQCTRL_TDE 0x0200 /* Tail-Drop Enable */
504*4882a593Smuzhiyun #define QM_FQCTRL_CTXASTASHING 0x0080 /* Context-A stashing */
505*4882a593Smuzhiyun #define QM_FQCTRL_CPCSTASH 0x0040 /* CPC Stash Enable */
506*4882a593Smuzhiyun #define QM_FQCTRL_FORCESFDR 0x0008 /* High-priority SFDRs */
507*4882a593Smuzhiyun #define QM_FQCTRL_AVOIDBLOCK 0x0004 /* Don't block active */
508*4882a593Smuzhiyun #define QM_FQCTRL_HOLDACTIVE 0x0002 /* Hold active in portal */
509*4882a593Smuzhiyun #define QM_FQCTRL_PREFERINCACHE 0x0001 /* Aggressively cache FQD */
510*4882a593Smuzhiyun #define QM_FQCTRL_LOCKINCACHE QM_FQCTRL_PREFERINCACHE /* older naming */
511*4882a593Smuzhiyun
512*4882a593Smuzhiyun /* See "FQD Context_A field used for [...] */
513*4882a593Smuzhiyun /* Frame Queue Descriptor (FQD) field 'CONTEXT_A' uses these constants */
514*4882a593Smuzhiyun #define QM_STASHING_EXCL_ANNOTATION 0x04
515*4882a593Smuzhiyun #define QM_STASHING_EXCL_DATA 0x02
516*4882a593Smuzhiyun #define QM_STASHING_EXCL_CTX 0x01
517*4882a593Smuzhiyun
518*4882a593Smuzhiyun /* See "Intra Class Scheduling" */
519*4882a593Smuzhiyun /* FQD field 'OAC' (Overhead ACcounting) uses these constants */
520*4882a593Smuzhiyun #define QM_OAC_ICS 0x2 /* Accounting for Intra-Class Scheduling */
521*4882a593Smuzhiyun #define QM_OAC_CG 0x1 /* Accounting for Congestion Groups */
522*4882a593Smuzhiyun
523*4882a593Smuzhiyun /*
524*4882a593Smuzhiyun * This struct represents the 32-bit "WR_PARM_[GYR]" parameters in CGR fields
525*4882a593Smuzhiyun * and associated commands/responses. The WRED parameters are calculated from
526*4882a593Smuzhiyun * these fields as follows;
527*4882a593Smuzhiyun * MaxTH = MA * (2 ^ Mn)
528*4882a593Smuzhiyun * Slope = SA / (2 ^ Sn)
529*4882a593Smuzhiyun * MaxP = 4 * (Pn + 1)
530*4882a593Smuzhiyun */
531*4882a593Smuzhiyun struct qm_cgr_wr_parm {
532*4882a593Smuzhiyun /* MA[24-31], Mn[19-23], SA[12-18], Sn[6-11], Pn[0-5] */
533*4882a593Smuzhiyun __be32 word;
534*4882a593Smuzhiyun };
535*4882a593Smuzhiyun /*
536*4882a593Smuzhiyun * This struct represents the 13-bit "CS_THRES" CGR field. In the corresponding
537*4882a593Smuzhiyun * management commands, this is padded to a 16-bit structure field, so that's
538*4882a593Smuzhiyun * how we represent it here. The congestion state threshold is calculated from
539*4882a593Smuzhiyun * these fields as follows;
540*4882a593Smuzhiyun * CS threshold = TA * (2 ^ Tn)
541*4882a593Smuzhiyun */
542*4882a593Smuzhiyun struct qm_cgr_cs_thres {
543*4882a593Smuzhiyun /* _res[13-15], TA[5-12], Tn[0-4] */
544*4882a593Smuzhiyun __be16 word;
545*4882a593Smuzhiyun };
546*4882a593Smuzhiyun /*
547*4882a593Smuzhiyun * This identical structure of CGR fields is present in the "Init/Modify CGR"
548*4882a593Smuzhiyun * commands and the "Query CGR" result. It's suctioned out here into its own
549*4882a593Smuzhiyun * struct.
550*4882a593Smuzhiyun */
551*4882a593Smuzhiyun struct __qm_mc_cgr {
552*4882a593Smuzhiyun struct qm_cgr_wr_parm wr_parm_g;
553*4882a593Smuzhiyun struct qm_cgr_wr_parm wr_parm_y;
554*4882a593Smuzhiyun struct qm_cgr_wr_parm wr_parm_r;
555*4882a593Smuzhiyun u8 wr_en_g; /* boolean, use QM_CGR_EN */
556*4882a593Smuzhiyun u8 wr_en_y; /* boolean, use QM_CGR_EN */
557*4882a593Smuzhiyun u8 wr_en_r; /* boolean, use QM_CGR_EN */
558*4882a593Smuzhiyun u8 cscn_en; /* boolean, use QM_CGR_EN */
559*4882a593Smuzhiyun union {
560*4882a593Smuzhiyun struct {
561*4882a593Smuzhiyun __be16 cscn_targ_upd_ctrl; /* use QM_CGR_TARG_UDP_* */
562*4882a593Smuzhiyun __be16 cscn_targ_dcp_low;
563*4882a593Smuzhiyun };
564*4882a593Smuzhiyun __be32 cscn_targ; /* use QM_CGR_TARG_* */
565*4882a593Smuzhiyun };
566*4882a593Smuzhiyun u8 cstd_en; /* boolean, use QM_CGR_EN */
567*4882a593Smuzhiyun u8 cs; /* boolean, only used in query response */
568*4882a593Smuzhiyun struct qm_cgr_cs_thres cs_thres; /* use qm_cgr_cs_thres_set64() */
569*4882a593Smuzhiyun u8 mode; /* QMAN_CGR_MODE_FRAME not supported in rev1.0 */
570*4882a593Smuzhiyun } __packed;
571*4882a593Smuzhiyun #define QM_CGR_EN 0x01 /* For wr_en_*, cscn_en, cstd_en */
572*4882a593Smuzhiyun #define QM_CGR_TARG_UDP_CTRL_WRITE_BIT 0x8000 /* value written to portal bit*/
573*4882a593Smuzhiyun #define QM_CGR_TARG_UDP_CTRL_DCP 0x4000 /* 0: SWP, 1: DCP */
574*4882a593Smuzhiyun #define QM_CGR_TARG_PORTAL(n) (0x80000000 >> (n)) /* s/w portal, 0-9 */
575*4882a593Smuzhiyun #define QM_CGR_TARG_FMAN0 0x00200000 /* direct-connect portal: fman0 */
576*4882a593Smuzhiyun #define QM_CGR_TARG_FMAN1 0x00100000 /* : fman1 */
577*4882a593Smuzhiyun /* Convert CGR thresholds to/from "cs_thres" format */
qm_cgr_cs_thres_get64(const struct qm_cgr_cs_thres * th)578*4882a593Smuzhiyun static inline u64 qm_cgr_cs_thres_get64(const struct qm_cgr_cs_thres *th)
579*4882a593Smuzhiyun {
580*4882a593Smuzhiyun int thres = be16_to_cpu(th->word);
581*4882a593Smuzhiyun
582*4882a593Smuzhiyun return ((thres >> 5) & 0xff) << (thres & 0x1f);
583*4882a593Smuzhiyun }
584*4882a593Smuzhiyun
qm_cgr_cs_thres_set64(struct qm_cgr_cs_thres * th,u64 val,int roundup)585*4882a593Smuzhiyun static inline int qm_cgr_cs_thres_set64(struct qm_cgr_cs_thres *th, u64 val,
586*4882a593Smuzhiyun int roundup)
587*4882a593Smuzhiyun {
588*4882a593Smuzhiyun u32 e = 0;
589*4882a593Smuzhiyun int oddbit = 0;
590*4882a593Smuzhiyun
591*4882a593Smuzhiyun while (val > 0xff) {
592*4882a593Smuzhiyun oddbit = val & 1;
593*4882a593Smuzhiyun val >>= 1;
594*4882a593Smuzhiyun e++;
595*4882a593Smuzhiyun if (roundup && oddbit)
596*4882a593Smuzhiyun val++;
597*4882a593Smuzhiyun }
598*4882a593Smuzhiyun th->word = cpu_to_be16(((val & 0xff) << 5) | (e & 0x1f));
599*4882a593Smuzhiyun return 0;
600*4882a593Smuzhiyun }
601*4882a593Smuzhiyun
602*4882a593Smuzhiyun /* "Initialize FQ" */
603*4882a593Smuzhiyun struct qm_mcc_initfq {
604*4882a593Smuzhiyun u8 __reserved1[2];
605*4882a593Smuzhiyun __be16 we_mask; /* Write Enable Mask */
606*4882a593Smuzhiyun __be32 fqid; /* 24-bit */
607*4882a593Smuzhiyun __be16 count; /* Initialises 'count+1' FQDs */
608*4882a593Smuzhiyun struct qm_fqd fqd; /* the FQD fields go here */
609*4882a593Smuzhiyun u8 __reserved2[30];
610*4882a593Smuzhiyun } __packed;
611*4882a593Smuzhiyun /* "Initialize/Modify CGR" */
612*4882a593Smuzhiyun struct qm_mcc_initcgr {
613*4882a593Smuzhiyun u8 __reserve1[2];
614*4882a593Smuzhiyun __be16 we_mask; /* Write Enable Mask */
615*4882a593Smuzhiyun struct __qm_mc_cgr cgr; /* CGR fields */
616*4882a593Smuzhiyun u8 __reserved2[2];
617*4882a593Smuzhiyun u8 cgid;
618*4882a593Smuzhiyun u8 __reserved3[32];
619*4882a593Smuzhiyun } __packed;
620*4882a593Smuzhiyun
621*4882a593Smuzhiyun /* INITFQ-specific flags */
622*4882a593Smuzhiyun #define QM_INITFQ_WE_MASK 0x01ff /* 'Write Enable' flags; */
623*4882a593Smuzhiyun #define QM_INITFQ_WE_OAC 0x0100
624*4882a593Smuzhiyun #define QM_INITFQ_WE_ORPC 0x0080
625*4882a593Smuzhiyun #define QM_INITFQ_WE_CGID 0x0040
626*4882a593Smuzhiyun #define QM_INITFQ_WE_FQCTRL 0x0020
627*4882a593Smuzhiyun #define QM_INITFQ_WE_DESTWQ 0x0010
628*4882a593Smuzhiyun #define QM_INITFQ_WE_ICSCRED 0x0008
629*4882a593Smuzhiyun #define QM_INITFQ_WE_TDTHRESH 0x0004
630*4882a593Smuzhiyun #define QM_INITFQ_WE_CONTEXTB 0x0002
631*4882a593Smuzhiyun #define QM_INITFQ_WE_CONTEXTA 0x0001
632*4882a593Smuzhiyun /* INITCGR/MODIFYCGR-specific flags */
633*4882a593Smuzhiyun #define QM_CGR_WE_MASK 0x07ff /* 'Write Enable Mask'; */
634*4882a593Smuzhiyun #define QM_CGR_WE_WR_PARM_G 0x0400
635*4882a593Smuzhiyun #define QM_CGR_WE_WR_PARM_Y 0x0200
636*4882a593Smuzhiyun #define QM_CGR_WE_WR_PARM_R 0x0100
637*4882a593Smuzhiyun #define QM_CGR_WE_WR_EN_G 0x0080
638*4882a593Smuzhiyun #define QM_CGR_WE_WR_EN_Y 0x0040
639*4882a593Smuzhiyun #define QM_CGR_WE_WR_EN_R 0x0020
640*4882a593Smuzhiyun #define QM_CGR_WE_CSCN_EN 0x0010
641*4882a593Smuzhiyun #define QM_CGR_WE_CSCN_TARG 0x0008
642*4882a593Smuzhiyun #define QM_CGR_WE_CSTD_EN 0x0004
643*4882a593Smuzhiyun #define QM_CGR_WE_CS_THRES 0x0002
644*4882a593Smuzhiyun #define QM_CGR_WE_MODE 0x0001
645*4882a593Smuzhiyun
646*4882a593Smuzhiyun #define QMAN_CGR_FLAG_USE_INIT 0x00000001
647*4882a593Smuzhiyun #define QMAN_CGR_MODE_FRAME 0x00000001
648*4882a593Smuzhiyun
649*4882a593Smuzhiyun /* Portal and Frame Queues */
650*4882a593Smuzhiyun /* Represents a managed portal */
651*4882a593Smuzhiyun struct qman_portal;
652*4882a593Smuzhiyun
653*4882a593Smuzhiyun /*
654*4882a593Smuzhiyun * This object type represents QMan frame queue descriptors (FQD), it is
655*4882a593Smuzhiyun * cacheline-aligned, and initialised by qman_create_fq(). The structure is
656*4882a593Smuzhiyun * defined further down.
657*4882a593Smuzhiyun */
658*4882a593Smuzhiyun struct qman_fq;
659*4882a593Smuzhiyun
660*4882a593Smuzhiyun /*
661*4882a593Smuzhiyun * This object type represents a QMan congestion group, it is defined further
662*4882a593Smuzhiyun * down.
663*4882a593Smuzhiyun */
664*4882a593Smuzhiyun struct qman_cgr;
665*4882a593Smuzhiyun
666*4882a593Smuzhiyun /*
667*4882a593Smuzhiyun * This enum, and the callback type that returns it, are used when handling
668*4882a593Smuzhiyun * dequeued frames via DQRR. Note that for "null" callbacks registered with the
669*4882a593Smuzhiyun * portal object (for handling dequeues that do not demux because context_b is
670*4882a593Smuzhiyun * NULL), the return value *MUST* be qman_cb_dqrr_consume.
671*4882a593Smuzhiyun */
672*4882a593Smuzhiyun enum qman_cb_dqrr_result {
673*4882a593Smuzhiyun /* DQRR entry can be consumed */
674*4882a593Smuzhiyun qman_cb_dqrr_consume,
675*4882a593Smuzhiyun /* Like _consume, but requests parking - FQ must be held-active */
676*4882a593Smuzhiyun qman_cb_dqrr_park,
677*4882a593Smuzhiyun /* Does not consume, for DCA mode only. */
678*4882a593Smuzhiyun qman_cb_dqrr_defer,
679*4882a593Smuzhiyun /*
680*4882a593Smuzhiyun * Stop processing without consuming this ring entry. Exits the current
681*4882a593Smuzhiyun * qman_p_poll_dqrr() or interrupt-handling, as appropriate. If within
682*4882a593Smuzhiyun * an interrupt handler, the callback would typically call
683*4882a593Smuzhiyun * qman_irqsource_remove(QM_PIRQ_DQRI) before returning this value,
684*4882a593Smuzhiyun * otherwise the interrupt will reassert immediately.
685*4882a593Smuzhiyun */
686*4882a593Smuzhiyun qman_cb_dqrr_stop,
687*4882a593Smuzhiyun /* Like qman_cb_dqrr_stop, but consumes the current entry. */
688*4882a593Smuzhiyun qman_cb_dqrr_consume_stop
689*4882a593Smuzhiyun };
690*4882a593Smuzhiyun typedef enum qman_cb_dqrr_result (*qman_cb_dqrr)(struct qman_portal *qm,
691*4882a593Smuzhiyun struct qman_fq *fq,
692*4882a593Smuzhiyun const struct qm_dqrr_entry *dqrr);
693*4882a593Smuzhiyun
694*4882a593Smuzhiyun /*
695*4882a593Smuzhiyun * This callback type is used when handling ERNs, FQRNs and FQRLs via MR. They
696*4882a593Smuzhiyun * are always consumed after the callback returns.
697*4882a593Smuzhiyun */
698*4882a593Smuzhiyun typedef void (*qman_cb_mr)(struct qman_portal *qm, struct qman_fq *fq,
699*4882a593Smuzhiyun const union qm_mr_entry *msg);
700*4882a593Smuzhiyun
701*4882a593Smuzhiyun /*
702*4882a593Smuzhiyun * s/w-visible states. Ie. tentatively scheduled + truly scheduled + active +
703*4882a593Smuzhiyun * held-active + held-suspended are just "sched". Things like "retired" will not
704*4882a593Smuzhiyun * be assumed until it is complete (ie. QMAN_FQ_STATE_CHANGING is set until
705*4882a593Smuzhiyun * then, to indicate it's completing and to gate attempts to retry the retire
706*4882a593Smuzhiyun * command). Note, park commands do not set QMAN_FQ_STATE_CHANGING because it's
707*4882a593Smuzhiyun * technically impossible in the case of enqueue DCAs (which refer to DQRR ring
708*4882a593Smuzhiyun * index rather than the FQ that ring entry corresponds to), so repeated park
709*4882a593Smuzhiyun * commands are allowed (if you're silly enough to try) but won't change FQ
710*4882a593Smuzhiyun * state, and the resulting park notifications move FQs from "sched" to
711*4882a593Smuzhiyun * "parked".
712*4882a593Smuzhiyun */
713*4882a593Smuzhiyun enum qman_fq_state {
714*4882a593Smuzhiyun qman_fq_state_oos,
715*4882a593Smuzhiyun qman_fq_state_parked,
716*4882a593Smuzhiyun qman_fq_state_sched,
717*4882a593Smuzhiyun qman_fq_state_retired
718*4882a593Smuzhiyun };
719*4882a593Smuzhiyun
720*4882a593Smuzhiyun #define QMAN_FQ_STATE_CHANGING 0x80000000 /* 'state' is changing */
721*4882a593Smuzhiyun #define QMAN_FQ_STATE_NE 0x40000000 /* retired FQ isn't empty */
722*4882a593Smuzhiyun #define QMAN_FQ_STATE_ORL 0x20000000 /* retired FQ has ORL */
723*4882a593Smuzhiyun #define QMAN_FQ_STATE_BLOCKOOS 0xe0000000 /* if any are set, no OOS */
724*4882a593Smuzhiyun #define QMAN_FQ_STATE_CGR_EN 0x10000000 /* CGR enabled */
725*4882a593Smuzhiyun #define QMAN_FQ_STATE_VDQCR 0x08000000 /* being volatile dequeued */
726*4882a593Smuzhiyun
727*4882a593Smuzhiyun /*
728*4882a593Smuzhiyun * Frame queue objects (struct qman_fq) are stored within memory passed to
729*4882a593Smuzhiyun * qman_create_fq(), as this allows stashing of caller-provided demux callback
730*4882a593Smuzhiyun * pointers at no extra cost to stashing of (driver-internal) FQ state. If the
731*4882a593Smuzhiyun * caller wishes to add per-FQ state and have it benefit from dequeue-stashing,
732*4882a593Smuzhiyun * they should;
733*4882a593Smuzhiyun *
734*4882a593Smuzhiyun * (a) extend the qman_fq structure with their state; eg.
735*4882a593Smuzhiyun *
736*4882a593Smuzhiyun * // myfq is allocated and driver_fq callbacks filled in;
737*4882a593Smuzhiyun * struct my_fq {
738*4882a593Smuzhiyun * struct qman_fq base;
739*4882a593Smuzhiyun * int an_extra_field;
740*4882a593Smuzhiyun * [ ... add other fields to be associated with each FQ ...]
741*4882a593Smuzhiyun * } *myfq = some_my_fq_allocator();
742*4882a593Smuzhiyun * struct qman_fq *fq = qman_create_fq(fqid, flags, &myfq->base);
743*4882a593Smuzhiyun *
744*4882a593Smuzhiyun * // in a dequeue callback, access extra fields from 'fq' via a cast;
745*4882a593Smuzhiyun * struct my_fq *myfq = (struct my_fq *)fq;
746*4882a593Smuzhiyun * do_something_with(myfq->an_extra_field);
747*4882a593Smuzhiyun * [...]
748*4882a593Smuzhiyun *
749*4882a593Smuzhiyun * (b) when and if configuring the FQ for context stashing, specify how ever
750*4882a593Smuzhiyun * many cachelines are required to stash 'struct my_fq', to accelerate not
751*4882a593Smuzhiyun * only the QMan driver but the callback as well.
752*4882a593Smuzhiyun */
753*4882a593Smuzhiyun
754*4882a593Smuzhiyun struct qman_fq_cb {
755*4882a593Smuzhiyun qman_cb_dqrr dqrr; /* for dequeued frames */
756*4882a593Smuzhiyun qman_cb_mr ern; /* for s/w ERNs */
757*4882a593Smuzhiyun qman_cb_mr fqs; /* frame-queue state changes*/
758*4882a593Smuzhiyun };
759*4882a593Smuzhiyun
760*4882a593Smuzhiyun struct qman_fq {
761*4882a593Smuzhiyun /* Caller of qman_create_fq() provides these demux callbacks */
762*4882a593Smuzhiyun struct qman_fq_cb cb;
763*4882a593Smuzhiyun /*
764*4882a593Smuzhiyun * These are internal to the driver, don't touch. In particular, they
765*4882a593Smuzhiyun * may change, be removed, or extended (so you shouldn't rely on
766*4882a593Smuzhiyun * sizeof(qman_fq) being a constant).
767*4882a593Smuzhiyun */
768*4882a593Smuzhiyun u32 fqid, idx;
769*4882a593Smuzhiyun unsigned long flags;
770*4882a593Smuzhiyun enum qman_fq_state state;
771*4882a593Smuzhiyun int cgr_groupid;
772*4882a593Smuzhiyun };
773*4882a593Smuzhiyun
774*4882a593Smuzhiyun /*
775*4882a593Smuzhiyun * This callback type is used when handling congestion group entry/exit.
776*4882a593Smuzhiyun * 'congested' is non-zero on congestion-entry, and zero on congestion-exit.
777*4882a593Smuzhiyun */
778*4882a593Smuzhiyun typedef void (*qman_cb_cgr)(struct qman_portal *qm,
779*4882a593Smuzhiyun struct qman_cgr *cgr, int congested);
780*4882a593Smuzhiyun
781*4882a593Smuzhiyun struct qman_cgr {
782*4882a593Smuzhiyun /* Set these prior to qman_create_cgr() */
783*4882a593Smuzhiyun u32 cgrid; /* 0..255, but u32 to allow specials like -1, 256, etc.*/
784*4882a593Smuzhiyun qman_cb_cgr cb;
785*4882a593Smuzhiyun /* These are private to the driver */
786*4882a593Smuzhiyun u16 chan; /* portal channel this object is created on */
787*4882a593Smuzhiyun struct list_head node;
788*4882a593Smuzhiyun };
789*4882a593Smuzhiyun
790*4882a593Smuzhiyun /* Flags to qman_create_fq() */
791*4882a593Smuzhiyun #define QMAN_FQ_FLAG_NO_ENQUEUE 0x00000001 /* can't enqueue */
792*4882a593Smuzhiyun #define QMAN_FQ_FLAG_NO_MODIFY 0x00000002 /* can only enqueue */
793*4882a593Smuzhiyun #define QMAN_FQ_FLAG_TO_DCPORTAL 0x00000004 /* consumed by CAAM/PME/Fman */
794*4882a593Smuzhiyun #define QMAN_FQ_FLAG_DYNAMIC_FQID 0x00000020 /* (de)allocate fqid */
795*4882a593Smuzhiyun
796*4882a593Smuzhiyun /* Flags to qman_init_fq() */
797*4882a593Smuzhiyun #define QMAN_INITFQ_FLAG_SCHED 0x00000001 /* schedule rather than park */
798*4882a593Smuzhiyun #define QMAN_INITFQ_FLAG_LOCAL 0x00000004 /* set dest portal */
799*4882a593Smuzhiyun
800*4882a593Smuzhiyun /*
801*4882a593Smuzhiyun * For qman_volatile_dequeue(); Choose one PRECEDENCE. EXACT is optional. Use
802*4882a593Smuzhiyun * NUMFRAMES(n) (6-bit) or NUMFRAMES_TILLEMPTY to fill in the frame-count. Use
803*4882a593Smuzhiyun * FQID(n) to fill in the frame queue ID.
804*4882a593Smuzhiyun */
805*4882a593Smuzhiyun #define QM_VDQCR_PRECEDENCE_VDQCR 0x0
806*4882a593Smuzhiyun #define QM_VDQCR_PRECEDENCE_SDQCR 0x80000000
807*4882a593Smuzhiyun #define QM_VDQCR_EXACT 0x40000000
808*4882a593Smuzhiyun #define QM_VDQCR_NUMFRAMES_MASK 0x3f000000
809*4882a593Smuzhiyun #define QM_VDQCR_NUMFRAMES_SET(n) (((n) & 0x3f) << 24)
810*4882a593Smuzhiyun #define QM_VDQCR_NUMFRAMES_GET(n) (((n) >> 24) & 0x3f)
811*4882a593Smuzhiyun #define QM_VDQCR_NUMFRAMES_TILLEMPTY QM_VDQCR_NUMFRAMES_SET(0)
812*4882a593Smuzhiyun
813*4882a593Smuzhiyun #define QMAN_VOLATILE_FLAG_WAIT 0x00000001 /* wait if VDQCR is in use */
814*4882a593Smuzhiyun #define QMAN_VOLATILE_FLAG_WAIT_INT 0x00000002 /* if wait, interruptible? */
815*4882a593Smuzhiyun #define QMAN_VOLATILE_FLAG_FINISH 0x00000004 /* wait till VDQCR completes */
816*4882a593Smuzhiyun
817*4882a593Smuzhiyun /* "Query FQ Non-Programmable Fields" */
818*4882a593Smuzhiyun struct qm_mcr_queryfq_np {
819*4882a593Smuzhiyun u8 verb;
820*4882a593Smuzhiyun u8 result;
821*4882a593Smuzhiyun u8 __reserved1;
822*4882a593Smuzhiyun u8 state; /* QM_MCR_NP_STATE_*** */
823*4882a593Smuzhiyun u32 fqd_link; /* 24-bit, _res2[24-31] */
824*4882a593Smuzhiyun u16 odp_seq; /* 14-bit, _res3[14-15] */
825*4882a593Smuzhiyun u16 orp_nesn; /* 14-bit, _res4[14-15] */
826*4882a593Smuzhiyun u16 orp_ea_hseq; /* 15-bit, _res5[15] */
827*4882a593Smuzhiyun u16 orp_ea_tseq; /* 15-bit, _res6[15] */
828*4882a593Smuzhiyun u32 orp_ea_hptr; /* 24-bit, _res7[24-31] */
829*4882a593Smuzhiyun u32 orp_ea_tptr; /* 24-bit, _res8[24-31] */
830*4882a593Smuzhiyun u32 pfdr_hptr; /* 24-bit, _res9[24-31] */
831*4882a593Smuzhiyun u32 pfdr_tptr; /* 24-bit, _res10[24-31] */
832*4882a593Smuzhiyun u8 __reserved2[5];
833*4882a593Smuzhiyun u8 is; /* 1-bit, _res12[1-7] */
834*4882a593Smuzhiyun u16 ics_surp;
835*4882a593Smuzhiyun u32 byte_cnt;
836*4882a593Smuzhiyun u32 frm_cnt; /* 24-bit, _res13[24-31] */
837*4882a593Smuzhiyun u32 __reserved3;
838*4882a593Smuzhiyun u16 ra1_sfdr; /* QM_MCR_NP_RA1_*** */
839*4882a593Smuzhiyun u16 ra2_sfdr; /* QM_MCR_NP_RA2_*** */
840*4882a593Smuzhiyun u16 __reserved4;
841*4882a593Smuzhiyun u16 od1_sfdr; /* QM_MCR_NP_OD1_*** */
842*4882a593Smuzhiyun u16 od2_sfdr; /* QM_MCR_NP_OD2_*** */
843*4882a593Smuzhiyun u16 od3_sfdr; /* QM_MCR_NP_OD3_*** */
844*4882a593Smuzhiyun } __packed;
845*4882a593Smuzhiyun
846*4882a593Smuzhiyun #define QM_MCR_NP_STATE_FE 0x10
847*4882a593Smuzhiyun #define QM_MCR_NP_STATE_R 0x08
848*4882a593Smuzhiyun #define QM_MCR_NP_STATE_MASK 0x07 /* Reads FQD::STATE; */
849*4882a593Smuzhiyun #define QM_MCR_NP_STATE_OOS 0x00
850*4882a593Smuzhiyun #define QM_MCR_NP_STATE_RETIRED 0x01
851*4882a593Smuzhiyun #define QM_MCR_NP_STATE_TEN_SCHED 0x02
852*4882a593Smuzhiyun #define QM_MCR_NP_STATE_TRU_SCHED 0x03
853*4882a593Smuzhiyun #define QM_MCR_NP_STATE_PARKED 0x04
854*4882a593Smuzhiyun #define QM_MCR_NP_STATE_ACTIVE 0x05
855*4882a593Smuzhiyun #define QM_MCR_NP_PTR_MASK 0x07ff /* for RA[12] & OD[123] */
856*4882a593Smuzhiyun #define QM_MCR_NP_RA1_NRA(v) (((v) >> 14) & 0x3) /* FQD::NRA */
857*4882a593Smuzhiyun #define QM_MCR_NP_RA2_IT(v) (((v) >> 14) & 0x1) /* FQD::IT */
858*4882a593Smuzhiyun #define QM_MCR_NP_OD1_NOD(v) (((v) >> 14) & 0x3) /* FQD::NOD */
859*4882a593Smuzhiyun #define QM_MCR_NP_OD3_NPC(v) (((v) >> 14) & 0x3) /* FQD::NPC */
860*4882a593Smuzhiyun
861*4882a593Smuzhiyun enum qm_mcr_queryfq_np_masks {
862*4882a593Smuzhiyun qm_mcr_fqd_link_mask = BIT(24) - 1,
863*4882a593Smuzhiyun qm_mcr_odp_seq_mask = BIT(14) - 1,
864*4882a593Smuzhiyun qm_mcr_orp_nesn_mask = BIT(14) - 1,
865*4882a593Smuzhiyun qm_mcr_orp_ea_hseq_mask = BIT(15) - 1,
866*4882a593Smuzhiyun qm_mcr_orp_ea_tseq_mask = BIT(15) - 1,
867*4882a593Smuzhiyun qm_mcr_orp_ea_hptr_mask = BIT(24) - 1,
868*4882a593Smuzhiyun qm_mcr_orp_ea_tptr_mask = BIT(24) - 1,
869*4882a593Smuzhiyun qm_mcr_pfdr_hptr_mask = BIT(24) - 1,
870*4882a593Smuzhiyun qm_mcr_pfdr_tptr_mask = BIT(24) - 1,
871*4882a593Smuzhiyun qm_mcr_is_mask = BIT(1) - 1,
872*4882a593Smuzhiyun qm_mcr_frm_cnt_mask = BIT(24) - 1,
873*4882a593Smuzhiyun };
874*4882a593Smuzhiyun
875*4882a593Smuzhiyun #define qm_mcr_np_get(np, field) \
876*4882a593Smuzhiyun ((np)->field & (qm_mcr_##field##_mask))
877*4882a593Smuzhiyun
878*4882a593Smuzhiyun /* Portal Management */
879*4882a593Smuzhiyun /**
880*4882a593Smuzhiyun * qman_p_irqsource_add - add processing sources to be interrupt-driven
881*4882a593Smuzhiyun * @bits: bitmask of QM_PIRQ_**I processing sources
882*4882a593Smuzhiyun *
883*4882a593Smuzhiyun * Adds processing sources that should be interrupt-driven (rather than
884*4882a593Smuzhiyun * processed via qman_poll_***() functions).
885*4882a593Smuzhiyun */
886*4882a593Smuzhiyun void qman_p_irqsource_add(struct qman_portal *p, u32 bits);
887*4882a593Smuzhiyun
888*4882a593Smuzhiyun /**
889*4882a593Smuzhiyun * qman_p_irqsource_remove - remove processing sources from being int-driven
890*4882a593Smuzhiyun * @bits: bitmask of QM_PIRQ_**I processing sources
891*4882a593Smuzhiyun *
892*4882a593Smuzhiyun * Removes processing sources from being interrupt-driven, so that they will
893*4882a593Smuzhiyun * instead be processed via qman_poll_***() functions.
894*4882a593Smuzhiyun */
895*4882a593Smuzhiyun void qman_p_irqsource_remove(struct qman_portal *p, u32 bits);
896*4882a593Smuzhiyun
897*4882a593Smuzhiyun /**
898*4882a593Smuzhiyun * qman_affine_cpus - return a mask of cpus that have affine portals
899*4882a593Smuzhiyun */
900*4882a593Smuzhiyun const cpumask_t *qman_affine_cpus(void);
901*4882a593Smuzhiyun
902*4882a593Smuzhiyun /**
903*4882a593Smuzhiyun * qman_affine_channel - return the channel ID of an portal
904*4882a593Smuzhiyun * @cpu: the cpu whose affine portal is the subject of the query
905*4882a593Smuzhiyun *
906*4882a593Smuzhiyun * If @cpu is -1, the affine portal for the current CPU will be used. It is a
907*4882a593Smuzhiyun * bug to call this function for any value of @cpu (other than -1) that is not a
908*4882a593Smuzhiyun * member of the mask returned from qman_affine_cpus().
909*4882a593Smuzhiyun */
910*4882a593Smuzhiyun u16 qman_affine_channel(int cpu);
911*4882a593Smuzhiyun
912*4882a593Smuzhiyun /**
913*4882a593Smuzhiyun * qman_get_affine_portal - return the portal pointer affine to cpu
914*4882a593Smuzhiyun * @cpu: the cpu whose affine portal is the subject of the query
915*4882a593Smuzhiyun */
916*4882a593Smuzhiyun struct qman_portal *qman_get_affine_portal(int cpu);
917*4882a593Smuzhiyun
918*4882a593Smuzhiyun /**
919*4882a593Smuzhiyun * qman_start_using_portal - register a device link for the portal user
920*4882a593Smuzhiyun * @p: the portal that will be in use
921*4882a593Smuzhiyun * @dev: the device that will use the portal
922*4882a593Smuzhiyun *
923*4882a593Smuzhiyun * Makes sure that the devices that use the portal are unbound when the
924*4882a593Smuzhiyun * portal is unbound
925*4882a593Smuzhiyun */
926*4882a593Smuzhiyun int qman_start_using_portal(struct qman_portal *p, struct device *dev);
927*4882a593Smuzhiyun
928*4882a593Smuzhiyun /**
929*4882a593Smuzhiyun * qman_p_poll_dqrr - process DQRR (fast-path) entries
930*4882a593Smuzhiyun * @limit: the maximum number of DQRR entries to process
931*4882a593Smuzhiyun *
932*4882a593Smuzhiyun * Use of this function requires that DQRR processing not be interrupt-driven.
933*4882a593Smuzhiyun * The return value represents the number of DQRR entries processed.
934*4882a593Smuzhiyun */
935*4882a593Smuzhiyun int qman_p_poll_dqrr(struct qman_portal *p, unsigned int limit);
936*4882a593Smuzhiyun
937*4882a593Smuzhiyun /**
938*4882a593Smuzhiyun * qman_p_static_dequeue_add - Add pool channels to the portal SDQCR
939*4882a593Smuzhiyun * @pools: bit-mask of pool channels, using QM_SDQCR_CHANNELS_POOL(n)
940*4882a593Smuzhiyun *
941*4882a593Smuzhiyun * Adds a set of pool channels to the portal's static dequeue command register
942*4882a593Smuzhiyun * (SDQCR). The requested pools are limited to those the portal has dequeue
943*4882a593Smuzhiyun * access to.
944*4882a593Smuzhiyun */
945*4882a593Smuzhiyun void qman_p_static_dequeue_add(struct qman_portal *p, u32 pools);
946*4882a593Smuzhiyun
947*4882a593Smuzhiyun /* FQ management */
948*4882a593Smuzhiyun /**
949*4882a593Smuzhiyun * qman_create_fq - Allocates a FQ
950*4882a593Smuzhiyun * @fqid: the index of the FQD to encapsulate, must be "Out of Service"
951*4882a593Smuzhiyun * @flags: bit-mask of QMAN_FQ_FLAG_*** options
952*4882a593Smuzhiyun * @fq: memory for storing the 'fq', with callbacks filled in
953*4882a593Smuzhiyun *
954*4882a593Smuzhiyun * Creates a frame queue object for the given @fqid, unless the
955*4882a593Smuzhiyun * QMAN_FQ_FLAG_DYNAMIC_FQID flag is set in @flags, in which case a FQID is
956*4882a593Smuzhiyun * dynamically allocated (or the function fails if none are available). Once
957*4882a593Smuzhiyun * created, the caller should not touch the memory at 'fq' except as extended to
958*4882a593Smuzhiyun * adjacent memory for user-defined fields (see the definition of "struct
959*4882a593Smuzhiyun * qman_fq" for more info). NO_MODIFY is only intended for enqueuing to
960*4882a593Smuzhiyun * pre-existing frame-queues that aren't to be otherwise interfered with, it
961*4882a593Smuzhiyun * prevents all other modifications to the frame queue. The TO_DCPORTAL flag
962*4882a593Smuzhiyun * causes the driver to honour any context_b modifications requested in the
963*4882a593Smuzhiyun * qm_init_fq() API, as this indicates the frame queue will be consumed by a
964*4882a593Smuzhiyun * direct-connect portal (PME, CAAM, or Fman). When frame queues are consumed by
965*4882a593Smuzhiyun * software portals, the context_b field is controlled by the driver and can't
966*4882a593Smuzhiyun * be modified by the caller.
967*4882a593Smuzhiyun */
968*4882a593Smuzhiyun int qman_create_fq(u32 fqid, u32 flags, struct qman_fq *fq);
969*4882a593Smuzhiyun
970*4882a593Smuzhiyun /**
971*4882a593Smuzhiyun * qman_destroy_fq - Deallocates a FQ
972*4882a593Smuzhiyun * @fq: the frame queue object to release
973*4882a593Smuzhiyun *
974*4882a593Smuzhiyun * The memory for this frame queue object ('fq' provided in qman_create_fq()) is
975*4882a593Smuzhiyun * not deallocated but the caller regains ownership, to do with as desired. The
976*4882a593Smuzhiyun * FQ must be in the 'out-of-service' or in the 'parked' state.
977*4882a593Smuzhiyun */
978*4882a593Smuzhiyun void qman_destroy_fq(struct qman_fq *fq);
979*4882a593Smuzhiyun
980*4882a593Smuzhiyun /**
981*4882a593Smuzhiyun * qman_fq_fqid - Queries the frame queue ID of a FQ object
982*4882a593Smuzhiyun * @fq: the frame queue object to query
983*4882a593Smuzhiyun */
984*4882a593Smuzhiyun u32 qman_fq_fqid(struct qman_fq *fq);
985*4882a593Smuzhiyun
986*4882a593Smuzhiyun /**
987*4882a593Smuzhiyun * qman_init_fq - Initialises FQ fields, leaves the FQ "parked" or "scheduled"
988*4882a593Smuzhiyun * @fq: the frame queue object to modify, must be 'parked' or new.
989*4882a593Smuzhiyun * @flags: bit-mask of QMAN_INITFQ_FLAG_*** options
990*4882a593Smuzhiyun * @opts: the FQ-modification settings, as defined in the low-level API
991*4882a593Smuzhiyun *
992*4882a593Smuzhiyun * The @opts parameter comes from the low-level portal API. Select
993*4882a593Smuzhiyun * QMAN_INITFQ_FLAG_SCHED in @flags to cause the frame queue to be scheduled
994*4882a593Smuzhiyun * rather than parked. NB, @opts can be NULL.
995*4882a593Smuzhiyun *
996*4882a593Smuzhiyun * Note that some fields and options within @opts may be ignored or overwritten
997*4882a593Smuzhiyun * by the driver;
998*4882a593Smuzhiyun * 1. the 'count' and 'fqid' fields are always ignored (this operation only
999*4882a593Smuzhiyun * affects one frame queue: @fq).
1000*4882a593Smuzhiyun * 2. the QM_INITFQ_WE_CONTEXTB option of the 'we_mask' field and the associated
1001*4882a593Smuzhiyun * 'fqd' structure's 'context_b' field are sometimes overwritten;
1002*4882a593Smuzhiyun * - if @fq was not created with QMAN_FQ_FLAG_TO_DCPORTAL, then context_b is
1003*4882a593Smuzhiyun * initialised to a value used by the driver for demux.
1004*4882a593Smuzhiyun * - if context_b is initialised for demux, so is context_a in case stashing
1005*4882a593Smuzhiyun * is requested (see item 4).
1006*4882a593Smuzhiyun * (So caller control of context_b is only possible for TO_DCPORTAL frame queue
1007*4882a593Smuzhiyun * objects.)
1008*4882a593Smuzhiyun * 3. if @flags contains QMAN_INITFQ_FLAG_LOCAL, the 'fqd' structure's
1009*4882a593Smuzhiyun * 'dest::channel' field will be overwritten to match the portal used to issue
1010*4882a593Smuzhiyun * the command. If the WE_DESTWQ write-enable bit had already been set by the
1011*4882a593Smuzhiyun * caller, the channel workqueue will be left as-is, otherwise the write-enable
1012*4882a593Smuzhiyun * bit is set and the workqueue is set to a default of 4. If the "LOCAL" flag
1013*4882a593Smuzhiyun * isn't set, the destination channel/workqueue fields and the write-enable bit
1014*4882a593Smuzhiyun * are left as-is.
1015*4882a593Smuzhiyun * 4. if the driver overwrites context_a/b for demux, then if
1016*4882a593Smuzhiyun * QM_INITFQ_WE_CONTEXTA is set, the driver will only overwrite
1017*4882a593Smuzhiyun * context_a.address fields and will leave the stashing fields provided by the
1018*4882a593Smuzhiyun * user alone, otherwise it will zero out the context_a.stashing fields.
1019*4882a593Smuzhiyun */
1020*4882a593Smuzhiyun int qman_init_fq(struct qman_fq *fq, u32 flags, struct qm_mcc_initfq *opts);
1021*4882a593Smuzhiyun
1022*4882a593Smuzhiyun /**
1023*4882a593Smuzhiyun * qman_schedule_fq - Schedules a FQ
1024*4882a593Smuzhiyun * @fq: the frame queue object to schedule, must be 'parked'
1025*4882a593Smuzhiyun *
1026*4882a593Smuzhiyun * Schedules the frame queue, which must be Parked, which takes it to
1027*4882a593Smuzhiyun * Tentatively-Scheduled or Truly-Scheduled depending on its fill-level.
1028*4882a593Smuzhiyun */
1029*4882a593Smuzhiyun int qman_schedule_fq(struct qman_fq *fq);
1030*4882a593Smuzhiyun
1031*4882a593Smuzhiyun /**
1032*4882a593Smuzhiyun * qman_retire_fq - Retires a FQ
1033*4882a593Smuzhiyun * @fq: the frame queue object to retire
1034*4882a593Smuzhiyun * @flags: FQ flags (QMAN_FQ_STATE*) if retirement completes immediately
1035*4882a593Smuzhiyun *
1036*4882a593Smuzhiyun * Retires the frame queue. This returns zero if it succeeds immediately, +1 if
1037*4882a593Smuzhiyun * the retirement was started asynchronously, otherwise it returns negative for
1038*4882a593Smuzhiyun * failure. When this function returns zero, @flags is set to indicate whether
1039*4882a593Smuzhiyun * the retired FQ is empty and/or whether it has any ORL fragments (to show up
1040*4882a593Smuzhiyun * as ERNs). Otherwise the corresponding flags will be known when a subsequent
1041*4882a593Smuzhiyun * FQRN message shows up on the portal's message ring.
1042*4882a593Smuzhiyun *
1043*4882a593Smuzhiyun * NB, if the retirement is asynchronous (the FQ was in the Truly Scheduled or
1044*4882a593Smuzhiyun * Active state), the completion will be via the message ring as a FQRN - but
1045*4882a593Smuzhiyun * the corresponding callback may occur before this function returns!! Ie. the
1046*4882a593Smuzhiyun * caller should be prepared to accept the callback as the function is called,
1047*4882a593Smuzhiyun * not only once it has returned.
1048*4882a593Smuzhiyun */
1049*4882a593Smuzhiyun int qman_retire_fq(struct qman_fq *fq, u32 *flags);
1050*4882a593Smuzhiyun
1051*4882a593Smuzhiyun /**
1052*4882a593Smuzhiyun * qman_oos_fq - Puts a FQ "out of service"
1053*4882a593Smuzhiyun * @fq: the frame queue object to be put out-of-service, must be 'retired'
1054*4882a593Smuzhiyun *
1055*4882a593Smuzhiyun * The frame queue must be retired and empty, and if any order restoration list
1056*4882a593Smuzhiyun * was released as ERNs at the time of retirement, they must all be consumed.
1057*4882a593Smuzhiyun */
1058*4882a593Smuzhiyun int qman_oos_fq(struct qman_fq *fq);
1059*4882a593Smuzhiyun
1060*4882a593Smuzhiyun /*
1061*4882a593Smuzhiyun * qman_volatile_dequeue - Issue a volatile dequeue command
1062*4882a593Smuzhiyun * @fq: the frame queue object to dequeue from
1063*4882a593Smuzhiyun * @flags: a bit-mask of QMAN_VOLATILE_FLAG_*** options
1064*4882a593Smuzhiyun * @vdqcr: bit mask of QM_VDQCR_*** options, as per qm_dqrr_vdqcr_set()
1065*4882a593Smuzhiyun *
1066*4882a593Smuzhiyun * Attempts to lock access to the portal's VDQCR volatile dequeue functionality.
1067*4882a593Smuzhiyun * The function will block and sleep if QMAN_VOLATILE_FLAG_WAIT is specified and
1068*4882a593Smuzhiyun * the VDQCR is already in use, otherwise returns non-zero for failure. If
1069*4882a593Smuzhiyun * QMAN_VOLATILE_FLAG_FINISH is specified, the function will only return once
1070*4882a593Smuzhiyun * the VDQCR command has finished executing (ie. once the callback for the last
1071*4882a593Smuzhiyun * DQRR entry resulting from the VDQCR command has been called). If not using
1072*4882a593Smuzhiyun * the FINISH flag, completion can be determined either by detecting the
1073*4882a593Smuzhiyun * presence of the QM_DQRR_STAT_UNSCHEDULED and QM_DQRR_STAT_DQCR_EXPIRED bits
1074*4882a593Smuzhiyun * in the "stat" parameter passed to the FQ's dequeue callback, or by waiting
1075*4882a593Smuzhiyun * for the QMAN_FQ_STATE_VDQCR bit to disappear.
1076*4882a593Smuzhiyun */
1077*4882a593Smuzhiyun int qman_volatile_dequeue(struct qman_fq *fq, u32 flags, u32 vdqcr);
1078*4882a593Smuzhiyun
1079*4882a593Smuzhiyun /**
1080*4882a593Smuzhiyun * qman_enqueue - Enqueue a frame to a frame queue
1081*4882a593Smuzhiyun * @fq: the frame queue object to enqueue to
1082*4882a593Smuzhiyun * @fd: a descriptor of the frame to be enqueued
1083*4882a593Smuzhiyun *
1084*4882a593Smuzhiyun * Fills an entry in the EQCR of portal @qm to enqueue the frame described by
1085*4882a593Smuzhiyun * @fd. The descriptor details are copied from @fd to the EQCR entry, the 'pid'
1086*4882a593Smuzhiyun * field is ignored. The return value is non-zero on error, such as ring full.
1087*4882a593Smuzhiyun */
1088*4882a593Smuzhiyun int qman_enqueue(struct qman_fq *fq, const struct qm_fd *fd);
1089*4882a593Smuzhiyun
1090*4882a593Smuzhiyun /**
1091*4882a593Smuzhiyun * qman_alloc_fqid_range - Allocate a contiguous range of FQIDs
1092*4882a593Smuzhiyun * @result: is set by the API to the base FQID of the allocated range
1093*4882a593Smuzhiyun * @count: the number of FQIDs required
1094*4882a593Smuzhiyun *
1095*4882a593Smuzhiyun * Returns 0 on success, or a negative error code.
1096*4882a593Smuzhiyun */
1097*4882a593Smuzhiyun int qman_alloc_fqid_range(u32 *result, u32 count);
1098*4882a593Smuzhiyun #define qman_alloc_fqid(result) qman_alloc_fqid_range(result, 1)
1099*4882a593Smuzhiyun
1100*4882a593Smuzhiyun /**
1101*4882a593Smuzhiyun * qman_release_fqid - Release the specified frame queue ID
1102*4882a593Smuzhiyun * @fqid: the FQID to be released back to the resource pool
1103*4882a593Smuzhiyun *
1104*4882a593Smuzhiyun * This function can also be used to seed the allocator with
1105*4882a593Smuzhiyun * FQID ranges that it can subsequently allocate from.
1106*4882a593Smuzhiyun * Returns 0 on success, or a negative error code.
1107*4882a593Smuzhiyun */
1108*4882a593Smuzhiyun int qman_release_fqid(u32 fqid);
1109*4882a593Smuzhiyun
1110*4882a593Smuzhiyun /**
1111*4882a593Smuzhiyun * qman_query_fq_np - Queries non-programmable FQD fields
1112*4882a593Smuzhiyun * @fq: the frame queue object to be queried
1113*4882a593Smuzhiyun * @np: storage for the queried FQD fields
1114*4882a593Smuzhiyun */
1115*4882a593Smuzhiyun int qman_query_fq_np(struct qman_fq *fq, struct qm_mcr_queryfq_np *np);
1116*4882a593Smuzhiyun
1117*4882a593Smuzhiyun /* Pool-channel management */
1118*4882a593Smuzhiyun /**
1119*4882a593Smuzhiyun * qman_alloc_pool_range - Allocate a contiguous range of pool-channel IDs
1120*4882a593Smuzhiyun * @result: is set by the API to the base pool-channel ID of the allocated range
1121*4882a593Smuzhiyun * @count: the number of pool-channel IDs required
1122*4882a593Smuzhiyun *
1123*4882a593Smuzhiyun * Returns 0 on success, or a negative error code.
1124*4882a593Smuzhiyun */
1125*4882a593Smuzhiyun int qman_alloc_pool_range(u32 *result, u32 count);
1126*4882a593Smuzhiyun #define qman_alloc_pool(result) qman_alloc_pool_range(result, 1)
1127*4882a593Smuzhiyun
1128*4882a593Smuzhiyun /**
1129*4882a593Smuzhiyun * qman_release_pool - Release the specified pool-channel ID
1130*4882a593Smuzhiyun * @id: the pool-chan ID to be released back to the resource pool
1131*4882a593Smuzhiyun *
1132*4882a593Smuzhiyun * This function can also be used to seed the allocator with
1133*4882a593Smuzhiyun * pool-channel ID ranges that it can subsequently allocate from.
1134*4882a593Smuzhiyun * Returns 0 on success, or a negative error code.
1135*4882a593Smuzhiyun */
1136*4882a593Smuzhiyun int qman_release_pool(u32 id);
1137*4882a593Smuzhiyun
1138*4882a593Smuzhiyun /* CGR management */
1139*4882a593Smuzhiyun /**
1140*4882a593Smuzhiyun * qman_create_cgr - Register a congestion group object
1141*4882a593Smuzhiyun * @cgr: the 'cgr' object, with fields filled in
1142*4882a593Smuzhiyun * @flags: QMAN_CGR_FLAG_* values
1143*4882a593Smuzhiyun * @opts: optional state of CGR settings
1144*4882a593Smuzhiyun *
1145*4882a593Smuzhiyun * Registers this object to receiving congestion entry/exit callbacks on the
1146*4882a593Smuzhiyun * portal affine to the cpu portal on which this API is executed. If opts is
1147*4882a593Smuzhiyun * NULL then only the callback (cgr->cb) function is registered. If @flags
1148*4882a593Smuzhiyun * contains QMAN_CGR_FLAG_USE_INIT, then an init hw command (which will reset
1149*4882a593Smuzhiyun * any unspecified parameters) will be used rather than a modify hw hardware
1150*4882a593Smuzhiyun * (which only modifies the specified parameters).
1151*4882a593Smuzhiyun */
1152*4882a593Smuzhiyun int qman_create_cgr(struct qman_cgr *cgr, u32 flags,
1153*4882a593Smuzhiyun struct qm_mcc_initcgr *opts);
1154*4882a593Smuzhiyun
1155*4882a593Smuzhiyun /**
1156*4882a593Smuzhiyun * qman_delete_cgr - Deregisters a congestion group object
1157*4882a593Smuzhiyun * @cgr: the 'cgr' object to deregister
1158*4882a593Smuzhiyun *
1159*4882a593Smuzhiyun * "Unplugs" this CGR object from the portal affine to the cpu on which this API
1160*4882a593Smuzhiyun * is executed. This must be excuted on the same affine portal on which it was
1161*4882a593Smuzhiyun * created.
1162*4882a593Smuzhiyun */
1163*4882a593Smuzhiyun int qman_delete_cgr(struct qman_cgr *cgr);
1164*4882a593Smuzhiyun
1165*4882a593Smuzhiyun /**
1166*4882a593Smuzhiyun * qman_delete_cgr_safe - Deregisters a congestion group object from any CPU
1167*4882a593Smuzhiyun * @cgr: the 'cgr' object to deregister
1168*4882a593Smuzhiyun *
1169*4882a593Smuzhiyun * This will select the proper CPU and run there qman_delete_cgr().
1170*4882a593Smuzhiyun */
1171*4882a593Smuzhiyun void qman_delete_cgr_safe(struct qman_cgr *cgr);
1172*4882a593Smuzhiyun
1173*4882a593Smuzhiyun /**
1174*4882a593Smuzhiyun * qman_query_cgr_congested - Queries CGR's congestion status
1175*4882a593Smuzhiyun * @cgr: the 'cgr' object to query
1176*4882a593Smuzhiyun * @result: returns 'cgr's congestion status, 1 (true) if congested
1177*4882a593Smuzhiyun */
1178*4882a593Smuzhiyun int qman_query_cgr_congested(struct qman_cgr *cgr, bool *result);
1179*4882a593Smuzhiyun
1180*4882a593Smuzhiyun /**
1181*4882a593Smuzhiyun * qman_alloc_cgrid_range - Allocate a contiguous range of CGR IDs
1182*4882a593Smuzhiyun * @result: is set by the API to the base CGR ID of the allocated range
1183*4882a593Smuzhiyun * @count: the number of CGR IDs required
1184*4882a593Smuzhiyun *
1185*4882a593Smuzhiyun * Returns 0 on success, or a negative error code.
1186*4882a593Smuzhiyun */
1187*4882a593Smuzhiyun int qman_alloc_cgrid_range(u32 *result, u32 count);
1188*4882a593Smuzhiyun #define qman_alloc_cgrid(result) qman_alloc_cgrid_range(result, 1)
1189*4882a593Smuzhiyun
1190*4882a593Smuzhiyun /**
1191*4882a593Smuzhiyun * qman_release_cgrid - Release the specified CGR ID
1192*4882a593Smuzhiyun * @id: the CGR ID to be released back to the resource pool
1193*4882a593Smuzhiyun *
1194*4882a593Smuzhiyun * This function can also be used to seed the allocator with
1195*4882a593Smuzhiyun * CGR ID ranges that it can subsequently allocate from.
1196*4882a593Smuzhiyun * Returns 0 on success, or a negative error code.
1197*4882a593Smuzhiyun */
1198*4882a593Smuzhiyun int qman_release_cgrid(u32 id);
1199*4882a593Smuzhiyun
1200*4882a593Smuzhiyun /**
1201*4882a593Smuzhiyun * qman_is_probed - Check if qman is probed
1202*4882a593Smuzhiyun *
1203*4882a593Smuzhiyun * Returns 1 if the qman driver successfully probed, -1 if the qman driver
1204*4882a593Smuzhiyun * failed to probe or 0 if the qman driver did not probed yet.
1205*4882a593Smuzhiyun */
1206*4882a593Smuzhiyun int qman_is_probed(void);
1207*4882a593Smuzhiyun
1208*4882a593Smuzhiyun /**
1209*4882a593Smuzhiyun * qman_portals_probed - Check if all cpu bound qman portals are probed
1210*4882a593Smuzhiyun *
1211*4882a593Smuzhiyun * Returns 1 if all the required cpu bound qman portals successfully probed,
1212*4882a593Smuzhiyun * -1 if probe errors appeared or 0 if the qman portals did not yet finished
1213*4882a593Smuzhiyun * probing.
1214*4882a593Smuzhiyun */
1215*4882a593Smuzhiyun int qman_portals_probed(void);
1216*4882a593Smuzhiyun
1217*4882a593Smuzhiyun /**
1218*4882a593Smuzhiyun * qman_dqrr_get_ithresh - Get coalesce interrupt threshold
1219*4882a593Smuzhiyun * @portal: portal to get the value for
1220*4882a593Smuzhiyun * @ithresh: threshold pointer
1221*4882a593Smuzhiyun */
1222*4882a593Smuzhiyun void qman_dqrr_get_ithresh(struct qman_portal *portal, u8 *ithresh);
1223*4882a593Smuzhiyun
1224*4882a593Smuzhiyun /**
1225*4882a593Smuzhiyun * qman_dqrr_set_ithresh - Set coalesce interrupt threshold
1226*4882a593Smuzhiyun * @portal: portal to set the new value on
1227*4882a593Smuzhiyun * @ithresh: new threshold value
1228*4882a593Smuzhiyun *
1229*4882a593Smuzhiyun * Returns 0 on success, or a negative error code.
1230*4882a593Smuzhiyun */
1231*4882a593Smuzhiyun int qman_dqrr_set_ithresh(struct qman_portal *portal, u8 ithresh);
1232*4882a593Smuzhiyun
1233*4882a593Smuzhiyun /**
1234*4882a593Smuzhiyun * qman_dqrr_get_iperiod - Get coalesce interrupt period
1235*4882a593Smuzhiyun * @portal: portal to get the value for
1236*4882a593Smuzhiyun * @iperiod: period pointer
1237*4882a593Smuzhiyun */
1238*4882a593Smuzhiyun void qman_portal_get_iperiod(struct qman_portal *portal, u32 *iperiod);
1239*4882a593Smuzhiyun
1240*4882a593Smuzhiyun /**
1241*4882a593Smuzhiyun * qman_dqrr_set_iperiod - Set coalesce interrupt period
1242*4882a593Smuzhiyun * @portal: portal to set the new value on
1243*4882a593Smuzhiyun * @ithresh: new period value
1244*4882a593Smuzhiyun *
1245*4882a593Smuzhiyun * Returns 0 on success, or a negative error code.
1246*4882a593Smuzhiyun */
1247*4882a593Smuzhiyun int qman_portal_set_iperiod(struct qman_portal *portal, u32 iperiod);
1248*4882a593Smuzhiyun
1249*4882a593Smuzhiyun #endif /* __FSL_QMAN_H */
1250