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