brintos

brintos / linux-shallow public Read only

0
0
Text · 26.8 KiB · fc7fce6 Raw
939 lines · c
1/* bnx2x_init_ops.h: Qlogic Everest network driver.2 *               Static functions needed during the initialization.3 *               This file is "included" in bnx2x_main.c.4 *5 * Copyright (c) 2007-2013 Broadcom Corporation6 * Copyright (c) 2014 QLogic Corporation7 All rights reserved8 *9 * This program is free software; you can redistribute it and/or modify10 * it under the terms of the GNU General Public License as published by11 * the Free Software Foundation.12 *13 * Maintained by: Ariel Elior <ariel.elior@qlogic.com>14 * Written by: Vladislav Zolotarov15 */16 17#ifndef BNX2X_INIT_OPS_H18#define BNX2X_INIT_OPS_H19 20 21#ifndef BP_ILT22#define BP_ILT(bp)	NULL23#endif24 25#ifndef BP_FUNC26#define BP_FUNC(bp)	027#endif28 29#ifndef BP_PORT30#define BP_PORT(bp)	031#endif32 33#ifndef BNX2X_ILT_FREE34#define BNX2X_ILT_FREE(x, y, sz)35#endif36 37#ifndef BNX2X_ILT_ZALLOC38#define BNX2X_ILT_ZALLOC(x, y, sz)39#endif40 41#ifndef ILOG242#define ILOG2(x)	x43#endif44 45static int bnx2x_gunzip(struct bnx2x *bp, const u8 *zbuf, int len);46static void bnx2x_reg_wr_ind(struct bnx2x *bp, u32 addr, u32 val);47static void bnx2x_write_dmae_phys_len(struct bnx2x *bp,48				      dma_addr_t phys_addr, u32 addr,49				      u32 len);50 51static void bnx2x_init_str_wr(struct bnx2x *bp, u32 addr,52			      const u32 *data, u32 len)53{54	u32 i;55 56	for (i = 0; i < len; i++)57		REG_WR(bp, addr + i*4, data[i]);58}59 60static void bnx2x_init_ind_wr(struct bnx2x *bp, u32 addr,61			      const u32 *data, u32 len)62{63	u32 i;64 65	for (i = 0; i < len; i++)66		bnx2x_reg_wr_ind(bp, addr + i*4, data[i]);67}68 69static void bnx2x_write_big_buf(struct bnx2x *bp, u32 addr, u32 len,70				u8 wb)71{72	if (bp->dmae_ready)73		bnx2x_write_dmae_phys_len(bp, GUNZIP_PHYS(bp), addr, len);74 75	/* in E1 chips BIOS initiated ZLR may interrupt widebus writes */76	else if (wb && CHIP_IS_E1(bp))77		bnx2x_init_ind_wr(bp, addr, GUNZIP_BUF(bp), len);78 79	/* in later chips PXP root complex handles BIOS ZLR w/o interrupting */80	else81		bnx2x_init_str_wr(bp, addr, GUNZIP_BUF(bp), len);82}83 84static void bnx2x_init_fill(struct bnx2x *bp, u32 addr, int fill,85			    u32 len, u8 wb)86{87	u32 buf_len = (((len*4) > FW_BUF_SIZE) ? FW_BUF_SIZE : (len*4));88	u32 buf_len32 = buf_len/4;89	u32 i;90 91	memset(GUNZIP_BUF(bp), (u8)fill, buf_len);92 93	for (i = 0; i < len; i += buf_len32) {94		u32 cur_len = min(buf_len32, len - i);95 96		bnx2x_write_big_buf(bp, addr + i*4, cur_len, wb);97	}98}99 100static void bnx2x_write_big_buf_wb(struct bnx2x *bp, u32 addr, u32 len)101{102	if (bp->dmae_ready)103		bnx2x_write_dmae_phys_len(bp, GUNZIP_PHYS(bp), addr, len);104 105	/* in E1 chips BIOS initiated ZLR may interrupt widebus writes */106	else if (CHIP_IS_E1(bp))107		bnx2x_init_ind_wr(bp, addr, GUNZIP_BUF(bp), len);108 109	/* in later chips PXP root complex handles BIOS ZLR w/o interrupting */110	else111		bnx2x_init_str_wr(bp, addr, GUNZIP_BUF(bp), len);112}113 114static void bnx2x_init_wr_64(struct bnx2x *bp, u32 addr,115			     const u32 *data, u32 len64)116{117	u32 buf_len32 = FW_BUF_SIZE/4;118	u32 len = len64*2;119	u64 data64 = 0;120	u32 i;121 122	/* 64 bit value is in a blob: first low DWORD, then high DWORD */123	data64 = HILO_U64((*(data + 1)), (*data));124 125	len64 = min((u32)(FW_BUF_SIZE/8), len64);126	for (i = 0; i < len64; i++) {127		u64 *pdata = ((u64 *)(GUNZIP_BUF(bp))) + i;128 129		*pdata = data64;130	}131 132	for (i = 0; i < len; i += buf_len32) {133		u32 cur_len = min(buf_len32, len - i);134 135		bnx2x_write_big_buf_wb(bp, addr + i*4, cur_len);136	}137}138 139/*********************************************************140   There are different blobs for each PRAM section.141   In addition, each blob write operation is divided into a few operations142   in order to decrease the amount of phys. contiguous buffer needed.143   Thus, when we select a blob the address may be with some offset144   from the beginning of PRAM section.145   The same holds for the INT_TABLE sections.146**********************************************************/147#define IF_IS_INT_TABLE_ADDR(base, addr) \148			if (((base) <= (addr)) && ((base) + 0x400 >= (addr)))149 150#define IF_IS_PRAM_ADDR(base, addr) \151			if (((base) <= (addr)) && ((base) + 0x40000 >= (addr)))152 153static const u8 *bnx2x_sel_blob(struct bnx2x *bp, u32 addr,154				const u8 *data)155{156	IF_IS_INT_TABLE_ADDR(TSEM_REG_INT_TABLE, addr)157		data = INIT_TSEM_INT_TABLE_DATA(bp);158	else159		IF_IS_INT_TABLE_ADDR(CSEM_REG_INT_TABLE, addr)160			data = INIT_CSEM_INT_TABLE_DATA(bp);161	else162		IF_IS_INT_TABLE_ADDR(USEM_REG_INT_TABLE, addr)163			data = INIT_USEM_INT_TABLE_DATA(bp);164	else165		IF_IS_INT_TABLE_ADDR(XSEM_REG_INT_TABLE, addr)166			data = INIT_XSEM_INT_TABLE_DATA(bp);167	else168		IF_IS_PRAM_ADDR(TSEM_REG_PRAM, addr)169			data = INIT_TSEM_PRAM_DATA(bp);170	else171		IF_IS_PRAM_ADDR(CSEM_REG_PRAM, addr)172			data = INIT_CSEM_PRAM_DATA(bp);173	else174		IF_IS_PRAM_ADDR(USEM_REG_PRAM, addr)175			data = INIT_USEM_PRAM_DATA(bp);176	else177		IF_IS_PRAM_ADDR(XSEM_REG_PRAM, addr)178			data = INIT_XSEM_PRAM_DATA(bp);179 180	return data;181}182 183static void bnx2x_init_wr_wb(struct bnx2x *bp, u32 addr,184			     const u32 *data, u32 len)185{186	if (bp->dmae_ready)187		VIRT_WR_DMAE_LEN(bp, data, addr, len, 0);188 189	/* in E1 chips BIOS initiated ZLR may interrupt widebus writes */190	else if (CHIP_IS_E1(bp))191		bnx2x_init_ind_wr(bp, addr, data, len);192 193	/* in later chips PXP root complex handles BIOS ZLR w/o interrupting */194	else195		bnx2x_init_str_wr(bp, addr, data, len);196}197 198static void bnx2x_wr_64(struct bnx2x *bp, u32 reg, u32 val_lo,199			u32 val_hi)200{201	u32 wb_write[2];202 203	wb_write[0] = val_lo;204	wb_write[1] = val_hi;205	REG_WR_DMAE_LEN(bp, reg, wb_write, 2);206}207static void bnx2x_init_wr_zp(struct bnx2x *bp, u32 addr, u32 len,208			     u32 blob_off)209{210	const u8 *data = NULL;211	int rc;212	u32 i;213 214	data = bnx2x_sel_blob(bp, addr, data) + blob_off*4;215 216	rc = bnx2x_gunzip(bp, data, len);217	if (rc)218		return;219 220	/* gunzip_outlen is in dwords */221	len = GUNZIP_OUTLEN(bp);222	for (i = 0; i < len; i++)223		((u32 *)GUNZIP_BUF(bp))[i] = (__force u32)224				cpu_to_le32(((u32 *)GUNZIP_BUF(bp))[i]);225 226	bnx2x_write_big_buf_wb(bp, addr, len);227}228 229static void bnx2x_init_block(struct bnx2x *bp, u32 block, u32 stage)230{231	u16 op_start =232		INIT_OPS_OFFSETS(bp)[BLOCK_OPS_IDX(block, stage,233						     STAGE_START)];234	u16 op_end =235		INIT_OPS_OFFSETS(bp)[BLOCK_OPS_IDX(block, stage,236						     STAGE_END)];237	const union init_op *op;238	u32 op_idx, op_type, addr, len;239	const u32 *data, *data_base;240 241	/* If empty block */242	if (op_start == op_end)243		return;244 245	data_base = INIT_DATA(bp);246 247	for (op_idx = op_start; op_idx < op_end; op_idx++) {248 249		op = (const union init_op *)&(INIT_OPS(bp)[op_idx]);250		/* Get generic data */251		op_type = op->raw.op;252		addr = op->raw.offset;253		/* Get data that's used for OP_SW, OP_WB, OP_FW, OP_ZP and254		 * OP_WR64 (we assume that op_arr_write and op_write have the255		 * same structure).256		 */257		len = op->arr_wr.data_len;258		data = data_base + op->arr_wr.data_off;259 260		switch (op_type) {261		case OP_RD:262			REG_RD(bp, addr);263			break;264		case OP_WR:265			REG_WR(bp, addr, op->write.val);266			break;267		case OP_SW:268			bnx2x_init_str_wr(bp, addr, data, len);269			break;270		case OP_WB:271			bnx2x_init_wr_wb(bp, addr, data, len);272			break;273		case OP_ZR:274			bnx2x_init_fill(bp, addr, 0, op->zero.len, 0);275			break;276		case OP_WB_ZR:277			bnx2x_init_fill(bp, addr, 0, op->zero.len, 1);278			break;279		case OP_ZP:280			bnx2x_init_wr_zp(bp, addr, len,281					 op->arr_wr.data_off);282			break;283		case OP_WR_64:284			bnx2x_init_wr_64(bp, addr, data, len);285			break;286		case OP_IF_MODE_AND:287			/* if any of the flags doesn't match, skip the288			 * conditional block.289			 */290			if ((INIT_MODE_FLAGS(bp) &291				op->if_mode.mode_bit_map) !=292				op->if_mode.mode_bit_map)293				op_idx += op->if_mode.cmd_offset;294			break;295		case OP_IF_MODE_OR:296			/* if all the flags don't match, skip the conditional297			 * block.298			 */299			if ((INIT_MODE_FLAGS(bp) &300				op->if_mode.mode_bit_map) == 0)301				op_idx += op->if_mode.cmd_offset;302			break;303		default:304			/* Should never get here! */305 306			break;307		}308	}309}310 311 312/****************************************************************************313* PXP Arbiter314****************************************************************************/315/*316 * This code configures the PCI read/write arbiter317 * which implements a weighted round robin318 * between the virtual queues in the chip.319 *320 * The values were derived for each PCI max payload and max request size.321 * since max payload and max request size are only known at run time,322 * this is done as a separate init stage.323 */324 325#define NUM_WR_Q			13326#define NUM_RD_Q			29327#define MAX_RD_ORD			3328#define MAX_WR_ORD			2329 330/* configuration for one arbiter queue */331struct arb_line {332	int l;333	int add;334	int ubound;335};336 337/* derived configuration for each read queue for each max request size */338static const struct arb_line read_arb_data[NUM_RD_Q][MAX_RD_ORD + 1] = {339/* 1 */	{ {8, 64, 25}, {16, 64, 25}, {32, 64, 25}, {64, 64, 41} },340	{ {4, 8,  4},  {4,  8,  4},  {4,  8,  4},  {4,  8,  4}  },341	{ {4, 3,  3},  {4,  3,  3},  {4,  3,  3},  {4,  3,  3}  },342	{ {8, 3,  6},  {16, 3,  11}, {16, 3,  11}, {16, 3,  11} },343	{ {8, 64, 25}, {16, 64, 25}, {32, 64, 25}, {64, 64, 41} },344	{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {64, 3,  41} },345	{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {64, 3,  41} },346	{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {64, 3,  41} },347	{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {64, 3,  41} },348/* 10 */{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {32, 3,  21} },349	{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {32, 3,  21} },350	{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {32, 3,  21} },351	{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {32, 3,  21} },352	{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {32, 3,  21} },353	{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {32, 3,  21} },354	{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {32, 3,  21} },355	{ {8, 64, 6},  {16, 64, 11}, {32, 64, 21}, {32, 64, 21} },356	{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {32, 3,  21} },357	{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {32, 3,  21} },358/* 20 */{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {32, 3,  21} },359	{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {32, 3,  21} },360	{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {32, 3,  21} },361	{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {32, 3,  21} },362	{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {32, 3,  21} },363	{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {32, 3,  21} },364	{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {32, 3,  21} },365	{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {32, 3,  21} },366	{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {32, 3,  21} },367	{ {8, 64, 25}, {16, 64, 41}, {32, 64, 81}, {64, 64, 120} }368};369 370/* derived configuration for each write queue for each max request size */371static const struct arb_line write_arb_data[NUM_WR_Q][MAX_WR_ORD + 1] = {372/* 1 */	{ {4, 6,  3},  {4,  6,  3},  {4,  6,  3} },373	{ {4, 2,  3},  {4,  2,  3},  {4,  2,  3} },374	{ {8, 2,  6},  {16, 2,  11}, {16, 2,  11} },375	{ {8, 2,  6},  {16, 2,  11}, {32, 2,  21} },376	{ {8, 2,  6},  {16, 2,  11}, {32, 2,  21} },377	{ {8, 2,  6},  {16, 2,  11}, {32, 2,  21} },378	{ {8, 64, 25}, {16, 64, 25}, {32, 64, 25} },379	{ {8, 2,  6},  {16, 2,  11}, {16, 2,  11} },380	{ {8, 2,  6},  {16, 2,  11}, {16, 2,  11} },381/* 10 */{ {8, 9,  6},  {16, 9,  11}, {32, 9,  21} },382	{ {8, 47, 19}, {16, 47, 19}, {32, 47, 21} },383	{ {8, 9,  6},  {16, 9,  11}, {16, 9,  11} },384	{ {8, 64, 25}, {16, 64, 41}, {32, 64, 81} }385};386 387/* register addresses for read queues */388static const struct arb_line read_arb_addr[NUM_RD_Q-1] = {389/* 1 */	{PXP2_REG_RQ_BW_RD_L0, PXP2_REG_RQ_BW_RD_ADD0,390		PXP2_REG_RQ_BW_RD_UBOUND0},391	{PXP2_REG_PSWRQ_BW_L1, PXP2_REG_PSWRQ_BW_ADD1,392		PXP2_REG_PSWRQ_BW_UB1},393	{PXP2_REG_PSWRQ_BW_L2, PXP2_REG_PSWRQ_BW_ADD2,394		PXP2_REG_PSWRQ_BW_UB2},395	{PXP2_REG_PSWRQ_BW_L3, PXP2_REG_PSWRQ_BW_ADD3,396		PXP2_REG_PSWRQ_BW_UB3},397	{PXP2_REG_RQ_BW_RD_L4, PXP2_REG_RQ_BW_RD_ADD4,398		PXP2_REG_RQ_BW_RD_UBOUND4},399	{PXP2_REG_RQ_BW_RD_L5, PXP2_REG_RQ_BW_RD_ADD5,400		PXP2_REG_RQ_BW_RD_UBOUND5},401	{PXP2_REG_PSWRQ_BW_L6, PXP2_REG_PSWRQ_BW_ADD6,402		PXP2_REG_PSWRQ_BW_UB6},403	{PXP2_REG_PSWRQ_BW_L7, PXP2_REG_PSWRQ_BW_ADD7,404		PXP2_REG_PSWRQ_BW_UB7},405	{PXP2_REG_PSWRQ_BW_L8, PXP2_REG_PSWRQ_BW_ADD8,406		PXP2_REG_PSWRQ_BW_UB8},407/* 10 */{PXP2_REG_PSWRQ_BW_L9, PXP2_REG_PSWRQ_BW_ADD9,408		PXP2_REG_PSWRQ_BW_UB9},409	{PXP2_REG_PSWRQ_BW_L10, PXP2_REG_PSWRQ_BW_ADD10,410		PXP2_REG_PSWRQ_BW_UB10},411	{PXP2_REG_PSWRQ_BW_L11, PXP2_REG_PSWRQ_BW_ADD11,412		PXP2_REG_PSWRQ_BW_UB11},413	{PXP2_REG_RQ_BW_RD_L12, PXP2_REG_RQ_BW_RD_ADD12,414		PXP2_REG_RQ_BW_RD_UBOUND12},415	{PXP2_REG_RQ_BW_RD_L13, PXP2_REG_RQ_BW_RD_ADD13,416		PXP2_REG_RQ_BW_RD_UBOUND13},417	{PXP2_REG_RQ_BW_RD_L14, PXP2_REG_RQ_BW_RD_ADD14,418		PXP2_REG_RQ_BW_RD_UBOUND14},419	{PXP2_REG_RQ_BW_RD_L15, PXP2_REG_RQ_BW_RD_ADD15,420		PXP2_REG_RQ_BW_RD_UBOUND15},421	{PXP2_REG_RQ_BW_RD_L16, PXP2_REG_RQ_BW_RD_ADD16,422		PXP2_REG_RQ_BW_RD_UBOUND16},423	{PXP2_REG_RQ_BW_RD_L17, PXP2_REG_RQ_BW_RD_ADD17,424		PXP2_REG_RQ_BW_RD_UBOUND17},425	{PXP2_REG_RQ_BW_RD_L18, PXP2_REG_RQ_BW_RD_ADD18,426		PXP2_REG_RQ_BW_RD_UBOUND18},427/* 20 */{PXP2_REG_RQ_BW_RD_L19, PXP2_REG_RQ_BW_RD_ADD19,428		PXP2_REG_RQ_BW_RD_UBOUND19},429	{PXP2_REG_RQ_BW_RD_L20, PXP2_REG_RQ_BW_RD_ADD20,430		PXP2_REG_RQ_BW_RD_UBOUND20},431	{PXP2_REG_RQ_BW_RD_L22, PXP2_REG_RQ_BW_RD_ADD22,432		PXP2_REG_RQ_BW_RD_UBOUND22},433	{PXP2_REG_RQ_BW_RD_L23, PXP2_REG_RQ_BW_RD_ADD23,434		PXP2_REG_RQ_BW_RD_UBOUND23},435	{PXP2_REG_RQ_BW_RD_L24, PXP2_REG_RQ_BW_RD_ADD24,436		PXP2_REG_RQ_BW_RD_UBOUND24},437	{PXP2_REG_RQ_BW_RD_L25, PXP2_REG_RQ_BW_RD_ADD25,438		PXP2_REG_RQ_BW_RD_UBOUND25},439	{PXP2_REG_RQ_BW_RD_L26, PXP2_REG_RQ_BW_RD_ADD26,440		PXP2_REG_RQ_BW_RD_UBOUND26},441	{PXP2_REG_RQ_BW_RD_L27, PXP2_REG_RQ_BW_RD_ADD27,442		PXP2_REG_RQ_BW_RD_UBOUND27},443	{PXP2_REG_PSWRQ_BW_L28, PXP2_REG_PSWRQ_BW_ADD28,444		PXP2_REG_PSWRQ_BW_UB28}445};446 447/* register addresses for write queues */448static const struct arb_line write_arb_addr[NUM_WR_Q-1] = {449/* 1 */	{PXP2_REG_PSWRQ_BW_L1, PXP2_REG_PSWRQ_BW_ADD1,450		PXP2_REG_PSWRQ_BW_UB1},451	{PXP2_REG_PSWRQ_BW_L2, PXP2_REG_PSWRQ_BW_ADD2,452		PXP2_REG_PSWRQ_BW_UB2},453	{PXP2_REG_PSWRQ_BW_L3, PXP2_REG_PSWRQ_BW_ADD3,454		PXP2_REG_PSWRQ_BW_UB3},455	{PXP2_REG_PSWRQ_BW_L6, PXP2_REG_PSWRQ_BW_ADD6,456		PXP2_REG_PSWRQ_BW_UB6},457	{PXP2_REG_PSWRQ_BW_L7, PXP2_REG_PSWRQ_BW_ADD7,458		PXP2_REG_PSWRQ_BW_UB7},459	{PXP2_REG_PSWRQ_BW_L8, PXP2_REG_PSWRQ_BW_ADD8,460		PXP2_REG_PSWRQ_BW_UB8},461	{PXP2_REG_PSWRQ_BW_L9, PXP2_REG_PSWRQ_BW_ADD9,462		PXP2_REG_PSWRQ_BW_UB9},463	{PXP2_REG_PSWRQ_BW_L10, PXP2_REG_PSWRQ_BW_ADD10,464		PXP2_REG_PSWRQ_BW_UB10},465	{PXP2_REG_PSWRQ_BW_L11, PXP2_REG_PSWRQ_BW_ADD11,466		PXP2_REG_PSWRQ_BW_UB11},467/* 10 */{PXP2_REG_PSWRQ_BW_L28, PXP2_REG_PSWRQ_BW_ADD28,468		PXP2_REG_PSWRQ_BW_UB28},469	{PXP2_REG_RQ_BW_WR_L29, PXP2_REG_RQ_BW_WR_ADD29,470		PXP2_REG_RQ_BW_WR_UBOUND29},471	{PXP2_REG_RQ_BW_WR_L30, PXP2_REG_RQ_BW_WR_ADD30,472		PXP2_REG_RQ_BW_WR_UBOUND30}473};474 475static void bnx2x_init_pxp_arb(struct bnx2x *bp, int r_order,476			       int w_order)477{478	u32 val, i;479 480	if (r_order > MAX_RD_ORD) {481		DP(NETIF_MSG_HW, "read order of %d  order adjusted to %d\n",482		   r_order, MAX_RD_ORD);483		r_order = MAX_RD_ORD;484	}485	if (w_order > MAX_WR_ORD) {486		DP(NETIF_MSG_HW, "write order of %d  order adjusted to %d\n",487		   w_order, MAX_WR_ORD);488		w_order = MAX_WR_ORD;489	}490	if (CHIP_REV_IS_FPGA(bp)) {491		DP(NETIF_MSG_HW, "write order adjusted to 1 for FPGA\n");492		w_order = 0;493	}494	DP(NETIF_MSG_HW, "read order %d  write order %d\n", r_order, w_order);495 496	for (i = 0; i < NUM_RD_Q-1; i++) {497		REG_WR(bp, read_arb_addr[i].l, read_arb_data[i][r_order].l);498		REG_WR(bp, read_arb_addr[i].add,499		       read_arb_data[i][r_order].add);500		REG_WR(bp, read_arb_addr[i].ubound,501		       read_arb_data[i][r_order].ubound);502	}503 504	for (i = 0; i < NUM_WR_Q-1; i++) {505		if ((write_arb_addr[i].l == PXP2_REG_RQ_BW_WR_L29) ||506		    (write_arb_addr[i].l == PXP2_REG_RQ_BW_WR_L30)) {507 508			REG_WR(bp, write_arb_addr[i].l,509			       write_arb_data[i][w_order].l);510 511			REG_WR(bp, write_arb_addr[i].add,512			       write_arb_data[i][w_order].add);513 514			REG_WR(bp, write_arb_addr[i].ubound,515			       write_arb_data[i][w_order].ubound);516		} else {517 518			val = REG_RD(bp, write_arb_addr[i].l);519			REG_WR(bp, write_arb_addr[i].l,520			       val | (write_arb_data[i][w_order].l << 10));521 522			val = REG_RD(bp, write_arb_addr[i].add);523			REG_WR(bp, write_arb_addr[i].add,524			       val | (write_arb_data[i][w_order].add << 10));525 526			val = REG_RD(bp, write_arb_addr[i].ubound);527			REG_WR(bp, write_arb_addr[i].ubound,528			       val | (write_arb_data[i][w_order].ubound << 7));529		}530	}531 532	val =  write_arb_data[NUM_WR_Q-1][w_order].add;533	val += write_arb_data[NUM_WR_Q-1][w_order].ubound << 10;534	val += write_arb_data[NUM_WR_Q-1][w_order].l << 17;535	REG_WR(bp, PXP2_REG_PSWRQ_BW_RD, val);536 537	val =  read_arb_data[NUM_RD_Q-1][r_order].add;538	val += read_arb_data[NUM_RD_Q-1][r_order].ubound << 10;539	val += read_arb_data[NUM_RD_Q-1][r_order].l << 17;540	REG_WR(bp, PXP2_REG_PSWRQ_BW_WR, val);541 542	REG_WR(bp, PXP2_REG_RQ_WR_MBS0, w_order);543	REG_WR(bp, PXP2_REG_RQ_WR_MBS1, w_order);544	REG_WR(bp, PXP2_REG_RQ_RD_MBS0, r_order);545	REG_WR(bp, PXP2_REG_RQ_RD_MBS1, r_order);546 547	if ((CHIP_IS_E1(bp) || CHIP_IS_E1H(bp)) && (r_order == MAX_RD_ORD))548		REG_WR(bp, PXP2_REG_RQ_PDR_LIMIT, 0xe00);549 550	if (CHIP_IS_E3(bp))551		REG_WR(bp, PXP2_REG_WR_USDMDP_TH, (0x4 << w_order));552	else if (CHIP_IS_E2(bp))553		REG_WR(bp, PXP2_REG_WR_USDMDP_TH, (0x8 << w_order));554	else555		REG_WR(bp, PXP2_REG_WR_USDMDP_TH, (0x18 << w_order));556 557	if (!CHIP_IS_E1(bp)) {558		/*    MPS      w_order     optimal TH      presently TH559		 *    128         0             0               2560		 *    256         1             1               3561		 *    >=512       2             2               3562		 */563		/* DMAE is special */564		if (!CHIP_IS_E1H(bp)) {565			/* E2 can use optimal TH */566			val = w_order;567			REG_WR(bp, PXP2_REG_WR_DMAE_MPS, val);568		} else {569			val = ((w_order == 0) ? 2 : 3);570			REG_WR(bp, PXP2_REG_WR_DMAE_MPS, 2);571		}572 573		REG_WR(bp, PXP2_REG_WR_HC_MPS, val);574		REG_WR(bp, PXP2_REG_WR_USDM_MPS, val);575		REG_WR(bp, PXP2_REG_WR_CSDM_MPS, val);576		REG_WR(bp, PXP2_REG_WR_TSDM_MPS, val);577		REG_WR(bp, PXP2_REG_WR_XSDM_MPS, val);578		REG_WR(bp, PXP2_REG_WR_QM_MPS, val);579		REG_WR(bp, PXP2_REG_WR_TM_MPS, val);580		REG_WR(bp, PXP2_REG_WR_SRC_MPS, val);581		REG_WR(bp, PXP2_REG_WR_DBG_MPS, val);582		REG_WR(bp, PXP2_REG_WR_CDU_MPS, val);583	}584 585	/* Validate number of tags suppoted by device */586#define PCIE_REG_PCIER_TL_HDR_FC_ST		0x2980587	val = REG_RD(bp, PCIE_REG_PCIER_TL_HDR_FC_ST);588	val &= 0xFF;589	if (val <= 0x20)590		REG_WR(bp, PXP2_REG_PGL_TAGS_LIMIT, 0x20);591}592 593/****************************************************************************594* ILT management595****************************************************************************/596/*597 * This codes hides the low level HW interaction for ILT management and598 * configuration. The API consists of a shadow ILT table which is set by the599 * driver and a set of routines to use it to configure the HW.600 *601 */602 603/* ILT HW init operations */604 605/* ILT memory management operations */606#define ILT_MEMOP_ALLOC		0607#define ILT_MEMOP_FREE		1608 609/* the phys address is shifted right 12 bits and has an added610 * 1=valid bit added to the 53rd bit611 * then since this is a wide register(TM)612 * we split it into two 32 bit writes613 */614#define ILT_ADDR1(x)		((u32)(((u64)x >> 12) & 0xFFFFFFFF))615#define ILT_ADDR2(x)		((u32)((1 << 20) | ((u64)x >> 44)))616#define ILT_RANGE(f, l)		(((l) << 10) | f)617 618static int bnx2x_ilt_line_mem_op(struct bnx2x *bp,619				 struct ilt_line *line, u32 size, u8 memop)620{621	if (memop == ILT_MEMOP_FREE) {622		BNX2X_ILT_FREE(line->page, line->page_mapping, line->size);623		return 0;624	}625	BNX2X_ILT_ZALLOC(line->page, &line->page_mapping, size);626	if (!line->page)627		return -1;628	line->size = size;629	return 0;630}631 632 633static int bnx2x_ilt_client_mem_op(struct bnx2x *bp, int cli_num,634				   u8 memop)635{636	int i, rc;637	struct bnx2x_ilt *ilt = BP_ILT(bp);638	struct ilt_client_info *ilt_cli;639 640	if (!ilt || !ilt->lines)641		return -1;642 643	ilt_cli = &ilt->clients[cli_num];644 645	if (ilt_cli->flags & (ILT_CLIENT_SKIP_INIT | ILT_CLIENT_SKIP_MEM))646		return 0;647 648	for (rc = 0, i = ilt_cli->start; i <= ilt_cli->end && !rc; i++) {649		rc = bnx2x_ilt_line_mem_op(bp, &ilt->lines[i],650					   ilt_cli->page_size, memop);651	}652	return rc;653}654 655static int bnx2x_ilt_mem_op_cnic(struct bnx2x *bp, u8 memop)656{657	int rc = 0;658 659	if (CONFIGURE_NIC_MODE(bp))660		rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_SRC, memop);661	if (!rc)662		rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_TM, memop);663 664	return rc;665}666 667static int bnx2x_ilt_mem_op(struct bnx2x *bp, u8 memop)668{669	int rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_CDU, memop);670	if (!rc)671		rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_QM, memop);672	if (!rc && CNIC_SUPPORT(bp) && !CONFIGURE_NIC_MODE(bp))673		rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_SRC, memop);674 675	return rc;676}677 678static void bnx2x_ilt_line_wr(struct bnx2x *bp, int abs_idx,679			      dma_addr_t page_mapping)680{681	u32 reg;682 683	if (CHIP_IS_E1(bp))684		reg = PXP2_REG_RQ_ONCHIP_AT + abs_idx*8;685	else686		reg = PXP2_REG_RQ_ONCHIP_AT_B0 + abs_idx*8;687 688	bnx2x_wr_64(bp, reg, ILT_ADDR1(page_mapping), ILT_ADDR2(page_mapping));689}690 691static void bnx2x_ilt_line_init_op(struct bnx2x *bp,692				   struct bnx2x_ilt *ilt, int idx, u8 initop)693{694	dma_addr_t	null_mapping;695	int abs_idx = ilt->start_line + idx;696 697 698	switch (initop) {699	case INITOP_INIT:700		/* set in the init-value array */701	case INITOP_SET:702		bnx2x_ilt_line_wr(bp, abs_idx, ilt->lines[idx].page_mapping);703		break;704	case INITOP_CLEAR:705		null_mapping = 0;706		bnx2x_ilt_line_wr(bp, abs_idx, null_mapping);707		break;708	}709}710 711static void bnx2x_ilt_boundry_init_op(struct bnx2x *bp,712				      struct ilt_client_info *ilt_cli,713				      u32 ilt_start, u8 initop)714{715	u32 start_reg = 0;716	u32 end_reg = 0;717 718	/* The boundary is either SET or INIT,719	   CLEAR => SET and for now SET ~~ INIT */720 721	/* find the appropriate regs */722	if (CHIP_IS_E1(bp)) {723		switch (ilt_cli->client_num) {724		case ILT_CLIENT_CDU:725			start_reg = PXP2_REG_PSWRQ_CDU0_L2P;726			break;727		case ILT_CLIENT_QM:728			start_reg = PXP2_REG_PSWRQ_QM0_L2P;729			break;730		case ILT_CLIENT_SRC:731			start_reg = PXP2_REG_PSWRQ_SRC0_L2P;732			break;733		case ILT_CLIENT_TM:734			start_reg = PXP2_REG_PSWRQ_TM0_L2P;735			break;736		}737		REG_WR(bp, start_reg + BP_FUNC(bp)*4,738		       ILT_RANGE((ilt_start + ilt_cli->start),739				 (ilt_start + ilt_cli->end)));740	} else {741		switch (ilt_cli->client_num) {742		case ILT_CLIENT_CDU:743			start_reg = PXP2_REG_RQ_CDU_FIRST_ILT;744			end_reg = PXP2_REG_RQ_CDU_LAST_ILT;745			break;746		case ILT_CLIENT_QM:747			start_reg = PXP2_REG_RQ_QM_FIRST_ILT;748			end_reg = PXP2_REG_RQ_QM_LAST_ILT;749			break;750		case ILT_CLIENT_SRC:751			start_reg = PXP2_REG_RQ_SRC_FIRST_ILT;752			end_reg = PXP2_REG_RQ_SRC_LAST_ILT;753			break;754		case ILT_CLIENT_TM:755			start_reg = PXP2_REG_RQ_TM_FIRST_ILT;756			end_reg = PXP2_REG_RQ_TM_LAST_ILT;757			break;758		}759		REG_WR(bp, start_reg, (ilt_start + ilt_cli->start));760		REG_WR(bp, end_reg, (ilt_start + ilt_cli->end));761	}762}763 764static void bnx2x_ilt_client_init_op_ilt(struct bnx2x *bp,765					 struct bnx2x_ilt *ilt,766					 struct ilt_client_info *ilt_cli,767					 u8 initop)768{769	int i;770 771	if (ilt_cli->flags & ILT_CLIENT_SKIP_INIT)772		return;773 774	for (i = ilt_cli->start; i <= ilt_cli->end; i++)775		bnx2x_ilt_line_init_op(bp, ilt, i, initop);776 777	/* init/clear the ILT boundries */778	bnx2x_ilt_boundry_init_op(bp, ilt_cli, ilt->start_line, initop);779}780 781static void bnx2x_ilt_client_init_op(struct bnx2x *bp,782				     struct ilt_client_info *ilt_cli, u8 initop)783{784	struct bnx2x_ilt *ilt = BP_ILT(bp);785 786	bnx2x_ilt_client_init_op_ilt(bp, ilt, ilt_cli, initop);787}788 789static void bnx2x_ilt_client_id_init_op(struct bnx2x *bp,790					int cli_num, u8 initop)791{792	struct bnx2x_ilt *ilt = BP_ILT(bp);793	struct ilt_client_info *ilt_cli = &ilt->clients[cli_num];794 795	bnx2x_ilt_client_init_op(bp, ilt_cli, initop);796}797 798static void bnx2x_ilt_init_op_cnic(struct bnx2x *bp, u8 initop)799{800	if (CONFIGURE_NIC_MODE(bp))801		bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_SRC, initop);802	bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_TM, initop);803}804 805static void bnx2x_ilt_init_op(struct bnx2x *bp, u8 initop)806{807	bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_CDU, initop);808	bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_QM, initop);809	if (CNIC_SUPPORT(bp) && !CONFIGURE_NIC_MODE(bp))810		bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_SRC, initop);811}812 813static void bnx2x_ilt_init_client_psz(struct bnx2x *bp, int cli_num,814				      u32 psz_reg, u8 initop)815{816	struct bnx2x_ilt *ilt = BP_ILT(bp);817	struct ilt_client_info *ilt_cli = &ilt->clients[cli_num];818 819	if (ilt_cli->flags & ILT_CLIENT_SKIP_INIT)820		return;821 822	switch (initop) {823	case INITOP_INIT:824		/* set in the init-value array */825	case INITOP_SET:826		REG_WR(bp, psz_reg, ILOG2(ilt_cli->page_size >> 12));827		break;828	case INITOP_CLEAR:829		break;830	}831}832 833/*834 * called during init common stage, ilt clients should be initialized835 * prioir to calling this function836 */837static void bnx2x_ilt_init_page_size(struct bnx2x *bp, u8 initop)838{839	bnx2x_ilt_init_client_psz(bp, ILT_CLIENT_CDU,840				  PXP2_REG_RQ_CDU_P_SIZE, initop);841	bnx2x_ilt_init_client_psz(bp, ILT_CLIENT_QM,842				  PXP2_REG_RQ_QM_P_SIZE, initop);843	bnx2x_ilt_init_client_psz(bp, ILT_CLIENT_SRC,844				  PXP2_REG_RQ_SRC_P_SIZE, initop);845	bnx2x_ilt_init_client_psz(bp, ILT_CLIENT_TM,846				  PXP2_REG_RQ_TM_P_SIZE, initop);847}848 849/****************************************************************************850* QM initializations851****************************************************************************/852#define QM_QUEUES_PER_FUNC	16 /* E1 has 32, but only 16 are used */853#define QM_INIT_MIN_CID_COUNT	31854#define QM_INIT(cid_cnt)	(cid_cnt > QM_INIT_MIN_CID_COUNT)855 856/* called during init port stage */857static void bnx2x_qm_init_cid_count(struct bnx2x *bp, int qm_cid_count,858				    u8 initop)859{860	int port = BP_PORT(bp);861 862	if (QM_INIT(qm_cid_count)) {863		switch (initop) {864		case INITOP_INIT:865			/* set in the init-value array */866		case INITOP_SET:867			REG_WR(bp, QM_REG_CONNNUM_0 + port*4,868			       qm_cid_count/16 - 1);869			break;870		case INITOP_CLEAR:871			break;872		}873	}874}875 876static void bnx2x_qm_set_ptr_table(struct bnx2x *bp, int qm_cid_count,877				   u32 base_reg, u32 reg)878{879	int i;880	u32 wb_data[2] = {0, 0};881	for (i = 0; i < 4 * QM_QUEUES_PER_FUNC; i++) {882		REG_WR(bp, base_reg + i*4,883		       qm_cid_count * 4 * (i % QM_QUEUES_PER_FUNC));884		bnx2x_init_wr_wb(bp, reg + i*8,	 wb_data, 2);885	}886}887 888/* called during init common stage */889static void bnx2x_qm_init_ptr_table(struct bnx2x *bp, int qm_cid_count,890				    u8 initop)891{892	if (!QM_INIT(qm_cid_count))893		return;894 895	switch (initop) {896	case INITOP_INIT:897		/* set in the init-value array */898	case INITOP_SET:899		bnx2x_qm_set_ptr_table(bp, qm_cid_count,900				       QM_REG_BASEADDR, QM_REG_PTRTBL);901		if (CHIP_IS_E1H(bp))902			bnx2x_qm_set_ptr_table(bp, qm_cid_count,903					       QM_REG_BASEADDR_EXT_A,904					       QM_REG_PTRTBL_EXT_A);905		break;906	case INITOP_CLEAR:907		break;908	}909}910 911/****************************************************************************912* SRC initializations913****************************************************************************/914/* called during init func stage */915static void bnx2x_src_init_t2(struct bnx2x *bp, struct src_ent *t2,916			      dma_addr_t t2_mapping, int src_cid_count)917{918	int i;919	int port = BP_PORT(bp);920 921	/* Initialize T2 */922	for (i = 0; i < src_cid_count-1; i++)923		t2[i].next = (u64)(t2_mapping +924			     (i+1)*sizeof(struct src_ent));925 926	/* tell the searcher where the T2 table is */927	REG_WR(bp, SRC_REG_COUNTFREE0 + port*4, src_cid_count);928 929	bnx2x_wr_64(bp, SRC_REG_FIRSTFREE0 + port*16,930		    U64_LO(t2_mapping), U64_HI(t2_mapping));931 932	bnx2x_wr_64(bp, SRC_REG_LASTFREE0 + port*16,933		    U64_LO((u64)t2_mapping +934			   (src_cid_count-1) * sizeof(struct src_ent)),935		    U64_HI((u64)t2_mapping +936			   (src_cid_count-1) * sizeof(struct src_ent)));937}938#endif /* BNX2X_INIT_OPS_H */939