brintos

brintos / linux-shallow public Read only

0
0
Text · 114.5 KiB · 47adff9 Raw
4210 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * QLogic iSCSI HBA Driver4 * Copyright (c)  2003-2013 QLogic Corporation5 */6#include <linux/delay.h>7#include <linux/io.h>8#include <linux/pci.h>9#include <linux/ratelimit.h>10#include "ql4_def.h"11#include "ql4_glbl.h"12#include "ql4_inline.h"13 14#include <linux/io-64-nonatomic-lo-hi.h>15 16#define TIMEOUT_100_MS	10017#define MASK(n)		DMA_BIT_MASK(n)18#define MN_WIN(addr)	(((addr & 0x1fc0000) >> 1) | ((addr >> 25) & 0x3ff))19#define OCM_WIN(addr)	(((addr & 0x1ff0000) >> 1) | ((addr >> 25) & 0x3ff))20#define MS_WIN(addr)	(addr & 0x0ffc0000)21#define QLA82XX_PCI_MN_2M	(0)22#define QLA82XX_PCI_MS_2M	(0x80000)23#define QLA82XX_PCI_OCM0_2M	(0xc0000)24#define VALID_OCM_ADDR(addr)	(((addr) & 0x3f800) != 0x3f800)25#define GET_MEM_OFFS_2M(addr)	(addr & MASK(18))26 27/* CRB window related */28#define CRB_BLK(off)	((off >> 20) & 0x3f)29#define CRB_SUBBLK(off)	((off >> 16) & 0xf)30#define CRB_WINDOW_2M	(0x130060)31#define CRB_HI(off)	((qla4_82xx_crb_hub_agt[CRB_BLK(off)] << 20) | \32			((off) & 0xf0000))33#define QLA82XX_PCI_CAMQM_2M_END	(0x04800800UL)34#define QLA82XX_PCI_CAMQM_2M_BASE	(0x000ff800UL)35#define CRB_INDIRECT_2M			(0x1e0000UL)36 37static inline void __iomem *38qla4_8xxx_pci_base_offsetfset(struct scsi_qla_host *ha, unsigned long off)39{40	if ((off < ha->first_page_group_end) &&41	    (off >= ha->first_page_group_start))42		return (void __iomem *)(ha->nx_pcibase + off);43 44	return NULL;45}46 47static const int MD_MIU_TEST_AGT_RDDATA[] = { 0x410000A8,48				0x410000AC, 0x410000B8, 0x410000BC };49#define MAX_CRB_XFORM 6050static unsigned long crb_addr_xform[MAX_CRB_XFORM];51static int qla4_8xxx_crb_table_initialized;52 53#define qla4_8xxx_crb_addr_transform(name) \54	(crb_addr_xform[QLA82XX_HW_PX_MAP_CRB_##name] = \55	 QLA82XX_HW_CRB_HUB_AGT_ADR_##name << 20)56static void57qla4_82xx_crb_addr_transform_setup(void)58{59	qla4_8xxx_crb_addr_transform(XDMA);60	qla4_8xxx_crb_addr_transform(TIMR);61	qla4_8xxx_crb_addr_transform(SRE);62	qla4_8xxx_crb_addr_transform(SQN3);63	qla4_8xxx_crb_addr_transform(SQN2);64	qla4_8xxx_crb_addr_transform(SQN1);65	qla4_8xxx_crb_addr_transform(SQN0);66	qla4_8xxx_crb_addr_transform(SQS3);67	qla4_8xxx_crb_addr_transform(SQS2);68	qla4_8xxx_crb_addr_transform(SQS1);69	qla4_8xxx_crb_addr_transform(SQS0);70	qla4_8xxx_crb_addr_transform(RPMX7);71	qla4_8xxx_crb_addr_transform(RPMX6);72	qla4_8xxx_crb_addr_transform(RPMX5);73	qla4_8xxx_crb_addr_transform(RPMX4);74	qla4_8xxx_crb_addr_transform(RPMX3);75	qla4_8xxx_crb_addr_transform(RPMX2);76	qla4_8xxx_crb_addr_transform(RPMX1);77	qla4_8xxx_crb_addr_transform(RPMX0);78	qla4_8xxx_crb_addr_transform(ROMUSB);79	qla4_8xxx_crb_addr_transform(SN);80	qla4_8xxx_crb_addr_transform(QMN);81	qla4_8xxx_crb_addr_transform(QMS);82	qla4_8xxx_crb_addr_transform(PGNI);83	qla4_8xxx_crb_addr_transform(PGND);84	qla4_8xxx_crb_addr_transform(PGN3);85	qla4_8xxx_crb_addr_transform(PGN2);86	qla4_8xxx_crb_addr_transform(PGN1);87	qla4_8xxx_crb_addr_transform(PGN0);88	qla4_8xxx_crb_addr_transform(PGSI);89	qla4_8xxx_crb_addr_transform(PGSD);90	qla4_8xxx_crb_addr_transform(PGS3);91	qla4_8xxx_crb_addr_transform(PGS2);92	qla4_8xxx_crb_addr_transform(PGS1);93	qla4_8xxx_crb_addr_transform(PGS0);94	qla4_8xxx_crb_addr_transform(PS);95	qla4_8xxx_crb_addr_transform(PH);96	qla4_8xxx_crb_addr_transform(NIU);97	qla4_8xxx_crb_addr_transform(I2Q);98	qla4_8xxx_crb_addr_transform(EG);99	qla4_8xxx_crb_addr_transform(MN);100	qla4_8xxx_crb_addr_transform(MS);101	qla4_8xxx_crb_addr_transform(CAS2);102	qla4_8xxx_crb_addr_transform(CAS1);103	qla4_8xxx_crb_addr_transform(CAS0);104	qla4_8xxx_crb_addr_transform(CAM);105	qla4_8xxx_crb_addr_transform(C2C1);106	qla4_8xxx_crb_addr_transform(C2C0);107	qla4_8xxx_crb_addr_transform(SMB);108	qla4_8xxx_crb_addr_transform(OCM0);109	qla4_8xxx_crb_addr_transform(I2C0);110 111	qla4_8xxx_crb_table_initialized = 1;112}113 114static struct crb_128M_2M_block_map crb_128M_2M_map[64] = {115	{{{0, 0,         0,         0} } },		/* 0: PCI */116	{{{1, 0x0100000, 0x0102000, 0x120000},	/* 1: PCIE */117		{1, 0x0110000, 0x0120000, 0x130000},118		{1, 0x0120000, 0x0122000, 0x124000},119		{1, 0x0130000, 0x0132000, 0x126000},120		{1, 0x0140000, 0x0142000, 0x128000},121		{1, 0x0150000, 0x0152000, 0x12a000},122		{1, 0x0160000, 0x0170000, 0x110000},123		{1, 0x0170000, 0x0172000, 0x12e000},124		{0, 0x0000000, 0x0000000, 0x000000},125		{0, 0x0000000, 0x0000000, 0x000000},126		{0, 0x0000000, 0x0000000, 0x000000},127		{0, 0x0000000, 0x0000000, 0x000000},128		{0, 0x0000000, 0x0000000, 0x000000},129		{0, 0x0000000, 0x0000000, 0x000000},130		{1, 0x01e0000, 0x01e0800, 0x122000},131		{0, 0x0000000, 0x0000000, 0x000000} } },132	{{{1, 0x0200000, 0x0210000, 0x180000} } },/* 2: MN */133	{{{0, 0,         0,         0} } },	    /* 3: */134	{{{1, 0x0400000, 0x0401000, 0x169000} } },/* 4: P2NR1 */135	{{{1, 0x0500000, 0x0510000, 0x140000} } },/* 5: SRE   */136	{{{1, 0x0600000, 0x0610000, 0x1c0000} } },/* 6: NIU   */137	{{{1, 0x0700000, 0x0704000, 0x1b8000} } },/* 7: QM    */138	{{{1, 0x0800000, 0x0802000, 0x170000},  /* 8: SQM0  */139		{0, 0x0000000, 0x0000000, 0x000000},140		{0, 0x0000000, 0x0000000, 0x000000},141		{0, 0x0000000, 0x0000000, 0x000000},142		{0, 0x0000000, 0x0000000, 0x000000},143		{0, 0x0000000, 0x0000000, 0x000000},144		{0, 0x0000000, 0x0000000, 0x000000},145		{0, 0x0000000, 0x0000000, 0x000000},146		{0, 0x0000000, 0x0000000, 0x000000},147		{0, 0x0000000, 0x0000000, 0x000000},148		{0, 0x0000000, 0x0000000, 0x000000},149		{0, 0x0000000, 0x0000000, 0x000000},150		{0, 0x0000000, 0x0000000, 0x000000},151		{0, 0x0000000, 0x0000000, 0x000000},152		{0, 0x0000000, 0x0000000, 0x000000},153		{1, 0x08f0000, 0x08f2000, 0x172000} } },154	{{{1, 0x0900000, 0x0902000, 0x174000},	/* 9: SQM1*/155		{0, 0x0000000, 0x0000000, 0x000000},156		{0, 0x0000000, 0x0000000, 0x000000},157		{0, 0x0000000, 0x0000000, 0x000000},158		{0, 0x0000000, 0x0000000, 0x000000},159		{0, 0x0000000, 0x0000000, 0x000000},160		{0, 0x0000000, 0x0000000, 0x000000},161		{0, 0x0000000, 0x0000000, 0x000000},162		{0, 0x0000000, 0x0000000, 0x000000},163		{0, 0x0000000, 0x0000000, 0x000000},164		{0, 0x0000000, 0x0000000, 0x000000},165		{0, 0x0000000, 0x0000000, 0x000000},166		{0, 0x0000000, 0x0000000, 0x000000},167		{0, 0x0000000, 0x0000000, 0x000000},168		{0, 0x0000000, 0x0000000, 0x000000},169		{1, 0x09f0000, 0x09f2000, 0x176000} } },170	{{{0, 0x0a00000, 0x0a02000, 0x178000},	/* 10: SQM2*/171		{0, 0x0000000, 0x0000000, 0x000000},172		{0, 0x0000000, 0x0000000, 0x000000},173		{0, 0x0000000, 0x0000000, 0x000000},174		{0, 0x0000000, 0x0000000, 0x000000},175		{0, 0x0000000, 0x0000000, 0x000000},176		{0, 0x0000000, 0x0000000, 0x000000},177		{0, 0x0000000, 0x0000000, 0x000000},178		{0, 0x0000000, 0x0000000, 0x000000},179		{0, 0x0000000, 0x0000000, 0x000000},180		{0, 0x0000000, 0x0000000, 0x000000},181		{0, 0x0000000, 0x0000000, 0x000000},182		{0, 0x0000000, 0x0000000, 0x000000},183		{0, 0x0000000, 0x0000000, 0x000000},184		{0, 0x0000000, 0x0000000, 0x000000},185		{1, 0x0af0000, 0x0af2000, 0x17a000} } },186	{{{0, 0x0b00000, 0x0b02000, 0x17c000},	/* 11: SQM3*/187		{0, 0x0000000, 0x0000000, 0x000000},188		{0, 0x0000000, 0x0000000, 0x000000},189		{0, 0x0000000, 0x0000000, 0x000000},190		{0, 0x0000000, 0x0000000, 0x000000},191		{0, 0x0000000, 0x0000000, 0x000000},192		{0, 0x0000000, 0x0000000, 0x000000},193		{0, 0x0000000, 0x0000000, 0x000000},194		{0, 0x0000000, 0x0000000, 0x000000},195		{0, 0x0000000, 0x0000000, 0x000000},196		{0, 0x0000000, 0x0000000, 0x000000},197		{0, 0x0000000, 0x0000000, 0x000000},198		{0, 0x0000000, 0x0000000, 0x000000},199		{0, 0x0000000, 0x0000000, 0x000000},200		{0, 0x0000000, 0x0000000, 0x000000},201		{1, 0x0bf0000, 0x0bf2000, 0x17e000} } },202	{{{1, 0x0c00000, 0x0c04000, 0x1d4000} } },/* 12: I2Q */203	{{{1, 0x0d00000, 0x0d04000, 0x1a4000} } },/* 13: TMR */204	{{{1, 0x0e00000, 0x0e04000, 0x1a0000} } },/* 14: ROMUSB */205	{{{1, 0x0f00000, 0x0f01000, 0x164000} } },/* 15: PEG4 */206	{{{0, 0x1000000, 0x1004000, 0x1a8000} } },/* 16: XDMA */207	{{{1, 0x1100000, 0x1101000, 0x160000} } },/* 17: PEG0 */208	{{{1, 0x1200000, 0x1201000, 0x161000} } },/* 18: PEG1 */209	{{{1, 0x1300000, 0x1301000, 0x162000} } },/* 19: PEG2 */210	{{{1, 0x1400000, 0x1401000, 0x163000} } },/* 20: PEG3 */211	{{{1, 0x1500000, 0x1501000, 0x165000} } },/* 21: P2ND */212	{{{1, 0x1600000, 0x1601000, 0x166000} } },/* 22: P2NI */213	{{{0, 0,         0,         0} } },	/* 23: */214	{{{0, 0,         0,         0} } },	/* 24: */215	{{{0, 0,         0,         0} } },	/* 25: */216	{{{0, 0,         0,         0} } },	/* 26: */217	{{{0, 0,         0,         0} } },	/* 27: */218	{{{0, 0,         0,         0} } },	/* 28: */219	{{{1, 0x1d00000, 0x1d10000, 0x190000} } },/* 29: MS */220	{{{1, 0x1e00000, 0x1e01000, 0x16a000} } },/* 30: P2NR2 */221	{{{1, 0x1f00000, 0x1f10000, 0x150000} } },/* 31: EPG */222	{{{0} } },				/* 32: PCI */223	{{{1, 0x2100000, 0x2102000, 0x120000},	/* 33: PCIE */224		{1, 0x2110000, 0x2120000, 0x130000},225		{1, 0x2120000, 0x2122000, 0x124000},226		{1, 0x2130000, 0x2132000, 0x126000},227		{1, 0x2140000, 0x2142000, 0x128000},228		{1, 0x2150000, 0x2152000, 0x12a000},229		{1, 0x2160000, 0x2170000, 0x110000},230		{1, 0x2170000, 0x2172000, 0x12e000},231		{0, 0x0000000, 0x0000000, 0x000000},232		{0, 0x0000000, 0x0000000, 0x000000},233		{0, 0x0000000, 0x0000000, 0x000000},234		{0, 0x0000000, 0x0000000, 0x000000},235		{0, 0x0000000, 0x0000000, 0x000000},236		{0, 0x0000000, 0x0000000, 0x000000},237		{0, 0x0000000, 0x0000000, 0x000000},238		{0, 0x0000000, 0x0000000, 0x000000} } },239	{{{1, 0x2200000, 0x2204000, 0x1b0000} } },/* 34: CAM */240	{{{0} } },				/* 35: */241	{{{0} } },				/* 36: */242	{{{0} } },				/* 37: */243	{{{0} } },				/* 38: */244	{{{0} } },				/* 39: */245	{{{1, 0x2800000, 0x2804000, 0x1a4000} } },/* 40: TMR */246	{{{1, 0x2900000, 0x2901000, 0x16b000} } },/* 41: P2NR3 */247	{{{1, 0x2a00000, 0x2a00400, 0x1ac400} } },/* 42: RPMX1 */248	{{{1, 0x2b00000, 0x2b00400, 0x1ac800} } },/* 43: RPMX2 */249	{{{1, 0x2c00000, 0x2c00400, 0x1acc00} } },/* 44: RPMX3 */250	{{{1, 0x2d00000, 0x2d00400, 0x1ad000} } },/* 45: RPMX4 */251	{{{1, 0x2e00000, 0x2e00400, 0x1ad400} } },/* 46: RPMX5 */252	{{{1, 0x2f00000, 0x2f00400, 0x1ad800} } },/* 47: RPMX6 */253	{{{1, 0x3000000, 0x3000400, 0x1adc00} } },/* 48: RPMX7 */254	{{{0, 0x3100000, 0x3104000, 0x1a8000} } },/* 49: XDMA */255	{{{1, 0x3200000, 0x3204000, 0x1d4000} } },/* 50: I2Q */256	{{{1, 0x3300000, 0x3304000, 0x1a0000} } },/* 51: ROMUSB */257	{{{0} } },				/* 52: */258	{{{1, 0x3500000, 0x3500400, 0x1ac000} } },/* 53: RPMX0 */259	{{{1, 0x3600000, 0x3600400, 0x1ae000} } },/* 54: RPMX8 */260	{{{1, 0x3700000, 0x3700400, 0x1ae400} } },/* 55: RPMX9 */261	{{{1, 0x3800000, 0x3804000, 0x1d0000} } },/* 56: OCM0 */262	{{{1, 0x3900000, 0x3904000, 0x1b4000} } },/* 57: CRYPTO */263	{{{1, 0x3a00000, 0x3a04000, 0x1d8000} } },/* 58: SMB */264	{{{0} } },				/* 59: I2C0 */265	{{{0} } },				/* 60: I2C1 */266	{{{1, 0x3d00000, 0x3d04000, 0x1dc000} } },/* 61: LPC */267	{{{1, 0x3e00000, 0x3e01000, 0x167000} } },/* 62: P2NC */268	{{{1, 0x3f00000, 0x3f01000, 0x168000} } }	/* 63: P2NR0 */269};270 271/*272 * top 12 bits of crb internal address (hub, agent)273 */274static unsigned qla4_82xx_crb_hub_agt[64] = {275	0,276	QLA82XX_HW_CRB_HUB_AGT_ADR_PS,277	QLA82XX_HW_CRB_HUB_AGT_ADR_MN,278	QLA82XX_HW_CRB_HUB_AGT_ADR_MS,279	0,280	QLA82XX_HW_CRB_HUB_AGT_ADR_SRE,281	QLA82XX_HW_CRB_HUB_AGT_ADR_NIU,282	QLA82XX_HW_CRB_HUB_AGT_ADR_QMN,283	QLA82XX_HW_CRB_HUB_AGT_ADR_SQN0,284	QLA82XX_HW_CRB_HUB_AGT_ADR_SQN1,285	QLA82XX_HW_CRB_HUB_AGT_ADR_SQN2,286	QLA82XX_HW_CRB_HUB_AGT_ADR_SQN3,287	QLA82XX_HW_CRB_HUB_AGT_ADR_I2Q,288	QLA82XX_HW_CRB_HUB_AGT_ADR_TIMR,289	QLA82XX_HW_CRB_HUB_AGT_ADR_ROMUSB,290	QLA82XX_HW_CRB_HUB_AGT_ADR_PGN4,291	QLA82XX_HW_CRB_HUB_AGT_ADR_XDMA,292	QLA82XX_HW_CRB_HUB_AGT_ADR_PGN0,293	QLA82XX_HW_CRB_HUB_AGT_ADR_PGN1,294	QLA82XX_HW_CRB_HUB_AGT_ADR_PGN2,295	QLA82XX_HW_CRB_HUB_AGT_ADR_PGN3,296	QLA82XX_HW_CRB_HUB_AGT_ADR_PGND,297	QLA82XX_HW_CRB_HUB_AGT_ADR_PGNI,298	QLA82XX_HW_CRB_HUB_AGT_ADR_PGS0,299	QLA82XX_HW_CRB_HUB_AGT_ADR_PGS1,300	QLA82XX_HW_CRB_HUB_AGT_ADR_PGS2,301	QLA82XX_HW_CRB_HUB_AGT_ADR_PGS3,302	0,303	QLA82XX_HW_CRB_HUB_AGT_ADR_PGSI,304	QLA82XX_HW_CRB_HUB_AGT_ADR_SN,305	0,306	QLA82XX_HW_CRB_HUB_AGT_ADR_EG,307	0,308	QLA82XX_HW_CRB_HUB_AGT_ADR_PS,309	QLA82XX_HW_CRB_HUB_AGT_ADR_CAM,310	0,311	0,312	0,313	0,314	0,315	QLA82XX_HW_CRB_HUB_AGT_ADR_TIMR,316	0,317	QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX1,318	QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX2,319	QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX3,320	QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX4,321	QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX5,322	QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX6,323	QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX7,324	QLA82XX_HW_CRB_HUB_AGT_ADR_XDMA,325	QLA82XX_HW_CRB_HUB_AGT_ADR_I2Q,326	QLA82XX_HW_CRB_HUB_AGT_ADR_ROMUSB,327	0,328	QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX0,329	QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX8,330	QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX9,331	QLA82XX_HW_CRB_HUB_AGT_ADR_OCM0,332	0,333	QLA82XX_HW_CRB_HUB_AGT_ADR_SMB,334	QLA82XX_HW_CRB_HUB_AGT_ADR_I2C0,335	QLA82XX_HW_CRB_HUB_AGT_ADR_I2C1,336	0,337	QLA82XX_HW_CRB_HUB_AGT_ADR_PGNC,338	0,339};340 341/* Device states */342static char *qdev_state[] = {343	"Unknown",344	"Cold",345	"Initializing",346	"Ready",347	"Need Reset",348	"Need Quiescent",349	"Failed",350	"Quiescent",351};352 353/*354 * In: 'off' is offset from CRB space in 128M pci map355 * Out: 'off' is 2M pci map addr356 * side effect: lock crb window357 */358static void359qla4_82xx_pci_set_crbwindow_2M(struct scsi_qla_host *ha, ulong *off)360{361	u32 win_read;362 363	ha->crb_win = CRB_HI(*off);364	writel(ha->crb_win,365		(void __iomem *)(CRB_WINDOW_2M + ha->nx_pcibase));366 367	/* Read back value to make sure write has gone through before trying368	* to use it. */369	win_read = readl((void __iomem *)(CRB_WINDOW_2M + ha->nx_pcibase));370	if (win_read != ha->crb_win) {371		DEBUG2(ql4_printk(KERN_INFO, ha,372		    "%s: Written crbwin (0x%x) != Read crbwin (0x%x),"373		    " off=0x%lx\n", __func__, ha->crb_win, win_read, *off));374	}375	*off = (*off & MASK(16)) + CRB_INDIRECT_2M + ha->nx_pcibase;376}377 378#define CRB_WIN_LOCK_TIMEOUT 100000000379 380/*381 * Context: atomic382 */383static int qla4_82xx_crb_win_lock(struct scsi_qla_host *ha)384{385	int done = 0, timeout = 0;386 387	while (!done) {388		/* acquire semaphore3 from PCI HW block */389		done = qla4_82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM7_LOCK));390		if (done == 1)391			break;392		if (timeout >= CRB_WIN_LOCK_TIMEOUT)393			return -1;394 395		timeout++;396		udelay(10);397	}398	qla4_82xx_wr_32(ha, QLA82XX_CRB_WIN_LOCK_ID, ha->func_num);399	return 0;400}401 402void qla4_82xx_crb_win_unlock(struct scsi_qla_host *ha)403{404	qla4_82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM7_UNLOCK));405}406 407void408qla4_82xx_wr_32(struct scsi_qla_host *ha, ulong off, u32 data)409{410	unsigned long flags = 0;411	int rv;412 413	rv = qla4_82xx_pci_get_crb_addr_2M(ha, &off);414 415	BUG_ON(rv == -1);416 417	if (rv == 1) {418		write_lock_irqsave(&ha->hw_lock, flags);419		qla4_82xx_crb_win_lock(ha);420		qla4_82xx_pci_set_crbwindow_2M(ha, &off);421	}422 423	writel(data, (void __iomem *)off);424 425	if (rv == 1) {426		qla4_82xx_crb_win_unlock(ha);427		write_unlock_irqrestore(&ha->hw_lock, flags);428	}429}430 431uint32_t qla4_82xx_rd_32(struct scsi_qla_host *ha, ulong off)432{433	unsigned long flags = 0;434	int rv;435	u32 data;436 437	rv = qla4_82xx_pci_get_crb_addr_2M(ha, &off);438 439	BUG_ON(rv == -1);440 441	if (rv == 1) {442		write_lock_irqsave(&ha->hw_lock, flags);443		qla4_82xx_crb_win_lock(ha);444		qla4_82xx_pci_set_crbwindow_2M(ha, &off);445	}446	data = readl((void __iomem *)off);447 448	if (rv == 1) {449		qla4_82xx_crb_win_unlock(ha);450		write_unlock_irqrestore(&ha->hw_lock, flags);451	}452	return data;453}454 455/* Minidump related functions */456int qla4_82xx_md_rd_32(struct scsi_qla_host *ha, uint32_t off, uint32_t *data)457{458	uint32_t win_read, off_value;459	int rval = QLA_SUCCESS;460 461	off_value  = off & 0xFFFF0000;462	writel(off_value, (void __iomem *)(CRB_WINDOW_2M + ha->nx_pcibase));463 464	/*465	 * Read back value to make sure write has gone through before trying466	 * to use it.467	 */468	win_read = readl((void __iomem *)(CRB_WINDOW_2M + ha->nx_pcibase));469	if (win_read != off_value) {470		DEBUG2(ql4_printk(KERN_INFO, ha,471				  "%s: Written (0x%x) != Read (0x%x), off=0x%x\n",472				  __func__, off_value, win_read, off));473		rval = QLA_ERROR;474	} else {475		off_value  = off & 0x0000FFFF;476		*data = readl((void __iomem *)(off_value + CRB_INDIRECT_2M +477					       ha->nx_pcibase));478	}479	return rval;480}481 482int qla4_82xx_md_wr_32(struct scsi_qla_host *ha, uint32_t off, uint32_t data)483{484	uint32_t win_read, off_value;485	int rval = QLA_SUCCESS;486 487	off_value  = off & 0xFFFF0000;488	writel(off_value, (void __iomem *)(CRB_WINDOW_2M + ha->nx_pcibase));489 490	/* Read back value to make sure write has gone through before trying491	 * to use it.492	 */493	win_read = readl((void __iomem *)(CRB_WINDOW_2M + ha->nx_pcibase));494	if (win_read != off_value) {495		DEBUG2(ql4_printk(KERN_INFO, ha,496				  "%s: Written (0x%x) != Read (0x%x), off=0x%x\n",497				  __func__, off_value, win_read, off));498		rval = QLA_ERROR;499	} else {500		off_value  = off & 0x0000FFFF;501		writel(data, (void __iomem *)(off_value + CRB_INDIRECT_2M +502					      ha->nx_pcibase));503	}504	return rval;505}506 507#define IDC_LOCK_TIMEOUT 100000000508 509/**510 * qla4_82xx_idc_lock - hw_lock511 * @ha: pointer to adapter structure512 *513 * General purpose lock used to synchronize access to514 * CRB_DEV_STATE, CRB_DEV_REF_COUNT, etc.515 *516 * Context: task, can sleep517 **/518int qla4_82xx_idc_lock(struct scsi_qla_host *ha)519{520	int done = 0, timeout = 0;521 522	might_sleep();523 524	while (!done) {525		/* acquire semaphore5 from PCI HW block */526		done = qla4_82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM5_LOCK));527		if (done == 1)528			break;529		if (timeout >= IDC_LOCK_TIMEOUT)530			return -1;531 532		timeout++;533		msleep(100);534	}535	return 0;536}537 538void qla4_82xx_idc_unlock(struct scsi_qla_host *ha)539{540	qla4_82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM5_UNLOCK));541}542 543int544qla4_82xx_pci_get_crb_addr_2M(struct scsi_qla_host *ha, ulong *off)545{546	struct crb_128M_2M_sub_block_map *m;547 548	if (*off >= QLA82XX_CRB_MAX)549		return -1;550 551	if (*off >= QLA82XX_PCI_CAMQM && (*off < QLA82XX_PCI_CAMQM_2M_END)) {552		*off = (*off - QLA82XX_PCI_CAMQM) +553		    QLA82XX_PCI_CAMQM_2M_BASE + ha->nx_pcibase;554		return 0;555	}556 557	if (*off < QLA82XX_PCI_CRBSPACE)558		return -1;559 560	*off -= QLA82XX_PCI_CRBSPACE;561	/*562	 * Try direct map563	 */564 565	m = &crb_128M_2M_map[CRB_BLK(*off)].sub_block[CRB_SUBBLK(*off)];566 567	if (m->valid && (m->start_128M <= *off) && (m->end_128M > *off)) {568		*off = *off + m->start_2M - m->start_128M + ha->nx_pcibase;569		return 0;570	}571 572	/*573	 * Not in direct map, use crb window574	 */575	return 1;576}577 578/*579* check memory access boundary.580* used by test agent. support ddr access only for now581*/582static unsigned long583qla4_82xx_pci_mem_bound_check(struct scsi_qla_host *ha,584		unsigned long long addr, int size)585{586	if (!QLA8XXX_ADDR_IN_RANGE(addr, QLA8XXX_ADDR_DDR_NET,587	    QLA8XXX_ADDR_DDR_NET_MAX) ||588	    !QLA8XXX_ADDR_IN_RANGE(addr + size - 1,589	    QLA8XXX_ADDR_DDR_NET, QLA8XXX_ADDR_DDR_NET_MAX) ||590	    ((size != 1) && (size != 2) && (size != 4) && (size != 8))) {591		return 0;592	}593	return 1;594}595 596static int qla4_82xx_pci_set_window_warning_count;597 598static unsigned long599qla4_82xx_pci_set_window(struct scsi_qla_host *ha, unsigned long long addr)600{601	int window;602	u32 win_read;603 604	if (QLA8XXX_ADDR_IN_RANGE(addr, QLA8XXX_ADDR_DDR_NET,605	    QLA8XXX_ADDR_DDR_NET_MAX)) {606		/* DDR network side */607		window = MN_WIN(addr);608		ha->ddr_mn_window = window;609		qla4_82xx_wr_32(ha, ha->mn_win_crb |610		    QLA82XX_PCI_CRBSPACE, window);611		win_read = qla4_82xx_rd_32(ha, ha->mn_win_crb |612		    QLA82XX_PCI_CRBSPACE);613		if ((win_read << 17) != window) {614			ql4_printk(KERN_WARNING, ha,615			"%s: Written MNwin (0x%x) != Read MNwin (0x%x)\n",616			__func__, window, win_read);617		}618		addr = GET_MEM_OFFS_2M(addr) + QLA82XX_PCI_DDR_NET;619	} else if (QLA8XXX_ADDR_IN_RANGE(addr, QLA8XXX_ADDR_OCM0,620				QLA8XXX_ADDR_OCM0_MAX)) {621		unsigned int temp1;622		/* if bits 19:18&17:11 are on */623		if ((addr & 0x00ff800) == 0xff800) {624			printk("%s: QM access not handled.\n", __func__);625			addr = -1UL;626		}627 628		window = OCM_WIN(addr);629		ha->ddr_mn_window = window;630		qla4_82xx_wr_32(ha, ha->mn_win_crb |631		    QLA82XX_PCI_CRBSPACE, window);632		win_read = qla4_82xx_rd_32(ha, ha->mn_win_crb |633		    QLA82XX_PCI_CRBSPACE);634		temp1 = ((window & 0x1FF) << 7) |635		    ((window & 0x0FFFE0000) >> 17);636		if (win_read != temp1) {637			printk("%s: Written OCMwin (0x%x) != Read"638			    " OCMwin (0x%x)\n", __func__, temp1, win_read);639		}640		addr = GET_MEM_OFFS_2M(addr) + QLA82XX_PCI_OCM0_2M;641 642	} else if (QLA8XXX_ADDR_IN_RANGE(addr, QLA8XXX_ADDR_QDR_NET,643				QLA82XX_P3_ADDR_QDR_NET_MAX)) {644		/* QDR network side */645		window = MS_WIN(addr);646		ha->qdr_sn_window = window;647		qla4_82xx_wr_32(ha, ha->ms_win_crb |648		    QLA82XX_PCI_CRBSPACE, window);649		win_read = qla4_82xx_rd_32(ha,650		     ha->ms_win_crb | QLA82XX_PCI_CRBSPACE);651		if (win_read != window) {652			printk("%s: Written MSwin (0x%x) != Read "653			    "MSwin (0x%x)\n", __func__, window, win_read);654		}655		addr = GET_MEM_OFFS_2M(addr) + QLA82XX_PCI_QDR_NET;656 657	} else {658		/*659		 * peg gdb frequently accesses memory that doesn't exist,660		 * this limits the chit chat so debugging isn't slowed down.661		 */662		if ((qla4_82xx_pci_set_window_warning_count++ < 8) ||663		    (qla4_82xx_pci_set_window_warning_count%64 == 0)) {664			printk("%s: Warning:%s Unknown address range!\n",665			    __func__, DRIVER_NAME);666		}667		addr = -1UL;668	}669	return addr;670}671 672/* check if address is in the same windows as the previous access */673static int qla4_82xx_pci_is_same_window(struct scsi_qla_host *ha,674		unsigned long long addr)675{676	int window;677	unsigned long long qdr_max;678 679	qdr_max = QLA82XX_P3_ADDR_QDR_NET_MAX;680 681	if (QLA8XXX_ADDR_IN_RANGE(addr, QLA8XXX_ADDR_DDR_NET,682	    QLA8XXX_ADDR_DDR_NET_MAX)) {683		/* DDR network side */684		BUG();	/* MN access can not come here */685	} else if (QLA8XXX_ADDR_IN_RANGE(addr, QLA8XXX_ADDR_OCM0,686	     QLA8XXX_ADDR_OCM0_MAX)) {687		return 1;688	} else if (QLA8XXX_ADDR_IN_RANGE(addr, QLA8XXX_ADDR_OCM1,689	     QLA8XXX_ADDR_OCM1_MAX)) {690		return 1;691	} else if (QLA8XXX_ADDR_IN_RANGE(addr, QLA8XXX_ADDR_QDR_NET,692	    qdr_max)) {693		/* QDR network side */694		window = ((addr - QLA8XXX_ADDR_QDR_NET) >> 22) & 0x3f;695		if (ha->qdr_sn_window == window)696			return 1;697	}698 699	return 0;700}701 702static int qla4_82xx_pci_mem_read_direct(struct scsi_qla_host *ha,703		u64 off, void *data, int size)704{705	unsigned long flags;706	void __iomem *addr;707	int ret = 0;708	u64 start;709	void __iomem *mem_ptr = NULL;710	unsigned long mem_base;711	unsigned long mem_page;712 713	write_lock_irqsave(&ha->hw_lock, flags);714 715	/*716	 * If attempting to access unknown address or straddle hw windows,717	 * do not access.718	 */719	start = qla4_82xx_pci_set_window(ha, off);720	if ((start == -1UL) ||721	    (qla4_82xx_pci_is_same_window(ha, off + size - 1) == 0)) {722		write_unlock_irqrestore(&ha->hw_lock, flags);723		printk(KERN_ERR"%s out of bound pci memory access. "724				"offset is 0x%llx\n", DRIVER_NAME, off);725		return -1;726	}727 728	addr = qla4_8xxx_pci_base_offsetfset(ha, start);729	if (!addr) {730		write_unlock_irqrestore(&ha->hw_lock, flags);731		mem_base = pci_resource_start(ha->pdev, 0);732		mem_page = start & PAGE_MASK;733		/* Map two pages whenever user tries to access addresses in two734		   consecutive pages.735		 */736		if (mem_page != ((start + size - 1) & PAGE_MASK))737			mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE * 2);738		else739			mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE);740 741		if (mem_ptr == NULL) {742			*(u8 *)data = 0;743			return -1;744		}745		addr = mem_ptr;746		addr += start & (PAGE_SIZE - 1);747		write_lock_irqsave(&ha->hw_lock, flags);748	}749 750	switch (size) {751	case 1:752		*(u8  *)data = readb(addr);753		break;754	case 2:755		*(u16 *)data = readw(addr);756		break;757	case 4:758		*(u32 *)data = readl(addr);759		break;760	case 8:761		*(u64 *)data = readq(addr);762		break;763	default:764		ret = -1;765		break;766	}767	write_unlock_irqrestore(&ha->hw_lock, flags);768 769	if (mem_ptr)770		iounmap(mem_ptr);771	return ret;772}773 774static int775qla4_82xx_pci_mem_write_direct(struct scsi_qla_host *ha, u64 off,776		void *data, int size)777{778	unsigned long flags;779	void __iomem *addr;780	int ret = 0;781	u64 start;782	void __iomem *mem_ptr = NULL;783	unsigned long mem_base;784	unsigned long mem_page;785 786	write_lock_irqsave(&ha->hw_lock, flags);787 788	/*789	 * If attempting to access unknown address or straddle hw windows,790	 * do not access.791	 */792	start = qla4_82xx_pci_set_window(ha, off);793	if ((start == -1UL) ||794	    (qla4_82xx_pci_is_same_window(ha, off + size - 1) == 0)) {795		write_unlock_irqrestore(&ha->hw_lock, flags);796		printk(KERN_ERR"%s out of bound pci memory access. "797				"offset is 0x%llx\n", DRIVER_NAME, off);798		return -1;799	}800 801	addr = qla4_8xxx_pci_base_offsetfset(ha, start);802	if (!addr) {803		write_unlock_irqrestore(&ha->hw_lock, flags);804		mem_base = pci_resource_start(ha->pdev, 0);805		mem_page = start & PAGE_MASK;806		/* Map two pages whenever user tries to access addresses in two807		   consecutive pages.808		 */809		if (mem_page != ((start + size - 1) & PAGE_MASK))810			mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE*2);811		else812			mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE);813		if (mem_ptr == NULL)814			return -1;815 816		addr = mem_ptr;817		addr += start & (PAGE_SIZE - 1);818		write_lock_irqsave(&ha->hw_lock, flags);819	}820 821	switch (size) {822	case 1:823		writeb(*(u8 *)data, addr);824		break;825	case 2:826		writew(*(u16 *)data, addr);827		break;828	case 4:829		writel(*(u32 *)data, addr);830		break;831	case 8:832		writeq(*(u64 *)data, addr);833		break;834	default:835		ret = -1;836		break;837	}838	write_unlock_irqrestore(&ha->hw_lock, flags);839	if (mem_ptr)840		iounmap(mem_ptr);841	return ret;842}843 844#define MTU_FUDGE_FACTOR 100845 846static unsigned long847qla4_82xx_decode_crb_addr(unsigned long addr)848{849	int i;850	unsigned long base_addr, offset, pci_base;851 852	if (!qla4_8xxx_crb_table_initialized)853		qla4_82xx_crb_addr_transform_setup();854 855	pci_base = ADDR_ERROR;856	base_addr = addr & 0xfff00000;857	offset = addr & 0x000fffff;858 859	for (i = 0; i < MAX_CRB_XFORM; i++) {860		if (crb_addr_xform[i] == base_addr) {861			pci_base = i << 20;862			break;863		}864	}865	if (pci_base == ADDR_ERROR)866		return pci_base;867	else868		return pci_base + offset;869}870 871static long rom_max_timeout = 100;872static long qla4_82xx_rom_lock_timeout = 100;873 874/*875 * Context: task, can_sleep876 */877static int878qla4_82xx_rom_lock(struct scsi_qla_host *ha)879{880	int done = 0, timeout = 0;881 882	might_sleep();883 884	while (!done) {885		/* acquire semaphore2 from PCI HW block */886		done = qla4_82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM2_LOCK));887		if (done == 1)888			break;889		if (timeout >= qla4_82xx_rom_lock_timeout)890			return -1;891 892		timeout++;893		msleep(20);894	}895	qla4_82xx_wr_32(ha, QLA82XX_ROM_LOCK_ID, ROM_LOCK_DRIVER);896	return 0;897}898 899static void900qla4_82xx_rom_unlock(struct scsi_qla_host *ha)901{902	qla4_82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM2_UNLOCK));903}904 905static int906qla4_82xx_wait_rom_done(struct scsi_qla_host *ha)907{908	long timeout = 0;909	long done = 0 ;910 911	while (done == 0) {912		done = qla4_82xx_rd_32(ha, QLA82XX_ROMUSB_GLB_STATUS);913		done &= 2;914		timeout++;915		if (timeout >= rom_max_timeout) {916			printk("%s: Timeout reached  waiting for rom done",917					DRIVER_NAME);918			return -1;919		}920	}921	return 0;922}923 924static int925qla4_82xx_do_rom_fast_read(struct scsi_qla_host *ha, int addr, int *valp)926{927	qla4_82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_ADDRESS, addr);928	qla4_82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);929	qla4_82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_ABYTE_CNT, 3);930	qla4_82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, 0xb);931	if (qla4_82xx_wait_rom_done(ha)) {932		printk("%s: Error waiting for rom done\n", DRIVER_NAME);933		return -1;934	}935	/* reset abyte_cnt and dummy_byte_cnt */936	qla4_82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);937	udelay(10);938	qla4_82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_ABYTE_CNT, 0);939 940	*valp = qla4_82xx_rd_32(ha, QLA82XX_ROMUSB_ROM_RDATA);941	return 0;942}943 944static int945qla4_82xx_rom_fast_read(struct scsi_qla_host *ha, int addr, int *valp)946{947	int ret, loops = 0;948 949	while ((qla4_82xx_rom_lock(ha) != 0) && (loops < 50000)) {950		udelay(100);951		loops++;952	}953	if (loops >= 50000) {954		ql4_printk(KERN_WARNING, ha, "%s: qla4_82xx_rom_lock failed\n",955			   DRIVER_NAME);956		return -1;957	}958	ret = qla4_82xx_do_rom_fast_read(ha, addr, valp);959	qla4_82xx_rom_unlock(ha);960	return ret;961}962 963/*964 * This routine does CRB initialize sequence965 * to put the ISP into operational state966 */967static int968qla4_82xx_pinit_from_rom(struct scsi_qla_host *ha, int verbose)969{970	int addr, val;971	int i ;972	struct crb_addr_pair *buf;973	unsigned long off;974	unsigned offset, n;975 976	struct crb_addr_pair {977		long addr;978		long data;979	};980 981	/* Halt all the indiviual PEGs and other blocks of the ISP */982	qla4_82xx_rom_lock(ha);983 984	/* disable all I2Q */985	qla4_82xx_wr_32(ha, QLA82XX_CRB_I2Q + 0x10, 0x0);986	qla4_82xx_wr_32(ha, QLA82XX_CRB_I2Q + 0x14, 0x0);987	qla4_82xx_wr_32(ha, QLA82XX_CRB_I2Q + 0x18, 0x0);988	qla4_82xx_wr_32(ha, QLA82XX_CRB_I2Q + 0x1c, 0x0);989	qla4_82xx_wr_32(ha, QLA82XX_CRB_I2Q + 0x20, 0x0);990	qla4_82xx_wr_32(ha, QLA82XX_CRB_I2Q + 0x24, 0x0);991 992	/* disable all niu interrupts */993	qla4_82xx_wr_32(ha, QLA82XX_CRB_NIU + 0x40, 0xff);994	/* disable xge rx/tx */995	qla4_82xx_wr_32(ha, QLA82XX_CRB_NIU + 0x70000, 0x00);996	/* disable xg1 rx/tx */997	qla4_82xx_wr_32(ha, QLA82XX_CRB_NIU + 0x80000, 0x00);998	/* disable sideband mac */999	qla4_82xx_wr_32(ha, QLA82XX_CRB_NIU + 0x90000, 0x00);1000	/* disable ap0 mac */1001	qla4_82xx_wr_32(ha, QLA82XX_CRB_NIU + 0xa0000, 0x00);1002	/* disable ap1 mac */1003	qla4_82xx_wr_32(ha, QLA82XX_CRB_NIU + 0xb0000, 0x00);1004 1005	/* halt sre */1006	val = qla4_82xx_rd_32(ha, QLA82XX_CRB_SRE + 0x1000);1007	qla4_82xx_wr_32(ha, QLA82XX_CRB_SRE + 0x1000, val & (~(0x1)));1008 1009	/* halt epg */1010	qla4_82xx_wr_32(ha, QLA82XX_CRB_EPG + 0x1300, 0x1);1011 1012	/* halt timers */1013	qla4_82xx_wr_32(ha, QLA82XX_CRB_TIMER + 0x0, 0x0);1014	qla4_82xx_wr_32(ha, QLA82XX_CRB_TIMER + 0x8, 0x0);1015	qla4_82xx_wr_32(ha, QLA82XX_CRB_TIMER + 0x10, 0x0);1016	qla4_82xx_wr_32(ha, QLA82XX_CRB_TIMER + 0x18, 0x0);1017	qla4_82xx_wr_32(ha, QLA82XX_CRB_TIMER + 0x100, 0x0);1018	qla4_82xx_wr_32(ha, QLA82XX_CRB_TIMER + 0x200, 0x0);1019 1020	/* halt pegs */1021	qla4_82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_0 + 0x3c, 1);1022	qla4_82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_1 + 0x3c, 1);1023	qla4_82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_2 + 0x3c, 1);1024	qla4_82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_3 + 0x3c, 1);1025	qla4_82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_4 + 0x3c, 1);1026	msleep(5);1027 1028	/* big hammer */1029	if (test_bit(DPC_RESET_HA, &ha->dpc_flags))1030		/* don't reset CAM block on reset */1031		qla4_82xx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0xfeffffff);1032	else1033		qla4_82xx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0xffffffff);1034 1035	qla4_82xx_rom_unlock(ha);1036 1037	/* Read the signature value from the flash.1038	 * Offset 0: Contain signature (0xcafecafe)1039	 * Offset 4: Offset and number of addr/value pairs1040	 * that present in CRB initialize sequence1041	 */1042	if (qla4_82xx_rom_fast_read(ha, 0, &n) != 0 || n != 0xcafecafeUL ||1043	    qla4_82xx_rom_fast_read(ha, 4, &n) != 0) {1044		ql4_printk(KERN_WARNING, ha,1045			"[ERROR] Reading crb_init area: n: %08x\n", n);1046		return -1;1047	}1048 1049	/* Offset in flash = lower 16 bits1050	 * Number of enteries = upper 16 bits1051	 */1052	offset = n & 0xffffU;1053	n = (n >> 16) & 0xffffU;1054 1055	/* number of addr/value pair should not exceed 1024 enteries */1056	if (n  >= 1024) {1057		ql4_printk(KERN_WARNING, ha,1058		    "%s: %s:n=0x%x [ERROR] Card flash not initialized.\n",1059		    DRIVER_NAME, __func__, n);1060		return -1;1061	}1062 1063	ql4_printk(KERN_INFO, ha,1064		"%s: %d CRB init values found in ROM.\n", DRIVER_NAME, n);1065 1066	buf = kmalloc_array(n, sizeof(struct crb_addr_pair), GFP_KERNEL);1067	if (buf == NULL) {1068		ql4_printk(KERN_WARNING, ha,1069		    "%s: [ERROR] Unable to malloc memory.\n", DRIVER_NAME);1070		return -1;1071	}1072 1073	for (i = 0; i < n; i++) {1074		if (qla4_82xx_rom_fast_read(ha, 8*i + 4*offset, &val) != 0 ||1075		    qla4_82xx_rom_fast_read(ha, 8*i + 4*offset + 4, &addr) !=1076		    0) {1077			kfree(buf);1078			return -1;1079		}1080 1081		buf[i].addr = addr;1082		buf[i].data = val;1083	}1084 1085	for (i = 0; i < n; i++) {1086		/* Translate internal CRB initialization1087		 * address to PCI bus address1088		 */1089		off = qla4_82xx_decode_crb_addr((unsigned long)buf[i].addr) +1090		    QLA82XX_PCI_CRBSPACE;1091		/* Not all CRB  addr/value pair to be written,1092		 * some of them are skipped1093		 */1094 1095		/* skip if LS bit is set*/1096		if (off & 0x1) {1097			DEBUG2(ql4_printk(KERN_WARNING, ha,1098			    "Skip CRB init replay for offset = 0x%lx\n", off));1099			continue;1100		}1101 1102		/* skipping cold reboot MAGIC */1103		if (off == QLA82XX_CAM_RAM(0x1fc))1104			continue;1105 1106		/* do not reset PCI */1107		if (off == (ROMUSB_GLB + 0xbc))1108			continue;1109 1110		/* skip core clock, so that firmware can increase the clock */1111		if (off == (ROMUSB_GLB + 0xc8))1112			continue;1113 1114		/* skip the function enable register */1115		if (off == QLA82XX_PCIE_REG(PCIE_SETUP_FUNCTION))1116			continue;1117 1118		if (off == QLA82XX_PCIE_REG(PCIE_SETUP_FUNCTION2))1119			continue;1120 1121		if ((off & 0x0ff00000) == QLA82XX_CRB_SMB)1122			continue;1123 1124		if ((off & 0x0ff00000) == QLA82XX_CRB_DDR_NET)1125			continue;1126 1127		if (off == ADDR_ERROR) {1128			ql4_printk(KERN_WARNING, ha,1129			    "%s: [ERROR] Unknown addr: 0x%08lx\n",1130			    DRIVER_NAME, buf[i].addr);1131			continue;1132		}1133 1134		qla4_82xx_wr_32(ha, off, buf[i].data);1135 1136		/* ISP requires much bigger delay to settle down,1137		 * else crb_window returns 0xffffffff1138		 */1139		if (off == QLA82XX_ROMUSB_GLB_SW_RESET)1140			msleep(1000);1141 1142		/* ISP requires millisec delay between1143		 * successive CRB register updation1144		 */1145		msleep(1);1146	}1147 1148	kfree(buf);1149 1150	/* Resetting the data and instruction cache */1151	qla4_82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_D+0xec, 0x1e);1152	qla4_82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_D+0x4c, 8);1153	qla4_82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_I+0x4c, 8);1154 1155	/* Clear all protocol processing engines */1156	qla4_82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_0+0x8, 0);1157	qla4_82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_0+0xc, 0);1158	qla4_82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_1+0x8, 0);1159	qla4_82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_1+0xc, 0);1160	qla4_82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_2+0x8, 0);1161	qla4_82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_2+0xc, 0);1162	qla4_82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_3+0x8, 0);1163	qla4_82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_3+0xc, 0);1164 1165	return 0;1166}1167 1168/**1169 * qla4_8xxx_ms_mem_write_128b - Writes data to MS/off-chip memory1170 * @ha: Pointer to adapter structure1171 * @addr: Flash address to write to1172 * @data: Data to be written1173 * @count: word_count to be written1174 *1175 * Return: On success return QLA_SUCCESS1176 *         On error return QLA_ERROR1177 **/1178int qla4_8xxx_ms_mem_write_128b(struct scsi_qla_host *ha, uint64_t addr,1179				uint32_t *data, uint32_t count)1180{1181	int i, j;1182	uint32_t agt_ctrl;1183	unsigned long flags;1184	int ret_val = QLA_SUCCESS;1185 1186	/* Only 128-bit aligned access */1187	if (addr & 0xF) {1188		ret_val = QLA_ERROR;1189		goto exit_ms_mem_write;1190	}1191 1192	write_lock_irqsave(&ha->hw_lock, flags);1193 1194	/* Write address */1195	ret_val = ha->isp_ops->wr_reg_indirect(ha, MD_MIU_TEST_AGT_ADDR_HI, 0);1196	if (ret_val == QLA_ERROR) {1197		ql4_printk(KERN_ERR, ha, "%s: write to AGT_ADDR_HI failed\n",1198			   __func__);1199		goto exit_ms_mem_write_unlock;1200	}1201 1202	for (i = 0; i < count; i++, addr += 16) {1203		if (!((QLA8XXX_ADDR_IN_RANGE(addr, QLA8XXX_ADDR_QDR_NET,1204					     QLA8XXX_ADDR_QDR_NET_MAX)) ||1205		      (QLA8XXX_ADDR_IN_RANGE(addr, QLA8XXX_ADDR_DDR_NET,1206					     QLA8XXX_ADDR_DDR_NET_MAX)))) {1207			ret_val = QLA_ERROR;1208			goto exit_ms_mem_write_unlock;1209		}1210 1211		ret_val = ha->isp_ops->wr_reg_indirect(ha,1212						       MD_MIU_TEST_AGT_ADDR_LO,1213						       addr);1214		/* Write data */1215		ret_val |= ha->isp_ops->wr_reg_indirect(ha,1216						MD_MIU_TEST_AGT_WRDATA_LO,1217						*data++);1218		ret_val |= ha->isp_ops->wr_reg_indirect(ha,1219						MD_MIU_TEST_AGT_WRDATA_HI,1220						*data++);1221		ret_val |= ha->isp_ops->wr_reg_indirect(ha,1222						MD_MIU_TEST_AGT_WRDATA_ULO,1223						*data++);1224		ret_val |= ha->isp_ops->wr_reg_indirect(ha,1225						MD_MIU_TEST_AGT_WRDATA_UHI,1226						*data++);1227		if (ret_val == QLA_ERROR) {1228			ql4_printk(KERN_ERR, ha, "%s: write to AGT_WRDATA failed\n",1229				   __func__);1230			goto exit_ms_mem_write_unlock;1231		}1232 1233		/* Check write status */1234		ret_val = ha->isp_ops->wr_reg_indirect(ha, MD_MIU_TEST_AGT_CTRL,1235						       MIU_TA_CTL_WRITE_ENABLE);1236		ret_val |= ha->isp_ops->wr_reg_indirect(ha,1237							MD_MIU_TEST_AGT_CTRL,1238							MIU_TA_CTL_WRITE_START);1239		if (ret_val == QLA_ERROR) {1240			ql4_printk(KERN_ERR, ha, "%s: write to AGT_CTRL failed\n",1241				   __func__);1242			goto exit_ms_mem_write_unlock;1243		}1244 1245		for (j = 0; j < MAX_CTL_CHECK; j++) {1246			ret_val = ha->isp_ops->rd_reg_indirect(ha,1247							MD_MIU_TEST_AGT_CTRL,1248							&agt_ctrl);1249			if (ret_val == QLA_ERROR) {1250				ql4_printk(KERN_ERR, ha, "%s: failed to read MD_MIU_TEST_AGT_CTRL\n",1251					   __func__);1252				goto exit_ms_mem_write_unlock;1253			}1254			if ((agt_ctrl & MIU_TA_CTL_BUSY) == 0)1255				break;1256		}1257 1258		/* Status check failed */1259		if (j >= MAX_CTL_CHECK) {1260			printk_ratelimited(KERN_ERR "%s: MS memory write failed!\n",1261					   __func__);1262			ret_val = QLA_ERROR;1263			goto exit_ms_mem_write_unlock;1264		}1265	}1266 1267exit_ms_mem_write_unlock:1268	write_unlock_irqrestore(&ha->hw_lock, flags);1269 1270exit_ms_mem_write:1271	return ret_val;1272}1273 1274static int1275qla4_82xx_load_from_flash(struct scsi_qla_host *ha, uint32_t image_start)1276{1277	int  i, rval = 0;1278	long size = 0;1279	long flashaddr, memaddr;1280	u64 data;1281	u32 high, low;1282 1283	flashaddr = memaddr = ha->hw.flt_region_bootload;1284	size = (image_start - flashaddr) / 8;1285 1286	DEBUG2(printk("scsi%ld: %s: bootldr=0x%lx, fw_image=0x%x\n",1287	    ha->host_no, __func__, flashaddr, image_start));1288 1289	for (i = 0; i < size; i++) {1290		if ((qla4_82xx_rom_fast_read(ha, flashaddr, (int *)&low)) ||1291		    (qla4_82xx_rom_fast_read(ha, flashaddr + 4,1292		    (int *)&high))) {1293			rval = -1;1294			goto exit_load_from_flash;1295		}1296		data = ((u64)high << 32) | low ;1297		rval = qla4_82xx_pci_mem_write_2M(ha, memaddr, &data, 8);1298		if (rval)1299			goto exit_load_from_flash;1300 1301		flashaddr += 8;1302		memaddr   += 8;1303 1304		if (i % 0x1000 == 0)1305			msleep(1);1306 1307	}1308 1309	udelay(100);1310 1311	read_lock(&ha->hw_lock);1312	qla4_82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_0 + 0x18, 0x1020);1313	qla4_82xx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0x80001e);1314	read_unlock(&ha->hw_lock);1315 1316exit_load_from_flash:1317	return rval;1318}1319 1320static int qla4_82xx_load_fw(struct scsi_qla_host *ha, uint32_t image_start)1321{1322	u32 rst;1323 1324	qla4_82xx_wr_32(ha, CRB_CMDPEG_STATE, 0);1325	if (qla4_82xx_pinit_from_rom(ha, 0) != QLA_SUCCESS) {1326		printk(KERN_WARNING "%s: Error during CRB Initialization\n",1327		    __func__);1328		return QLA_ERROR;1329	}1330 1331	udelay(500);1332 1333	/* at this point, QM is in reset. This could be a problem if there are1334	 * incoming d* transition queue messages. QM/PCIE could wedge.1335	 * To get around this, QM is brought out of reset.1336	 */1337 1338	rst = qla4_82xx_rd_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET);1339	/* unreset qm */1340	rst &= ~(1 << 28);1341	qla4_82xx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, rst);1342 1343	if (qla4_82xx_load_from_flash(ha, image_start)) {1344		printk("%s: Error trying to load fw from flash!\n", __func__);1345		return QLA_ERROR;1346	}1347 1348	return QLA_SUCCESS;1349}1350 1351int1352qla4_82xx_pci_mem_read_2M(struct scsi_qla_host *ha,1353		u64 off, void *data, int size)1354{1355	int i, j = 0, k, start, end, loop, sz[2], off0[2];1356	int shift_amount;1357	uint32_t temp;1358	uint64_t off8, val, mem_crb, word[2] = {0, 0};1359 1360	/*1361	 * If not MN, go check for MS or invalid.1362	 */1363 1364	if (off >= QLA8XXX_ADDR_QDR_NET && off <= QLA82XX_P3_ADDR_QDR_NET_MAX)1365		mem_crb = QLA82XX_CRB_QDR_NET;1366	else {1367		mem_crb = QLA82XX_CRB_DDR_NET;1368		if (qla4_82xx_pci_mem_bound_check(ha, off, size) == 0)1369			return qla4_82xx_pci_mem_read_direct(ha,1370					off, data, size);1371	}1372 1373 1374	off8 = off & 0xfffffff0;1375	off0[0] = off & 0xf;1376	sz[0] = (size < (16 - off0[0])) ? size : (16 - off0[0]);1377	shift_amount = 4;1378 1379	loop = ((off0[0] + size - 1) >> shift_amount) + 1;1380	off0[1] = 0;1381	sz[1] = size - sz[0];1382 1383	for (i = 0; i < loop; i++) {1384		temp = off8 + (i << shift_amount);1385		qla4_82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_ADDR_LO, temp);1386		temp = 0;1387		qla4_82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_ADDR_HI, temp);1388		temp = MIU_TA_CTL_ENABLE;1389		qla4_82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp);1390		temp = MIU_TA_CTL_START_ENABLE;1391		qla4_82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp);1392 1393		for (j = 0; j < MAX_CTL_CHECK; j++) {1394			temp = qla4_82xx_rd_32(ha, mem_crb + MIU_TEST_AGT_CTRL);1395			if ((temp & MIU_TA_CTL_BUSY) == 0)1396				break;1397		}1398 1399		if (j >= MAX_CTL_CHECK) {1400			printk_ratelimited(KERN_ERR1401					   "%s: failed to read through agent\n",1402					   __func__);1403			break;1404		}1405 1406		start = off0[i] >> 2;1407		end   = (off0[i] + sz[i] - 1) >> 2;1408		for (k = start; k <= end; k++) {1409			temp = qla4_82xx_rd_32(ha,1410				mem_crb + MIU_TEST_AGT_RDDATA(k));1411			word[i] |= ((uint64_t)temp << (32 * (k & 1)));1412		}1413	}1414 1415	if (j >= MAX_CTL_CHECK)1416		return -1;1417 1418	if ((off0[0] & 7) == 0) {1419		val = word[0];1420	} else {1421		val = ((word[0] >> (off0[0] * 8)) & (~(~0ULL << (sz[0] * 8)))) |1422		((word[1] & (~(~0ULL << (sz[1] * 8)))) << (sz[0] * 8));1423	}1424 1425	switch (size) {1426	case 1:1427		*(uint8_t  *)data = val;1428		break;1429	case 2:1430		*(uint16_t *)data = val;1431		break;1432	case 4:1433		*(uint32_t *)data = val;1434		break;1435	case 8:1436		*(uint64_t *)data = val;1437		break;1438	}1439	return 0;1440}1441 1442int1443qla4_82xx_pci_mem_write_2M(struct scsi_qla_host *ha,1444		u64 off, void *data, int size)1445{1446	int i, j, ret = 0, loop, sz[2], off0;1447	int scale, shift_amount, startword;1448	uint32_t temp;1449	uint64_t off8, mem_crb, tmpw, word[2] = {0, 0};1450 1451	/*1452	 * If not MN, go check for MS or invalid.1453	 */1454	if (off >= QLA8XXX_ADDR_QDR_NET && off <= QLA82XX_P3_ADDR_QDR_NET_MAX)1455		mem_crb = QLA82XX_CRB_QDR_NET;1456	else {1457		mem_crb = QLA82XX_CRB_DDR_NET;1458		if (qla4_82xx_pci_mem_bound_check(ha, off, size) == 0)1459			return qla4_82xx_pci_mem_write_direct(ha,1460					off, data, size);1461	}1462 1463	off0 = off & 0x7;1464	sz[0] = (size < (8 - off0)) ? size : (8 - off0);1465	sz[1] = size - sz[0];1466 1467	off8 = off & 0xfffffff0;1468	loop = (((off & 0xf) + size - 1) >> 4) + 1;1469	shift_amount = 4;1470	scale = 2;1471	startword = (off & 0xf)/8;1472 1473	for (i = 0; i < loop; i++) {1474		if (qla4_82xx_pci_mem_read_2M(ha, off8 +1475		    (i << shift_amount), &word[i * scale], 8))1476			return -1;1477	}1478 1479	switch (size) {1480	case 1:1481		tmpw = *((uint8_t *)data);1482		break;1483	case 2:1484		tmpw = *((uint16_t *)data);1485		break;1486	case 4:1487		tmpw = *((uint32_t *)data);1488		break;1489	case 8:1490	default:1491		tmpw = *((uint64_t *)data);1492		break;1493	}1494 1495	if (sz[0] == 8)1496		word[startword] = tmpw;1497	else {1498		word[startword] &=1499		    ~((~(~0ULL << (sz[0] * 8))) << (off0 * 8));1500		word[startword] |= tmpw << (off0 * 8);1501	}1502 1503	if (sz[1] != 0) {1504		word[startword+1] &= ~(~0ULL << (sz[1] * 8));1505		word[startword+1] |= tmpw >> (sz[0] * 8);1506	}1507 1508	for (i = 0; i < loop; i++) {1509		temp = off8 + (i << shift_amount);1510		qla4_82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_ADDR_LO, temp);1511		temp = 0;1512		qla4_82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_ADDR_HI, temp);1513		temp = word[i * scale] & 0xffffffff;1514		qla4_82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_WRDATA_LO, temp);1515		temp = (word[i * scale] >> 32) & 0xffffffff;1516		qla4_82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_WRDATA_HI, temp);1517		temp = word[i*scale + 1] & 0xffffffff;1518		qla4_82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_WRDATA_UPPER_LO,1519		    temp);1520		temp = (word[i*scale + 1] >> 32) & 0xffffffff;1521		qla4_82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_WRDATA_UPPER_HI,1522		    temp);1523 1524		temp = MIU_TA_CTL_WRITE_ENABLE;1525		qla4_82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_CTRL, temp);1526		temp = MIU_TA_CTL_WRITE_START;1527		qla4_82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_CTRL, temp);1528 1529		for (j = 0; j < MAX_CTL_CHECK; j++) {1530			temp = qla4_82xx_rd_32(ha, mem_crb + MIU_TEST_AGT_CTRL);1531			if ((temp & MIU_TA_CTL_BUSY) == 0)1532				break;1533		}1534 1535		if (j >= MAX_CTL_CHECK) {1536			if (printk_ratelimit())1537				ql4_printk(KERN_ERR, ha,1538					   "%s: failed to read through agent\n",1539					   __func__);1540			ret = -1;1541			break;1542		}1543	}1544 1545	return ret;1546}1547 1548static int qla4_82xx_cmdpeg_ready(struct scsi_qla_host *ha, int pegtune_val)1549{1550	u32 val = 0;1551	int retries = 60;1552 1553	if (!pegtune_val) {1554		do {1555			val = qla4_82xx_rd_32(ha, CRB_CMDPEG_STATE);1556			if ((val == PHAN_INITIALIZE_COMPLETE) ||1557			    (val == PHAN_INITIALIZE_ACK))1558				return 0;1559			set_current_state(TASK_UNINTERRUPTIBLE);1560			schedule_timeout(500);1561 1562		} while (--retries);1563 1564		if (!retries) {1565			pegtune_val = qla4_82xx_rd_32(ha,1566				QLA82XX_ROMUSB_GLB_PEGTUNE_DONE);1567			printk(KERN_WARNING "%s: init failed, "1568				"pegtune_val = %x\n", __func__, pegtune_val);1569			return -1;1570		}1571	}1572	return 0;1573}1574 1575static int qla4_82xx_rcvpeg_ready(struct scsi_qla_host *ha)1576{1577	uint32_t state = 0;1578	int loops = 0;1579 1580	/* Window 1 call */1581	read_lock(&ha->hw_lock);1582	state = qla4_82xx_rd_32(ha, CRB_RCVPEG_STATE);1583	read_unlock(&ha->hw_lock);1584 1585	while ((state != PHAN_PEG_RCV_INITIALIZED) && (loops < 30000)) {1586		udelay(100);1587		/* Window 1 call */1588		read_lock(&ha->hw_lock);1589		state = qla4_82xx_rd_32(ha, CRB_RCVPEG_STATE);1590		read_unlock(&ha->hw_lock);1591 1592		loops++;1593	}1594 1595	if (loops >= 30000) {1596		DEBUG2(ql4_printk(KERN_INFO, ha,1597		    "Receive Peg initialization not complete: 0x%x.\n", state));1598		return QLA_ERROR;1599	}1600 1601	return QLA_SUCCESS;1602}1603 1604void1605qla4_8xxx_set_drv_active(struct scsi_qla_host *ha)1606{1607	uint32_t drv_active;1608 1609	drv_active = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_ACTIVE);1610 1611	/*1612	 * For ISP8324 and ISP8042, drv_active register has 1 bit per function,1613	 * shift 1 by func_num to set a bit for the function.1614	 * For ISP8022, drv_active has 4 bits per function1615	 */1616	if (is_qla8032(ha) || is_qla8042(ha))1617		drv_active |= (1 << ha->func_num);1618	else1619		drv_active |= (1 << (ha->func_num * 4));1620 1621	ql4_printk(KERN_INFO, ha, "%s(%ld): drv_active: 0x%08x\n",1622		   __func__, ha->host_no, drv_active);1623	qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DRV_ACTIVE, drv_active);1624}1625 1626void1627qla4_8xxx_clear_drv_active(struct scsi_qla_host *ha)1628{1629	uint32_t drv_active;1630 1631	drv_active = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_ACTIVE);1632 1633	/*1634	 * For ISP8324 and ISP8042, drv_active register has 1 bit per function,1635	 * shift 1 by func_num to set a bit for the function.1636	 * For ISP8022, drv_active has 4 bits per function1637	 */1638	if (is_qla8032(ha) || is_qla8042(ha))1639		drv_active &= ~(1 << (ha->func_num));1640	else1641		drv_active &= ~(1 << (ha->func_num * 4));1642 1643	ql4_printk(KERN_INFO, ha, "%s(%ld): drv_active: 0x%08x\n",1644		   __func__, ha->host_no, drv_active);1645	qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DRV_ACTIVE, drv_active);1646}1647 1648inline int qla4_8xxx_need_reset(struct scsi_qla_host *ha)1649{1650	uint32_t drv_state, drv_active;1651	int rval;1652 1653	drv_active = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_ACTIVE);1654	drv_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_STATE);1655 1656	/*1657	 * For ISP8324 and ISP8042, drv_active register has 1 bit per function,1658	 * shift 1 by func_num to set a bit for the function.1659	 * For ISP8022, drv_active has 4 bits per function1660	 */1661	if (is_qla8032(ha) || is_qla8042(ha))1662		rval = drv_state & (1 << ha->func_num);1663	else1664		rval = drv_state & (1 << (ha->func_num * 4));1665 1666	if ((test_bit(AF_EEH_BUSY, &ha->flags)) && drv_active)1667		rval = 1;1668 1669	return rval;1670}1671 1672void qla4_8xxx_set_rst_ready(struct scsi_qla_host *ha)1673{1674	uint32_t drv_state;1675 1676	drv_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_STATE);1677 1678	/*1679	 * For ISP8324 and ISP8042, drv_active register has 1 bit per function,1680	 * shift 1 by func_num to set a bit for the function.1681	 * For ISP8022, drv_active has 4 bits per function1682	 */1683	if (is_qla8032(ha) || is_qla8042(ha))1684		drv_state |= (1 << ha->func_num);1685	else1686		drv_state |= (1 << (ha->func_num * 4));1687 1688	ql4_printk(KERN_INFO, ha, "%s(%ld): drv_state: 0x%08x\n",1689		   __func__, ha->host_no, drv_state);1690	qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DRV_STATE, drv_state);1691}1692 1693void qla4_8xxx_clear_rst_ready(struct scsi_qla_host *ha)1694{1695	uint32_t drv_state;1696 1697	drv_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_STATE);1698 1699	/*1700	 * For ISP8324 and ISP8042, drv_active register has 1 bit per function,1701	 * shift 1 by func_num to set a bit for the function.1702	 * For ISP8022, drv_active has 4 bits per function1703	 */1704	if (is_qla8032(ha) || is_qla8042(ha))1705		drv_state &= ~(1 << ha->func_num);1706	else1707		drv_state &= ~(1 << (ha->func_num * 4));1708 1709	ql4_printk(KERN_INFO, ha, "%s(%ld): drv_state: 0x%08x\n",1710		   __func__, ha->host_no, drv_state);1711	qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DRV_STATE, drv_state);1712}1713 1714static inline void1715qla4_8xxx_set_qsnt_ready(struct scsi_qla_host *ha)1716{1717	uint32_t qsnt_state;1718 1719	qsnt_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_STATE);1720 1721	/*1722	 * For ISP8324 and ISP8042, drv_active register has 1 bit per function,1723	 * shift 1 by func_num to set a bit for the function.1724	 * For ISP8022, drv_active has 4 bits per function.1725	 */1726	if (is_qla8032(ha) || is_qla8042(ha))1727		qsnt_state |= (1 << ha->func_num);1728	else1729		qsnt_state |= (2 << (ha->func_num * 4));1730 1731	qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DRV_STATE, qsnt_state);1732}1733 1734 1735static int1736qla4_82xx_start_firmware(struct scsi_qla_host *ha, uint32_t image_start)1737{1738	uint16_t lnk;1739 1740	/* scrub dma mask expansion register */1741	qla4_82xx_wr_32(ha, CRB_DMA_SHIFT, 0x55555555);1742 1743	/* Overwrite stale initialization register values */1744	qla4_82xx_wr_32(ha, CRB_CMDPEG_STATE, 0);1745	qla4_82xx_wr_32(ha, CRB_RCVPEG_STATE, 0);1746	qla4_82xx_wr_32(ha, QLA82XX_PEG_HALT_STATUS1, 0);1747	qla4_82xx_wr_32(ha, QLA82XX_PEG_HALT_STATUS2, 0);1748 1749	if (qla4_82xx_load_fw(ha, image_start) != QLA_SUCCESS) {1750		printk("%s: Error trying to start fw!\n", __func__);1751		return QLA_ERROR;1752	}1753 1754	/* Handshake with the card before we register the devices. */1755	if (qla4_82xx_cmdpeg_ready(ha, 0) != QLA_SUCCESS) {1756		printk("%s: Error during card handshake!\n", __func__);1757		return QLA_ERROR;1758	}1759 1760	/* Negotiated Link width */1761	pcie_capability_read_word(ha->pdev, PCI_EXP_LNKSTA, &lnk);1762	ha->link_width = (lnk >> 4) & 0x3f;1763 1764	/* Synchronize with Receive peg */1765	return qla4_82xx_rcvpeg_ready(ha);1766}1767 1768int qla4_82xx_try_start_fw(struct scsi_qla_host *ha)1769{1770	int rval;1771 1772	/*1773	 * FW Load priority:1774	 * 1) Operational firmware residing in flash.1775	 * 2) Fail1776	 */1777 1778	ql4_printk(KERN_INFO, ha,1779	    "FW: Retrieving flash offsets from FLT/FDT ...\n");1780	rval = qla4_8xxx_get_flash_info(ha);1781	if (rval != QLA_SUCCESS)1782		return rval;1783 1784	ql4_printk(KERN_INFO, ha,1785	    "FW: Attempting to load firmware from flash...\n");1786	rval = qla4_82xx_start_firmware(ha, ha->hw.flt_region_fw);1787 1788	if (rval != QLA_SUCCESS) {1789		ql4_printk(KERN_ERR, ha, "FW: Load firmware from flash"1790		    " FAILED...\n");1791		return rval;1792	}1793 1794	return rval;1795}1796 1797void qla4_82xx_rom_lock_recovery(struct scsi_qla_host *ha)1798{1799	if (qla4_82xx_rom_lock(ha)) {1800		/* Someone else is holding the lock. */1801		dev_info(&ha->pdev->dev, "Resetting rom_lock\n");1802	}1803 1804	/*1805	 * Either we got the lock, or someone1806	 * else died while holding it.1807	 * In either case, unlock.1808	 */1809	qla4_82xx_rom_unlock(ha);1810}1811 1812static uint32_t ql4_84xx_poll_wait_for_ready(struct scsi_qla_host *ha,1813					     uint32_t addr1, uint32_t mask)1814{1815	unsigned long timeout;1816	uint32_t rval = QLA_SUCCESS;1817	uint32_t temp;1818 1819	timeout = jiffies + msecs_to_jiffies(TIMEOUT_100_MS);1820	do {1821		ha->isp_ops->rd_reg_indirect(ha, addr1, &temp);1822		if ((temp & mask) != 0)1823			break;1824 1825		if (time_after_eq(jiffies, timeout)) {1826			ql4_printk(KERN_INFO, ha, "Error in processing rdmdio entry\n");1827			return QLA_ERROR;1828		}1829	} while (1);1830 1831	return rval;1832}1833 1834static uint32_t ql4_84xx_ipmdio_rd_reg(struct scsi_qla_host *ha, uint32_t addr1,1835				uint32_t addr3, uint32_t mask, uint32_t addr,1836				uint32_t *data_ptr)1837{1838	int rval = QLA_SUCCESS;1839	uint32_t temp;1840	uint32_t data;1841 1842	rval = ql4_84xx_poll_wait_for_ready(ha, addr1, mask);1843	if (rval)1844		goto exit_ipmdio_rd_reg;1845 1846	temp = (0x40000000 | addr);1847	ha->isp_ops->wr_reg_indirect(ha, addr1, temp);1848 1849	rval = ql4_84xx_poll_wait_for_ready(ha, addr1, mask);1850	if (rval)1851		goto exit_ipmdio_rd_reg;1852 1853	ha->isp_ops->rd_reg_indirect(ha, addr3, &data);1854	*data_ptr = data;1855 1856exit_ipmdio_rd_reg:1857	return rval;1858}1859 1860 1861static uint32_t ql4_84xx_poll_wait_ipmdio_bus_idle(struct scsi_qla_host *ha,1862						    uint32_t addr1,1863						    uint32_t addr2,1864						    uint32_t addr3,1865						    uint32_t mask)1866{1867	unsigned long timeout;1868	uint32_t temp;1869	uint32_t rval = QLA_SUCCESS;1870 1871	timeout = jiffies + msecs_to_jiffies(TIMEOUT_100_MS);1872	do {1873		ql4_84xx_ipmdio_rd_reg(ha, addr1, addr3, mask, addr2, &temp);1874		if ((temp & 0x1) != 1)1875			break;1876		if (time_after_eq(jiffies, timeout)) {1877			ql4_printk(KERN_INFO, ha, "Error in processing mdiobus idle\n");1878			return QLA_ERROR;1879		}1880	} while (1);1881 1882	return rval;1883}1884 1885static int ql4_84xx_ipmdio_wr_reg(struct scsi_qla_host *ha,1886				  uint32_t addr1, uint32_t addr3,1887				  uint32_t mask, uint32_t addr,1888				  uint32_t value)1889{1890	int rval = QLA_SUCCESS;1891 1892	rval = ql4_84xx_poll_wait_for_ready(ha, addr1, mask);1893	if (rval)1894		goto exit_ipmdio_wr_reg;1895 1896	ha->isp_ops->wr_reg_indirect(ha, addr3, value);1897	ha->isp_ops->wr_reg_indirect(ha, addr1, addr);1898 1899	rval = ql4_84xx_poll_wait_for_ready(ha, addr1, mask);1900	if (rval)1901		goto exit_ipmdio_wr_reg;1902 1903exit_ipmdio_wr_reg:1904	return rval;1905}1906 1907static void qla4_8xxx_minidump_process_rdcrb(struct scsi_qla_host *ha,1908				struct qla8xxx_minidump_entry_hdr *entry_hdr,1909				uint32_t **d_ptr)1910{1911	uint32_t r_addr, r_stride, loop_cnt, i, r_value;1912	struct qla8xxx_minidump_entry_crb *crb_hdr;1913	uint32_t *data_ptr = *d_ptr;1914 1915	DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__));1916	crb_hdr = (struct qla8xxx_minidump_entry_crb *)entry_hdr;1917	r_addr = crb_hdr->addr;1918	r_stride = crb_hdr->crb_strd.addr_stride;1919	loop_cnt = crb_hdr->op_count;1920 1921	for (i = 0; i < loop_cnt; i++) {1922		ha->isp_ops->rd_reg_indirect(ha, r_addr, &r_value);1923		*data_ptr++ = cpu_to_le32(r_addr);1924		*data_ptr++ = cpu_to_le32(r_value);1925		r_addr += r_stride;1926	}1927	*d_ptr = data_ptr;1928}1929 1930static int qla4_83xx_check_dma_engine_state(struct scsi_qla_host *ha)1931{1932	int rval = QLA_SUCCESS;1933	uint32_t dma_eng_num = 0, cmd_sts_and_cntrl = 0;1934	uint64_t dma_base_addr = 0;1935	struct qla4_8xxx_minidump_template_hdr *tmplt_hdr = NULL;1936 1937	tmplt_hdr = (struct qla4_8xxx_minidump_template_hdr *)1938							ha->fw_dump_tmplt_hdr;1939	dma_eng_num =1940		tmplt_hdr->saved_state_array[QLA83XX_PEX_DMA_ENGINE_INDEX];1941	dma_base_addr = QLA83XX_PEX_DMA_BASE_ADDRESS +1942				(dma_eng_num * QLA83XX_PEX_DMA_NUM_OFFSET);1943 1944	/* Read the pex-dma's command-status-and-control register. */1945	rval = ha->isp_ops->rd_reg_indirect(ha,1946			(dma_base_addr + QLA83XX_PEX_DMA_CMD_STS_AND_CNTRL),1947			&cmd_sts_and_cntrl);1948 1949	if (rval)1950		return QLA_ERROR;1951 1952	/* Check if requested pex-dma engine is available. */1953	if (cmd_sts_and_cntrl & BIT_31)1954		return QLA_SUCCESS;1955	else1956		return QLA_ERROR;1957}1958 1959static int qla4_83xx_start_pex_dma(struct scsi_qla_host *ha,1960			   struct qla4_83xx_minidump_entry_rdmem_pex_dma *m_hdr)1961{1962	int rval = QLA_SUCCESS, wait = 0;1963	uint32_t dma_eng_num = 0, cmd_sts_and_cntrl = 0;1964	uint64_t dma_base_addr = 0;1965	struct qla4_8xxx_minidump_template_hdr *tmplt_hdr = NULL;1966 1967	tmplt_hdr = (struct qla4_8xxx_minidump_template_hdr *)1968							ha->fw_dump_tmplt_hdr;1969	dma_eng_num =1970		tmplt_hdr->saved_state_array[QLA83XX_PEX_DMA_ENGINE_INDEX];1971	dma_base_addr = QLA83XX_PEX_DMA_BASE_ADDRESS +1972				(dma_eng_num * QLA83XX_PEX_DMA_NUM_OFFSET);1973 1974	rval = ha->isp_ops->wr_reg_indirect(ha,1975				dma_base_addr + QLA83XX_PEX_DMA_CMD_ADDR_LOW,1976				m_hdr->desc_card_addr);1977	if (rval)1978		goto error_exit;1979 1980	rval = ha->isp_ops->wr_reg_indirect(ha,1981			      dma_base_addr + QLA83XX_PEX_DMA_CMD_ADDR_HIGH, 0);1982	if (rval)1983		goto error_exit;1984 1985	rval = ha->isp_ops->wr_reg_indirect(ha,1986			      dma_base_addr + QLA83XX_PEX_DMA_CMD_STS_AND_CNTRL,1987			      m_hdr->start_dma_cmd);1988	if (rval)1989		goto error_exit;1990 1991	/* Wait for dma operation to complete. */1992	for (wait = 0; wait < QLA83XX_PEX_DMA_MAX_WAIT; wait++) {1993		rval = ha->isp_ops->rd_reg_indirect(ha,1994			    (dma_base_addr + QLA83XX_PEX_DMA_CMD_STS_AND_CNTRL),1995			    &cmd_sts_and_cntrl);1996		if (rval)1997			goto error_exit;1998 1999		if ((cmd_sts_and_cntrl & BIT_1) == 0)2000			break;2001		else2002			udelay(10);2003	}2004 2005	/* Wait a max of 100 ms, otherwise fallback to rdmem entry read */2006	if (wait >= QLA83XX_PEX_DMA_MAX_WAIT) {2007		rval = QLA_ERROR;2008		goto error_exit;2009	}2010 2011error_exit:2012	return rval;2013}2014 2015static int qla4_8xxx_minidump_pex_dma_read(struct scsi_qla_host *ha,2016				struct qla8xxx_minidump_entry_hdr *entry_hdr,2017				uint32_t **d_ptr)2018{2019	int rval = QLA_SUCCESS;2020	struct qla4_83xx_minidump_entry_rdmem_pex_dma *m_hdr = NULL;2021	uint32_t size, read_size;2022	uint8_t *data_ptr = (uint8_t *)*d_ptr;2023	void *rdmem_buffer = NULL;2024	dma_addr_t rdmem_dma;2025	struct qla4_83xx_pex_dma_descriptor dma_desc;2026 2027	DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__));2028 2029	rval = qla4_83xx_check_dma_engine_state(ha);2030	if (rval != QLA_SUCCESS) {2031		DEBUG2(ql4_printk(KERN_INFO, ha,2032				  "%s: DMA engine not available. Fallback to rdmem-read.\n",2033				  __func__));2034		return QLA_ERROR;2035	}2036 2037	m_hdr = (struct qla4_83xx_minidump_entry_rdmem_pex_dma *)entry_hdr;2038	rdmem_buffer = dma_alloc_coherent(&ha->pdev->dev,2039					  QLA83XX_PEX_DMA_READ_SIZE,2040					  &rdmem_dma, GFP_KERNEL);2041	if (!rdmem_buffer) {2042		DEBUG2(ql4_printk(KERN_INFO, ha,2043				  "%s: Unable to allocate rdmem dma buffer\n",2044				  __func__));2045		return QLA_ERROR;2046	}2047 2048	/* Prepare pex-dma descriptor to be written to MS memory. */2049	/* dma-desc-cmd layout:2050	 *              0-3: dma-desc-cmd 0-32051	 *              4-7: pcid function number2052	 *              8-15: dma-desc-cmd 8-152053	 */2054	dma_desc.cmd.dma_desc_cmd = (m_hdr->dma_desc_cmd & 0xff0f);2055	dma_desc.cmd.dma_desc_cmd |= ((PCI_FUNC(ha->pdev->devfn) & 0xf) << 0x4);2056	dma_desc.dma_bus_addr = rdmem_dma;2057 2058	size = 0;2059	read_size = 0;2060	/*2061	 * Perform rdmem operation using pex-dma.2062	 * Prepare dma in chunks of QLA83XX_PEX_DMA_READ_SIZE.2063	 */2064	while (read_size < m_hdr->read_data_size) {2065		if (m_hdr->read_data_size - read_size >=2066		    QLA83XX_PEX_DMA_READ_SIZE)2067			size = QLA83XX_PEX_DMA_READ_SIZE;2068		else {2069			size = (m_hdr->read_data_size - read_size);2070 2071			if (rdmem_buffer)2072				dma_free_coherent(&ha->pdev->dev,2073						  QLA83XX_PEX_DMA_READ_SIZE,2074						  rdmem_buffer, rdmem_dma);2075 2076			rdmem_buffer = dma_alloc_coherent(&ha->pdev->dev, size,2077							  &rdmem_dma,2078							  GFP_KERNEL);2079			if (!rdmem_buffer) {2080				DEBUG2(ql4_printk(KERN_INFO, ha,2081						  "%s: Unable to allocate rdmem dma buffer\n",2082						  __func__));2083				return QLA_ERROR;2084			}2085			dma_desc.dma_bus_addr = rdmem_dma;2086		}2087 2088		dma_desc.src_addr = m_hdr->read_addr + read_size;2089		dma_desc.cmd.read_data_size = size;2090 2091		/* Prepare: Write pex-dma descriptor to MS memory. */2092		rval = qla4_8xxx_ms_mem_write_128b(ha,2093			      (uint64_t)m_hdr->desc_card_addr,2094			      (uint32_t *)&dma_desc,2095			      (sizeof(struct qla4_83xx_pex_dma_descriptor)/16));2096		if (rval != QLA_SUCCESS) {2097			ql4_printk(KERN_INFO, ha,2098				   "%s: Error writing rdmem-dma-init to MS !!!\n",2099				   __func__);2100			goto error_exit;2101		}2102 2103		DEBUG2(ql4_printk(KERN_INFO, ha,2104				  "%s: Dma-desc: Instruct for rdmem dma (size 0x%x).\n",2105				  __func__, size));2106		/* Execute: Start pex-dma operation. */2107		rval = qla4_83xx_start_pex_dma(ha, m_hdr);2108		if (rval != QLA_SUCCESS) {2109			DEBUG2(ql4_printk(KERN_INFO, ha,2110					  "scsi(%ld): start-pex-dma failed rval=0x%x\n",2111					  ha->host_no, rval));2112			goto error_exit;2113		}2114 2115		memcpy(data_ptr, rdmem_buffer, size);2116		data_ptr += size;2117		read_size += size;2118	}2119 2120	DEBUG2(ql4_printk(KERN_INFO, ha, "Leaving fn: %s\n", __func__));2121 2122	*d_ptr = (uint32_t *)data_ptr;2123 2124error_exit:2125	if (rdmem_buffer)2126		dma_free_coherent(&ha->pdev->dev, size, rdmem_buffer,2127				  rdmem_dma);2128 2129	return rval;2130}2131 2132static int qla4_8xxx_minidump_process_l2tag(struct scsi_qla_host *ha,2133				 struct qla8xxx_minidump_entry_hdr *entry_hdr,2134				 uint32_t **d_ptr)2135{2136	uint32_t addr, r_addr, c_addr, t_r_addr;2137	uint32_t i, k, loop_count, t_value, r_cnt, r_value;2138	unsigned long p_wait, w_time, p_mask;2139	uint32_t c_value_w, c_value_r;2140	struct qla8xxx_minidump_entry_cache *cache_hdr;2141	int rval = QLA_ERROR;2142	uint32_t *data_ptr = *d_ptr;2143 2144	DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__));2145	cache_hdr = (struct qla8xxx_minidump_entry_cache *)entry_hdr;2146 2147	loop_count = cache_hdr->op_count;2148	r_addr = cache_hdr->read_addr;2149	c_addr = cache_hdr->control_addr;2150	c_value_w = cache_hdr->cache_ctrl.write_value;2151 2152	t_r_addr = cache_hdr->tag_reg_addr;2153	t_value = cache_hdr->addr_ctrl.init_tag_value;2154	r_cnt = cache_hdr->read_ctrl.read_addr_cnt;2155	p_wait = cache_hdr->cache_ctrl.poll_wait;2156	p_mask = cache_hdr->cache_ctrl.poll_mask;2157 2158	for (i = 0; i < loop_count; i++) {2159		ha->isp_ops->wr_reg_indirect(ha, t_r_addr, t_value);2160 2161		if (c_value_w)2162			ha->isp_ops->wr_reg_indirect(ha, c_addr, c_value_w);2163 2164		if (p_mask) {2165			w_time = jiffies + p_wait;2166			do {2167				ha->isp_ops->rd_reg_indirect(ha, c_addr,2168							     &c_value_r);2169				if ((c_value_r & p_mask) == 0) {2170					break;2171				} else if (time_after_eq(jiffies, w_time)) {2172					/* capturing dump failed */2173					return rval;2174				}2175			} while (1);2176		}2177 2178		addr = r_addr;2179		for (k = 0; k < r_cnt; k++) {2180			ha->isp_ops->rd_reg_indirect(ha, addr, &r_value);2181			*data_ptr++ = cpu_to_le32(r_value);2182			addr += cache_hdr->read_ctrl.read_addr_stride;2183		}2184 2185		t_value += cache_hdr->addr_ctrl.tag_value_stride;2186	}2187	*d_ptr = data_ptr;2188	return QLA_SUCCESS;2189}2190 2191static int qla4_8xxx_minidump_process_control(struct scsi_qla_host *ha,2192				struct qla8xxx_minidump_entry_hdr *entry_hdr)2193{2194	struct qla8xxx_minidump_entry_crb *crb_entry;2195	uint32_t read_value, opcode, poll_time, addr, index, rval = QLA_SUCCESS;2196	uint32_t crb_addr;2197	unsigned long wtime;2198	struct qla4_8xxx_minidump_template_hdr *tmplt_hdr;2199	int i;2200 2201	DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__));2202	tmplt_hdr = (struct qla4_8xxx_minidump_template_hdr *)2203						ha->fw_dump_tmplt_hdr;2204	crb_entry = (struct qla8xxx_minidump_entry_crb *)entry_hdr;2205 2206	crb_addr = crb_entry->addr;2207	for (i = 0; i < crb_entry->op_count; i++) {2208		opcode = crb_entry->crb_ctrl.opcode;2209		if (opcode & QLA8XXX_DBG_OPCODE_WR) {2210			ha->isp_ops->wr_reg_indirect(ha, crb_addr,2211						     crb_entry->value_1);2212			opcode &= ~QLA8XXX_DBG_OPCODE_WR;2213		}2214		if (opcode & QLA8XXX_DBG_OPCODE_RW) {2215			ha->isp_ops->rd_reg_indirect(ha, crb_addr, &read_value);2216			ha->isp_ops->wr_reg_indirect(ha, crb_addr, read_value);2217			opcode &= ~QLA8XXX_DBG_OPCODE_RW;2218		}2219		if (opcode & QLA8XXX_DBG_OPCODE_AND) {2220			ha->isp_ops->rd_reg_indirect(ha, crb_addr, &read_value);2221			read_value &= crb_entry->value_2;2222			opcode &= ~QLA8XXX_DBG_OPCODE_AND;2223			if (opcode & QLA8XXX_DBG_OPCODE_OR) {2224				read_value |= crb_entry->value_3;2225				opcode &= ~QLA8XXX_DBG_OPCODE_OR;2226			}2227			ha->isp_ops->wr_reg_indirect(ha, crb_addr, read_value);2228		}2229		if (opcode & QLA8XXX_DBG_OPCODE_OR) {2230			ha->isp_ops->rd_reg_indirect(ha, crb_addr, &read_value);2231			read_value |= crb_entry->value_3;2232			ha->isp_ops->wr_reg_indirect(ha, crb_addr, read_value);2233			opcode &= ~QLA8XXX_DBG_OPCODE_OR;2234		}2235		if (opcode & QLA8XXX_DBG_OPCODE_POLL) {2236			poll_time = crb_entry->crb_strd.poll_timeout;2237			wtime = jiffies + poll_time;2238			ha->isp_ops->rd_reg_indirect(ha, crb_addr, &read_value);2239 2240			do {2241				if ((read_value & crb_entry->value_2) ==2242				    crb_entry->value_1) {2243					break;2244				} else if (time_after_eq(jiffies, wtime)) {2245					/* capturing dump failed */2246					rval = QLA_ERROR;2247					break;2248				} else {2249					ha->isp_ops->rd_reg_indirect(ha,2250							crb_addr, &read_value);2251				}2252			} while (1);2253			opcode &= ~QLA8XXX_DBG_OPCODE_POLL;2254		}2255 2256		if (opcode & QLA8XXX_DBG_OPCODE_RDSTATE) {2257			if (crb_entry->crb_strd.state_index_a) {2258				index = crb_entry->crb_strd.state_index_a;2259				addr = tmplt_hdr->saved_state_array[index];2260			} else {2261				addr = crb_addr;2262			}2263 2264			ha->isp_ops->rd_reg_indirect(ha, addr, &read_value);2265			index = crb_entry->crb_ctrl.state_index_v;2266			tmplt_hdr->saved_state_array[index] = read_value;2267			opcode &= ~QLA8XXX_DBG_OPCODE_RDSTATE;2268		}2269 2270		if (opcode & QLA8XXX_DBG_OPCODE_WRSTATE) {2271			if (crb_entry->crb_strd.state_index_a) {2272				index = crb_entry->crb_strd.state_index_a;2273				addr = tmplt_hdr->saved_state_array[index];2274			} else {2275				addr = crb_addr;2276			}2277 2278			if (crb_entry->crb_ctrl.state_index_v) {2279				index = crb_entry->crb_ctrl.state_index_v;2280				read_value =2281					tmplt_hdr->saved_state_array[index];2282			} else {2283				read_value = crb_entry->value_1;2284			}2285 2286			ha->isp_ops->wr_reg_indirect(ha, addr, read_value);2287			opcode &= ~QLA8XXX_DBG_OPCODE_WRSTATE;2288		}2289 2290		if (opcode & QLA8XXX_DBG_OPCODE_MDSTATE) {2291			index = crb_entry->crb_ctrl.state_index_v;2292			read_value = tmplt_hdr->saved_state_array[index];2293			read_value <<= crb_entry->crb_ctrl.shl;2294			read_value >>= crb_entry->crb_ctrl.shr;2295			if (crb_entry->value_2)2296				read_value &= crb_entry->value_2;2297			read_value |= crb_entry->value_3;2298			read_value += crb_entry->value_1;2299			tmplt_hdr->saved_state_array[index] = read_value;2300			opcode &= ~QLA8XXX_DBG_OPCODE_MDSTATE;2301		}2302		crb_addr += crb_entry->crb_strd.addr_stride;2303	}2304	DEBUG2(ql4_printk(KERN_INFO, ha, "Leaving fn: %s\n", __func__));2305	return rval;2306}2307 2308static void qla4_8xxx_minidump_process_rdocm(struct scsi_qla_host *ha,2309				struct qla8xxx_minidump_entry_hdr *entry_hdr,2310				uint32_t **d_ptr)2311{2312	uint32_t r_addr, r_stride, loop_cnt, i, r_value;2313	struct qla8xxx_minidump_entry_rdocm *ocm_hdr;2314	uint32_t *data_ptr = *d_ptr;2315 2316	DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__));2317	ocm_hdr = (struct qla8xxx_minidump_entry_rdocm *)entry_hdr;2318	r_addr = ocm_hdr->read_addr;2319	r_stride = ocm_hdr->read_addr_stride;2320	loop_cnt = ocm_hdr->op_count;2321 2322	DEBUG2(ql4_printk(KERN_INFO, ha,2323			  "[%s]: r_addr: 0x%x, r_stride: 0x%x, loop_cnt: 0x%x\n",2324			  __func__, r_addr, r_stride, loop_cnt));2325 2326	for (i = 0; i < loop_cnt; i++) {2327		r_value = readl((void __iomem *)(r_addr + ha->nx_pcibase));2328		*data_ptr++ = cpu_to_le32(r_value);2329		r_addr += r_stride;2330	}2331	DEBUG2(ql4_printk(KERN_INFO, ha, "Leaving fn: %s datacount: 0x%lx\n",2332		__func__, (long unsigned int) (loop_cnt * sizeof(uint32_t))));2333	*d_ptr = data_ptr;2334}2335 2336static void qla4_8xxx_minidump_process_rdmux(struct scsi_qla_host *ha,2337				struct qla8xxx_minidump_entry_hdr *entry_hdr,2338				uint32_t **d_ptr)2339{2340	uint32_t r_addr, s_stride, s_addr, s_value, loop_cnt, i, r_value;2341	struct qla8xxx_minidump_entry_mux *mux_hdr;2342	uint32_t *data_ptr = *d_ptr;2343 2344	DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__));2345	mux_hdr = (struct qla8xxx_minidump_entry_mux *)entry_hdr;2346	r_addr = mux_hdr->read_addr;2347	s_addr = mux_hdr->select_addr;2348	s_stride = mux_hdr->select_value_stride;2349	s_value = mux_hdr->select_value;2350	loop_cnt = mux_hdr->op_count;2351 2352	for (i = 0; i < loop_cnt; i++) {2353		ha->isp_ops->wr_reg_indirect(ha, s_addr, s_value);2354		ha->isp_ops->rd_reg_indirect(ha, r_addr, &r_value);2355		*data_ptr++ = cpu_to_le32(s_value);2356		*data_ptr++ = cpu_to_le32(r_value);2357		s_value += s_stride;2358	}2359	*d_ptr = data_ptr;2360}2361 2362static void qla4_8xxx_minidump_process_l1cache(struct scsi_qla_host *ha,2363				struct qla8xxx_minidump_entry_hdr *entry_hdr,2364				uint32_t **d_ptr)2365{2366	uint32_t addr, r_addr, c_addr, t_r_addr;2367	uint32_t i, k, loop_count, t_value, r_cnt, r_value;2368	uint32_t c_value_w;2369	struct qla8xxx_minidump_entry_cache *cache_hdr;2370	uint32_t *data_ptr = *d_ptr;2371 2372	cache_hdr = (struct qla8xxx_minidump_entry_cache *)entry_hdr;2373	loop_count = cache_hdr->op_count;2374	r_addr = cache_hdr->read_addr;2375	c_addr = cache_hdr->control_addr;2376	c_value_w = cache_hdr->cache_ctrl.write_value;2377 2378	t_r_addr = cache_hdr->tag_reg_addr;2379	t_value = cache_hdr->addr_ctrl.init_tag_value;2380	r_cnt = cache_hdr->read_ctrl.read_addr_cnt;2381 2382	for (i = 0; i < loop_count; i++) {2383		ha->isp_ops->wr_reg_indirect(ha, t_r_addr, t_value);2384		ha->isp_ops->wr_reg_indirect(ha, c_addr, c_value_w);2385		addr = r_addr;2386		for (k = 0; k < r_cnt; k++) {2387			ha->isp_ops->rd_reg_indirect(ha, addr, &r_value);2388			*data_ptr++ = cpu_to_le32(r_value);2389			addr += cache_hdr->read_ctrl.read_addr_stride;2390		}2391		t_value += cache_hdr->addr_ctrl.tag_value_stride;2392	}2393	*d_ptr = data_ptr;2394}2395 2396static void qla4_8xxx_minidump_process_queue(struct scsi_qla_host *ha,2397				struct qla8xxx_minidump_entry_hdr *entry_hdr,2398				uint32_t **d_ptr)2399{2400	uint32_t s_addr, r_addr;2401	uint32_t r_stride, r_value, r_cnt, qid = 0;2402	uint32_t i, k, loop_cnt;2403	struct qla8xxx_minidump_entry_queue *q_hdr;2404	uint32_t *data_ptr = *d_ptr;2405 2406	DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__));2407	q_hdr = (struct qla8xxx_minidump_entry_queue *)entry_hdr;2408	s_addr = q_hdr->select_addr;2409	r_cnt = q_hdr->rd_strd.read_addr_cnt;2410	r_stride = q_hdr->rd_strd.read_addr_stride;2411	loop_cnt = q_hdr->op_count;2412 2413	for (i = 0; i < loop_cnt; i++) {2414		ha->isp_ops->wr_reg_indirect(ha, s_addr, qid);2415		r_addr = q_hdr->read_addr;2416		for (k = 0; k < r_cnt; k++) {2417			ha->isp_ops->rd_reg_indirect(ha, r_addr, &r_value);2418			*data_ptr++ = cpu_to_le32(r_value);2419			r_addr += r_stride;2420		}2421		qid += q_hdr->q_strd.queue_id_stride;2422	}2423	*d_ptr = data_ptr;2424}2425 2426#define MD_DIRECT_ROM_WINDOW		0x421100302427#define MD_DIRECT_ROM_READ_BASE		0x421500002428 2429static void qla4_82xx_minidump_process_rdrom(struct scsi_qla_host *ha,2430				struct qla8xxx_minidump_entry_hdr *entry_hdr,2431				uint32_t **d_ptr)2432{2433	uint32_t r_addr, r_value;2434	uint32_t i, loop_cnt;2435	struct qla8xxx_minidump_entry_rdrom *rom_hdr;2436	uint32_t *data_ptr = *d_ptr;2437 2438	DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__));2439	rom_hdr = (struct qla8xxx_minidump_entry_rdrom *)entry_hdr;2440	r_addr = rom_hdr->read_addr;2441	loop_cnt = rom_hdr->read_data_size/sizeof(uint32_t);2442 2443	DEBUG2(ql4_printk(KERN_INFO, ha,2444			  "[%s]: flash_addr: 0x%x, read_data_size: 0x%x\n",2445			   __func__, r_addr, loop_cnt));2446 2447	for (i = 0; i < loop_cnt; i++) {2448		ha->isp_ops->wr_reg_indirect(ha, MD_DIRECT_ROM_WINDOW,2449					     (r_addr & 0xFFFF0000));2450		ha->isp_ops->rd_reg_indirect(ha,2451				MD_DIRECT_ROM_READ_BASE + (r_addr & 0x0000FFFF),2452				&r_value);2453		*data_ptr++ = cpu_to_le32(r_value);2454		r_addr += sizeof(uint32_t);2455	}2456	*d_ptr = data_ptr;2457}2458 2459#define MD_MIU_TEST_AGT_CTRL		0x410000902460#define MD_MIU_TEST_AGT_ADDR_LO		0x410000942461#define MD_MIU_TEST_AGT_ADDR_HI		0x410000982462 2463static int __qla4_8xxx_minidump_process_rdmem(struct scsi_qla_host *ha,2464				struct qla8xxx_minidump_entry_hdr *entry_hdr,2465				uint32_t **d_ptr)2466{2467	uint32_t r_addr, r_value, r_data;2468	uint32_t i, j, loop_cnt;2469	struct qla8xxx_minidump_entry_rdmem *m_hdr;2470	unsigned long flags;2471	uint32_t *data_ptr = *d_ptr;2472 2473	DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__));2474	m_hdr = (struct qla8xxx_minidump_entry_rdmem *)entry_hdr;2475	r_addr = m_hdr->read_addr;2476	loop_cnt = m_hdr->read_data_size/16;2477 2478	DEBUG2(ql4_printk(KERN_INFO, ha,2479			  "[%s]: Read addr: 0x%x, read_data_size: 0x%x\n",2480			  __func__, r_addr, m_hdr->read_data_size));2481 2482	if (r_addr & 0xf) {2483		DEBUG2(ql4_printk(KERN_INFO, ha,2484				  "[%s]: Read addr 0x%x not 16 bytes aligned\n",2485				  __func__, r_addr));2486		return QLA_ERROR;2487	}2488 2489	if (m_hdr->read_data_size % 16) {2490		DEBUG2(ql4_printk(KERN_INFO, ha,2491				  "[%s]: Read data[0x%x] not multiple of 16 bytes\n",2492				  __func__, m_hdr->read_data_size));2493		return QLA_ERROR;2494	}2495 2496	DEBUG2(ql4_printk(KERN_INFO, ha,2497			  "[%s]: rdmem_addr: 0x%x, read_data_size: 0x%x, loop_cnt: 0x%x\n",2498			  __func__, r_addr, m_hdr->read_data_size, loop_cnt));2499 2500	write_lock_irqsave(&ha->hw_lock, flags);2501	for (i = 0; i < loop_cnt; i++) {2502		ha->isp_ops->wr_reg_indirect(ha, MD_MIU_TEST_AGT_ADDR_LO,2503					     r_addr);2504		r_value = 0;2505		ha->isp_ops->wr_reg_indirect(ha, MD_MIU_TEST_AGT_ADDR_HI,2506					     r_value);2507		r_value = MIU_TA_CTL_ENABLE;2508		ha->isp_ops->wr_reg_indirect(ha, MD_MIU_TEST_AGT_CTRL, r_value);2509		r_value = MIU_TA_CTL_START_ENABLE;2510		ha->isp_ops->wr_reg_indirect(ha, MD_MIU_TEST_AGT_CTRL, r_value);2511 2512		for (j = 0; j < MAX_CTL_CHECK; j++) {2513			ha->isp_ops->rd_reg_indirect(ha, MD_MIU_TEST_AGT_CTRL,2514						     &r_value);2515			if ((r_value & MIU_TA_CTL_BUSY) == 0)2516				break;2517		}2518 2519		if (j >= MAX_CTL_CHECK) {2520			printk_ratelimited(KERN_ERR2521					   "%s: failed to read through agent\n",2522					    __func__);2523			write_unlock_irqrestore(&ha->hw_lock, flags);2524			return QLA_SUCCESS;2525		}2526 2527		for (j = 0; j < 4; j++) {2528			ha->isp_ops->rd_reg_indirect(ha,2529						     MD_MIU_TEST_AGT_RDDATA[j],2530						     &r_data);2531			*data_ptr++ = cpu_to_le32(r_data);2532		}2533 2534		r_addr += 16;2535	}2536	write_unlock_irqrestore(&ha->hw_lock, flags);2537 2538	DEBUG2(ql4_printk(KERN_INFO, ha, "Leaving fn: %s datacount: 0x%x\n",2539			  __func__, (loop_cnt * 16)));2540 2541	*d_ptr = data_ptr;2542	return QLA_SUCCESS;2543}2544 2545static int qla4_8xxx_minidump_process_rdmem(struct scsi_qla_host *ha,2546				struct qla8xxx_minidump_entry_hdr *entry_hdr,2547				uint32_t **d_ptr)2548{2549	uint32_t *data_ptr = *d_ptr;2550	int rval = QLA_SUCCESS;2551 2552	rval = qla4_8xxx_minidump_pex_dma_read(ha, entry_hdr, &data_ptr);2553	if (rval != QLA_SUCCESS)2554		rval = __qla4_8xxx_minidump_process_rdmem(ha, entry_hdr,2555							  &data_ptr);2556	*d_ptr = data_ptr;2557	return rval;2558}2559 2560static void qla4_8xxx_mark_entry_skipped(struct scsi_qla_host *ha,2561				struct qla8xxx_minidump_entry_hdr *entry_hdr,2562				int index)2563{2564	entry_hdr->d_ctrl.driver_flags |= QLA8XXX_DBG_SKIPPED_FLAG;2565	DEBUG2(ql4_printk(KERN_INFO, ha,2566			  "scsi(%ld): Skipping entry[%d]: ETYPE[0x%x]-ELEVEL[0x%x]\n",2567			  ha->host_no, index, entry_hdr->entry_type,2568			  entry_hdr->d_ctrl.entry_capture_mask));2569	/* If driver encounters a new entry type that it cannot process,2570	 * it should just skip the entry and adjust the total buffer size by2571	 * from subtracting the skipped bytes from it2572	 */2573	ha->fw_dump_skip_size += entry_hdr->entry_capture_size;2574}2575 2576/* ISP83xx functions to process new minidump entries... */2577static uint32_t qla83xx_minidump_process_pollrd(struct scsi_qla_host *ha,2578				struct qla8xxx_minidump_entry_hdr *entry_hdr,2579				uint32_t **d_ptr)2580{2581	uint32_t r_addr, s_addr, s_value, r_value, poll_wait, poll_mask;2582	uint16_t s_stride, i;2583	uint32_t *data_ptr = *d_ptr;2584	uint32_t rval = QLA_SUCCESS;2585	struct qla83xx_minidump_entry_pollrd *pollrd_hdr;2586 2587	pollrd_hdr = (struct qla83xx_minidump_entry_pollrd *)entry_hdr;2588	s_addr = le32_to_cpu(pollrd_hdr->select_addr);2589	r_addr = le32_to_cpu(pollrd_hdr->read_addr);2590	s_value = le32_to_cpu(pollrd_hdr->select_value);2591	s_stride = le32_to_cpu(pollrd_hdr->select_value_stride);2592 2593	poll_wait = le32_to_cpu(pollrd_hdr->poll_wait);2594	poll_mask = le32_to_cpu(pollrd_hdr->poll_mask);2595 2596	for (i = 0; i < le32_to_cpu(pollrd_hdr->op_count); i++) {2597		ha->isp_ops->wr_reg_indirect(ha, s_addr, s_value);2598		poll_wait = le32_to_cpu(pollrd_hdr->poll_wait);2599		while (1) {2600			ha->isp_ops->rd_reg_indirect(ha, s_addr, &r_value);2601 2602			if ((r_value & poll_mask) != 0) {2603				break;2604			} else {2605				msleep(1);2606				if (--poll_wait == 0) {2607					ql4_printk(KERN_ERR, ha, "%s: TIMEOUT\n",2608						   __func__);2609					rval = QLA_ERROR;2610					goto exit_process_pollrd;2611				}2612			}2613		}2614		ha->isp_ops->rd_reg_indirect(ha, r_addr, &r_value);2615		*data_ptr++ = cpu_to_le32(s_value);2616		*data_ptr++ = cpu_to_le32(r_value);2617		s_value += s_stride;2618	}2619 2620	*d_ptr = data_ptr;2621 2622exit_process_pollrd:2623	return rval;2624}2625 2626static uint32_t qla4_84xx_minidump_process_rddfe(struct scsi_qla_host *ha,2627				struct qla8xxx_minidump_entry_hdr *entry_hdr,2628				uint32_t **d_ptr)2629{2630	int loop_cnt;2631	uint32_t addr1, addr2, value, data, temp, wrval;2632	uint8_t stride, stride2;2633	uint16_t count;2634	uint32_t poll, mask, modify_mask;2635	uint32_t wait_count = 0;2636	uint32_t *data_ptr = *d_ptr;2637	struct qla8044_minidump_entry_rddfe *rddfe;2638	uint32_t rval = QLA_SUCCESS;2639 2640	rddfe = (struct qla8044_minidump_entry_rddfe *)entry_hdr;2641	addr1 = le32_to_cpu(rddfe->addr_1);2642	value = le32_to_cpu(rddfe->value);2643	stride = le32_to_cpu(rddfe->stride);2644	stride2 = le32_to_cpu(rddfe->stride2);2645	count = le32_to_cpu(rddfe->count);2646 2647	poll = le32_to_cpu(rddfe->poll);2648	mask = le32_to_cpu(rddfe->mask);2649	modify_mask = le32_to_cpu(rddfe->modify_mask);2650 2651	addr2 = addr1 + stride;2652 2653	for (loop_cnt = 0x0; loop_cnt < count; loop_cnt++) {2654		ha->isp_ops->wr_reg_indirect(ha, addr1, (0x40000000 | value));2655 2656		wait_count = 0;2657		while (wait_count < poll) {2658			ha->isp_ops->rd_reg_indirect(ha, addr1, &temp);2659			if ((temp & mask) != 0)2660				break;2661			wait_count++;2662		}2663 2664		if (wait_count == poll) {2665			ql4_printk(KERN_ERR, ha, "%s: TIMEOUT\n", __func__);2666			rval = QLA_ERROR;2667			goto exit_process_rddfe;2668		} else {2669			ha->isp_ops->rd_reg_indirect(ha, addr2, &temp);2670			temp = temp & modify_mask;2671			temp = (temp | ((loop_cnt << 16) | loop_cnt));2672			wrval = ((temp << 16) | temp);2673 2674			ha->isp_ops->wr_reg_indirect(ha, addr2, wrval);2675			ha->isp_ops->wr_reg_indirect(ha, addr1, value);2676 2677			wait_count = 0;2678			while (wait_count < poll) {2679				ha->isp_ops->rd_reg_indirect(ha, addr1, &temp);2680				if ((temp & mask) != 0)2681					break;2682				wait_count++;2683			}2684			if (wait_count == poll) {2685				ql4_printk(KERN_ERR, ha, "%s: TIMEOUT\n",2686					   __func__);2687				rval = QLA_ERROR;2688				goto exit_process_rddfe;2689			}2690 2691			ha->isp_ops->wr_reg_indirect(ha, addr1,2692						     ((0x40000000 | value) +2693						     stride2));2694			wait_count = 0;2695			while (wait_count < poll) {2696				ha->isp_ops->rd_reg_indirect(ha, addr1, &temp);2697				if ((temp & mask) != 0)2698					break;2699				wait_count++;2700			}2701 2702			if (wait_count == poll) {2703				ql4_printk(KERN_ERR, ha, "%s: TIMEOUT\n",2704					   __func__);2705				rval = QLA_ERROR;2706				goto exit_process_rddfe;2707			}2708 2709			ha->isp_ops->rd_reg_indirect(ha, addr2, &data);2710 2711			*data_ptr++ = cpu_to_le32(wrval);2712			*data_ptr++ = cpu_to_le32(data);2713		}2714	}2715 2716	*d_ptr = data_ptr;2717exit_process_rddfe:2718	return rval;2719}2720 2721static uint32_t qla4_84xx_minidump_process_rdmdio(struct scsi_qla_host *ha,2722				struct qla8xxx_minidump_entry_hdr *entry_hdr,2723				uint32_t **d_ptr)2724{2725	int rval = QLA_SUCCESS;2726	uint32_t addr1, addr2, value1, value2, data, selval;2727	uint8_t stride1, stride2;2728	uint32_t addr3, addr4, addr5, addr6, addr7;2729	uint16_t count, loop_cnt;2730	uint32_t mask;2731	uint32_t *data_ptr = *d_ptr;2732	struct qla8044_minidump_entry_rdmdio *rdmdio;2733 2734	rdmdio = (struct qla8044_minidump_entry_rdmdio *)entry_hdr;2735	addr1 = le32_to_cpu(rdmdio->addr_1);2736	addr2 = le32_to_cpu(rdmdio->addr_2);2737	value1 = le32_to_cpu(rdmdio->value_1);2738	stride1 = le32_to_cpu(rdmdio->stride_1);2739	stride2 = le32_to_cpu(rdmdio->stride_2);2740	count = le32_to_cpu(rdmdio->count);2741 2742	mask = le32_to_cpu(rdmdio->mask);2743	value2 = le32_to_cpu(rdmdio->value_2);2744 2745	addr3 = addr1 + stride1;2746 2747	for (loop_cnt = 0; loop_cnt < count; loop_cnt++) {2748		rval = ql4_84xx_poll_wait_ipmdio_bus_idle(ha, addr1, addr2,2749							 addr3, mask);2750		if (rval)2751			goto exit_process_rdmdio;2752 2753		addr4 = addr2 - stride1;2754		rval = ql4_84xx_ipmdio_wr_reg(ha, addr1, addr3, mask, addr4,2755					     value2);2756		if (rval)2757			goto exit_process_rdmdio;2758 2759		addr5 = addr2 - (2 * stride1);2760		rval = ql4_84xx_ipmdio_wr_reg(ha, addr1, addr3, mask, addr5,2761					     value1);2762		if (rval)2763			goto exit_process_rdmdio;2764 2765		addr6 = addr2 - (3 * stride1);2766		rval = ql4_84xx_ipmdio_wr_reg(ha, addr1, addr3, mask,2767					     addr6, 0x2);2768		if (rval)2769			goto exit_process_rdmdio;2770 2771		rval = ql4_84xx_poll_wait_ipmdio_bus_idle(ha, addr1, addr2,2772							 addr3, mask);2773		if (rval)2774			goto exit_process_rdmdio;2775 2776		addr7 = addr2 - (4 * stride1);2777		rval = ql4_84xx_ipmdio_rd_reg(ha, addr1, addr3,2778						      mask, addr7, &data);2779		if (rval)2780			goto exit_process_rdmdio;2781 2782		selval = (value2 << 18) | (value1 << 2) | 2;2783 2784		stride2 = le32_to_cpu(rdmdio->stride_2);2785		*data_ptr++ = cpu_to_le32(selval);2786		*data_ptr++ = cpu_to_le32(data);2787 2788		value1 = value1 + stride2;2789		*d_ptr = data_ptr;2790	}2791 2792exit_process_rdmdio:2793	return rval;2794}2795 2796static uint32_t qla4_84xx_minidump_process_pollwr(struct scsi_qla_host *ha,2797				struct qla8xxx_minidump_entry_hdr *entry_hdr,2798				uint32_t **d_ptr)2799{2800	uint32_t addr1, addr2, value1, value2, poll, r_value;2801	struct qla8044_minidump_entry_pollwr *pollwr_hdr;2802	uint32_t wait_count = 0;2803	uint32_t rval = QLA_SUCCESS;2804 2805	pollwr_hdr = (struct qla8044_minidump_entry_pollwr *)entry_hdr;2806	addr1 = le32_to_cpu(pollwr_hdr->addr_1);2807	addr2 = le32_to_cpu(pollwr_hdr->addr_2);2808	value1 = le32_to_cpu(pollwr_hdr->value_1);2809	value2 = le32_to_cpu(pollwr_hdr->value_2);2810 2811	poll = le32_to_cpu(pollwr_hdr->poll);2812 2813	while (wait_count < poll) {2814		ha->isp_ops->rd_reg_indirect(ha, addr1, &r_value);2815 2816		if ((r_value & poll) != 0)2817			break;2818 2819		wait_count++;2820	}2821 2822	if (wait_count == poll) {2823		ql4_printk(KERN_ERR, ha, "%s: TIMEOUT\n", __func__);2824		rval = QLA_ERROR;2825		goto exit_process_pollwr;2826	}2827 2828	ha->isp_ops->wr_reg_indirect(ha, addr2, value2);2829	ha->isp_ops->wr_reg_indirect(ha, addr1, value1);2830 2831	wait_count = 0;2832	while (wait_count < poll) {2833		ha->isp_ops->rd_reg_indirect(ha, addr1, &r_value);2834 2835		if ((r_value & poll) != 0)2836			break;2837		wait_count++;2838	}2839 2840exit_process_pollwr:2841	return rval;2842}2843 2844static void qla83xx_minidump_process_rdmux2(struct scsi_qla_host *ha,2845				struct qla8xxx_minidump_entry_hdr *entry_hdr,2846				uint32_t **d_ptr)2847{2848	uint32_t sel_val1, sel_val2, t_sel_val, data, i;2849	uint32_t sel_addr1, sel_addr2, sel_val_mask, read_addr;2850	struct qla83xx_minidump_entry_rdmux2 *rdmux2_hdr;2851	uint32_t *data_ptr = *d_ptr;2852 2853	rdmux2_hdr = (struct qla83xx_minidump_entry_rdmux2 *)entry_hdr;2854	sel_val1 = le32_to_cpu(rdmux2_hdr->select_value_1);2855	sel_val2 = le32_to_cpu(rdmux2_hdr->select_value_2);2856	sel_addr1 = le32_to_cpu(rdmux2_hdr->select_addr_1);2857	sel_addr2 = le32_to_cpu(rdmux2_hdr->select_addr_2);2858	sel_val_mask = le32_to_cpu(rdmux2_hdr->select_value_mask);2859	read_addr = le32_to_cpu(rdmux2_hdr->read_addr);2860 2861	for (i = 0; i < rdmux2_hdr->op_count; i++) {2862		ha->isp_ops->wr_reg_indirect(ha, sel_addr1, sel_val1);2863		t_sel_val = sel_val1 & sel_val_mask;2864		*data_ptr++ = cpu_to_le32(t_sel_val);2865 2866		ha->isp_ops->wr_reg_indirect(ha, sel_addr2, t_sel_val);2867		ha->isp_ops->rd_reg_indirect(ha, read_addr, &data);2868 2869		*data_ptr++ = cpu_to_le32(data);2870 2871		ha->isp_ops->wr_reg_indirect(ha, sel_addr1, sel_val2);2872		t_sel_val = sel_val2 & sel_val_mask;2873		*data_ptr++ = cpu_to_le32(t_sel_val);2874 2875		ha->isp_ops->wr_reg_indirect(ha, sel_addr2, t_sel_val);2876		ha->isp_ops->rd_reg_indirect(ha, read_addr, &data);2877 2878		*data_ptr++ = cpu_to_le32(data);2879 2880		sel_val1 += rdmux2_hdr->select_value_stride;2881		sel_val2 += rdmux2_hdr->select_value_stride;2882	}2883 2884	*d_ptr = data_ptr;2885}2886 2887static uint32_t qla83xx_minidump_process_pollrdmwr(struct scsi_qla_host *ha,2888				struct qla8xxx_minidump_entry_hdr *entry_hdr,2889				uint32_t **d_ptr)2890{2891	uint32_t poll_wait, poll_mask, r_value, data;2892	uint32_t addr_1, addr_2, value_1, value_2;2893	uint32_t *data_ptr = *d_ptr;2894	uint32_t rval = QLA_SUCCESS;2895	struct qla83xx_minidump_entry_pollrdmwr *poll_hdr;2896 2897	poll_hdr = (struct qla83xx_minidump_entry_pollrdmwr *)entry_hdr;2898	addr_1 = le32_to_cpu(poll_hdr->addr_1);2899	addr_2 = le32_to_cpu(poll_hdr->addr_2);2900	value_1 = le32_to_cpu(poll_hdr->value_1);2901	value_2 = le32_to_cpu(poll_hdr->value_2);2902	poll_mask = le32_to_cpu(poll_hdr->poll_mask);2903 2904	ha->isp_ops->wr_reg_indirect(ha, addr_1, value_1);2905 2906	poll_wait = le32_to_cpu(poll_hdr->poll_wait);2907	while (1) {2908		ha->isp_ops->rd_reg_indirect(ha, addr_1, &r_value);2909 2910		if ((r_value & poll_mask) != 0) {2911			break;2912		} else {2913			msleep(1);2914			if (--poll_wait == 0) {2915				ql4_printk(KERN_ERR, ha, "%s: TIMEOUT_1\n",2916					   __func__);2917				rval = QLA_ERROR;2918				goto exit_process_pollrdmwr;2919			}2920		}2921	}2922 2923	ha->isp_ops->rd_reg_indirect(ha, addr_2, &data);2924	data &= le32_to_cpu(poll_hdr->modify_mask);2925	ha->isp_ops->wr_reg_indirect(ha, addr_2, data);2926	ha->isp_ops->wr_reg_indirect(ha, addr_1, value_2);2927 2928	poll_wait = le32_to_cpu(poll_hdr->poll_wait);2929	while (1) {2930		ha->isp_ops->rd_reg_indirect(ha, addr_1, &r_value);2931 2932		if ((r_value & poll_mask) != 0) {2933			break;2934		} else {2935			msleep(1);2936			if (--poll_wait == 0) {2937				ql4_printk(KERN_ERR, ha, "%s: TIMEOUT_2\n",2938					   __func__);2939				rval = QLA_ERROR;2940				goto exit_process_pollrdmwr;2941			}2942		}2943	}2944 2945	*data_ptr++ = cpu_to_le32(addr_2);2946	*data_ptr++ = cpu_to_le32(data);2947	*d_ptr = data_ptr;2948 2949exit_process_pollrdmwr:2950	return rval;2951}2952 2953static uint32_t qla4_83xx_minidump_process_rdrom(struct scsi_qla_host *ha,2954				struct qla8xxx_minidump_entry_hdr *entry_hdr,2955				uint32_t **d_ptr)2956{2957	uint32_t fl_addr, u32_count, rval;2958	struct qla8xxx_minidump_entry_rdrom *rom_hdr;2959	uint32_t *data_ptr = *d_ptr;2960 2961	rom_hdr = (struct qla8xxx_minidump_entry_rdrom *)entry_hdr;2962	fl_addr = le32_to_cpu(rom_hdr->read_addr);2963	u32_count = le32_to_cpu(rom_hdr->read_data_size)/sizeof(uint32_t);2964 2965	DEBUG2(ql4_printk(KERN_INFO, ha, "[%s]: fl_addr: 0x%x, count: 0x%x\n",2966			  __func__, fl_addr, u32_count));2967 2968	rval = qla4_83xx_lockless_flash_read_u32(ha, fl_addr,2969						 (u8 *)(data_ptr), u32_count);2970 2971	if (rval == QLA_ERROR) {2972		ql4_printk(KERN_ERR, ha, "%s: Flash Read Error,Count=%d\n",2973			   __func__, u32_count);2974		goto exit_process_rdrom;2975	}2976 2977	data_ptr += u32_count;2978	*d_ptr = data_ptr;2979 2980exit_process_rdrom:2981	return rval;2982}2983 2984/**2985 * qla4_8xxx_collect_md_data - Retrieve firmware minidump data.2986 * @ha: pointer to adapter structure2987 **/2988static int qla4_8xxx_collect_md_data(struct scsi_qla_host *ha)2989{2990	int num_entry_hdr = 0;2991	struct qla8xxx_minidump_entry_hdr *entry_hdr;2992	struct qla4_8xxx_minidump_template_hdr *tmplt_hdr;2993	uint32_t *data_ptr;2994	uint32_t data_collected = 0;2995	int i, rval = QLA_ERROR;2996	uint64_t now;2997	uint32_t timestamp;2998 2999	ha->fw_dump_skip_size = 0;3000	if (!ha->fw_dump) {3001		ql4_printk(KERN_INFO, ha, "%s(%ld) No buffer to dump\n",3002			   __func__, ha->host_no);3003		return rval;3004	}3005 3006	tmplt_hdr = (struct qla4_8xxx_minidump_template_hdr *)3007						ha->fw_dump_tmplt_hdr;3008	data_ptr = (uint32_t *)((uint8_t *)ha->fw_dump +3009						ha->fw_dump_tmplt_size);3010	data_collected += ha->fw_dump_tmplt_size;3011 3012	num_entry_hdr = tmplt_hdr->num_of_entries;3013	ql4_printk(KERN_INFO, ha, "[%s]: starting data ptr: %p\n",3014		   __func__, data_ptr);3015	ql4_printk(KERN_INFO, ha,3016		   "[%s]: no of entry headers in Template: 0x%x\n",3017		   __func__, num_entry_hdr);3018	ql4_printk(KERN_INFO, ha, "[%s]: Capture Mask obtained: 0x%x\n",3019		   __func__, ha->fw_dump_capture_mask);3020	ql4_printk(KERN_INFO, ha, "[%s]: Total_data_size 0x%x, %d obtained\n",3021		   __func__, ha->fw_dump_size, ha->fw_dump_size);3022 3023	/* Update current timestamp before taking dump */3024	now = get_jiffies_64();3025	timestamp = (u32)(jiffies_to_msecs(now) / 1000);3026	tmplt_hdr->driver_timestamp = timestamp;3027 3028	entry_hdr = (struct qla8xxx_minidump_entry_hdr *)3029					(((uint8_t *)ha->fw_dump_tmplt_hdr) +3030					 tmplt_hdr->first_entry_offset);3031 3032	if (is_qla8032(ha) || is_qla8042(ha))3033		tmplt_hdr->saved_state_array[QLA83XX_SS_OCM_WNDREG_INDEX] =3034					tmplt_hdr->ocm_window_reg[ha->func_num];3035 3036	/* Walk through the entry headers - validate/perform required action */3037	for (i = 0; i < num_entry_hdr; i++) {3038		if (data_collected > ha->fw_dump_size) {3039			ql4_printk(KERN_INFO, ha,3040				   "Data collected: [0x%x], Total Dump size: [0x%x]\n",3041				   data_collected, ha->fw_dump_size);3042			return rval;3043		}3044 3045		if (!(entry_hdr->d_ctrl.entry_capture_mask &3046		      ha->fw_dump_capture_mask)) {3047			entry_hdr->d_ctrl.driver_flags |=3048						QLA8XXX_DBG_SKIPPED_FLAG;3049			goto skip_nxt_entry;3050		}3051 3052		DEBUG2(ql4_printk(KERN_INFO, ha,3053				  "Data collected: [0x%x], Dump size left:[0x%x]\n",3054				  data_collected,3055				  (ha->fw_dump_size - data_collected)));3056 3057		/* Decode the entry type and take required action to capture3058		 * debug data3059		 */3060		switch (entry_hdr->entry_type) {3061		case QLA8XXX_RDEND:3062			qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i);3063			break;3064		case QLA8XXX_CNTRL:3065			rval = qla4_8xxx_minidump_process_control(ha,3066								  entry_hdr);3067			if (rval != QLA_SUCCESS) {3068				qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i);3069				goto md_failed;3070			}3071			break;3072		case QLA8XXX_RDCRB:3073			qla4_8xxx_minidump_process_rdcrb(ha, entry_hdr,3074							 &data_ptr);3075			break;3076		case QLA8XXX_RDMEM:3077			rval = qla4_8xxx_minidump_process_rdmem(ha, entry_hdr,3078								&data_ptr);3079			if (rval != QLA_SUCCESS) {3080				qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i);3081				goto md_failed;3082			}3083			break;3084		case QLA8XXX_BOARD:3085		case QLA8XXX_RDROM:3086			if (is_qla8022(ha)) {3087				qla4_82xx_minidump_process_rdrom(ha, entry_hdr,3088								 &data_ptr);3089			} else if (is_qla8032(ha) || is_qla8042(ha)) {3090				rval = qla4_83xx_minidump_process_rdrom(ha,3091								    entry_hdr,3092								    &data_ptr);3093				if (rval != QLA_SUCCESS)3094					qla4_8xxx_mark_entry_skipped(ha,3095								     entry_hdr,3096								     i);3097			}3098			break;3099		case QLA8XXX_L2DTG:3100		case QLA8XXX_L2ITG:3101		case QLA8XXX_L2DAT:3102		case QLA8XXX_L2INS:3103			rval = qla4_8xxx_minidump_process_l2tag(ha, entry_hdr,3104								&data_ptr);3105			if (rval != QLA_SUCCESS) {3106				qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i);3107				goto md_failed;3108			}3109			break;3110		case QLA8XXX_L1DTG:3111		case QLA8XXX_L1ITG:3112		case QLA8XXX_L1DAT:3113		case QLA8XXX_L1INS:3114			qla4_8xxx_minidump_process_l1cache(ha, entry_hdr,3115							   &data_ptr);3116			break;3117		case QLA8XXX_RDOCM:3118			qla4_8xxx_minidump_process_rdocm(ha, entry_hdr,3119							 &data_ptr);3120			break;3121		case QLA8XXX_RDMUX:3122			qla4_8xxx_minidump_process_rdmux(ha, entry_hdr,3123							 &data_ptr);3124			break;3125		case QLA8XXX_QUEUE:3126			qla4_8xxx_minidump_process_queue(ha, entry_hdr,3127							 &data_ptr);3128			break;3129		case QLA83XX_POLLRD:3130			if (is_qla8022(ha)) {3131				qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i);3132				break;3133			}3134			rval = qla83xx_minidump_process_pollrd(ha, entry_hdr,3135							       &data_ptr);3136			if (rval != QLA_SUCCESS)3137				qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i);3138			break;3139		case QLA83XX_RDMUX2:3140			if (is_qla8022(ha)) {3141				qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i);3142				break;3143			}3144			qla83xx_minidump_process_rdmux2(ha, entry_hdr,3145							&data_ptr);3146			break;3147		case QLA83XX_POLLRDMWR:3148			if (is_qla8022(ha)) {3149				qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i);3150				break;3151			}3152			rval = qla83xx_minidump_process_pollrdmwr(ha, entry_hdr,3153								  &data_ptr);3154			if (rval != QLA_SUCCESS)3155				qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i);3156			break;3157		case QLA8044_RDDFE:3158			rval = qla4_84xx_minidump_process_rddfe(ha, entry_hdr,3159								&data_ptr);3160			if (rval != QLA_SUCCESS)3161				qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i);3162			break;3163		case QLA8044_RDMDIO:3164			rval = qla4_84xx_minidump_process_rdmdio(ha, entry_hdr,3165								 &data_ptr);3166			if (rval != QLA_SUCCESS)3167				qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i);3168			break;3169		case QLA8044_POLLWR:3170			rval = qla4_84xx_minidump_process_pollwr(ha, entry_hdr,3171								 &data_ptr);3172			if (rval != QLA_SUCCESS)3173				qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i);3174			break;3175		case QLA8XXX_RDNOP:3176		default:3177			qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i);3178			break;3179		}3180 3181		data_collected = (uint8_t *)data_ptr - (uint8_t *)ha->fw_dump;3182skip_nxt_entry:3183		/*  next entry in the template */3184		entry_hdr = (struct qla8xxx_minidump_entry_hdr *)3185				(((uint8_t *)entry_hdr) +3186				 entry_hdr->entry_size);3187	}3188 3189	if ((data_collected + ha->fw_dump_skip_size) != ha->fw_dump_size) {3190		ql4_printk(KERN_INFO, ha,3191			   "Dump data mismatch: Data collected: [0x%x], total_data_size:[0x%x]\n",3192			   data_collected, ha->fw_dump_size);3193		rval = QLA_ERROR;3194		goto md_failed;3195	}3196 3197	DEBUG2(ql4_printk(KERN_INFO, ha, "Leaving fn: %s Last entry: 0x%x\n",3198			  __func__, i));3199md_failed:3200	return rval;3201}3202 3203/**3204 * qla4_8xxx_uevent_emit - Send uevent when the firmware dump is ready.3205 * @ha: pointer to adapter structure3206 * @code: uevent code to act upon3207 **/3208static void qla4_8xxx_uevent_emit(struct scsi_qla_host *ha, u32 code)3209{3210	char event_string[40];3211	char *envp[] = { event_string, NULL };3212 3213	switch (code) {3214	case QL4_UEVENT_CODE_FW_DUMP:3215		snprintf(event_string, sizeof(event_string), "FW_DUMP=%lu",3216			 ha->host_no);3217		break;3218	default:3219		/*do nothing*/3220		break;3221	}3222 3223	kobject_uevent_env(&(&ha->pdev->dev)->kobj, KOBJ_CHANGE, envp);3224}3225 3226void qla4_8xxx_get_minidump(struct scsi_qla_host *ha)3227{3228	if (ql4xenablemd && test_bit(AF_FW_RECOVERY, &ha->flags) &&3229	    !test_bit(AF_82XX_FW_DUMPED, &ha->flags)) {3230		if (!qla4_8xxx_collect_md_data(ha)) {3231			qla4_8xxx_uevent_emit(ha, QL4_UEVENT_CODE_FW_DUMP);3232			set_bit(AF_82XX_FW_DUMPED, &ha->flags);3233		} else {3234			ql4_printk(KERN_INFO, ha, "%s: Unable to collect minidump\n",3235				   __func__);3236		}3237	}3238}3239 3240/**3241 * qla4_8xxx_device_bootstrap - Initialize device, set DEV_READY, start fw3242 * @ha: pointer to adapter structure3243 *3244 * Note: IDC lock must be held upon entry3245 **/3246int qla4_8xxx_device_bootstrap(struct scsi_qla_host *ha)3247{3248	int rval = QLA_ERROR;3249	int i;3250	uint32_t old_count, count;3251	int need_reset = 0;3252 3253	need_reset = ha->isp_ops->need_reset(ha);3254 3255	if (need_reset) {3256		/* We are trying to perform a recovery here. */3257		if (test_bit(AF_FW_RECOVERY, &ha->flags))3258			ha->isp_ops->rom_lock_recovery(ha);3259	} else  {3260		old_count = qla4_8xxx_rd_direct(ha, QLA8XXX_PEG_ALIVE_COUNTER);3261		for (i = 0; i < 10; i++) {3262			msleep(200);3263			count = qla4_8xxx_rd_direct(ha,3264						    QLA8XXX_PEG_ALIVE_COUNTER);3265			if (count != old_count) {3266				rval = QLA_SUCCESS;3267				goto dev_ready;3268			}3269		}3270		ha->isp_ops->rom_lock_recovery(ha);3271	}3272 3273	/* set to DEV_INITIALIZING */3274	ql4_printk(KERN_INFO, ha, "HW State: INITIALIZING\n");3275	qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DEV_STATE,3276			    QLA8XXX_DEV_INITIALIZING);3277 3278	ha->isp_ops->idc_unlock(ha);3279 3280	if (is_qla8022(ha))3281		qla4_8xxx_get_minidump(ha);3282 3283	rval = ha->isp_ops->restart_firmware(ha);3284	ha->isp_ops->idc_lock(ha);3285 3286	if (rval != QLA_SUCCESS) {3287		ql4_printk(KERN_INFO, ha, "HW State: FAILED\n");3288		qla4_8xxx_clear_drv_active(ha);3289		qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DEV_STATE,3290				    QLA8XXX_DEV_FAILED);3291		return rval;3292	}3293 3294dev_ready:3295	ql4_printk(KERN_INFO, ha, "HW State: READY\n");3296	qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DEV_STATE, QLA8XXX_DEV_READY);3297 3298	return rval;3299}3300 3301/**3302 * qla4_82xx_need_reset_handler - Code to start reset sequence3303 * @ha: pointer to adapter structure3304 *3305 * Note: IDC lock must be held upon entry3306 **/3307static void3308qla4_82xx_need_reset_handler(struct scsi_qla_host *ha)3309{3310	uint32_t dev_state, drv_state, drv_active;3311	uint32_t active_mask = 0xFFFFFFFF;3312	unsigned long reset_timeout;3313 3314	ql4_printk(KERN_INFO, ha,3315		"Performing ISP error recovery\n");3316 3317	if (test_and_clear_bit(AF_ONLINE, &ha->flags)) {3318		qla4_82xx_idc_unlock(ha);3319		ha->isp_ops->disable_intrs(ha);3320		qla4_82xx_idc_lock(ha);3321	}3322 3323	if (!test_bit(AF_8XXX_RST_OWNER, &ha->flags)) {3324		DEBUG2(ql4_printk(KERN_INFO, ha,3325				  "%s(%ld): reset acknowledged\n",3326				  __func__, ha->host_no));3327		qla4_8xxx_set_rst_ready(ha);3328	} else {3329		active_mask = (~(1 << (ha->func_num * 4)));3330	}3331 3332	/* wait for 10 seconds for reset ack from all functions */3333	reset_timeout = jiffies + (ha->nx_reset_timeout * HZ);3334 3335	drv_state = qla4_82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE);3336	drv_active = qla4_82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE);3337 3338	ql4_printk(KERN_INFO, ha,3339		"%s(%ld): drv_state = 0x%x, drv_active = 0x%x\n",3340		__func__, ha->host_no, drv_state, drv_active);3341 3342	while (drv_state != (drv_active & active_mask)) {3343		if (time_after_eq(jiffies, reset_timeout)) {3344			ql4_printk(KERN_INFO, ha,3345				   "%s: RESET TIMEOUT! drv_state: 0x%08x, drv_active: 0x%08x\n",3346				   DRIVER_NAME, drv_state, drv_active);3347			break;3348		}3349 3350		/*3351		 * When reset_owner times out, check which functions3352		 * acked/did not ack3353		 */3354		if (test_bit(AF_8XXX_RST_OWNER, &ha->flags)) {3355			ql4_printk(KERN_INFO, ha,3356				   "%s(%ld): drv_state = 0x%x, drv_active = 0x%x\n",3357				   __func__, ha->host_no, drv_state,3358				   drv_active);3359		}3360		qla4_82xx_idc_unlock(ha);3361		msleep(1000);3362		qla4_82xx_idc_lock(ha);3363 3364		drv_state = qla4_82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE);3365		drv_active = qla4_82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE);3366	}3367 3368	/* Clear RESET OWNER as we are not going to use it any further */3369	clear_bit(AF_8XXX_RST_OWNER, &ha->flags);3370 3371	dev_state = qla4_82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);3372	ql4_printk(KERN_INFO, ha, "Device state is 0x%x = %s\n", dev_state,3373		   dev_state < MAX_STATES ? qdev_state[dev_state] : "Unknown");3374 3375	/* Force to DEV_COLD unless someone else is starting a reset */3376	if (dev_state != QLA8XXX_DEV_INITIALIZING) {3377		ql4_printk(KERN_INFO, ha, "HW State: COLD/RE-INIT\n");3378		qla4_82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA8XXX_DEV_COLD);3379		qla4_8xxx_set_rst_ready(ha);3380	}3381}3382 3383/**3384 * qla4_8xxx_need_qsnt_handler - Code to start qsnt3385 * @ha: pointer to adapter structure3386 **/3387void3388qla4_8xxx_need_qsnt_handler(struct scsi_qla_host *ha)3389{3390	ha->isp_ops->idc_lock(ha);3391	qla4_8xxx_set_qsnt_ready(ha);3392	ha->isp_ops->idc_unlock(ha);3393}3394 3395static void qla4_82xx_set_idc_ver(struct scsi_qla_host *ha)3396{3397	int idc_ver;3398	uint32_t drv_active;3399 3400	drv_active = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_ACTIVE);3401	if (drv_active == (1 << (ha->func_num * 4))) {3402		qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DRV_IDC_VERSION,3403				    QLA82XX_IDC_VERSION);3404		ql4_printk(KERN_INFO, ha,3405			   "%s: IDC version updated to %d\n", __func__,3406			   QLA82XX_IDC_VERSION);3407	} else {3408		idc_ver = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_IDC_VERSION);3409		if (QLA82XX_IDC_VERSION != idc_ver) {3410			ql4_printk(KERN_INFO, ha,3411				   "%s: qla4xxx driver IDC version %d is not compatible with IDC version %d of other drivers!\n",3412				   __func__, QLA82XX_IDC_VERSION, idc_ver);3413		}3414	}3415}3416 3417static int qla4_83xx_set_idc_ver(struct scsi_qla_host *ha)3418{3419	int idc_ver;3420	uint32_t drv_active;3421	int rval = QLA_SUCCESS;3422 3423	drv_active = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_ACTIVE);3424	if (drv_active == (1 << ha->func_num)) {3425		idc_ver = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_IDC_VERSION);3426		idc_ver &= (~0xFF);3427		idc_ver |= QLA83XX_IDC_VER_MAJ_VALUE;3428		qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DRV_IDC_VERSION, idc_ver);3429		ql4_printk(KERN_INFO, ha,3430			   "%s: IDC version updated to %d\n", __func__,3431			   idc_ver);3432	} else {3433		idc_ver = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_IDC_VERSION);3434		idc_ver &= 0xFF;3435		if (QLA83XX_IDC_VER_MAJ_VALUE != idc_ver) {3436			ql4_printk(KERN_INFO, ha,3437				   "%s: qla4xxx driver IDC version %d is not compatible with IDC version %d of other drivers!\n",3438				   __func__, QLA83XX_IDC_VER_MAJ_VALUE,3439				   idc_ver);3440			rval = QLA_ERROR;3441			goto exit_set_idc_ver;3442		}3443	}3444 3445	/* Update IDC_MINOR_VERSION */3446	idc_ver = qla4_83xx_rd_reg(ha, QLA83XX_CRB_IDC_VER_MINOR);3447	idc_ver &= ~(0x03 << (ha->func_num * 2));3448	idc_ver |= (QLA83XX_IDC_VER_MIN_VALUE << (ha->func_num * 2));3449	qla4_83xx_wr_reg(ha, QLA83XX_CRB_IDC_VER_MINOR, idc_ver);3450 3451exit_set_idc_ver:3452	return rval;3453}3454 3455int qla4_8xxx_update_idc_reg(struct scsi_qla_host *ha)3456{3457	uint32_t drv_active;3458	int rval = QLA_SUCCESS;3459 3460	if (test_bit(AF_INIT_DONE, &ha->flags))3461		goto exit_update_idc_reg;3462 3463	ha->isp_ops->idc_lock(ha);3464	qla4_8xxx_set_drv_active(ha);3465 3466	/*3467	 * If we are the first driver to load and3468	 * ql4xdontresethba is not set, clear IDC_CTRL BIT0.3469	 */3470	if (is_qla8032(ha) || is_qla8042(ha)) {3471		drv_active = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_ACTIVE);3472		if ((drv_active == (1 << ha->func_num)) && !ql4xdontresethba)3473			qla4_83xx_clear_idc_dontreset(ha);3474	}3475 3476	if (is_qla8022(ha)) {3477		qla4_82xx_set_idc_ver(ha);3478	} else if (is_qla8032(ha) || is_qla8042(ha)) {3479		rval = qla4_83xx_set_idc_ver(ha);3480		if (rval == QLA_ERROR)3481			qla4_8xxx_clear_drv_active(ha);3482	}3483 3484	ha->isp_ops->idc_unlock(ha);3485 3486exit_update_idc_reg:3487	return rval;3488}3489 3490/**3491 * qla4_8xxx_device_state_handler - Adapter state machine3492 * @ha: pointer to host adapter structure.3493 *3494 * Note: IDC lock must be UNLOCKED upon entry3495 **/3496int qla4_8xxx_device_state_handler(struct scsi_qla_host *ha)3497{3498	uint32_t dev_state;3499	int rval = QLA_SUCCESS;3500	unsigned long dev_init_timeout;3501 3502	rval = qla4_8xxx_update_idc_reg(ha);3503	if (rval == QLA_ERROR)3504		goto exit_state_handler;3505 3506	dev_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DEV_STATE);3507	DEBUG2(ql4_printk(KERN_INFO, ha, "Device state is 0x%x = %s\n",3508			  dev_state, dev_state < MAX_STATES ?3509			  qdev_state[dev_state] : "Unknown"));3510 3511	/* wait for 30 seconds for device to go ready */3512	dev_init_timeout = jiffies + (ha->nx_dev_init_timeout * HZ);3513 3514	ha->isp_ops->idc_lock(ha);3515	while (1) {3516 3517		if (time_after_eq(jiffies, dev_init_timeout)) {3518			ql4_printk(KERN_WARNING, ha,3519				   "%s: Device Init Failed 0x%x = %s\n",3520				   DRIVER_NAME,3521				   dev_state, dev_state < MAX_STATES ?3522				   qdev_state[dev_state] : "Unknown");3523			qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DEV_STATE,3524					    QLA8XXX_DEV_FAILED);3525		}3526 3527		dev_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DEV_STATE);3528		ql4_printk(KERN_INFO, ha, "Device state is 0x%x = %s\n",3529			   dev_state, dev_state < MAX_STATES ?3530			   qdev_state[dev_state] : "Unknown");3531 3532		/* NOTE: Make sure idc unlocked upon exit of switch statement */3533		switch (dev_state) {3534		case QLA8XXX_DEV_READY:3535			goto exit;3536		case QLA8XXX_DEV_COLD:3537			rval = qla4_8xxx_device_bootstrap(ha);3538			goto exit;3539		case QLA8XXX_DEV_INITIALIZING:3540			ha->isp_ops->idc_unlock(ha);3541			msleep(1000);3542			ha->isp_ops->idc_lock(ha);3543			break;3544		case QLA8XXX_DEV_NEED_RESET:3545			/*3546			 * For ISP8324 and ISP8042, if NEED_RESET is set by any3547			 * driver, it should be honored, irrespective of3548			 * IDC_CTRL DONTRESET_BIT03549			 */3550			if (is_qla8032(ha) || is_qla8042(ha)) {3551				qla4_83xx_need_reset_handler(ha);3552			} else if (is_qla8022(ha)) {3553				if (!ql4xdontresethba) {3554					qla4_82xx_need_reset_handler(ha);3555					/* Update timeout value after need3556					 * reset handler */3557					dev_init_timeout = jiffies +3558						(ha->nx_dev_init_timeout * HZ);3559				} else {3560					ha->isp_ops->idc_unlock(ha);3561					msleep(1000);3562					ha->isp_ops->idc_lock(ha);3563				}3564			}3565			break;3566		case QLA8XXX_DEV_NEED_QUIESCENT:3567			/* idc locked/unlocked in handler */3568			qla4_8xxx_need_qsnt_handler(ha);3569			break;3570		case QLA8XXX_DEV_QUIESCENT:3571			ha->isp_ops->idc_unlock(ha);3572			msleep(1000);3573			ha->isp_ops->idc_lock(ha);3574			break;3575		case QLA8XXX_DEV_FAILED:3576			ha->isp_ops->idc_unlock(ha);3577			qla4xxx_dead_adapter_cleanup(ha);3578			rval = QLA_ERROR;3579			ha->isp_ops->idc_lock(ha);3580			goto exit;3581		default:3582			ha->isp_ops->idc_unlock(ha);3583			qla4xxx_dead_adapter_cleanup(ha);3584			rval = QLA_ERROR;3585			ha->isp_ops->idc_lock(ha);3586			goto exit;3587		}3588	}3589exit:3590	ha->isp_ops->idc_unlock(ha);3591exit_state_handler:3592	return rval;3593}3594 3595int qla4_8xxx_load_risc(struct scsi_qla_host *ha)3596{3597	int retval;3598 3599	/* clear the interrupt */3600	if (is_qla8032(ha) || is_qla8042(ha)) {3601		writel(0, &ha->qla4_83xx_reg->risc_intr);3602		readl(&ha->qla4_83xx_reg->risc_intr);3603	} else if (is_qla8022(ha)) {3604		writel(0, &ha->qla4_82xx_reg->host_int);3605		readl(&ha->qla4_82xx_reg->host_int);3606	}3607 3608	retval = qla4_8xxx_device_state_handler(ha);3609 3610	/* Initialize request and response queues. */3611	if (retval == QLA_SUCCESS)3612		qla4xxx_init_rings(ha);3613 3614	if (retval == QLA_SUCCESS && !test_bit(AF_IRQ_ATTACHED, &ha->flags))3615		retval = qla4xxx_request_irqs(ha);3616 3617	return retval;3618}3619 3620/*****************************************************************************/3621/* Flash Manipulation Routines                                               */3622/*****************************************************************************/3623 3624#define OPTROM_BURST_SIZE       0x10003625#define OPTROM_BURST_DWORDS     (OPTROM_BURST_SIZE / 4)3626 3627#define FARX_DATA_FLAG	BIT_313628#define FARX_ACCESS_FLASH_CONF	0x7FFD00003629#define FARX_ACCESS_FLASH_DATA	0x7FF000003630 3631static inline uint32_t3632flash_conf_addr(struct ql82xx_hw_data *hw, uint32_t faddr)3633{3634	return hw->flash_conf_off | faddr;3635}3636 3637static uint32_t *3638qla4_82xx_read_flash_data(struct scsi_qla_host *ha, uint32_t *dwptr,3639    uint32_t faddr, uint32_t length)3640{3641	uint32_t i;3642	uint32_t val;3643	int loops = 0;3644	while ((qla4_82xx_rom_lock(ha) != 0) && (loops < 50000)) {3645		udelay(100);3646		cond_resched();3647		loops++;3648	}3649	if (loops >= 50000) {3650		ql4_printk(KERN_WARNING, ha, "ROM lock failed\n");3651		return dwptr;3652	}3653 3654	/* Dword reads to flash. */3655	for (i = 0; i < length/4; i++, faddr += 4) {3656		if (qla4_82xx_do_rom_fast_read(ha, faddr, &val)) {3657			ql4_printk(KERN_WARNING, ha,3658			    "Do ROM fast read failed\n");3659			goto done_read;3660		}3661		dwptr[i] = cpu_to_le32(val);3662	}3663 3664done_read:3665	qla4_82xx_rom_unlock(ha);3666	return dwptr;3667}3668 3669/*3670 * Address and length are byte address3671 */3672static uint8_t *3673qla4_82xx_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,3674		uint32_t offset, uint32_t length)3675{3676	qla4_82xx_read_flash_data(ha, (uint32_t *)buf, offset, length);3677	return buf;3678}3679 3680static int3681qla4_8xxx_find_flt_start(struct scsi_qla_host *ha, uint32_t *start)3682{3683	const char *loc, *locations[] = { "DEF", "PCI" };3684 3685	/*3686	 * FLT-location structure resides after the last PCI region.3687	 */3688 3689	/* Begin with sane defaults. */3690	loc = locations[0];3691	*start = FA_FLASH_LAYOUT_ADDR_82;3692 3693	DEBUG2(ql4_printk(KERN_INFO, ha, "FLTL[%s] = 0x%x.\n", loc, *start));3694	return QLA_SUCCESS;3695}3696 3697static void3698qla4_8xxx_get_flt_info(struct scsi_qla_host *ha, uint32_t flt_addr)3699{3700	const char *loc, *locations[] = { "DEF", "FLT" };3701	uint16_t *wptr;3702	uint16_t cnt, chksum;3703	uint32_t start, status;3704	struct qla_flt_header *flt;3705	struct qla_flt_region *region;3706	struct ql82xx_hw_data *hw = &ha->hw;3707 3708	hw->flt_region_flt = flt_addr;3709	wptr = (uint16_t *)ha->request_ring;3710	flt = (struct qla_flt_header *)ha->request_ring;3711	region = (struct qla_flt_region *)&flt[1];3712 3713	if (is_qla8022(ha)) {3714		qla4_82xx_read_optrom_data(ha, (uint8_t *)ha->request_ring,3715					   flt_addr << 2, OPTROM_BURST_SIZE);3716	} else if (is_qla8032(ha) || is_qla8042(ha)) {3717		status = qla4_83xx_flash_read_u32(ha, flt_addr << 2,3718						  (uint8_t *)ha->request_ring,3719						  0x400);3720		if (status != QLA_SUCCESS)3721			goto no_flash_data;3722	}3723 3724	if (*wptr == cpu_to_le16(0xffff))3725		goto no_flash_data;3726	if (flt->version != cpu_to_le16(1)) {3727		DEBUG2(ql4_printk(KERN_INFO, ha, "Unsupported FLT detected: "3728			"version=0x%x length=0x%x checksum=0x%x.\n",3729			le16_to_cpu(flt->version), le16_to_cpu(flt->length),3730			le16_to_cpu(flt->checksum)));3731		goto no_flash_data;3732	}3733 3734	cnt = (sizeof(struct qla_flt_header) + le16_to_cpu(flt->length)) >> 1;3735	for (chksum = 0; cnt; cnt--)3736		chksum += le16_to_cpu(*wptr++);3737	if (chksum) {3738		DEBUG2(ql4_printk(KERN_INFO, ha, "Inconsistent FLT detected: "3739			"version=0x%x length=0x%x checksum=0x%x.\n",3740			le16_to_cpu(flt->version), le16_to_cpu(flt->length),3741			chksum));3742		goto no_flash_data;3743	}3744 3745	loc = locations[1];3746	cnt = le16_to_cpu(flt->length) / sizeof(struct qla_flt_region);3747	for ( ; cnt; cnt--, region++) {3748		/* Store addresses as DWORD offsets. */3749		start = le32_to_cpu(region->start) >> 2;3750 3751		DEBUG3(ql4_printk(KERN_DEBUG, ha, "FLT[%02x]: start=0x%x "3752		    "end=0x%x size=0x%x.\n", le32_to_cpu(region->code), start,3753		    le32_to_cpu(region->end) >> 2, le32_to_cpu(region->size)));3754 3755		switch (le32_to_cpu(region->code) & 0xff) {3756		case FLT_REG_FDT:3757			hw->flt_region_fdt = start;3758			break;3759		case FLT_REG_BOOT_CODE_82:3760			hw->flt_region_boot = start;3761			break;3762		case FLT_REG_FW_82:3763		case FLT_REG_FW_82_1:3764			hw->flt_region_fw = start;3765			break;3766		case FLT_REG_BOOTLOAD_82:3767			hw->flt_region_bootload = start;3768			break;3769		case FLT_REG_ISCSI_PARAM:3770			hw->flt_iscsi_param =  start;3771			break;3772		case FLT_REG_ISCSI_CHAP:3773			hw->flt_region_chap =  start;3774			hw->flt_chap_size =  le32_to_cpu(region->size);3775			break;3776		case FLT_REG_ISCSI_DDB:3777			hw->flt_region_ddb =  start;3778			hw->flt_ddb_size =  le32_to_cpu(region->size);3779			break;3780		}3781	}3782	goto done;3783 3784no_flash_data:3785	/* Use hardcoded defaults. */3786	loc = locations[0];3787 3788	hw->flt_region_fdt      = FA_FLASH_DESCR_ADDR_82;3789	hw->flt_region_boot     = FA_BOOT_CODE_ADDR_82;3790	hw->flt_region_bootload = FA_BOOT_LOAD_ADDR_82;3791	hw->flt_region_fw       = FA_RISC_CODE_ADDR_82;3792	hw->flt_region_chap	= FA_FLASH_ISCSI_CHAP >> 2;3793	hw->flt_chap_size	= FA_FLASH_CHAP_SIZE;3794	hw->flt_region_ddb	= FA_FLASH_ISCSI_DDB >> 2;3795	hw->flt_ddb_size	= FA_FLASH_DDB_SIZE;3796 3797done:3798	DEBUG2(ql4_printk(KERN_INFO, ha,3799			  "FLT[%s]: flt=0x%x fdt=0x%x boot=0x%x bootload=0x%x fw=0x%x chap=0x%x chap_size=0x%x ddb=0x%x  ddb_size=0x%x\n",3800			  loc, hw->flt_region_flt, hw->flt_region_fdt,3801			  hw->flt_region_boot, hw->flt_region_bootload,3802			  hw->flt_region_fw, hw->flt_region_chap,3803			  hw->flt_chap_size, hw->flt_region_ddb,3804			  hw->flt_ddb_size));3805}3806 3807static void3808qla4_82xx_get_fdt_info(struct scsi_qla_host *ha)3809{3810#define FLASH_BLK_SIZE_4K       0x10003811#define FLASH_BLK_SIZE_32K      0x80003812#define FLASH_BLK_SIZE_64K      0x100003813	const char *loc, *locations[] = { "MID", "FDT" };3814	uint16_t cnt, chksum;3815	uint16_t *wptr;3816	struct qla_fdt_layout *fdt;3817	uint16_t mid = 0;3818	uint16_t fid = 0;3819	struct ql82xx_hw_data *hw = &ha->hw;3820 3821	hw->flash_conf_off = FARX_ACCESS_FLASH_CONF;3822	hw->flash_data_off = FARX_ACCESS_FLASH_DATA;3823 3824	wptr = (uint16_t *)ha->request_ring;3825	fdt = (struct qla_fdt_layout *)ha->request_ring;3826	qla4_82xx_read_optrom_data(ha, (uint8_t *)ha->request_ring,3827	    hw->flt_region_fdt << 2, OPTROM_BURST_SIZE);3828 3829	if (*wptr == cpu_to_le16(0xffff))3830		goto no_flash_data;3831 3832	if (fdt->sig[0] != 'Q' || fdt->sig[1] != 'L' || fdt->sig[2] != 'I' ||3833	    fdt->sig[3] != 'D')3834		goto no_flash_data;3835 3836	for (cnt = 0, chksum = 0; cnt < sizeof(struct qla_fdt_layout) >> 1;3837	    cnt++)3838		chksum += le16_to_cpu(*wptr++);3839 3840	if (chksum) {3841		DEBUG2(ql4_printk(KERN_INFO, ha, "Inconsistent FDT detected: "3842		    "checksum=0x%x id=%c version=0x%x.\n", chksum, fdt->sig[0],3843		    le16_to_cpu(fdt->version)));3844		goto no_flash_data;3845	}3846 3847	loc = locations[1];3848	mid = le16_to_cpu(fdt->man_id);3849	fid = le16_to_cpu(fdt->id);3850	hw->fdt_wrt_disable = fdt->wrt_disable_bits;3851	hw->fdt_erase_cmd = flash_conf_addr(hw, 0x0300 | fdt->erase_cmd);3852	hw->fdt_block_size = le32_to_cpu(fdt->block_size);3853 3854	if (fdt->unprotect_sec_cmd) {3855		hw->fdt_unprotect_sec_cmd = flash_conf_addr(hw, 0x0300 |3856		    fdt->unprotect_sec_cmd);3857		hw->fdt_protect_sec_cmd = fdt->protect_sec_cmd ?3858		    flash_conf_addr(hw, 0x0300 | fdt->protect_sec_cmd) :3859		    flash_conf_addr(hw, 0x0336);3860	}3861	goto done;3862 3863no_flash_data:3864	loc = locations[0];3865	hw->fdt_block_size = FLASH_BLK_SIZE_64K;3866done:3867	DEBUG2(ql4_printk(KERN_INFO, ha, "FDT[%s]: (0x%x/0x%x) erase=0x%x "3868		"pro=%x upro=%x wrtd=0x%x blk=0x%x.\n", loc, mid, fid,3869		hw->fdt_erase_cmd, hw->fdt_protect_sec_cmd,3870		hw->fdt_unprotect_sec_cmd, hw->fdt_wrt_disable,3871		hw->fdt_block_size));3872}3873 3874static void3875qla4_82xx_get_idc_param(struct scsi_qla_host *ha)3876{3877#define QLA82XX_IDC_PARAM_ADDR      0x003e885c3878	uint32_t *wptr;3879 3880	if (!is_qla8022(ha))3881		return;3882	wptr = (uint32_t *)ha->request_ring;3883	qla4_82xx_read_optrom_data(ha, (uint8_t *)ha->request_ring,3884			QLA82XX_IDC_PARAM_ADDR , 8);3885 3886	if (*wptr == cpu_to_le32(0xffffffff)) {3887		ha->nx_dev_init_timeout = ROM_DEV_INIT_TIMEOUT;3888		ha->nx_reset_timeout = ROM_DRV_RESET_ACK_TIMEOUT;3889	} else {3890		ha->nx_dev_init_timeout = le32_to_cpu(*wptr++);3891		ha->nx_reset_timeout = le32_to_cpu(*wptr);3892	}3893 3894	DEBUG2(ql4_printk(KERN_DEBUG, ha,3895		"ha->nx_dev_init_timeout = %d\n", ha->nx_dev_init_timeout));3896	DEBUG2(ql4_printk(KERN_DEBUG, ha,3897		"ha->nx_reset_timeout = %d\n", ha->nx_reset_timeout));3898	return;3899}3900 3901void qla4_82xx_queue_mbox_cmd(struct scsi_qla_host *ha, uint32_t *mbx_cmd,3902			      int in_count)3903{3904	int i;3905 3906	/* Load all mailbox registers, except mailbox 0. */3907	for (i = 1; i < in_count; i++)3908		writel(mbx_cmd[i], &ha->qla4_82xx_reg->mailbox_in[i]);3909 3910	/* Wakeup firmware  */3911	writel(mbx_cmd[0], &ha->qla4_82xx_reg->mailbox_in[0]);3912	readl(&ha->qla4_82xx_reg->mailbox_in[0]);3913	writel(HINT_MBX_INT_PENDING, &ha->qla4_82xx_reg->hint);3914	readl(&ha->qla4_82xx_reg->hint);3915}3916 3917void qla4_82xx_process_mbox_intr(struct scsi_qla_host *ha, int out_count)3918{3919	int intr_status;3920 3921	intr_status = readl(&ha->qla4_82xx_reg->host_int);3922	if (intr_status & ISRX_82XX_RISC_INT) {3923		ha->mbox_status_count = out_count;3924		intr_status = readl(&ha->qla4_82xx_reg->host_status);3925		ha->isp_ops->interrupt_service_routine(ha, intr_status);3926 3927		if (test_bit(AF_INTERRUPTS_ON, &ha->flags) &&3928		    (!ha->pdev->msi_enabled && !ha->pdev->msix_enabled))3929			qla4_82xx_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg,3930					0xfbff);3931	}3932}3933 3934int3935qla4_8xxx_get_flash_info(struct scsi_qla_host *ha)3936{3937	int ret;3938	uint32_t flt_addr;3939 3940	ret = qla4_8xxx_find_flt_start(ha, &flt_addr);3941	if (ret != QLA_SUCCESS)3942		return ret;3943 3944	qla4_8xxx_get_flt_info(ha, flt_addr);3945	if (is_qla8022(ha)) {3946		qla4_82xx_get_fdt_info(ha);3947		qla4_82xx_get_idc_param(ha);3948	} else if (is_qla8032(ha) || is_qla8042(ha)) {3949		qla4_83xx_get_idc_param(ha);3950	}3951 3952	return QLA_SUCCESS;3953}3954 3955/**3956 * qla4_8xxx_stop_firmware - stops firmware on specified adapter instance3957 * @ha: pointer to host adapter structure.3958 *3959 * Remarks:3960 * For iSCSI, throws away all I/O and AENs into bit bucket, so they will3961 * not be available after successful return.  Driver must cleanup potential3962 * outstanding I/O's after calling this funcion.3963 **/3964int3965qla4_8xxx_stop_firmware(struct scsi_qla_host *ha)3966{3967	int status;3968	uint32_t mbox_cmd[MBOX_REG_COUNT];3969	uint32_t mbox_sts[MBOX_REG_COUNT];3970 3971	memset(&mbox_cmd, 0, sizeof(mbox_cmd));3972	memset(&mbox_sts, 0, sizeof(mbox_sts));3973 3974	mbox_cmd[0] = MBOX_CMD_STOP_FW;3975	status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1,3976	    &mbox_cmd[0], &mbox_sts[0]);3977 3978	DEBUG2(printk("scsi%ld: %s: status = %d\n", ha->host_no,3979	    __func__, status));3980	return status;3981}3982 3983/**3984 * qla4_82xx_isp_reset - Resets ISP and aborts all outstanding commands.3985 * @ha: pointer to host adapter structure.3986 **/3987int3988qla4_82xx_isp_reset(struct scsi_qla_host *ha)3989{3990	int rval;3991	uint32_t dev_state;3992 3993	qla4_82xx_idc_lock(ha);3994	dev_state = qla4_82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);3995 3996	if (dev_state == QLA8XXX_DEV_READY) {3997		ql4_printk(KERN_INFO, ha, "HW State: NEED RESET\n");3998		qla4_82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,3999		    QLA8XXX_DEV_NEED_RESET);4000		set_bit(AF_8XXX_RST_OWNER, &ha->flags);4001	} else4002		ql4_printk(KERN_INFO, ha, "HW State: DEVICE INITIALIZING\n");4003 4004	qla4_82xx_idc_unlock(ha);4005 4006	rval = qla4_8xxx_device_state_handler(ha);4007 4008	qla4_82xx_idc_lock(ha);4009	qla4_8xxx_clear_rst_ready(ha);4010	qla4_82xx_idc_unlock(ha);4011 4012	if (rval == QLA_SUCCESS) {4013		ql4_printk(KERN_INFO, ha, "Clearing AF_RECOVERY in qla4_82xx_isp_reset\n");4014		clear_bit(AF_FW_RECOVERY, &ha->flags);4015	}4016 4017	return rval;4018}4019 4020/**4021 * qla4_8xxx_get_sys_info - get adapter MAC address(es) and serial number4022 * @ha: pointer to host adapter structure.4023 *4024 **/4025int qla4_8xxx_get_sys_info(struct scsi_qla_host *ha)4026{4027	uint32_t mbox_cmd[MBOX_REG_COUNT];4028	uint32_t mbox_sts[MBOX_REG_COUNT];4029	struct mbx_sys_info *sys_info;4030	dma_addr_t sys_info_dma;4031	int status = QLA_ERROR;4032 4033	sys_info = dma_alloc_coherent(&ha->pdev->dev, sizeof(*sys_info),4034				      &sys_info_dma, GFP_KERNEL);4035	if (sys_info == NULL) {4036		DEBUG2(printk("scsi%ld: %s: Unable to allocate dma buffer.\n",4037		    ha->host_no, __func__));4038		return status;4039	}4040 4041	memset(&mbox_cmd, 0, sizeof(mbox_cmd));4042	memset(&mbox_sts, 0, sizeof(mbox_sts));4043 4044	mbox_cmd[0] = MBOX_CMD_GET_SYS_INFO;4045	mbox_cmd[1] = LSDW(sys_info_dma);4046	mbox_cmd[2] = MSDW(sys_info_dma);4047	mbox_cmd[4] = sizeof(*sys_info);4048 4049	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 6, &mbox_cmd[0],4050	    &mbox_sts[0]) != QLA_SUCCESS) {4051		DEBUG2(printk("scsi%ld: %s: GET_SYS_INFO failed\n",4052		    ha->host_no, __func__));4053		goto exit_validate_mac82;4054	}4055 4056	/* Make sure we receive the minimum required data to cache internally */4057	if (((is_qla8032(ha) || is_qla8042(ha)) ? mbox_sts[3] : mbox_sts[4]) <4058	    offsetof(struct mbx_sys_info, reserved)) {4059		DEBUG2(printk("scsi%ld: %s: GET_SYS_INFO data receive"4060		    " error (%x)\n", ha->host_no, __func__, mbox_sts[4]));4061		goto exit_validate_mac82;4062	}4063 4064	/* Save M.A.C. address & serial_number */4065	ha->port_num = sys_info->port_num;4066	memcpy(ha->my_mac, &sys_info->mac_addr[0],4067	    min(sizeof(ha->my_mac), sizeof(sys_info->mac_addr)));4068	memcpy(ha->serial_number, &sys_info->serial_number,4069	    min(sizeof(ha->serial_number), sizeof(sys_info->serial_number)));4070	memcpy(ha->model_name, &sys_info->board_id_str,4071	       min(sizeof(ha->model_name), sizeof(sys_info->board_id_str)));4072	ha->phy_port_cnt = sys_info->phys_port_cnt;4073	ha->phy_port_num = sys_info->port_num;4074	ha->iscsi_pci_func_cnt = sys_info->iscsi_pci_func_cnt;4075 4076	DEBUG2(printk("scsi%ld: %s: mac %pM serial %s\n",4077	    ha->host_no, __func__, ha->my_mac, ha->serial_number));4078 4079	status = QLA_SUCCESS;4080 4081exit_validate_mac82:4082	dma_free_coherent(&ha->pdev->dev, sizeof(*sys_info), sys_info,4083			  sys_info_dma);4084	return status;4085}4086 4087/* Interrupt handling helpers. */4088 4089int qla4_8xxx_intr_enable(struct scsi_qla_host *ha)4090{4091	uint32_t mbox_cmd[MBOX_REG_COUNT];4092	uint32_t mbox_sts[MBOX_REG_COUNT];4093 4094	DEBUG2(ql4_printk(KERN_INFO, ha, "%s\n", __func__));4095 4096	memset(&mbox_cmd, 0, sizeof(mbox_cmd));4097	memset(&mbox_sts, 0, sizeof(mbox_sts));4098	mbox_cmd[0] = MBOX_CMD_ENABLE_INTRS;4099	mbox_cmd[1] = INTR_ENABLE;4100	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0],4101		&mbox_sts[0]) != QLA_SUCCESS) {4102		DEBUG2(ql4_printk(KERN_INFO, ha,4103		    "%s: MBOX_CMD_ENABLE_INTRS failed (0x%04x)\n",4104		    __func__, mbox_sts[0]));4105		return QLA_ERROR;4106	}4107	return QLA_SUCCESS;4108}4109 4110int qla4_8xxx_intr_disable(struct scsi_qla_host *ha)4111{4112	uint32_t mbox_cmd[MBOX_REG_COUNT];4113	uint32_t mbox_sts[MBOX_REG_COUNT];4114 4115	DEBUG2(ql4_printk(KERN_INFO, ha, "%s\n", __func__));4116 4117	memset(&mbox_cmd, 0, sizeof(mbox_cmd));4118	memset(&mbox_sts, 0, sizeof(mbox_sts));4119	mbox_cmd[0] = MBOX_CMD_ENABLE_INTRS;4120	mbox_cmd[1] = INTR_DISABLE;4121	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0],4122	    &mbox_sts[0]) != QLA_SUCCESS) {4123		DEBUG2(ql4_printk(KERN_INFO, ha,4124			"%s: MBOX_CMD_ENABLE_INTRS failed (0x%04x)\n",4125			__func__, mbox_sts[0]));4126		return QLA_ERROR;4127	}4128 4129	return QLA_SUCCESS;4130}4131 4132void4133qla4_82xx_enable_intrs(struct scsi_qla_host *ha)4134{4135	qla4_8xxx_intr_enable(ha);4136 4137	spin_lock_irq(&ha->hardware_lock);4138	/* BIT 10 - reset */4139	qla4_82xx_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 0xfbff);4140	spin_unlock_irq(&ha->hardware_lock);4141	set_bit(AF_INTERRUPTS_ON, &ha->flags);4142}4143 4144void4145qla4_82xx_disable_intrs(struct scsi_qla_host *ha)4146{4147	if (test_and_clear_bit(AF_INTERRUPTS_ON, &ha->flags))4148		qla4_8xxx_intr_disable(ha);4149 4150	spin_lock_irq(&ha->hardware_lock);4151	/* BIT 10 - set */4152	qla4_82xx_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 0x0400);4153	spin_unlock_irq(&ha->hardware_lock);4154}4155 4156int4157qla4_8xxx_enable_msix(struct scsi_qla_host *ha)4158{4159	int ret;4160 4161	ret = pci_alloc_irq_vectors(ha->pdev, QLA_MSIX_ENTRIES,4162			QLA_MSIX_ENTRIES, PCI_IRQ_MSIX);4163	if (ret < 0) {4164		ql4_printk(KERN_WARNING, ha,4165		    "MSI-X: Failed to enable support -- %d/%d\n",4166		    QLA_MSIX_ENTRIES, ret);4167		return ret;4168	}4169 4170	ret = request_irq(pci_irq_vector(ha->pdev, 0),4171			qla4_8xxx_default_intr_handler, 0, "qla4xxx (default)",4172			ha);4173	if (ret)4174		goto out_free_vectors;4175 4176	ret = request_irq(pci_irq_vector(ha->pdev, 1),4177			qla4_8xxx_msix_rsp_q, 0, "qla4xxx (rsp_q)", ha);4178	if (ret)4179		goto out_free_default_irq;4180 4181	return 0;4182 4183out_free_default_irq:4184	free_irq(pci_irq_vector(ha->pdev, 0), ha);4185out_free_vectors:4186	pci_free_irq_vectors(ha->pdev);4187	return ret;4188}4189 4190int qla4_8xxx_check_init_adapter_retry(struct scsi_qla_host *ha)4191{4192	int status = QLA_SUCCESS;4193 4194	/* Dont retry adapter initialization if IRQ allocation failed */4195	if (!test_bit(AF_IRQ_ATTACHED, &ha->flags)) {4196		ql4_printk(KERN_WARNING, ha, "%s: Skipping retry of adapter initialization as IRQs are not attached\n",4197			   __func__);4198		status = QLA_ERROR;4199		goto exit_init_adapter_failure;4200	}4201 4202	/* Since interrupts are registered in start_firmware for4203	 * 8xxx, release them here if initialize_adapter fails4204	 * and retry adapter initialization */4205	qla4xxx_free_irqs(ha);4206 4207exit_init_adapter_failure:4208	return status;4209}4210