/* bnx2x_init_ops.h: Qlogic Everest network driver. * Static functions needed during the initialization. * This file is "included" in bnx2x_main.c. * * Copyright (c) 2007-2013 Broadcom Corporation * Copyright (c) 2014 QLogic Corporation All rights reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation. * * Maintained by: Ariel Elior <ariel.elior@qlogic.com> * Written by: Vladislav Zolotarov
*/
#ifndef BNX2X_INIT_OPS_H #define BNX2X_INIT_OPS_H
#ifndef BP_ILT #define BP_ILT(bp) NULL #endif
#ifndef BP_FUNC #define BP_FUNC(bp) 0 #endif
#ifndef BP_PORT #define BP_PORT(bp) 0 #endif
#ifndef BNX2X_ILT_FREE #define BNX2X_ILT_FREE(x, y, sz) #endif
#ifndef BNX2X_ILT_ZALLOC #define BNX2X_ILT_ZALLOC(x, y, sz) #endif
/********************************************************* There are different blobs for each PRAM section. In addition, each blob write operation is divided into a few operations in order to decrease the amount of phys. contiguous buffer needed. Thus, when we select a blob the address may be with some offset from the beginning of PRAM section. The same holds for the INT_TABLE sections.
**********************************************************/ #define IF_IS_INT_TABLE_ADDR(base, addr) \ if (((base) <= (addr)) && ((base) + 0x400 >= (addr)))
data = bnx2x_sel_blob(bp, addr, data) + blob_off*4;
rc = bnx2x_gunzip(bp, data, len); if (rc) return;
/* gunzip_outlen is in dwords */
len = GUNZIP_OUTLEN(bp); for (i = 0; i < len; i++)
((u32 *)GUNZIP_BUF(bp))[i] = (__force u32)
cpu_to_le32(((u32 *)GUNZIP_BUF(bp))[i]);
/* If empty block */ if (op_start == op_end) return;
data_base = INIT_DATA(bp);
for (op_idx = op_start; op_idx < op_end; op_idx++) {
op = (constunion init_op *)&(INIT_OPS(bp)[op_idx]); /* Get generic data */
op_type = op->raw.op;
addr = op->raw.offset; /* Get data that's used for OP_SW, OP_WB, OP_FW, OP_ZP and * OP_WR64 (we assume that op_arr_write and op_write have the * same structure).
*/
len = op->arr_wr.data_len;
data = data_base + op->arr_wr.data_off;
switch (op_type) { case OP_RD:
REG_RD(bp, addr); break; case OP_WR:
REG_WR(bp, addr, op->write.val); break; case OP_SW:
bnx2x_init_str_wr(bp, addr, data, len); break; case OP_WB:
bnx2x_init_wr_wb(bp, addr, data, len); break; case OP_ZR:
bnx2x_init_fill(bp, addr, 0, op->zero.len, 0); break; case OP_WB_ZR:
bnx2x_init_fill(bp, addr, 0, op->zero.len, 1); break; case OP_ZP:
bnx2x_init_wr_zp(bp, addr, len,
op->arr_wr.data_off); break; case OP_WR_64:
bnx2x_init_wr_64(bp, addr, data, len); break; case OP_IF_MODE_AND: /* if any of the flags doesn't match, skip the * conditional block.
*/ if ((INIT_MODE_FLAGS(bp) &
op->if_mode.mode_bit_map) !=
op->if_mode.mode_bit_map)
op_idx += op->if_mode.cmd_offset; break; case OP_IF_MODE_OR: /* if all the flags don't match, skip the conditional * block.
*/ if ((INIT_MODE_FLAGS(bp) &
op->if_mode.mode_bit_map) == 0)
op_idx += op->if_mode.cmd_offset; break; default: /* Should never get here! */
break;
}
}
}
/**************************************************************************** * PXP Arbiter
****************************************************************************/ /* * This code configures the PCI read/write arbiter * which implements a weighted round robin * between the virtual queues in the chip. * * The values were derived for each PCI max payload and max request size. * since max payload and max request size are only known at run time, * this is done as a separate init stage.
*/
staticvoid bnx2x_init_pxp_arb(struct bnx2x *bp, int r_order, int w_order)
{
u32 val, i;
if (r_order > MAX_RD_ORD) {
DP(NETIF_MSG_HW, "read order of %d order adjusted to %d\n",
r_order, MAX_RD_ORD);
r_order = MAX_RD_ORD;
} if (w_order > MAX_WR_ORD) {
DP(NETIF_MSG_HW, "write order of %d order adjusted to %d\n",
w_order, MAX_WR_ORD);
w_order = MAX_WR_ORD;
} if (CHIP_REV_IS_FPGA(bp)) {
DP(NETIF_MSG_HW, "write order adjusted to 1 for FPGA\n");
w_order = 0;
}
DP(NETIF_MSG_HW, "read order %d write order %d\n", r_order, w_order);
for (i = 0; i < NUM_RD_Q-1; i++) {
REG_WR(bp, read_arb_addr[i].l, read_arb_data[i][r_order].l);
REG_WR(bp, read_arb_addr[i].add,
read_arb_data[i][r_order].add);
REG_WR(bp, read_arb_addr[i].ubound,
read_arb_data[i][r_order].ubound);
}
for (i = 0; i < NUM_WR_Q-1; i++) { if ((write_arb_addr[i].l == PXP2_REG_RQ_BW_WR_L29) ||
(write_arb_addr[i].l == PXP2_REG_RQ_BW_WR_L30)) {
/* Validate number of tags suppoted by device */ #define PCIE_REG_PCIER_TL_HDR_FC_ST 0x2980
val = REG_RD(bp, PCIE_REG_PCIER_TL_HDR_FC_ST);
val &= 0xFF; if (val <= 0x20)
REG_WR(bp, PXP2_REG_PGL_TAGS_LIMIT, 0x20);
}
/**************************************************************************** * ILT management
****************************************************************************/ /* * This codes hides the low level HW interaction for ILT management and * configuration. The API consists of a shadow ILT table which is set by the * driver and a set of routines to use it to configure the HW. *
*/
/* the phys address is shifted right 12 bits and has an added * 1=valid bit added to the 53rd bit * then since this is a wide register(TM) * we split it into two 32 bit writes
*/ #define ILT_ADDR1(x) ((u32)(((u64)x >> 12) & 0xFFFFFFFF)) #define ILT_ADDR2(x) ((u32)((1 << 20) | ((u64)x >> 44))) #define ILT_RANGE(f, l) (((l) << 10) | f)
staticvoid bnx2x_ilt_line_init_op(struct bnx2x *bp, struct bnx2x_ilt *ilt, int idx, u8 initop)
{
dma_addr_t null_mapping; int abs_idx = ilt->start_line + idx;
switch (initop) { case INITOP_INIT: /* set in the init-value array */ case INITOP_SET:
bnx2x_ilt_line_wr(bp, abs_idx, ilt->lines[idx].page_mapping); break; case INITOP_CLEAR:
null_mapping = 0;
bnx2x_ilt_line_wr(bp, abs_idx, null_mapping); break;
}
}
if (ilt_cli->flags & ILT_CLIENT_SKIP_INIT) return;
switch (initop) { case INITOP_INIT: /* set in the init-value array */ case INITOP_SET:
REG_WR(bp, psz_reg, ILOG2(ilt_cli->page_size >> 12)); break; case INITOP_CLEAR: break;
}
}
/* * called during init common stage, ilt clients should be initialized * prioir to calling this function
*/ staticvoid bnx2x_ilt_init_page_size(struct bnx2x *bp, u8 initop)
{
bnx2x_ilt_init_client_psz(bp, ILT_CLIENT_CDU,
PXP2_REG_RQ_CDU_P_SIZE, initop);
bnx2x_ilt_init_client_psz(bp, ILT_CLIENT_QM,
PXP2_REG_RQ_QM_P_SIZE, initop);
bnx2x_ilt_init_client_psz(bp, ILT_CLIENT_SRC,
PXP2_REG_RQ_SRC_P_SIZE, initop);
bnx2x_ilt_init_client_psz(bp, ILT_CLIENT_TM,
PXP2_REG_RQ_TM_P_SIZE, initop);
}
/**************************************************************************** * QM initializations
****************************************************************************/ #define QM_QUEUES_PER_FUNC 16 /* E1 has 32, but only 16 are used */ #define QM_INIT_MIN_CID_COUNT 31 #define QM_INIT(cid_cnt) (cid_cnt > QM_INIT_MIN_CID_COUNT)
/* called during init port stage */ staticvoid bnx2x_qm_init_cid_count(struct bnx2x *bp, int qm_cid_count,
u8 initop)
{ int port = BP_PORT(bp);
if (QM_INIT(qm_cid_count)) { switch (initop) { case INITOP_INIT: /* set in the init-value array */ case INITOP_SET:
REG_WR(bp, QM_REG_CONNNUM_0 + port*4,
qm_cid_count/16 - 1); break; case INITOP_CLEAR: break;
}
}
}
staticvoid bnx2x_qm_set_ptr_table(struct bnx2x *bp, int qm_cid_count,
u32 base_reg, u32 reg)
{ int i;
u32 wb_data[2] = {0, 0}; for (i = 0; i < 4 * QM_QUEUES_PER_FUNC; i++) {
REG_WR(bp, base_reg + i*4,
qm_cid_count * 4 * (i % QM_QUEUES_PER_FUNC));
bnx2x_init_wr_wb(bp, reg + i*8, wb_data, 2);
}
}
/* called during init common stage */ staticvoid bnx2x_qm_init_ptr_table(struct bnx2x *bp, int qm_cid_count,
u8 initop)
{ if (!QM_INIT(qm_cid_count)) return;
switch (initop) { case INITOP_INIT: /* set in the init-value array */ case INITOP_SET:
bnx2x_qm_set_ptr_table(bp, qm_cid_count,
QM_REG_BASEADDR, QM_REG_PTRTBL); if (CHIP_IS_E1H(bp))
bnx2x_qm_set_ptr_table(bp, qm_cid_count,
QM_REG_BASEADDR_EXT_A,
QM_REG_PTRTBL_EXT_A); break; case INITOP_CLEAR: break;
}
}
/**************************************************************************** * SRC initializations
****************************************************************************/ /* called during init func stage */ staticvoid bnx2x_src_init_t2(struct bnx2x *bp, struct src_ent *t2,
dma_addr_t t2_mapping, int src_cid_count)
{ int i; int port = BP_PORT(bp);
/* Initialize T2 */ for (i = 0; i < src_cid_count-1; i++)
t2[i].next = (u64)(t2_mapping +
(i+1)*sizeof(struct src_ent));
/* tell the searcher where the T2 table is */
REG_WR(bp, SRC_REG_COUNTFREE0 + port*4, src_cid_count);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.