summaryrefslogtreecommitdiff
path: root/drivers/staging/fsl-mc/bus/dpio/qbman_debug.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/fsl-mc/bus/dpio/qbman_debug.c')
-rw-r--r--drivers/staging/fsl-mc/bus/dpio/qbman_debug.c853
1 files changed, 853 insertions, 0 deletions
diff --git a/drivers/staging/fsl-mc/bus/dpio/qbman_debug.c b/drivers/staging/fsl-mc/bus/dpio/qbman_debug.c
new file mode 100644
index 0000000..1c77fa6
--- /dev/null
+++ b/drivers/staging/fsl-mc/bus/dpio/qbman_debug.c
@@ -0,0 +1,853 @@
+/* Copyright (C) 2015 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/errno.h>
+
+#include "../../include/dpaa2-global.h"
+#include "qbman-portal.h"
+#include "qbman_debug.h"
+
+/* QBMan portal management command code */
+#define QBMAN_BP_QUERY 0x32
+#define QBMAN_FQ_QUERY 0x44
+#define QBMAN_FQ_QUERY_NP 0x45
+#define QBMAN_CGR_QUERY 0x51
+#define QBMAN_WRED_QUERY 0x54
+#define QBMAN_CGR_STAT_QUERY 0x55
+#define QBMAN_CGR_STAT_QUERY_CLR 0x56
+
+enum qbman_attr_usage_e {
+ qbman_attr_usage_fq,
+ qbman_attr_usage_bpool,
+ qbman_attr_usage_cgr,
+};
+
+struct int_qbman_attr {
+ u32 words[32];
+ enum qbman_attr_usage_e usage;
+};
+
+#define attr_type_set(a, e) \
+{ \
+ struct qbman_attr *__attr = a; \
+ enum qbman_attr_usage_e __usage = e; \
+ ((struct int_qbman_attr *)__attr)->usage = __usage; \
+}
+
+#define ATTR32(d) (&(d)->dont_manipulate_directly[0])
+#define ATTR32_1(d) (&(d)->dont_manipulate_directly[16])
+
+static struct qb_attr_code code_bp_bpid = QB_CODE(0, 16, 16);
+static struct qb_attr_code code_bp_bdi = QB_CODE(1, 16, 1);
+static struct qb_attr_code code_bp_va = QB_CODE(1, 17, 1);
+static struct qb_attr_code code_bp_wae = QB_CODE(1, 18, 1);
+static struct qb_attr_code code_bp_swdet = QB_CODE(4, 0, 16);
+static struct qb_attr_code code_bp_swdxt = QB_CODE(4, 16, 16);
+static struct qb_attr_code code_bp_hwdet = QB_CODE(5, 0, 16);
+static struct qb_attr_code code_bp_hwdxt = QB_CODE(5, 16, 16);
+static struct qb_attr_code code_bp_swset = QB_CODE(6, 0, 16);
+static struct qb_attr_code code_bp_swsxt = QB_CODE(6, 16, 16);
+static struct qb_attr_code code_bp_vbpid = QB_CODE(7, 0, 14);
+static struct qb_attr_code code_bp_icid = QB_CODE(7, 16, 15);
+static struct qb_attr_code code_bp_pl = QB_CODE(7, 31, 1);
+static struct qb_attr_code code_bp_bpscn_addr_lo = QB_CODE(8, 0, 32);
+static struct qb_attr_code code_bp_bpscn_addr_hi = QB_CODE(9, 0, 32);
+static struct qb_attr_code code_bp_bpscn_ctx_lo = QB_CODE(10, 0, 32);
+static struct qb_attr_code code_bp_bpscn_ctx_hi = QB_CODE(11, 0, 32);
+static struct qb_attr_code code_bp_hw_targ = QB_CODE(12, 0, 16);
+static struct qb_attr_code code_bp_state = QB_CODE(1, 24, 3);
+static struct qb_attr_code code_bp_fill = QB_CODE(2, 0, 32);
+static struct qb_attr_code code_bp_hdptr = QB_CODE(3, 0, 32);
+static struct qb_attr_code code_bp_sdcnt = QB_CODE(13, 0, 8);
+static struct qb_attr_code code_bp_hdcnt = QB_CODE(13, 1, 8);
+static struct qb_attr_code code_bp_sscnt = QB_CODE(13, 2, 8);
+
+void qbman_bp_attr_clear(struct qbman_attr *a)
+{
+ memset(a, 0, sizeof(*a));
+ attr_type_set(a, qbman_attr_usage_bpool);
+}
+
+int qbman_bp_query(struct qbman_swp *s, u32 bpid,
+ struct qbman_attr *a)
+{
+ u32 *p;
+ u32 verb, rslt;
+ u32 *attr = ATTR32(a);
+
+ qbman_bp_attr_clear(a);
+
+ /* Start the management command */
+ p = qbman_swp_mc_start(s);
+ if (!p)
+ return -EBUSY;
+
+ /* Encode the caller-provided attributes */
+ qb_attr_code_encode(&code_bp_bpid, p, bpid);
+
+ /* Complete the management command */
+ p = qbman_swp_mc_complete(s, p, QBMAN_BP_QUERY);
+
+ /* Decode the outcome */
+ verb = qb_attr_code_decode(&code_generic_verb, p);
+ rslt = qb_attr_code_decode(&code_generic_rslt, p);
+ WARN_ON(verb != QBMAN_BP_QUERY);
+
+ /* Determine success or failure */
+ if (unlikely(rslt != QBMAN_MC_RSLT_OK)) {
+ pr_err("Query of BPID 0x%x failed, code=0x%02x\n", bpid, rslt);
+ return -EIO;
+ }
+
+ /* For the query, word[0] of the result contains only the
+ * verb/rslt fields, so skip word[0].
+ */
+ word_copy(&attr[1], &p[1], 15);
+ return 0;
+}
+
+void qbman_bp_attr_get_bdi(struct qbman_attr *a, int *bdi, int *va, int *wae)
+{
+ u32 *p = ATTR32(a);
+
+ *bdi = !!qb_attr_code_decode(&code_bp_bdi, p);
+ *va = !!qb_attr_code_decode(&code_bp_va, p);
+ *wae = !!qb_attr_code_decode(&code_bp_wae, p);
+}
+
+static u32 qbman_bp_thresh_to_value(u32 val)
+{
+ return (val & 0xff) << ((val & 0xf00) >> 8);
+}
+
+void qbman_bp_attr_get_swdet(struct qbman_attr *a, u32 *swdet)
+{
+ u32 *p = ATTR32(a);
+
+ *swdet = qbman_bp_thresh_to_value(qb_attr_code_decode(&code_bp_swdet,
+ p));
+}
+
+void qbman_bp_attr_get_swdxt(struct qbman_attr *a, u32 *swdxt)
+{
+ u32 *p = ATTR32(a);
+
+ *swdxt = qbman_bp_thresh_to_value(qb_attr_code_decode(&code_bp_swdxt,
+ p));
+}
+
+void qbman_bp_attr_get_hwdet(struct qbman_attr *a, u32 *hwdet)
+{
+ u32 *p = ATTR32(a);
+
+ *hwdet = qbman_bp_thresh_to_value(qb_attr_code_decode(&code_bp_hwdet,
+ p));
+}
+
+void qbman_bp_attr_get_hwdxt(struct qbman_attr *a, u32 *hwdxt)
+{
+ u32 *p = ATTR32(a);
+
+ *hwdxt = qbman_bp_thresh_to_value(qb_attr_code_decode(&code_bp_hwdxt,
+ p));
+}
+
+void qbman_bp_attr_get_swset(struct qbman_attr *a, u32 *swset)
+{
+ u32 *p = ATTR32(a);
+
+ *swset = qbman_bp_thresh_to_value(qb_attr_code_decode(&code_bp_swset,
+ p));
+}
+
+void qbman_bp_attr_get_swsxt(struct qbman_attr *a, u32 *swsxt)
+{
+ u32 *p = ATTR32(a);
+
+ *swsxt = qbman_bp_thresh_to_value(qb_attr_code_decode(&code_bp_swsxt,
+ p));
+}
+
+void qbman_bp_attr_get_vbpid(struct qbman_attr *a, u32 *vbpid)
+{
+ u32 *p = ATTR32(a);
+
+ *vbpid = qb_attr_code_decode(&code_bp_vbpid, p);
+}
+
+void qbman_bp_attr_get_icid(struct qbman_attr *a, u32 *icid, int *pl)
+{
+ u32 *p = ATTR32(a);
+
+ *icid = qb_attr_code_decode(&code_bp_icid, p);
+ *pl = !!qb_attr_code_decode(&code_bp_pl, p);
+}
+
+void qbman_bp_attr_get_bpscn_addr(struct qbman_attr *a, u64 *bpscn_addr)
+{
+ u32 *p = ATTR32(a);
+
+ *bpscn_addr = ((u64)qb_attr_code_decode(&code_bp_bpscn_addr_hi,
+ p) << 32) |
+ (u64)qb_attr_code_decode(&code_bp_bpscn_addr_lo,
+ p);
+}
+
+void qbman_bp_attr_get_bpscn_ctx(struct qbman_attr *a, u64 *bpscn_ctx)
+{
+ u32 *p = ATTR32(a);
+
+ *bpscn_ctx = ((u64)qb_attr_code_decode(&code_bp_bpscn_ctx_hi, p)
+ << 32) |
+ (u64)qb_attr_code_decode(&code_bp_bpscn_ctx_lo,
+ p);
+}
+
+void qbman_bp_attr_get_hw_targ(struct qbman_attr *a, u32 *hw_targ)
+{
+ u32 *p = ATTR32(a);
+
+ *hw_targ = qb_attr_code_decode(&code_bp_hw_targ, p);
+}
+
+int qbman_bp_info_has_free_bufs(struct qbman_attr *a)
+{
+ u32 *p = ATTR32(a);
+
+ return !(int)(qb_attr_code_decode(&code_bp_state, p) & 0x1);
+}
+
+int qbman_bp_info_is_depleted(struct qbman_attr *a)
+{
+ u32 *p = ATTR32(a);
+
+ return (int)(qb_attr_code_decode(&code_bp_state, p) & 0x2);
+}
+
+int qbman_bp_info_is_surplus(struct qbman_attr *a)
+{
+ u32 *p = ATTR32(a);
+
+ return (int)(qb_attr_code_decode(&code_bp_state, p) & 0x4);
+}
+
+u32 qbman_bp_info_num_free_bufs(struct qbman_attr *a)
+{
+ u32 *p = ATTR32(a);
+
+ return qb_attr_code_decode(&code_bp_fill, p);
+}
+
+u32 qbman_bp_info_hdptr(struct qbman_attr *a)
+{
+ u32 *p = ATTR32(a);
+
+ return qb_attr_code_decode(&code_bp_hdptr, p);
+}
+
+u32 qbman_bp_info_sdcnt(struct qbman_attr *a)
+{
+ u32 *p = ATTR32(a);
+
+ return qb_attr_code_decode(&code_bp_sdcnt, p);
+}
+
+u32 qbman_bp_info_hdcnt(struct qbman_attr *a)
+{
+ u32 *p = ATTR32(a);
+
+ return qb_attr_code_decode(&code_bp_hdcnt, p);
+}
+
+u32 qbman_bp_info_sscnt(struct qbman_attr *a)
+{
+ u32 *p = ATTR32(a);
+
+ return qb_attr_code_decode(&code_bp_sscnt, p);
+}
+
+static struct qb_attr_code code_fq_fqid = QB_CODE(1, 0, 24);
+static struct qb_attr_code code_fq_cgrid = QB_CODE(2, 16, 16);
+static struct qb_attr_code code_fq_destwq = QB_CODE(3, 0, 15);
+static struct qb_attr_code code_fq_fqctrl = QB_CODE(3, 24, 8);
+static struct qb_attr_code code_fq_icscred = QB_CODE(4, 0, 15);
+static struct qb_attr_code code_fq_tdthresh = QB_CODE(4, 16, 13);
+static struct qb_attr_code code_fq_oa_len = QB_CODE(5, 0, 12);
+static struct qb_attr_code code_fq_oa_ics = QB_CODE(5, 14, 1);
+static struct qb_attr_code code_fq_oa_cgr = QB_CODE(5, 15, 1);
+static struct qb_attr_code code_fq_mctl_bdi = QB_CODE(5, 24, 1);
+static struct qb_attr_code code_fq_mctl_ff = QB_CODE(5, 25, 1);
+static struct qb_attr_code code_fq_mctl_va = QB_CODE(5, 26, 1);
+static struct qb_attr_code code_fq_mctl_ps = QB_CODE(5, 27, 1);
+static struct qb_attr_code code_fq_ctx_lower32 = QB_CODE(6, 0, 32);
+static struct qb_attr_code code_fq_ctx_upper32 = QB_CODE(7, 0, 32);
+static struct qb_attr_code code_fq_icid = QB_CODE(8, 0, 15);
+static struct qb_attr_code code_fq_pl = QB_CODE(8, 15, 1);
+static struct qb_attr_code code_fq_vfqid = QB_CODE(9, 0, 24);
+static struct qb_attr_code code_fq_erfqid = QB_CODE(10, 0, 24);
+
+void qbman_fq_attr_clear(struct qbman_attr *a)
+{
+ memset(a, 0, sizeof(*a));
+ attr_type_set(a, qbman_attr_usage_fq);
+}
+
+/* FQ query function for programmable fields */
+int qbman_fq_query(struct qbman_swp *s, u32 fqid, struct qbman_attr *desc)
+{
+ u32 *p;
+ u32 verb, rslt;
+ u32 *d = ATTR32(desc);
+
+ qbman_fq_attr_clear(desc);
+
+ p = qbman_swp_mc_start(s);
+ if (!p)
+ return -EBUSY;
+ qb_attr_code_encode(&code_fq_fqid, p, fqid);
+ p = qbman_swp_mc_complete(s, p, QBMAN_FQ_QUERY);
+
+ /* Decode the outcome */
+ verb = qb_attr_code_decode(&code_generic_verb, p);
+ rslt = qb_attr_code_decode(&code_generic_rslt, p);
+ WARN_ON(verb != QBMAN_FQ_QUERY);
+
+ /* Determine success or failure */
+ if (unlikely(rslt != QBMAN_MC_RSLT_OK)) {
+ pr_err("Query of FQID 0x%x failed, code=0x%02x\n",
+ fqid, rslt);
+ return -EIO;
+ }
+ /*
+ * For the configure, word[0] of the command contains only the WE-mask.
+ * For the query, word[0] of the result contains only the verb/rslt
+ * fields. Skip word[0] in the latter case.
+ */
+ word_copy(&d[1], &p[1], 15);
+ return 0;
+}
+
+void qbman_fq_attr_get_fqctrl(struct qbman_attr *d, u32 *fqctrl)
+{
+ u32 *p = ATTR32(d);
+
+ *fqctrl = qb_attr_code_decode(&code_fq_fqctrl, p);
+}
+
+void qbman_fq_attr_get_cgrid(struct qbman_attr *d, u32 *cgrid)
+{
+ u32 *p = ATTR32(d);
+
+ *cgrid = qb_attr_code_decode(&code_fq_cgrid, p);
+}
+
+void qbman_fq_attr_get_destwq(struct qbman_attr *d, u32 *destwq)
+{
+ u32 *p = ATTR32(d);
+
+ *destwq = qb_attr_code_decode(&code_fq_destwq, p);
+}
+
+void qbman_fq_attr_get_icscred(struct qbman_attr *d, u32 *icscred)
+{
+ u32 *p = ATTR32(d);
+
+ *icscred = qb_attr_code_decode(&code_fq_icscred, p);
+}
+
+static struct qb_attr_code code_tdthresh_exp = QB_CODE(0, 0, 5);
+static struct qb_attr_code code_tdthresh_mant = QB_CODE(0, 5, 8);
+static u32 qbman_thresh_to_value(u32 val)
+{
+ u32 m, e;
+
+ m = qb_attr_code_decode(&code_tdthresh_mant, &val);
+ e = qb_attr_code_decode(&code_tdthresh_exp, &val);
+ return m << e;
+}
+
+void qbman_fq_attr_get_tdthresh(struct qbman_attr *d, u32 *tdthresh)
+{
+ u32 *p = ATTR32(d);
+
+ *tdthresh = qbman_thresh_to_value(qb_attr_code_decode(&code_fq_tdthresh,
+ p));
+}
+
+void qbman_fq_attr_get_oa(struct qbman_attr *d,
+ int *oa_ics, int *oa_cgr, int32_t *oa_len)
+{
+ u32 *p = ATTR32(d);
+
+ *oa_ics = !!qb_attr_code_decode(&code_fq_oa_ics, p);
+ *oa_cgr = !!qb_attr_code_decode(&code_fq_oa_cgr, p);
+ *oa_len = qb_attr_code_makesigned(&code_fq_oa_len,
+ qb_attr_code_decode(&code_fq_oa_len, p));
+}
+
+void qbman_fq_attr_get_mctl(struct qbman_attr *d,
+ int *bdi, int *ff, int *va, int *ps)
+{
+ u32 *p = ATTR32(d);
+
+ *bdi = !!qb_attr_code_decode(&code_fq_mctl_bdi, p);
+ *ff = !!qb_attr_code_decode(&code_fq_mctl_ff, p);
+ *va = !!qb_attr_code_decode(&code_fq_mctl_va, p);
+ *ps = !!qb_attr_code_decode(&code_fq_mctl_ps, p);
+}
+
+void qbman_fq_attr_get_ctx(struct qbman_attr *d, u32 *hi, u32 *lo)
+{
+ u32 *p = ATTR32(d);
+
+ *hi = qb_attr_code_decode(&code_fq_ctx_upper32, p);
+ *lo = qb_attr_code_decode(&code_fq_ctx_lower32, p);
+}
+
+void qbman_fq_attr_get_icid(struct qbman_attr *d, u32 *icid, int *pl)
+{
+ u32 *p = ATTR32(d);
+
+ *icid = qb_attr_code_decode(&code_fq_icid, p);
+ *pl = !!qb_attr_code_decode(&code_fq_pl, p);
+}
+
+void qbman_fq_attr_get_vfqid(struct qbman_attr *d, u32 *vfqid)
+{
+ u32 *p = ATTR32(d);
+
+ *vfqid = qb_attr_code_decode(&code_fq_vfqid, p);
+}
+
+void qbman_fq_attr_get_erfqid(struct qbman_attr *d, u32 *erfqid)
+{
+ u32 *p = ATTR32(d);
+
+ *erfqid = qb_attr_code_decode(&code_fq_erfqid, p);
+}
+
+/* Query FQ Non-Programmalbe Fields */
+static struct qb_attr_code code_fq_np_state = QB_CODE(0, 16, 3);
+static struct qb_attr_code code_fq_np_fe = QB_CODE(0, 19, 1);
+static struct qb_attr_code code_fq_np_x = QB_CODE(0, 20, 1);
+static struct qb_attr_code code_fq_np_r = QB_CODE(0, 21, 1);
+static struct qb_attr_code code_fq_np_oe = QB_CODE(0, 22, 1);
+static struct qb_attr_code code_fq_np_frm_cnt = QB_CODE(6, 0, 24);
+static struct qb_attr_code code_fq_np_byte_cnt = QB_CODE(7, 0, 32);
+
+int qbman_fq_query_state(struct qbman_swp *s, u32 fqid,
+ struct qbman_attr *state)
+{
+ u32 *p;
+ u32 verb, rslt;
+ u32 *d = ATTR32(state);
+
+ qbman_fq_attr_clear(state);
+
+ p = qbman_swp_mc_start(s);
+ if (!p)
+ return -EBUSY;
+ qb_attr_code_encode(&code_fq_fqid, p, fqid);
+ p = qbman_swp_mc_complete(s, p, QBMAN_FQ_QUERY_NP);
+
+ /* Decode the outcome */
+ verb = qb_attr_code_decode(&code_generic_verb, p);
+ rslt = qb_attr_code_decode(&code_generic_rslt, p);
+ WARN_ON(verb != QBMAN_FQ_QUERY_NP);
+
+ /* Determine success or failure */
+ if (unlikely(rslt != QBMAN_MC_RSLT_OK)) {
+ pr_err("Query NP fields of FQID 0x%x failed, code=0x%02x\n",
+ fqid, rslt);
+ return -EIO;
+ }
+ word_copy(&d[0], &p[0], 16);
+ return 0;
+}
+
+u32 qbman_fq_state_schedstate(const struct qbman_attr *state)
+{
+ const u32 *p = ATTR32(state);
+
+ return qb_attr_code_decode(&code_fq_np_state, p);
+}
+
+int qbman_fq_state_force_eligible(const struct qbman_attr *state)
+{
+ const u32 *p = ATTR32(state);
+
+ return !!qb_attr_code_decode(&code_fq_np_fe, p);
+}
+
+int qbman_fq_state_xoff(const struct qbman_attr *state)
+{
+ const u32 *p = ATTR32(state);
+
+ return !!qb_attr_code_decode(&code_fq_np_x, p);
+}
+
+int qbman_fq_state_retirement_pending(const struct qbman_attr *state)
+{
+ const u32 *p = ATTR32(state);
+
+ return !!qb_attr_code_decode(&code_fq_np_r, p);
+}
+
+int qbman_fq_state_overflow_error(const struct qbman_attr *state)
+{
+ const u32 *p = ATTR32(state);
+
+ return !!qb_attr_code_decode(&code_fq_np_oe, p);
+}
+
+u32 qbman_fq_state_frame_count(const struct qbman_attr *state)
+{
+ const u32 *p = ATTR32(state);
+
+ return qb_attr_code_decode(&code_fq_np_frm_cnt, p);
+}
+
+u32 qbman_fq_state_byte_count(const struct qbman_attr *state)
+{
+ const u32 *p = ATTR32(state);
+
+ return qb_attr_code_decode(&code_fq_np_byte_cnt, p);
+}
+
+/* Query CGR */
+static struct qb_attr_code code_cgr_cgid = QB_CODE(0, 16, 16);
+static struct qb_attr_code code_cgr_cscn_wq_en_enter = QB_CODE(2, 0, 1);
+static struct qb_attr_code code_cgr_cscn_wq_en_exit = QB_CODE(2, 1, 1);
+static struct qb_attr_code code_cgr_cscn_wq_icd = QB_CODE(2, 2, 1);
+static struct qb_attr_code code_cgr_mode = QB_CODE(3, 16, 2);
+static struct qb_attr_code code_cgr_rej_cnt_mode = QB_CODE(3, 18, 1);
+static struct qb_attr_code code_cgr_cscn_bdi = QB_CODE(3, 19, 1);
+static struct qb_attr_code code_cgr_cscn_wr_en_enter = QB_CODE(3, 24, 1);
+static struct qb_attr_code code_cgr_cscn_wr_en_exit = QB_CODE(3, 25, 1);
+static struct qb_attr_code code_cgr_cg_wr_ae = QB_CODE(3, 26, 1);
+static struct qb_attr_code code_cgr_cscn_dcp_en = QB_CODE(3, 27, 1);
+static struct qb_attr_code code_cgr_cg_wr_va = QB_CODE(3, 28, 1);
+static struct qb_attr_code code_cgr_i_cnt_wr_en = QB_CODE(4, 0, 1);
+static struct qb_attr_code code_cgr_i_cnt_wr_bnd = QB_CODE(4, 1, 5);
+static struct qb_attr_code code_cgr_td_en = QB_CODE(4, 8, 1);
+static struct qb_attr_code code_cgr_cs_thres = QB_CODE(4, 16, 13);
+static struct qb_attr_code code_cgr_cs_thres_x = QB_CODE(5, 0, 13);
+static struct qb_attr_code code_cgr_td_thres = QB_CODE(5, 16, 13);
+static struct qb_attr_code code_cgr_cscn_tdcp = QB_CODE(6, 0, 16);
+static struct qb_attr_code code_cgr_cscn_wqid = QB_CODE(6, 16, 16);
+static struct qb_attr_code code_cgr_cscn_vcgid = QB_CODE(7, 0, 16);
+static struct qb_attr_code code_cgr_cg_icid = QB_CODE(7, 16, 15);
+static struct qb_attr_code code_cgr_cg_pl = QB_CODE(7, 31, 1);
+static struct qb_attr_code code_cgr_cg_wr_addr_lo = QB_CODE(8, 0, 32);
+static struct qb_attr_code code_cgr_cg_wr_addr_hi = QB_CODE(9, 0, 32);
+static struct qb_attr_code code_cgr_cscn_ctx_lo = QB_CODE(10, 0, 32);
+static struct qb_attr_code code_cgr_cscn_ctx_hi = QB_CODE(11, 0, 32);
+
+void qbman_cgr_attr_clear(struct qbman_attr *a)
+{
+ memset(a, 0, sizeof(*a));
+ attr_type_set(a, qbman_attr_usage_cgr);
+}
+
+int qbman_cgr_query(struct qbman_swp *s, u32 cgid, struct qbman_attr *attr)
+{
+ u32 *p;
+ u32 verb, rslt;
+ u32 *d[2];
+ int i;
+ u32 query_verb;
+
+ d[0] = ATTR32(attr);
+ d[1] = ATTR32_1(attr);
+
+ qbman_cgr_attr_clear(attr);
+
+ for (i = 0; i < 2; i++) {
+ p = qbman_swp_mc_start(s);
+ if (!p)
+ return -EBUSY;
+ query_verb = i ? QBMAN_WRED_QUERY : QBMAN_CGR_QUERY;
+
+ qb_attr_code_encode(&code_cgr_cgid, p, cgid);
+ p = qbman_swp_mc_complete(s, p, p[0] | query_verb);
+
+ /* Decode the outcome */
+ verb = qb_attr_code_decode(&code_generic_verb, p);
+ rslt = qb_attr_code_decode(&code_generic_rslt, p);
+ WARN_ON(verb != query_verb);
+
+ /* Determine success or failure */
+ if (unlikely(rslt != QBMAN_MC_RSLT_OK)) {
+ pr_err("Query CGID 0x%x failed,", cgid);
+ pr_err(" verb=0x%02x, code=0x%02x\n", verb, rslt);
+ return -EIO;
+ }
+ /* For the configure, word[0] of the command contains only the
+ * verb/cgid. For the query, word[0] of the result contains
+ * only the verb/rslt fields. Skip word[0] in the latter case.
+ */
+ word_copy(&d[i][1], &p[1], 15);
+ }
+ return 0;
+}
+
+void qbman_cgr_attr_get_ctl1(struct qbman_attr *d, int *cscn_wq_en_enter,
+ int *cscn_wq_en_exit, int *cscn_wq_icd)
+ {
+ u32 *p = ATTR32(d);
+ *cscn_wq_en_enter = !!qb_attr_code_decode(&code_cgr_cscn_wq_en_enter,
+ p);
+ *cscn_wq_en_exit = !!qb_attr_code_decode(&code_cgr_cscn_wq_en_exit, p);
+ *cscn_wq_icd = !!qb_attr_code_decode(&code_cgr_cscn_wq_icd, p);
+}
+
+void qbman_cgr_attr_get_mode(struct qbman_attr *d, u32 *mode,
+ int *rej_cnt_mode, int *cscn_bdi)
+{
+ u32 *p = ATTR32(d);
+ *mode = qb_attr_code_decode(&code_cgr_mode, p);
+ *rej_cnt_mode = !!qb_attr_code_decode(&code_cgr_rej_cnt_mode, p);
+ *cscn_bdi = !!qb_attr_code_decode(&code_cgr_cscn_bdi, p);
+}
+
+void qbman_cgr_attr_get_ctl2(struct qbman_attr *d, int *cscn_wr_en_enter,
+ int *cscn_wr_en_exit, int *cg_wr_ae,
+ int *cscn_dcp_en, int *cg_wr_va)
+{
+ u32 *p = ATTR32(d);
+ *cscn_wr_en_enter = !!qb_attr_code_decode(&code_cgr_cscn_wr_en_enter,
+ p);
+ *cscn_wr_en_exit = !!qb_attr_code_decode(&code_cgr_cscn_wr_en_exit, p);
+ *cg_wr_ae = !!qb_attr_code_decode(&code_cgr_cg_wr_ae, p);
+ *cscn_dcp_en = !!qb_attr_code_decode(&code_cgr_cscn_dcp_en, p);
+ *cg_wr_va = !!qb_attr_code_decode(&code_cgr_cg_wr_va, p);
+}
+
+void qbman_cgr_attr_get_iwc(struct qbman_attr *d, int *i_cnt_wr_en,
+ u32 *i_cnt_wr_bnd)
+{
+ u32 *p = ATTR32(d);
+ *i_cnt_wr_en = !!qb_attr_code_decode(&code_cgr_i_cnt_wr_en, p);
+ *i_cnt_wr_bnd = qb_attr_code_decode(&code_cgr_i_cnt_wr_bnd, p);
+}
+
+void qbman_cgr_attr_get_tdc(struct qbman_attr *d, int *td_en)
+{
+ u32 *p = ATTR32(d);
+ *td_en = !!qb_attr_code_decode(&code_cgr_td_en, p);
+}
+
+void qbman_cgr_attr_get_cs_thres(struct qbman_attr *d, u32 *cs_thres)
+{
+ u32 *p = ATTR32(d);
+ *cs_thres = qbman_thresh_to_value(qb_attr_code_decode(
+ &code_cgr_cs_thres, p));
+}
+
+void qbman_cgr_attr_get_cs_thres_x(struct qbman_attr *d,
+ u32 *cs_thres_x)
+{
+ u32 *p = ATTR32(d);
+ *cs_thres_x = qbman_thresh_to_value(qb_attr_code_decode(
+ &code_cgr_cs_thres_x, p));
+}
+
+void qbman_cgr_attr_get_td_thres(struct qbman_attr *d, u32 *td_thres)
+{
+ u32 *p = ATTR32(d);
+ *td_thres = qbman_thresh_to_value(qb_attr_code_decode(
+ &code_cgr_td_thres, p));
+}
+
+void qbman_cgr_attr_get_cscn_tdcp(struct qbman_attr *d, u32 *cscn_tdcp)
+{
+ u32 *p = ATTR32(d);
+ *cscn_tdcp = qb_attr_code_decode(&code_cgr_cscn_tdcp, p);
+}
+
+void qbman_cgr_attr_get_cscn_wqid(struct qbman_attr *d, u32 *cscn_wqid)
+{
+ u32 *p = ATTR32(d);
+ *cscn_wqid = qb_attr_code_decode(&code_cgr_cscn_wqid, p);
+}
+
+void qbman_cgr_attr_get_cscn_vcgid(struct qbman_attr *d,
+ u32 *cscn_vcgid)
+{
+ u32 *p = ATTR32(d);
+ *cscn_vcgid = qb_attr_code_decode(&code_cgr_cscn_vcgid, p);
+}
+
+void qbman_cgr_attr_get_cg_icid(struct qbman_attr *d, u32 *icid,
+ int *pl)
+{
+ u32 *p = ATTR32(d);
+ *icid = qb_attr_code_decode(&code_cgr_cg_icid, p);
+ *pl = !!qb_attr_code_decode(&code_cgr_cg_pl, p);
+}
+
+void qbman_cgr_attr_get_cg_wr_addr(struct qbman_attr *d,
+ u64 *cg_wr_addr)
+{
+ u32 *p = ATTR32(d);
+ *cg_wr_addr = ((u64)qb_attr_code_decode(&code_cgr_cg_wr_addr_hi,
+ p) << 32) |
+ (u64)qb_attr_code_decode(&code_cgr_cg_wr_addr_lo,
+ p);
+}
+
+void qbman_cgr_attr_get_cscn_ctx(struct qbman_attr *d, u64 *cscn_ctx)
+{
+ u32 *p = ATTR32(d);
+ *cscn_ctx = ((u64)qb_attr_code_decode(&code_cgr_cscn_ctx_hi, p)
+ << 32) |
+ (u64)qb_attr_code_decode(&code_cgr_cscn_ctx_lo, p);
+}
+
+#define WRED_EDP_WORD(n) (18 + (n) / 4)
+#define WRED_EDP_OFFSET(n) (8 * ((n) % 4))
+#define WRED_PARM_DP_WORD(n) ((n) + 20)
+#define WRED_WE_EDP(n) (16 + (n) * 2)
+#define WRED_WE_PARM_DP(n) (17 + (n) * 2)
+void qbman_cgr_attr_wred_get_edp(struct qbman_attr *d, u32 idx,
+ int *edp)
+{
+ u32 *p = ATTR32(d);
+ struct qb_attr_code code_wred_edp = QB_CODE(WRED_EDP_WORD(idx),
+ WRED_EDP_OFFSET(idx), 8);
+ *edp = (int)qb_attr_code_decode(&code_wred_edp, p);
+}
+
+void qbman_cgr_attr_wred_dp_decompose(u32 dp, u64 *minth,
+ u64 *maxth, u8 *maxp)
+{
+ u8 ma, mn, step_i, step_s, pn;
+
+ ma = (u8)(dp >> 24);
+ mn = (u8)(dp >> 19) & 0x1f;
+ step_i = (u8)(dp >> 11);
+ step_s = (u8)(dp >> 6) & 0x1f;
+ pn = (u8)dp & 0x3f;
+
+ *maxp = ((pn << 2) * 100) / 256;
+
+ if (mn == 0)
+ *maxth = ma;
+ else
+ *maxth = ((ma + 256) * (1 << (mn - 1)));
+
+ if (step_s == 0)
+ *minth = *maxth - step_i;
+ else
+ *minth = *maxth - (256 + step_i) * (1 << (step_s - 1));
+}
+
+void qbman_cgr_attr_wred_get_parm_dp(struct qbman_attr *d, u32 idx,
+ u32 *dp)
+{
+ u32 *p = ATTR32(d);
+ struct qb_attr_code code_wred_parm_dp = QB_CODE(WRED_PARM_DP_WORD(idx),
+ 0, 8);
+ *dp = qb_attr_code_decode(&code_wred_parm_dp, p);
+}
+
+/* Query CGR/CCGR/CQ statistics */
+static struct qb_attr_code code_cgr_stat_ct = QB_CODE(4, 0, 32);
+static struct qb_attr_code code_cgr_stat_frame_cnt_lo = QB_CODE(4, 0, 32);
+static struct qb_attr_code code_cgr_stat_frame_cnt_hi = QB_CODE(5, 0, 8);
+static struct qb_attr_code code_cgr_stat_byte_cnt_lo = QB_CODE(6, 0, 32);
+static struct qb_attr_code code_cgr_stat_byte_cnt_hi = QB_CODE(7, 0, 16);
+static int qbman_cgr_statistics_query(struct qbman_swp *s, u32 cgid,
+ int clear, u32 command_type,
+ u64 *frame_cnt, u64 *byte_cnt)
+{
+ u32 *p;
+ u32 verb, rslt;
+ u32 query_verb;
+ u32 hi, lo;
+
+ p = qbman_swp_mc_start(s);
+ if (!p)
+ return -EBUSY;
+
+ qb_attr_code_encode(&code_cgr_cgid, p, cgid);
+ if (command_type < 2)
+ qb_attr_code_encode(&code_cgr_stat_ct, p, command_type);
+ query_verb = clear ?
+ QBMAN_CGR_STAT_QUERY_CLR : QBMAN_CGR_STAT_QUERY;
+ p = qbman_swp_mc_complete(s, p, p[0] | query_verb);
+
+ /* Decode the outcome */
+ verb = qb_attr_code_decode(&code_generic_verb, p);
+ rslt = qb_attr_code_decode(&code_generic_rslt, p);
+ WARN_ON(verb != query_verb);
+
+ /* Determine success or failure */
+ if (unlikely(rslt != QBMAN_MC_RSLT_OK)) {
+ pr_err("Query statistics of CGID 0x%x failed,", cgid);
+ pr_err(" verb=0x%02x code=0x%02x\n", verb, rslt);
+ return -EIO;
+ }
+
+ if (*frame_cnt) {
+ hi = qb_attr_code_decode(&code_cgr_stat_frame_cnt_hi, p);
+ lo = qb_attr_code_decode(&code_cgr_stat_frame_cnt_lo, p);
+ *frame_cnt = ((u64)hi << 32) | (u64)lo;
+ }
+ if (*byte_cnt) {
+ hi = qb_attr_code_decode(&code_cgr_stat_byte_cnt_hi, p);
+ lo = qb_attr_code_decode(&code_cgr_stat_byte_cnt_lo, p);
+ *byte_cnt = ((u64)hi << 32) | (u64)lo;
+ }
+
+ return 0;
+}
+
+int qbman_cgr_reject_statistics(struct qbman_swp *s, u32 cgid, int clear,
+ u64 *frame_cnt, u64 *byte_cnt)
+{
+ return qbman_cgr_statistics_query(s, cgid, clear, 0xff,
+ frame_cnt, byte_cnt);
+}
+
+int qbman_ccgr_reject_statistics(struct qbman_swp *s, u32 cgid, int clear,
+ u64 *frame_cnt, u64 *byte_cnt)
+{
+ return qbman_cgr_statistics_query(s, cgid, clear, 1,
+ frame_cnt, byte_cnt);
+}
+
+int qbman_cq_dequeue_statistics(struct qbman_swp *s, u32 cgid, int clear,
+ u64 *frame_cnt, u64 *byte_cnt)
+{
+ return qbman_cgr_statistics_query(s, cgid, clear, 0,
+ frame_cnt, byte_cnt);
+}