14e400768SDavid Christensen /*-
2*7282444bSPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause
3*7282444bSPedro F. Giffuni *
44ef8ebfdSDavid C Somayajulu * Copyright (c) 2007-2017 QLogic Corporation. All rights reserved.
54e400768SDavid Christensen *
64e400768SDavid Christensen * Redistribution and use in source and binary forms, with or without
74e400768SDavid Christensen * modification, are permitted provided that the following conditions
84e400768SDavid Christensen * are met:
94e400768SDavid Christensen *
104e400768SDavid Christensen * 1. Redistributions of source code must retain the above copyright
114e400768SDavid Christensen * notice, this list of conditions and the following disclaimer.
124e400768SDavid Christensen * 2. Redistributions in binary form must reproduce the above copyright
134e400768SDavid Christensen * notice, this list of conditions and the following disclaimer in the
144e400768SDavid Christensen * documentation and/or other materials provided with the distribution.
154e400768SDavid Christensen *
164ef8ebfdSDavid C Somayajulu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
174e400768SDavid Christensen * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
184e400768SDavid Christensen * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
194e400768SDavid Christensen * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
204e400768SDavid Christensen * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
214e400768SDavid Christensen * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
224e400768SDavid Christensen * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
234e400768SDavid Christensen * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
244e400768SDavid Christensen * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
254e400768SDavid Christensen * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
264e400768SDavid Christensen * THE POSSIBILITY OF SUCH DAMAGE.
274e400768SDavid Christensen */
284e400768SDavid Christensen
294e400768SDavid Christensen #include <sys/cdefs.h>
304e400768SDavid Christensen #ifndef ECORE_INIT_H
314e400768SDavid Christensen #define ECORE_INIT_H
324e400768SDavid Christensen
334e400768SDavid Christensen /* Init operation types and structures */
344e400768SDavid Christensen enum {
354e400768SDavid Christensen OP_RD = 0x1, /* read a single register */
364e400768SDavid Christensen OP_WR, /* write a single register */
374e400768SDavid Christensen OP_SW, /* copy a string to the device */
384e400768SDavid Christensen OP_ZR, /* clear memory */
394e400768SDavid Christensen OP_ZP, /* unzip then copy with DMAE */
404e400768SDavid Christensen OP_WR_64, /* write 64 bit pattern */
414e400768SDavid Christensen OP_WB, /* copy a string using DMAE */
424e400768SDavid Christensen #ifndef FW_ZIP_SUPPORT
434e400768SDavid Christensen OP_FW, /* copy an array from fw data (only used with unzipped FW) */
444e400768SDavid Christensen #endif
454e400768SDavid Christensen OP_WB_ZR, /* Clear a string using DMAE or indirect-wr */
464e400768SDavid Christensen OP_IF_MODE_OR, /* Skip the following ops if all init modes don't match */
474e400768SDavid Christensen OP_IF_MODE_AND, /* Skip the following ops if any init modes don't match */
484e400768SDavid Christensen OP_IF_PHASE,
494e400768SDavid Christensen OP_RT,
504e400768SDavid Christensen OP_DELAY,
514e400768SDavid Christensen OP_VERIFY,
524e400768SDavid Christensen OP_MAX
534e400768SDavid Christensen };
544e400768SDavid Christensen
554e400768SDavid Christensen enum {
564e400768SDavid Christensen STAGE_START,
574e400768SDavid Christensen STAGE_END,
584e400768SDavid Christensen };
594e400768SDavid Christensen
604e400768SDavid Christensen /* Returns the index of start or end of a specific block stage in ops array*/
614e400768SDavid Christensen #define BLOCK_OPS_IDX(block, stage, end) \
624e400768SDavid Christensen (2*(((block)*NUM_OF_INIT_PHASES) + (stage)) + (end))
634e400768SDavid Christensen
644e400768SDavid Christensen
654e400768SDavid Christensen /* structs for the various opcodes */
664e400768SDavid Christensen struct raw_op {
674e400768SDavid Christensen uint32_t op:8;
684e400768SDavid Christensen uint32_t offset:24;
694e400768SDavid Christensen uint32_t raw_data;
704e400768SDavid Christensen };
714e400768SDavid Christensen
724e400768SDavid Christensen struct op_read {
734e400768SDavid Christensen uint32_t op:8;
744e400768SDavid Christensen uint32_t offset:24;
754e400768SDavid Christensen uint32_t val;
764e400768SDavid Christensen };
774e400768SDavid Christensen
784e400768SDavid Christensen struct op_write {
794e400768SDavid Christensen uint32_t op:8;
804e400768SDavid Christensen uint32_t offset:24;
814e400768SDavid Christensen uint32_t val;
824e400768SDavid Christensen };
834e400768SDavid Christensen
844e400768SDavid Christensen struct op_arr_write {
854e400768SDavid Christensen uint32_t op:8;
864e400768SDavid Christensen uint32_t offset:24;
874e400768SDavid Christensen #ifdef __BIG_ENDIAN
884e400768SDavid Christensen uint16_t data_len;
894e400768SDavid Christensen uint16_t data_off;
904e400768SDavid Christensen #else /* __LITTLE_ENDIAN */
914e400768SDavid Christensen uint16_t data_off;
924e400768SDavid Christensen uint16_t data_len;
934e400768SDavid Christensen #endif
944e400768SDavid Christensen };
954e400768SDavid Christensen
964e400768SDavid Christensen struct op_zero {
974e400768SDavid Christensen uint32_t op:8;
984e400768SDavid Christensen uint32_t offset:24;
994e400768SDavid Christensen uint32_t len;
1004e400768SDavid Christensen };
1014e400768SDavid Christensen
1024e400768SDavid Christensen struct op_if_mode {
1034e400768SDavid Christensen uint32_t op:8;
1044e400768SDavid Christensen uint32_t cmd_offset:24;
1054e400768SDavid Christensen uint32_t mode_bit_map;
1064e400768SDavid Christensen };
1074e400768SDavid Christensen
1084e400768SDavid Christensen struct op_if_phase {
1094e400768SDavid Christensen uint32_t op:8;
1104e400768SDavid Christensen uint32_t cmd_offset:24;
1114e400768SDavid Christensen uint32_t phase_bit_map;
1124e400768SDavid Christensen };
1134e400768SDavid Christensen
1144e400768SDavid Christensen struct op_delay {
1154e400768SDavid Christensen uint32_t op:8;
1164e400768SDavid Christensen uint32_t reserved:24;
1174e400768SDavid Christensen uint32_t delay;
1184e400768SDavid Christensen };
1194e400768SDavid Christensen
1204e400768SDavid Christensen union init_op {
1214e400768SDavid Christensen struct op_read read;
1224e400768SDavid Christensen struct op_write write;
1234e400768SDavid Christensen struct op_arr_write arr_wr;
1244e400768SDavid Christensen struct op_zero zero;
1254e400768SDavid Christensen struct raw_op raw;
1264e400768SDavid Christensen struct op_if_mode if_mode;
1274e400768SDavid Christensen struct op_if_phase if_phase;
1284e400768SDavid Christensen struct op_delay delay;
1294e400768SDavid Christensen };
1304e400768SDavid Christensen
1314e400768SDavid Christensen
1324e400768SDavid Christensen /* Init Phases */
1334e400768SDavid Christensen enum {
1344e400768SDavid Christensen PHASE_COMMON,
1354e400768SDavid Christensen PHASE_PORT0,
1364e400768SDavid Christensen PHASE_PORT1,
1374e400768SDavid Christensen PHASE_PF0,
1384e400768SDavid Christensen PHASE_PF1,
1394e400768SDavid Christensen PHASE_PF2,
1404e400768SDavid Christensen PHASE_PF3,
1414e400768SDavid Christensen PHASE_PF4,
1424e400768SDavid Christensen PHASE_PF5,
1434e400768SDavid Christensen PHASE_PF6,
1444e400768SDavid Christensen PHASE_PF7,
1454e400768SDavid Christensen NUM_OF_INIT_PHASES
1464e400768SDavid Christensen };
1474e400768SDavid Christensen
1484e400768SDavid Christensen /* Init Modes */
1494e400768SDavid Christensen enum {
1504e400768SDavid Christensen MODE_ASIC = 0x00000001,
1514e400768SDavid Christensen MODE_FPGA = 0x00000002,
1524e400768SDavid Christensen MODE_EMUL = 0x00000004,
1534e400768SDavid Christensen MODE_E2 = 0x00000008,
1544e400768SDavid Christensen MODE_E3 = 0x00000010,
1554e400768SDavid Christensen MODE_PORT2 = 0x00000020,
1564e400768SDavid Christensen MODE_PORT4 = 0x00000040,
1574e400768SDavid Christensen MODE_SF = 0x00000080,
1584e400768SDavid Christensen MODE_MF = 0x00000100,
1594e400768SDavid Christensen MODE_MF_SD = 0x00000200,
1604e400768SDavid Christensen MODE_MF_SI = 0x00000400,
1614e400768SDavid Christensen MODE_MF_AFEX = 0x00000800,
1624e400768SDavid Christensen MODE_E3_A0 = 0x00001000,
1634e400768SDavid Christensen MODE_E3_B0 = 0x00002000,
1644e400768SDavid Christensen MODE_COS3 = 0x00004000,
1654e400768SDavid Christensen MODE_COS6 = 0x00008000,
1664e400768SDavid Christensen MODE_LITTLE_ENDIAN = 0x00010000,
1674e400768SDavid Christensen MODE_BIG_ENDIAN = 0x00020000,
1684e400768SDavid Christensen };
1694e400768SDavid Christensen
1704e400768SDavid Christensen /* Init Blocks */
1714e400768SDavid Christensen enum {
1724e400768SDavid Christensen BLOCK_ATC,
1734e400768SDavid Christensen BLOCK_BRB1,
1744e400768SDavid Christensen BLOCK_CCM,
1754e400768SDavid Christensen BLOCK_CDU,
1764e400768SDavid Christensen BLOCK_CFC,
1774e400768SDavid Christensen BLOCK_CSDM,
1784e400768SDavid Christensen BLOCK_CSEM,
1794e400768SDavid Christensen BLOCK_DBG,
1804e400768SDavid Christensen BLOCK_DMAE,
1814e400768SDavid Christensen BLOCK_DORQ,
1824e400768SDavid Christensen BLOCK_HC,
1834e400768SDavid Christensen BLOCK_IGU,
1844e400768SDavid Christensen BLOCK_MISC,
1854e400768SDavid Christensen BLOCK_NIG,
1864e400768SDavid Christensen BLOCK_PBF,
1874e400768SDavid Christensen BLOCK_PGLUE_B,
1884e400768SDavid Christensen BLOCK_PRS,
1894e400768SDavid Christensen BLOCK_PXP2,
1904e400768SDavid Christensen BLOCK_PXP,
1914e400768SDavid Christensen BLOCK_QM,
1924e400768SDavid Christensen BLOCK_SRC,
1934e400768SDavid Christensen BLOCK_TCM,
1944e400768SDavid Christensen BLOCK_TM,
1954e400768SDavid Christensen BLOCK_TSDM,
1964e400768SDavid Christensen BLOCK_TSEM,
1974e400768SDavid Christensen BLOCK_UCM,
1984e400768SDavid Christensen BLOCK_UPB,
1994e400768SDavid Christensen BLOCK_USDM,
2004e400768SDavid Christensen BLOCK_USEM,
2014e400768SDavid Christensen BLOCK_XCM,
2024e400768SDavid Christensen BLOCK_XPB,
2034e400768SDavid Christensen BLOCK_XSDM,
2044e400768SDavid Christensen BLOCK_XSEM,
2054e400768SDavid Christensen BLOCK_MISC_AEU,
2064e400768SDavid Christensen NUM_OF_INIT_BLOCKS
2074e400768SDavid Christensen };
2084e400768SDavid Christensen
2094e400768SDavid Christensen
2104e400768SDavid Christensen
2114e400768SDavid Christensen
2124e400768SDavid Christensen
2134e400768SDavid Christensen
2144e400768SDavid Christensen
2154e400768SDavid Christensen
2164e400768SDavid Christensen /* Vnics per mode */
2174e400768SDavid Christensen #define ECORE_PORT2_MODE_NUM_VNICS 4
2184e400768SDavid Christensen
2194e400768SDavid Christensen
2204e400768SDavid Christensen /* QM queue numbers */
2214e400768SDavid Christensen #define ECORE_ETH_Q 0
2224e400768SDavid Christensen #define ECORE_TOE_Q 3
2234e400768SDavid Christensen #define ECORE_TOE_ACK_Q 6
2244e400768SDavid Christensen #define ECORE_ISCSI_Q 9
2254e400768SDavid Christensen #define ECORE_ISCSI_ACK_Q 11
2264e400768SDavid Christensen #define ECORE_FCOE_Q 10
2274e400768SDavid Christensen
2284e400768SDavid Christensen /* Vnics per mode */
2294e400768SDavid Christensen #define ECORE_PORT4_MODE_NUM_VNICS 2
2304e400768SDavid Christensen
2314e400768SDavid Christensen /* COS offset for port1 in E3 B0 4port mode */
2324e400768SDavid Christensen #define ECORE_E3B0_PORT1_COS_OFFSET 3
2334e400768SDavid Christensen
2344e400768SDavid Christensen /* QM Register addresses */
2354e400768SDavid Christensen #define ECORE_Q_VOQ_REG_ADDR(pf_q_num)\
2364e400768SDavid Christensen (QM_REG_QVOQIDX_0 + 4 * (pf_q_num))
2374e400768SDavid Christensen #define ECORE_VOQ_Q_REG_ADDR(cos, pf_q_num)\
2384e400768SDavid Christensen (QM_REG_VOQQMASK_0_LSB + 4 * ((cos) * 2 + ((pf_q_num) >> 5)))
2394e400768SDavid Christensen #define ECORE_Q_CMDQ_REG_ADDR(pf_q_num)\
2404e400768SDavid Christensen (QM_REG_BYTECRDCMDQ_0 + 4 * ((pf_q_num) >> 4))
2414e400768SDavid Christensen
2424e400768SDavid Christensen /* extracts the QM queue number for the specified port and vnic */
2434e400768SDavid Christensen #define ECORE_PF_Q_NUM(q_num, port, vnic)\
2444e400768SDavid Christensen ((((port) << 1) | (vnic)) * 16 + (q_num))
2454e400768SDavid Christensen
2464e400768SDavid Christensen
2474e400768SDavid Christensen /* Maps the specified queue to the specified COS */
ecore_map_q_cos(struct bxe_softc * sc,uint32_t q_num,uint32_t new_cos)2484e400768SDavid Christensen static inline void ecore_map_q_cos(struct bxe_softc *sc, uint32_t q_num, uint32_t new_cos)
2494e400768SDavid Christensen {
2504e400768SDavid Christensen /* find current COS mapping */
2514e400768SDavid Christensen uint32_t curr_cos = REG_RD(sc, QM_REG_QVOQIDX_0 + q_num * 4);
2524e400768SDavid Christensen
2534e400768SDavid Christensen /* check if queue->COS mapping has changed */
2544e400768SDavid Christensen if (curr_cos != new_cos) {
2554e400768SDavid Christensen uint32_t num_vnics = ECORE_PORT2_MODE_NUM_VNICS;
2564e400768SDavid Christensen uint32_t reg_addr, reg_bit_map, vnic;
2574e400768SDavid Christensen
2584e400768SDavid Christensen /* update parameters for 4port mode */
2594e400768SDavid Christensen if (INIT_MODE_FLAGS(sc) & MODE_PORT4) {
2604e400768SDavid Christensen num_vnics = ECORE_PORT4_MODE_NUM_VNICS;
2614e400768SDavid Christensen if (PORT_ID(sc)) {
2624e400768SDavid Christensen curr_cos += ECORE_E3B0_PORT1_COS_OFFSET;
2634e400768SDavid Christensen new_cos += ECORE_E3B0_PORT1_COS_OFFSET;
2644e400768SDavid Christensen }
2654e400768SDavid Christensen }
2664e400768SDavid Christensen
2674e400768SDavid Christensen /* change queue mapping for each VNIC */
2684e400768SDavid Christensen for (vnic = 0; vnic < num_vnics; vnic++) {
2694e400768SDavid Christensen uint32_t pf_q_num =
2704e400768SDavid Christensen ECORE_PF_Q_NUM(q_num, PORT_ID(sc), vnic);
2714e400768SDavid Christensen uint32_t q_bit_map = 1 << (pf_q_num & 0x1f);
2724e400768SDavid Christensen
2734e400768SDavid Christensen /* overwrite queue->VOQ mapping */
2744e400768SDavid Christensen REG_WR(sc, ECORE_Q_VOQ_REG_ADDR(pf_q_num), new_cos);
2754e400768SDavid Christensen
2764e400768SDavid Christensen /* clear queue bit from current COS bit map */
2774e400768SDavid Christensen reg_addr = ECORE_VOQ_Q_REG_ADDR(curr_cos, pf_q_num);
2784e400768SDavid Christensen reg_bit_map = REG_RD(sc, reg_addr);
2794e400768SDavid Christensen REG_WR(sc, reg_addr, reg_bit_map & (~q_bit_map));
2804e400768SDavid Christensen
2814e400768SDavid Christensen /* set queue bit in new COS bit map */
2824e400768SDavid Christensen reg_addr = ECORE_VOQ_Q_REG_ADDR(new_cos, pf_q_num);
2834e400768SDavid Christensen reg_bit_map = REG_RD(sc, reg_addr);
2844e400768SDavid Christensen REG_WR(sc, reg_addr, reg_bit_map | q_bit_map);
2854e400768SDavid Christensen
2864e400768SDavid Christensen /* set/clear queue bit in command-queue bit map
2874e400768SDavid Christensen (E2/E3A0 only, valid COS values are 0/1) */
2884e400768SDavid Christensen if (!(INIT_MODE_FLAGS(sc) & MODE_E3_B0)) {
2894e400768SDavid Christensen reg_addr = ECORE_Q_CMDQ_REG_ADDR(pf_q_num);
2904e400768SDavid Christensen reg_bit_map = REG_RD(sc, reg_addr);
2914e400768SDavid Christensen q_bit_map = 1 << (2 * (pf_q_num & 0xf));
2924e400768SDavid Christensen reg_bit_map = new_cos ?
2934e400768SDavid Christensen (reg_bit_map | q_bit_map) :
2944e400768SDavid Christensen (reg_bit_map & (~q_bit_map));
2954e400768SDavid Christensen REG_WR(sc, reg_addr, reg_bit_map);
2964e400768SDavid Christensen }
2974e400768SDavid Christensen }
2984e400768SDavid Christensen }
2994e400768SDavid Christensen }
3004e400768SDavid Christensen
3014e400768SDavid Christensen /* Configures the QM according to the specified per-traffic-type COSes */
ecore_dcb_config_qm(struct bxe_softc * sc,enum cos_mode mode,struct priority_cos * traffic_cos)3024e400768SDavid Christensen static inline void ecore_dcb_config_qm(struct bxe_softc *sc, enum cos_mode mode,
3034e400768SDavid Christensen struct priority_cos *traffic_cos)
3044e400768SDavid Christensen {
3054e400768SDavid Christensen ecore_map_q_cos(sc, ECORE_FCOE_Q,
3064e400768SDavid Christensen traffic_cos[LLFC_TRAFFIC_TYPE_FCOE].cos);
3074e400768SDavid Christensen ecore_map_q_cos(sc, ECORE_ISCSI_Q,
3084e400768SDavid Christensen traffic_cos[LLFC_TRAFFIC_TYPE_ISCSI].cos);
3094e400768SDavid Christensen ecore_map_q_cos(sc, ECORE_ISCSI_ACK_Q,
3104e400768SDavid Christensen traffic_cos[LLFC_TRAFFIC_TYPE_ISCSI].cos);
3114e400768SDavid Christensen if (mode != STATIC_COS) {
3124e400768SDavid Christensen /* required only in OVERRIDE_COS mode */
3134e400768SDavid Christensen ecore_map_q_cos(sc, ECORE_ETH_Q,
3144e400768SDavid Christensen traffic_cos[LLFC_TRAFFIC_TYPE_NW].cos);
3154e400768SDavid Christensen ecore_map_q_cos(sc, ECORE_TOE_Q,
3164e400768SDavid Christensen traffic_cos[LLFC_TRAFFIC_TYPE_NW].cos);
3174e400768SDavid Christensen ecore_map_q_cos(sc, ECORE_TOE_ACK_Q,
3184e400768SDavid Christensen traffic_cos[LLFC_TRAFFIC_TYPE_NW].cos);
3194e400768SDavid Christensen }
3204e400768SDavid Christensen }
3214e400768SDavid Christensen
3224e400768SDavid Christensen
3234e400768SDavid Christensen /*
324453130d9SPedro F. Giffuni * congestion management port init api description
3254e400768SDavid Christensen * the api works as follows:
3264e400768SDavid Christensen * the driver should pass the cmng_init_input struct, the port_init function
3274e400768SDavid Christensen * will prepare the required internal ram structure which will be passed back
3284e400768SDavid Christensen * to the driver (cmng_init) that will write it into the internal ram.
3294e400768SDavid Christensen *
3304e400768SDavid Christensen * IMPORTANT REMARKS:
3314e400768SDavid Christensen * 1. the cmng_init struct does not represent the contiguous internal ram
3324e400768SDavid Christensen * structure. the driver should use the XSTORM_CMNG_PERPORT_VARS_OFFSET
3334e400768SDavid Christensen * offset in order to write the port sub struct and the
3344e400768SDavid Christensen * PFID_FROM_PORT_AND_VNIC offset for writing the vnic sub struct (in other
3354e400768SDavid Christensen * words - don't use memcpy!).
3364e400768SDavid Christensen * 2. although the cmng_init struct is filled for the maximal vnic number
3374e400768SDavid Christensen * possible, the driver should only write the valid vnics into the internal
3384e400768SDavid Christensen * ram according to the appropriate port mode.
3394e400768SDavid Christensen */
3404e400768SDavid Christensen #define BITS_TO_BYTES(x) ((x)/8)
3414e400768SDavid Christensen
3424e400768SDavid Christensen /* CMNG constants, as derived from system spec calculations */
3434e400768SDavid Christensen
3444e400768SDavid Christensen /* default MIN rate in case VNIC min rate is configured to zero- 100Mbps */
3454e400768SDavid Christensen #define DEF_MIN_RATE 100
3464e400768SDavid Christensen
3474e400768SDavid Christensen /* resolution of the rate shaping timer - 400 usec */
3484e400768SDavid Christensen #define RS_PERIODIC_TIMEOUT_USEC 400
3494e400768SDavid Christensen
3504e400768SDavid Christensen /*
3514e400768SDavid Christensen * number of bytes in single QM arbitration cycle -
3524e400768SDavid Christensen * coefficient for calculating the fairness timer
3534e400768SDavid Christensen */
3544e400768SDavid Christensen #define QM_ARB_BYTES 160000
3554e400768SDavid Christensen
3564e400768SDavid Christensen /* resolution of Min algorithm 1:100 */
3574e400768SDavid Christensen #define MIN_RES 100
3584e400768SDavid Christensen
3594e400768SDavid Christensen /*
3604e400768SDavid Christensen * how many bytes above threshold for
3614e400768SDavid Christensen * the minimal credit of Min algorithm
3624e400768SDavid Christensen */
3634e400768SDavid Christensen #define MIN_ABOVE_THRESH 32768
3644e400768SDavid Christensen
3654e400768SDavid Christensen /*
3664e400768SDavid Christensen * Fairness algorithm integration time coefficient -
3674e400768SDavid Christensen * for calculating the actual Tfair
3684e400768SDavid Christensen */
3694e400768SDavid Christensen #define T_FAIR_COEF ((MIN_ABOVE_THRESH + QM_ARB_BYTES) * 8 * MIN_RES)
3704e400768SDavid Christensen
3714e400768SDavid Christensen /* Memory of fairness algorithm - 2 cycles */
3724e400768SDavid Christensen #define FAIR_MEM 2
3734e400768SDavid Christensen #define SAFC_TIMEOUT_USEC 52
3744e400768SDavid Christensen
3754e400768SDavid Christensen #define SDM_TICKS 4
3764e400768SDavid Christensen
3774e400768SDavid Christensen
ecore_init_max(const struct cmng_init_input * input_data,uint32_t r_param,struct cmng_init * ram_data)3784e400768SDavid Christensen static inline void ecore_init_max(const struct cmng_init_input *input_data,
3794e400768SDavid Christensen uint32_t r_param, struct cmng_init *ram_data)
3804e400768SDavid Christensen {
3814e400768SDavid Christensen uint32_t vnic;
3824e400768SDavid Christensen struct cmng_vnic *vdata = &ram_data->vnic;
3834e400768SDavid Christensen struct cmng_struct_per_port *pdata = &ram_data->port;
3844e400768SDavid Christensen /*
3854e400768SDavid Christensen * rate shaping per-port variables
3864e400768SDavid Christensen * 100 micro seconds in SDM ticks = 25
3874e400768SDavid Christensen * since each tick is 4 microSeconds
3884e400768SDavid Christensen */
3894e400768SDavid Christensen
3904e400768SDavid Christensen pdata->rs_vars.rs_periodic_timeout =
3914e400768SDavid Christensen RS_PERIODIC_TIMEOUT_USEC / SDM_TICKS;
3924e400768SDavid Christensen
3934e400768SDavid Christensen /* this is the threshold below which no timer arming will occur.
3944e400768SDavid Christensen * 1.25 coefficient is for the threshold to be a little bigger
3954e400768SDavid Christensen * then the real time to compensate for timer in-accuracy
3964e400768SDavid Christensen */
3974e400768SDavid Christensen pdata->rs_vars.rs_threshold =
3984e400768SDavid Christensen (5 * RS_PERIODIC_TIMEOUT_USEC * r_param)/4;
3994e400768SDavid Christensen
4004e400768SDavid Christensen /* rate shaping per-vnic variables */
4014e400768SDavid Christensen for (vnic = 0; vnic < ECORE_PORT2_MODE_NUM_VNICS; vnic++) {
4024e400768SDavid Christensen /* global vnic counter */
4034e400768SDavid Christensen vdata->vnic_max_rate[vnic].vn_counter.rate =
4044e400768SDavid Christensen input_data->vnic_max_rate[vnic];
4054e400768SDavid Christensen /*
4064e400768SDavid Christensen * maximal Mbps for this vnic
4074e400768SDavid Christensen * the quota in each timer period - number of bytes
4084e400768SDavid Christensen * transmitted in this period
4094e400768SDavid Christensen */
4104e400768SDavid Christensen vdata->vnic_max_rate[vnic].vn_counter.quota =
4114e400768SDavid Christensen RS_PERIODIC_TIMEOUT_USEC *
4124e400768SDavid Christensen (uint32_t)vdata->vnic_max_rate[vnic].vn_counter.rate / 8;
4134e400768SDavid Christensen }
4144e400768SDavid Christensen
4154e400768SDavid Christensen }
4164e400768SDavid Christensen
ecore_init_max_per_vn(uint16_t vnic_max_rate,struct rate_shaping_vars_per_vn * ram_data)4174e400768SDavid Christensen static inline void ecore_init_max_per_vn(uint16_t vnic_max_rate,
4184e400768SDavid Christensen struct rate_shaping_vars_per_vn *ram_data)
4194e400768SDavid Christensen {
4204e400768SDavid Christensen /* global vnic counter */
4214e400768SDavid Christensen ram_data->vn_counter.rate = vnic_max_rate;
4224e400768SDavid Christensen
4234e400768SDavid Christensen /*
4244e400768SDavid Christensen * maximal Mbps for this vnic
4254e400768SDavid Christensen * the quota in each timer period - number of bytes
4264e400768SDavid Christensen * transmitted in this period
4274e400768SDavid Christensen */
4284e400768SDavid Christensen ram_data->vn_counter.quota =
4294e400768SDavid Christensen RS_PERIODIC_TIMEOUT_USEC * (uint32_t)vnic_max_rate / 8;
4304e400768SDavid Christensen }
4314e400768SDavid Christensen
ecore_init_min(const struct cmng_init_input * input_data,uint32_t r_param,struct cmng_init * ram_data)4324e400768SDavid Christensen static inline void ecore_init_min(const struct cmng_init_input *input_data,
4334e400768SDavid Christensen uint32_t r_param, struct cmng_init *ram_data)
4344e400768SDavid Christensen {
4354e400768SDavid Christensen uint32_t vnic, fair_periodic_timeout_usec, vnicWeightSum, tFair;
4364e400768SDavid Christensen struct cmng_vnic *vdata = &ram_data->vnic;
4374e400768SDavid Christensen struct cmng_struct_per_port *pdata = &ram_data->port;
4384e400768SDavid Christensen
4394e400768SDavid Christensen /* this is the resolution of the fairness timer */
4404e400768SDavid Christensen fair_periodic_timeout_usec = QM_ARB_BYTES / r_param;
4414e400768SDavid Christensen
4424e400768SDavid Christensen /*
4434e400768SDavid Christensen * fairness per-port variables
4444e400768SDavid Christensen * for 10G it is 1000usec. for 1G it is 10000usec.
4454e400768SDavid Christensen */
4464e400768SDavid Christensen tFair = T_FAIR_COEF / input_data->port_rate;
4474e400768SDavid Christensen
4484e400768SDavid Christensen /* this is the threshold below which we won't arm the timer anymore */
4494e400768SDavid Christensen pdata->fair_vars.fair_threshold = QM_ARB_BYTES;
4504e400768SDavid Christensen
4514e400768SDavid Christensen /*
4524e400768SDavid Christensen * we multiply by 1e3/8 to get bytes/msec. We don't want the credits
4534e400768SDavid Christensen * to pass a credit of the T_FAIR*FAIR_MEM (algorithm resolution)
4544e400768SDavid Christensen */
4554e400768SDavid Christensen pdata->fair_vars.upper_bound = r_param * tFair * FAIR_MEM;
4564e400768SDavid Christensen
4574e400768SDavid Christensen /* since each tick is 4 microSeconds */
4584e400768SDavid Christensen pdata->fair_vars.fairness_timeout =
4594e400768SDavid Christensen fair_periodic_timeout_usec / SDM_TICKS;
4604e400768SDavid Christensen
4614e400768SDavid Christensen /* calculate sum of weights */
4624e400768SDavid Christensen vnicWeightSum = 0;
4634e400768SDavid Christensen
4644e400768SDavid Christensen for (vnic = 0; vnic < ECORE_PORT2_MODE_NUM_VNICS; vnic++)
4654e400768SDavid Christensen vnicWeightSum += input_data->vnic_min_rate[vnic];
4664e400768SDavid Christensen
4674e400768SDavid Christensen /* global vnic counter */
4684e400768SDavid Christensen if (vnicWeightSum > 0) {
4694e400768SDavid Christensen /* fairness per-vnic variables */
4704e400768SDavid Christensen for (vnic = 0; vnic < ECORE_PORT2_MODE_NUM_VNICS; vnic++) {
4714e400768SDavid Christensen /*
4724e400768SDavid Christensen * this is the credit for each period of the fairness
4734e400768SDavid Christensen * algorithm - number of bytes in T_FAIR (this vnic
4744e400768SDavid Christensen * share of the port rate)
4754e400768SDavid Christensen */
4764e400768SDavid Christensen vdata->vnic_min_rate[vnic].vn_credit_delta =
4774e400768SDavid Christensen ((uint32_t)(input_data->vnic_min_rate[vnic]) * 100 *
4784e400768SDavid Christensen (T_FAIR_COEF / (8 * 100 * vnicWeightSum)));
4794e400768SDavid Christensen if (vdata->vnic_min_rate[vnic].vn_credit_delta <
4804e400768SDavid Christensen pdata->fair_vars.fair_threshold +
4814e400768SDavid Christensen MIN_ABOVE_THRESH) {
4824e400768SDavid Christensen vdata->vnic_min_rate[vnic].vn_credit_delta =
4834e400768SDavid Christensen pdata->fair_vars.fair_threshold +
4844e400768SDavid Christensen MIN_ABOVE_THRESH;
4854e400768SDavid Christensen }
4864e400768SDavid Christensen }
4874e400768SDavid Christensen }
4884e400768SDavid Christensen }
4894e400768SDavid Christensen
ecore_init_fw_wrr(const struct cmng_init_input * input_data,uint32_t r_param,struct cmng_init * ram_data)4904e400768SDavid Christensen static inline void ecore_init_fw_wrr(const struct cmng_init_input *input_data,
4914e400768SDavid Christensen uint32_t r_param, struct cmng_init *ram_data)
4924e400768SDavid Christensen {
4934e400768SDavid Christensen uint32_t vnic, cos;
4944e400768SDavid Christensen uint32_t cosWeightSum = 0;
4954e400768SDavid Christensen struct cmng_vnic *vdata = &ram_data->vnic;
4964e400768SDavid Christensen struct cmng_struct_per_port *pdata = &ram_data->port;
4974e400768SDavid Christensen
4984e400768SDavid Christensen for (cos = 0; cos < MAX_COS_NUMBER; cos++)
4994e400768SDavid Christensen cosWeightSum += input_data->cos_min_rate[cos];
5004e400768SDavid Christensen
5014e400768SDavid Christensen if (cosWeightSum > 0) {
5024e400768SDavid Christensen
5034e400768SDavid Christensen for (vnic = 0; vnic < ECORE_PORT2_MODE_NUM_VNICS; vnic++) {
5044e400768SDavid Christensen /*
5054e400768SDavid Christensen * Since cos and vnic shouldn't work together the rate
5064e400768SDavid Christensen * to divide between the coses is the port rate.
5074e400768SDavid Christensen */
5084e400768SDavid Christensen uint32_t *ccd = vdata->vnic_min_rate[vnic].cos_credit_delta;
5094e400768SDavid Christensen for (cos = 0; cos < MAX_COS_NUMBER; cos++) {
5104e400768SDavid Christensen /*
5114e400768SDavid Christensen * this is the credit for each period of
5124e400768SDavid Christensen * the fairness algorithm - number of bytes
5134e400768SDavid Christensen * in T_FAIR (this cos share of the vnic rate)
5144e400768SDavid Christensen */
5154e400768SDavid Christensen ccd[cos] =
5164e400768SDavid Christensen ((uint32_t)input_data->cos_min_rate[cos] * 100 *
5174e400768SDavid Christensen (T_FAIR_COEF / (8 * 100 * cosWeightSum)));
5184e400768SDavid Christensen if (ccd[cos] < pdata->fair_vars.fair_threshold
5194e400768SDavid Christensen + MIN_ABOVE_THRESH) {
5204e400768SDavid Christensen ccd[cos] =
5214e400768SDavid Christensen pdata->fair_vars.fair_threshold +
5224e400768SDavid Christensen MIN_ABOVE_THRESH;
5234e400768SDavid Christensen }
5244e400768SDavid Christensen }
5254e400768SDavid Christensen }
5264e400768SDavid Christensen }
5274e400768SDavid Christensen }
5284e400768SDavid Christensen
ecore_init_safc(const struct cmng_init_input * input_data,struct cmng_init * ram_data)5294e400768SDavid Christensen static inline void ecore_init_safc(const struct cmng_init_input *input_data,
5304e400768SDavid Christensen struct cmng_init *ram_data)
5314e400768SDavid Christensen {
5324e400768SDavid Christensen /* in microSeconds */
5334e400768SDavid Christensen ram_data->port.safc_vars.safc_timeout_usec = SAFC_TIMEOUT_USEC;
5344e400768SDavid Christensen }
5354e400768SDavid Christensen
5364e400768SDavid Christensen /* Congestion management port init */
ecore_init_cmng(const struct cmng_init_input * input_data,struct cmng_init * ram_data)5374e400768SDavid Christensen static inline void ecore_init_cmng(const struct cmng_init_input *input_data,
5384e400768SDavid Christensen struct cmng_init *ram_data)
5394e400768SDavid Christensen {
5404e400768SDavid Christensen uint32_t r_param;
5414e400768SDavid Christensen ECORE_MEMSET(ram_data, 0,sizeof(struct cmng_init));
5424e400768SDavid Christensen
5434e400768SDavid Christensen ram_data->port.flags = input_data->flags;
5444e400768SDavid Christensen
5454e400768SDavid Christensen /*
5464e400768SDavid Christensen * number of bytes transmitted in a rate of 10Gbps
5474e400768SDavid Christensen * in one usec = 1.25KB.
5484e400768SDavid Christensen */
5494e400768SDavid Christensen r_param = BITS_TO_BYTES(input_data->port_rate);
5504e400768SDavid Christensen ecore_init_max(input_data, r_param, ram_data);
5514e400768SDavid Christensen ecore_init_min(input_data, r_param, ram_data);
5524e400768SDavid Christensen ecore_init_fw_wrr(input_data, r_param, ram_data);
5534e400768SDavid Christensen ecore_init_safc(input_data, ram_data);
5544e400768SDavid Christensen }
5554e400768SDavid Christensen
5564e400768SDavid Christensen
5574e400768SDavid Christensen
5584e400768SDavid Christensen
5594e400768SDavid Christensen /* Returns the index of start or end of a specific block stage in ops array*/
5604e400768SDavid Christensen #define BLOCK_OPS_IDX(block, stage, end) \
5614e400768SDavid Christensen (2*(((block)*NUM_OF_INIT_PHASES) + (stage)) + (end))
5624e400768SDavid Christensen
5634e400768SDavid Christensen
5644e400768SDavid Christensen #define INITOP_SET 0 /* set the HW directly */
5654e400768SDavid Christensen #define INITOP_CLEAR 1 /* clear the HW directly */
5664e400768SDavid Christensen #define INITOP_INIT 2 /* set the init-value array */
5674e400768SDavid Christensen
5684e400768SDavid Christensen /****************************************************************************
5694e400768SDavid Christensen * ILT management
5704e400768SDavid Christensen ****************************************************************************/
5714e400768SDavid Christensen struct ilt_line {
5724e400768SDavid Christensen ecore_dma_addr_t page_mapping;
5734e400768SDavid Christensen void *page;
5744e400768SDavid Christensen uint32_t size;
5754e400768SDavid Christensen };
5764e400768SDavid Christensen
5774e400768SDavid Christensen struct ilt_client_info {
5784e400768SDavid Christensen uint32_t page_size;
5794e400768SDavid Christensen uint16_t start;
5804e400768SDavid Christensen uint16_t end;
5814e400768SDavid Christensen uint16_t client_num;
5824e400768SDavid Christensen uint16_t flags;
5834e400768SDavid Christensen #define ILT_CLIENT_SKIP_INIT 0x1
5844e400768SDavid Christensen #define ILT_CLIENT_SKIP_MEM 0x2
5854e400768SDavid Christensen };
5864e400768SDavid Christensen
5874e400768SDavid Christensen struct ecore_ilt {
5884e400768SDavid Christensen uint32_t start_line;
5894e400768SDavid Christensen struct ilt_line *lines;
5904e400768SDavid Christensen struct ilt_client_info clients[4];
5914e400768SDavid Christensen #define ILT_CLIENT_CDU 0
5924e400768SDavid Christensen #define ILT_CLIENT_QM 1
5934e400768SDavid Christensen #define ILT_CLIENT_SRC 2
5944e400768SDavid Christensen #define ILT_CLIENT_TM 3
5954e400768SDavid Christensen };
5964e400768SDavid Christensen
5974e400768SDavid Christensen /****************************************************************************
5984e400768SDavid Christensen * SRC configuration
5994e400768SDavid Christensen ****************************************************************************/
6004e400768SDavid Christensen struct src_ent {
6014e400768SDavid Christensen uint8_t opaque[56];
6024e400768SDavid Christensen uint64_t next;
6034e400768SDavid Christensen };
6044e400768SDavid Christensen
6054e400768SDavid Christensen /****************************************************************************
6064e400768SDavid Christensen * Parity configuration
6074e400768SDavid Christensen ****************************************************************************/
6084e400768SDavid Christensen #define BLOCK_PRTY_INFO(block, en_mask, m1, m1h, m2, m3) \
6094e400768SDavid Christensen { \
6104e400768SDavid Christensen block##_REG_##block##_PRTY_MASK, \
6114e400768SDavid Christensen block##_REG_##block##_PRTY_STS_CLR, \
6124e400768SDavid Christensen en_mask, {m1, m1h, m2, m3}, #block \
6134e400768SDavid Christensen }
6144e400768SDavid Christensen
6154e400768SDavid Christensen #define BLOCK_PRTY_INFO_0(block, en_mask, m1, m1h, m2, m3) \
6164e400768SDavid Christensen { \
6174e400768SDavid Christensen block##_REG_##block##_PRTY_MASK_0, \
6184e400768SDavid Christensen block##_REG_##block##_PRTY_STS_CLR_0, \
6194e400768SDavid Christensen en_mask, {m1, m1h, m2, m3}, #block"_0" \
6204e400768SDavid Christensen }
6214e400768SDavid Christensen
6224e400768SDavid Christensen #define BLOCK_PRTY_INFO_1(block, en_mask, m1, m1h, m2, m3) \
6234e400768SDavid Christensen { \
6244e400768SDavid Christensen block##_REG_##block##_PRTY_MASK_1, \
6254e400768SDavid Christensen block##_REG_##block##_PRTY_STS_CLR_1, \
6264e400768SDavid Christensen en_mask, {m1, m1h, m2, m3}, #block"_1" \
6274e400768SDavid Christensen }
6284e400768SDavid Christensen
6294e400768SDavid Christensen static const struct {
6304e400768SDavid Christensen uint32_t mask_addr;
6314e400768SDavid Christensen uint32_t sts_clr_addr;
6324e400768SDavid Christensen uint32_t en_mask; /* Mask to enable parity attentions */
6334e400768SDavid Christensen struct {
6344e400768SDavid Christensen uint32_t e1; /* 57710 */
6354e400768SDavid Christensen uint32_t e1h; /* 57711 */
6364e400768SDavid Christensen uint32_t e2; /* 57712 */
6374e400768SDavid Christensen uint32_t e3; /* 578xx */
6384e400768SDavid Christensen } reg_mask; /* Register mask (all valid bits) */
6394e400768SDavid Christensen char name[8]; /* Block's longest name is 7 characters long
6404e400768SDavid Christensen * (name + suffix)
6414e400768SDavid Christensen */
6424e400768SDavid Christensen } ecore_blocks_parity_data[] = {
6434e400768SDavid Christensen /* bit 19 masked */
6444e400768SDavid Christensen /* REG_WR(bp, PXP_REG_PXP_PRTY_MASK, 0x80000); */
6454e400768SDavid Christensen /* bit 5,18,20-31 */
6464e400768SDavid Christensen /* REG_WR(bp, PXP2_REG_PXP2_PRTY_MASK_0, 0xfff40020); */
6474e400768SDavid Christensen /* bit 5 */
6484e400768SDavid Christensen /* REG_WR(bp, PXP2_REG_PXP2_PRTY_MASK_1, 0x20); */
6494e400768SDavid Christensen /* REG_WR(bp, HC_REG_HC_PRTY_MASK, 0x0); */
6504e400768SDavid Christensen /* REG_WR(bp, MISC_REG_MISC_PRTY_MASK, 0x0); */
6514e400768SDavid Christensen
6524e400768SDavid Christensen /* Block IGU, MISC, PXP and PXP2 parity errors as long as we don't
6534e400768SDavid Christensen * want to handle "system kill" flow at the moment.
6544e400768SDavid Christensen */
6554e400768SDavid Christensen BLOCK_PRTY_INFO(PXP, 0x7ffffff, 0x3ffffff, 0x3ffffff, 0x7ffffff,
6564e400768SDavid Christensen 0x7ffffff),
6574e400768SDavid Christensen BLOCK_PRTY_INFO_0(PXP2, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
6584e400768SDavid Christensen 0xffffffff),
6594e400768SDavid Christensen BLOCK_PRTY_INFO_1(PXP2, 0x1ffffff, 0x7f, 0x7f, 0x7ff, 0x1ffffff),
6604e400768SDavid Christensen BLOCK_PRTY_INFO(HC, 0x7, 0x7, 0x7, 0, 0),
6614e400768SDavid Christensen BLOCK_PRTY_INFO(NIG, 0xffffffff, 0x3fffffff, 0xffffffff, 0, 0),
6624e400768SDavid Christensen BLOCK_PRTY_INFO_0(NIG, 0xffffffff, 0, 0, 0xffffffff, 0xffffffff),
6634e400768SDavid Christensen BLOCK_PRTY_INFO_1(NIG, 0xffff, 0, 0, 0xff, 0xffff),
6644e400768SDavid Christensen BLOCK_PRTY_INFO(IGU, 0x7ff, 0, 0, 0x7ff, 0x7ff),
6654e400768SDavid Christensen BLOCK_PRTY_INFO(MISC, 0x1, 0x1, 0x1, 0x1, 0x1),
6664e400768SDavid Christensen BLOCK_PRTY_INFO(QM, 0, 0x1ff, 0xfff, 0xfff, 0xfff),
6674e400768SDavid Christensen BLOCK_PRTY_INFO(ATC, 0x1f, 0, 0, 0x1f, 0x1f),
6684e400768SDavid Christensen BLOCK_PRTY_INFO(PGLUE_B, 0x3, 0, 0, 0x3, 0x3),
6694e400768SDavid Christensen BLOCK_PRTY_INFO(DORQ, 0, 0x3, 0x3, 0x3, 0x3),
6704e400768SDavid Christensen {GRCBASE_UPB + PB_REG_PB_PRTY_MASK,
6714e400768SDavid Christensen GRCBASE_UPB + PB_REG_PB_PRTY_STS_CLR, 0xf,
6724e400768SDavid Christensen {0xf, 0xf, 0xf, 0xf}, "UPB"},
6734e400768SDavid Christensen {GRCBASE_XPB + PB_REG_PB_PRTY_MASK,
6744e400768SDavid Christensen GRCBASE_XPB + PB_REG_PB_PRTY_STS_CLR, 0,
6754e400768SDavid Christensen {0xf, 0xf, 0xf, 0xf}, "XPB"},
6764e400768SDavid Christensen BLOCK_PRTY_INFO(SRC, 0x4, 0x7, 0x7, 0x7, 0x7),
6774e400768SDavid Christensen BLOCK_PRTY_INFO(CDU, 0, 0x1f, 0x1f, 0x1f, 0x1f),
6784e400768SDavid Christensen BLOCK_PRTY_INFO(CFC, 0, 0xf, 0xf, 0xf, 0x3f),
6794e400768SDavid Christensen BLOCK_PRTY_INFO(DBG, 0, 0x1, 0x1, 0x1, 0x1),
6804e400768SDavid Christensen BLOCK_PRTY_INFO(DMAE, 0, 0xf, 0xf, 0xf, 0xf),
6814e400768SDavid Christensen BLOCK_PRTY_INFO(BRB1, 0, 0xf, 0xf, 0xf, 0xf),
6824e400768SDavid Christensen BLOCK_PRTY_INFO(PRS, (1<<6), 0xff, 0xff, 0xff, 0xff),
6834e400768SDavid Christensen BLOCK_PRTY_INFO(PBF, 0, 0, 0x3ffff, 0xfffff, 0xfffffff),
6844e400768SDavid Christensen BLOCK_PRTY_INFO(TM, 0, 0, 0x7f, 0x7f, 0x7f),
6854e400768SDavid Christensen BLOCK_PRTY_INFO(TSDM, 0x18, 0x7ff, 0x7ff, 0x7ff, 0x7ff),
6864e400768SDavid Christensen BLOCK_PRTY_INFO(CSDM, 0x8, 0x7ff, 0x7ff, 0x7ff, 0x7ff),
6874e400768SDavid Christensen BLOCK_PRTY_INFO(USDM, 0x38, 0x7ff, 0x7ff, 0x7ff, 0x7ff),
6884e400768SDavid Christensen BLOCK_PRTY_INFO(XSDM, 0x8, 0x7ff, 0x7ff, 0x7ff, 0x7ff),
6894e400768SDavid Christensen BLOCK_PRTY_INFO(TCM, 0, 0, 0x7ffffff, 0x7ffffff, 0x7ffffff),
6904e400768SDavid Christensen BLOCK_PRTY_INFO(CCM, 0, 0, 0x7ffffff, 0x7ffffff, 0x7ffffff),
6914e400768SDavid Christensen BLOCK_PRTY_INFO(UCM, 0, 0, 0x7ffffff, 0x7ffffff, 0x7ffffff),
6924e400768SDavid Christensen BLOCK_PRTY_INFO(XCM, 0, 0, 0x3fffffff, 0x3fffffff, 0x3fffffff),
6934e400768SDavid Christensen BLOCK_PRTY_INFO_0(TSEM, 0, 0xffffffff, 0xffffffff, 0xffffffff,
6944e400768SDavid Christensen 0xffffffff),
6954e400768SDavid Christensen BLOCK_PRTY_INFO_1(TSEM, 0, 0x3, 0x1f, 0x3f, 0x3f),
6964e400768SDavid Christensen BLOCK_PRTY_INFO_0(USEM, 0, 0xffffffff, 0xffffffff, 0xffffffff,
6974e400768SDavid Christensen 0xffffffff),
6984e400768SDavid Christensen BLOCK_PRTY_INFO_1(USEM, 0, 0x3, 0x1f, 0x1f, 0x1f),
6994e400768SDavid Christensen BLOCK_PRTY_INFO_0(CSEM, 0, 0xffffffff, 0xffffffff, 0xffffffff,
7004e400768SDavid Christensen 0xffffffff),
7014e400768SDavid Christensen BLOCK_PRTY_INFO_1(CSEM, 0, 0x3, 0x1f, 0x1f, 0x1f),
7024e400768SDavid Christensen BLOCK_PRTY_INFO_0(XSEM, 0, 0xffffffff, 0xffffffff, 0xffffffff,
7034e400768SDavid Christensen 0xffffffff),
7044e400768SDavid Christensen BLOCK_PRTY_INFO_1(XSEM, 0, 0x3, 0x1f, 0x3f, 0x3f),
7054e400768SDavid Christensen };
7064e400768SDavid Christensen
7074e400768SDavid Christensen
7084e400768SDavid Christensen /* [28] MCP Latched rom_parity
7094e400768SDavid Christensen * [29] MCP Latched ump_rx_parity
7104e400768SDavid Christensen * [30] MCP Latched ump_tx_parity
7114e400768SDavid Christensen * [31] MCP Latched scpad_parity
7124e400768SDavid Christensen */
7135e33becaSEric Davis #define MISC_AEU_ENABLE_MCP_PRTY_SUB_BITS \
7144e400768SDavid Christensen (AEU_INPUTS_ATTN_BITS_MCP_LATCHED_ROM_PARITY | \
7154e400768SDavid Christensen AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_RX_PARITY | \
7165e33becaSEric Davis AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_TX_PARITY)
7175e33becaSEric Davis
7185e33becaSEric Davis #define MISC_AEU_ENABLE_MCP_PRTY_BITS \
7195e33becaSEric Davis (MISC_AEU_ENABLE_MCP_PRTY_SUB_BITS | \
7204e400768SDavid Christensen AEU_INPUTS_ATTN_BITS_MCP_LATCHED_SCPAD_PARITY)
7214e400768SDavid Christensen
7224e400768SDavid Christensen /* Below registers control the MCP parity attention output. When
7234e400768SDavid Christensen * MISC_AEU_ENABLE_MCP_PRTY_BITS are set - attentions are
7244e400768SDavid Christensen * enabled, when cleared - disabled.
7254e400768SDavid Christensen */
7265e33becaSEric Davis static const struct {
7275e33becaSEric Davis uint32_t addr;
7285e33becaSEric Davis uint32_t bits;
7295e33becaSEric Davis } mcp_attn_ctl_regs[] = {
7305e33becaSEric Davis { MISC_REG_AEU_ENABLE4_FUNC_0_OUT_0,
7315e33becaSEric Davis MISC_AEU_ENABLE_MCP_PRTY_BITS },
7325e33becaSEric Davis { MISC_REG_AEU_ENABLE4_NIG_0,
7335e33becaSEric Davis MISC_AEU_ENABLE_MCP_PRTY_SUB_BITS },
7345e33becaSEric Davis { MISC_REG_AEU_ENABLE4_PXP_0,
7355e33becaSEric Davis MISC_AEU_ENABLE_MCP_PRTY_SUB_BITS },
7365e33becaSEric Davis { MISC_REG_AEU_ENABLE4_FUNC_1_OUT_0,
7375e33becaSEric Davis MISC_AEU_ENABLE_MCP_PRTY_BITS },
7385e33becaSEric Davis { MISC_REG_AEU_ENABLE4_NIG_1,
7395e33becaSEric Davis MISC_AEU_ENABLE_MCP_PRTY_SUB_BITS },
7405e33becaSEric Davis { MISC_REG_AEU_ENABLE4_PXP_1,
7415e33becaSEric Davis MISC_AEU_ENABLE_MCP_PRTY_SUB_BITS }
7424e400768SDavid Christensen };
7434e400768SDavid Christensen
ecore_set_mcp_parity(struct bxe_softc * sc,uint8_t enable)7444e400768SDavid Christensen static inline void ecore_set_mcp_parity(struct bxe_softc *sc, uint8_t enable)
7454e400768SDavid Christensen {
7464e400768SDavid Christensen int i;
7474e400768SDavid Christensen uint32_t reg_val;
7484e400768SDavid Christensen
7494e400768SDavid Christensen for (i = 0; i < ARRSIZE(mcp_attn_ctl_regs); i++) {
7505e33becaSEric Davis reg_val = REG_RD(sc, mcp_attn_ctl_regs[i].addr);
7514e400768SDavid Christensen
75229e60198SDavid C Somayajulu if (enable)
7534ef8ebfdSDavid C Somayajulu reg_val |= MISC_AEU_ENABLE_MCP_PRTY_BITS; /* Linux is using mcp_attn_ctl_regs[i].bits */
75429e60198SDavid C Somayajulu else
7554ef8ebfdSDavid C Somayajulu reg_val &= ~MISC_AEU_ENABLE_MCP_PRTY_BITS; /* Linux is using mcp_attn_ctl_regs[i].bits */
7564e400768SDavid Christensen
7575e33becaSEric Davis REG_WR(sc, mcp_attn_ctl_regs[i].addr, reg_val);
7584e400768SDavid Christensen }
7594e400768SDavid Christensen }
7604e400768SDavid Christensen
ecore_parity_reg_mask(struct bxe_softc * sc,int idx)7614e400768SDavid Christensen static inline uint32_t ecore_parity_reg_mask(struct bxe_softc *sc, int idx)
7624e400768SDavid Christensen {
7634e400768SDavid Christensen if (CHIP_IS_E1(sc))
7644e400768SDavid Christensen return ecore_blocks_parity_data[idx].reg_mask.e1;
7654e400768SDavid Christensen else if (CHIP_IS_E1H(sc))
7664e400768SDavid Christensen return ecore_blocks_parity_data[idx].reg_mask.e1h;
7674e400768SDavid Christensen else if (CHIP_IS_E2(sc))
7684e400768SDavid Christensen return ecore_blocks_parity_data[idx].reg_mask.e2;
7694e400768SDavid Christensen else /* CHIP_IS_E3 */
7704e400768SDavid Christensen return ecore_blocks_parity_data[idx].reg_mask.e3;
7714e400768SDavid Christensen }
7724e400768SDavid Christensen
ecore_disable_blocks_parity(struct bxe_softc * sc)7734e400768SDavid Christensen static inline void ecore_disable_blocks_parity(struct bxe_softc *sc)
7744e400768SDavid Christensen {
7754e400768SDavid Christensen int i;
7764e400768SDavid Christensen
7774e400768SDavid Christensen for (i = 0; i < ARRSIZE(ecore_blocks_parity_data); i++) {
7784e400768SDavid Christensen uint32_t dis_mask = ecore_parity_reg_mask(sc, i);
7794e400768SDavid Christensen
7804e400768SDavid Christensen if (dis_mask) {
7814e400768SDavid Christensen REG_WR(sc, ecore_blocks_parity_data[i].mask_addr,
7824e400768SDavid Christensen dis_mask);
7834e400768SDavid Christensen ECORE_MSG(sc, "Setting parity mask "
7844e400768SDavid Christensen "for %s to\t\t0x%x\n",
7854e400768SDavid Christensen ecore_blocks_parity_data[i].name, dis_mask);
7864e400768SDavid Christensen }
7874e400768SDavid Christensen }
7884e400768SDavid Christensen
7894e400768SDavid Christensen /* Disable MCP parity attentions */
7904e400768SDavid Christensen ecore_set_mcp_parity(sc, FALSE);
7914e400768SDavid Christensen }
7924e400768SDavid Christensen
7934e400768SDavid Christensen /**
7944e400768SDavid Christensen * Clear the parity error status registers.
7954e400768SDavid Christensen */
ecore_clear_blocks_parity(struct bxe_softc * sc)7964e400768SDavid Christensen static inline void ecore_clear_blocks_parity(struct bxe_softc *sc)
7974e400768SDavid Christensen {
7984e400768SDavid Christensen int i;
7994e400768SDavid Christensen uint32_t reg_val, mcp_aeu_bits =
8004e400768SDavid Christensen AEU_INPUTS_ATTN_BITS_MCP_LATCHED_ROM_PARITY |
8014e400768SDavid Christensen AEU_INPUTS_ATTN_BITS_MCP_LATCHED_SCPAD_PARITY |
8024e400768SDavid Christensen AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_RX_PARITY |
8034e400768SDavid Christensen AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_TX_PARITY;
8044e400768SDavid Christensen
8054e400768SDavid Christensen /* Clear SEM_FAST parities */
8064e400768SDavid Christensen REG_WR(sc, XSEM_REG_FAST_MEMORY + SEM_FAST_REG_PARITY_RST, 0x1);
8074e400768SDavid Christensen REG_WR(sc, TSEM_REG_FAST_MEMORY + SEM_FAST_REG_PARITY_RST, 0x1);
8084e400768SDavid Christensen REG_WR(sc, USEM_REG_FAST_MEMORY + SEM_FAST_REG_PARITY_RST, 0x1);
8094e400768SDavid Christensen REG_WR(sc, CSEM_REG_FAST_MEMORY + SEM_FAST_REG_PARITY_RST, 0x1);
8104e400768SDavid Christensen
8114e400768SDavid Christensen for (i = 0; i < ARRSIZE(ecore_blocks_parity_data); i++) {
8124e400768SDavid Christensen uint32_t reg_mask = ecore_parity_reg_mask(sc, i);
8134e400768SDavid Christensen
8144e400768SDavid Christensen if (reg_mask) {
8154e400768SDavid Christensen reg_val = REG_RD(sc, ecore_blocks_parity_data[i].
8164e400768SDavid Christensen sts_clr_addr);
8174e400768SDavid Christensen if (reg_val & reg_mask)
8184e400768SDavid Christensen ECORE_MSG(sc,
8194e400768SDavid Christensen "Parity errors in %s: 0x%x\n",
8204e400768SDavid Christensen ecore_blocks_parity_data[i].name,
8214e400768SDavid Christensen reg_val & reg_mask);
8224e400768SDavid Christensen }
8234e400768SDavid Christensen }
8244e400768SDavid Christensen
8254e400768SDavid Christensen /* Check if there were parity attentions in MCP */
8264e400768SDavid Christensen reg_val = REG_RD(sc, MISC_REG_AEU_AFTER_INVERT_4_MCP);
8274e400768SDavid Christensen if (reg_val & mcp_aeu_bits)
8284e400768SDavid Christensen ECORE_MSG(sc, "Parity error in MCP: 0x%x\n",
8294e400768SDavid Christensen reg_val & mcp_aeu_bits);
8304e400768SDavid Christensen
8314e400768SDavid Christensen /* Clear parity attentions in MCP:
8324e400768SDavid Christensen * [7] clears Latched rom_parity
8334e400768SDavid Christensen * [8] clears Latched ump_rx_parity
8344e400768SDavid Christensen * [9] clears Latched ump_tx_parity
8354e400768SDavid Christensen * [10] clears Latched scpad_parity (both ports)
8364e400768SDavid Christensen */
8374e400768SDavid Christensen REG_WR(sc, MISC_REG_AEU_CLR_LATCH_SIGNAL, 0x780);
8384e400768SDavid Christensen }
8394e400768SDavid Christensen
ecore_enable_blocks_parity(struct bxe_softc * sc)8404e400768SDavid Christensen static inline void ecore_enable_blocks_parity(struct bxe_softc *sc)
8414e400768SDavid Christensen {
8424e400768SDavid Christensen int i;
8434e400768SDavid Christensen
8444e400768SDavid Christensen for (i = 0; i < ARRSIZE(ecore_blocks_parity_data); i++) {
8454e400768SDavid Christensen uint32_t reg_mask = ecore_parity_reg_mask(sc, i);
8464e400768SDavid Christensen
8474e400768SDavid Christensen if (reg_mask)
8484e400768SDavid Christensen REG_WR(sc, ecore_blocks_parity_data[i].mask_addr,
8494e400768SDavid Christensen ecore_blocks_parity_data[i].en_mask & reg_mask);
8504e400768SDavid Christensen }
8514e400768SDavid Christensen
8524e400768SDavid Christensen /* Enable MCP parity attentions */
8534e400768SDavid Christensen ecore_set_mcp_parity(sc, TRUE);
8544e400768SDavid Christensen }
8554e400768SDavid Christensen
8564e400768SDavid Christensen
8574e400768SDavid Christensen #endif /* ECORE_INIT_H */
8584e400768SDavid Christensen
859