18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * QLogic iSCSI HBA Driver 48c2ecf20Sopenharmony_ci * Copyright (c) 2003-2013 QLogic Corporation 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci#include <linux/delay.h> 78c2ecf20Sopenharmony_ci#include <linux/io.h> 88c2ecf20Sopenharmony_ci#include <linux/pci.h> 98c2ecf20Sopenharmony_ci#include <linux/ratelimit.h> 108c2ecf20Sopenharmony_ci#include "ql4_def.h" 118c2ecf20Sopenharmony_ci#include "ql4_glbl.h" 128c2ecf20Sopenharmony_ci#include "ql4_inline.h" 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#include <linux/io-64-nonatomic-lo-hi.h> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#define TIMEOUT_100_MS 100 178c2ecf20Sopenharmony_ci#define MASK(n) DMA_BIT_MASK(n) 188c2ecf20Sopenharmony_ci#define MN_WIN(addr) (((addr & 0x1fc0000) >> 1) | ((addr >> 25) & 0x3ff)) 198c2ecf20Sopenharmony_ci#define OCM_WIN(addr) (((addr & 0x1ff0000) >> 1) | ((addr >> 25) & 0x3ff)) 208c2ecf20Sopenharmony_ci#define MS_WIN(addr) (addr & 0x0ffc0000) 218c2ecf20Sopenharmony_ci#define QLA82XX_PCI_MN_2M (0) 228c2ecf20Sopenharmony_ci#define QLA82XX_PCI_MS_2M (0x80000) 238c2ecf20Sopenharmony_ci#define QLA82XX_PCI_OCM0_2M (0xc0000) 248c2ecf20Sopenharmony_ci#define VALID_OCM_ADDR(addr) (((addr) & 0x3f800) != 0x3f800) 258c2ecf20Sopenharmony_ci#define GET_MEM_OFFS_2M(addr) (addr & MASK(18)) 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci/* CRB window related */ 288c2ecf20Sopenharmony_ci#define CRB_BLK(off) ((off >> 20) & 0x3f) 298c2ecf20Sopenharmony_ci#define CRB_SUBBLK(off) ((off >> 16) & 0xf) 308c2ecf20Sopenharmony_ci#define CRB_WINDOW_2M (0x130060) 318c2ecf20Sopenharmony_ci#define CRB_HI(off) ((qla4_82xx_crb_hub_agt[CRB_BLK(off)] << 20) | \ 328c2ecf20Sopenharmony_ci ((off) & 0xf0000)) 338c2ecf20Sopenharmony_ci#define QLA82XX_PCI_CAMQM_2M_END (0x04800800UL) 348c2ecf20Sopenharmony_ci#define QLA82XX_PCI_CAMQM_2M_BASE (0x000ff800UL) 358c2ecf20Sopenharmony_ci#define CRB_INDIRECT_2M (0x1e0000UL) 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_cistatic inline void __iomem * 388c2ecf20Sopenharmony_ciqla4_8xxx_pci_base_offsetfset(struct scsi_qla_host *ha, unsigned long off) 398c2ecf20Sopenharmony_ci{ 408c2ecf20Sopenharmony_ci if ((off < ha->first_page_group_end) && 418c2ecf20Sopenharmony_ci (off >= ha->first_page_group_start)) 428c2ecf20Sopenharmony_ci return (void __iomem *)(ha->nx_pcibase + off); 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci return NULL; 458c2ecf20Sopenharmony_ci} 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_cistatic const int MD_MIU_TEST_AGT_RDDATA[] = { 0x410000A8, 488c2ecf20Sopenharmony_ci 0x410000AC, 0x410000B8, 0x410000BC }; 498c2ecf20Sopenharmony_ci#define MAX_CRB_XFORM 60 508c2ecf20Sopenharmony_cistatic unsigned long crb_addr_xform[MAX_CRB_XFORM]; 518c2ecf20Sopenharmony_cistatic int qla4_8xxx_crb_table_initialized; 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci#define qla4_8xxx_crb_addr_transform(name) \ 548c2ecf20Sopenharmony_ci (crb_addr_xform[QLA82XX_HW_PX_MAP_CRB_##name] = \ 558c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_##name << 20) 568c2ecf20Sopenharmony_cistatic void 578c2ecf20Sopenharmony_ciqla4_82xx_crb_addr_transform_setup(void) 588c2ecf20Sopenharmony_ci{ 598c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(XDMA); 608c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(TIMR); 618c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(SRE); 628c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(SQN3); 638c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(SQN2); 648c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(SQN1); 658c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(SQN0); 668c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(SQS3); 678c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(SQS2); 688c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(SQS1); 698c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(SQS0); 708c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(RPMX7); 718c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(RPMX6); 728c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(RPMX5); 738c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(RPMX4); 748c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(RPMX3); 758c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(RPMX2); 768c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(RPMX1); 778c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(RPMX0); 788c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(ROMUSB); 798c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(SN); 808c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(QMN); 818c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(QMS); 828c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(PGNI); 838c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(PGND); 848c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(PGN3); 858c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(PGN2); 868c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(PGN1); 878c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(PGN0); 888c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(PGSI); 898c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(PGSD); 908c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(PGS3); 918c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(PGS2); 928c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(PGS1); 938c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(PGS0); 948c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(PS); 958c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(PH); 968c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(NIU); 978c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(I2Q); 988c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(EG); 998c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(MN); 1008c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(MS); 1018c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(CAS2); 1028c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(CAS1); 1038c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(CAS0); 1048c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(CAM); 1058c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(C2C1); 1068c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(C2C0); 1078c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(SMB); 1088c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(OCM0); 1098c2ecf20Sopenharmony_ci qla4_8xxx_crb_addr_transform(I2C0); 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci qla4_8xxx_crb_table_initialized = 1; 1128c2ecf20Sopenharmony_ci} 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_cistatic struct crb_128M_2M_block_map crb_128M_2M_map[64] = { 1158c2ecf20Sopenharmony_ci {{{0, 0, 0, 0} } }, /* 0: PCI */ 1168c2ecf20Sopenharmony_ci {{{1, 0x0100000, 0x0102000, 0x120000}, /* 1: PCIE */ 1178c2ecf20Sopenharmony_ci {1, 0x0110000, 0x0120000, 0x130000}, 1188c2ecf20Sopenharmony_ci {1, 0x0120000, 0x0122000, 0x124000}, 1198c2ecf20Sopenharmony_ci {1, 0x0130000, 0x0132000, 0x126000}, 1208c2ecf20Sopenharmony_ci {1, 0x0140000, 0x0142000, 0x128000}, 1218c2ecf20Sopenharmony_ci {1, 0x0150000, 0x0152000, 0x12a000}, 1228c2ecf20Sopenharmony_ci {1, 0x0160000, 0x0170000, 0x110000}, 1238c2ecf20Sopenharmony_ci {1, 0x0170000, 0x0172000, 0x12e000}, 1248c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1258c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1268c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1278c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1288c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1298c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1308c2ecf20Sopenharmony_ci {1, 0x01e0000, 0x01e0800, 0x122000}, 1318c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000} } }, 1328c2ecf20Sopenharmony_ci {{{1, 0x0200000, 0x0210000, 0x180000} } },/* 2: MN */ 1338c2ecf20Sopenharmony_ci {{{0, 0, 0, 0} } }, /* 3: */ 1348c2ecf20Sopenharmony_ci {{{1, 0x0400000, 0x0401000, 0x169000} } },/* 4: P2NR1 */ 1358c2ecf20Sopenharmony_ci {{{1, 0x0500000, 0x0510000, 0x140000} } },/* 5: SRE */ 1368c2ecf20Sopenharmony_ci {{{1, 0x0600000, 0x0610000, 0x1c0000} } },/* 6: NIU */ 1378c2ecf20Sopenharmony_ci {{{1, 0x0700000, 0x0704000, 0x1b8000} } },/* 7: QM */ 1388c2ecf20Sopenharmony_ci {{{1, 0x0800000, 0x0802000, 0x170000}, /* 8: SQM0 */ 1398c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1408c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1418c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1428c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1438c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1448c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1458c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1468c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1478c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1488c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1498c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1508c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1518c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1528c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1538c2ecf20Sopenharmony_ci {1, 0x08f0000, 0x08f2000, 0x172000} } }, 1548c2ecf20Sopenharmony_ci {{{1, 0x0900000, 0x0902000, 0x174000}, /* 9: SQM1*/ 1558c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1568c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1578c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1588c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1598c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1608c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1618c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1628c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1638c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1648c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1658c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1668c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1678c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1688c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1698c2ecf20Sopenharmony_ci {1, 0x09f0000, 0x09f2000, 0x176000} } }, 1708c2ecf20Sopenharmony_ci {{{0, 0x0a00000, 0x0a02000, 0x178000}, /* 10: SQM2*/ 1718c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1728c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1738c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1748c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1758c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1768c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1778c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1788c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1798c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1808c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1818c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1828c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1838c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1848c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1858c2ecf20Sopenharmony_ci {1, 0x0af0000, 0x0af2000, 0x17a000} } }, 1868c2ecf20Sopenharmony_ci {{{0, 0x0b00000, 0x0b02000, 0x17c000}, /* 11: SQM3*/ 1878c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1888c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1898c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1908c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1918c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1928c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1938c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1948c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1958c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1968c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1978c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1988c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 1998c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 2008c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 2018c2ecf20Sopenharmony_ci {1, 0x0bf0000, 0x0bf2000, 0x17e000} } }, 2028c2ecf20Sopenharmony_ci {{{1, 0x0c00000, 0x0c04000, 0x1d4000} } },/* 12: I2Q */ 2038c2ecf20Sopenharmony_ci {{{1, 0x0d00000, 0x0d04000, 0x1a4000} } },/* 13: TMR */ 2048c2ecf20Sopenharmony_ci {{{1, 0x0e00000, 0x0e04000, 0x1a0000} } },/* 14: ROMUSB */ 2058c2ecf20Sopenharmony_ci {{{1, 0x0f00000, 0x0f01000, 0x164000} } },/* 15: PEG4 */ 2068c2ecf20Sopenharmony_ci {{{0, 0x1000000, 0x1004000, 0x1a8000} } },/* 16: XDMA */ 2078c2ecf20Sopenharmony_ci {{{1, 0x1100000, 0x1101000, 0x160000} } },/* 17: PEG0 */ 2088c2ecf20Sopenharmony_ci {{{1, 0x1200000, 0x1201000, 0x161000} } },/* 18: PEG1 */ 2098c2ecf20Sopenharmony_ci {{{1, 0x1300000, 0x1301000, 0x162000} } },/* 19: PEG2 */ 2108c2ecf20Sopenharmony_ci {{{1, 0x1400000, 0x1401000, 0x163000} } },/* 20: PEG3 */ 2118c2ecf20Sopenharmony_ci {{{1, 0x1500000, 0x1501000, 0x165000} } },/* 21: P2ND */ 2128c2ecf20Sopenharmony_ci {{{1, 0x1600000, 0x1601000, 0x166000} } },/* 22: P2NI */ 2138c2ecf20Sopenharmony_ci {{{0, 0, 0, 0} } }, /* 23: */ 2148c2ecf20Sopenharmony_ci {{{0, 0, 0, 0} } }, /* 24: */ 2158c2ecf20Sopenharmony_ci {{{0, 0, 0, 0} } }, /* 25: */ 2168c2ecf20Sopenharmony_ci {{{0, 0, 0, 0} } }, /* 26: */ 2178c2ecf20Sopenharmony_ci {{{0, 0, 0, 0} } }, /* 27: */ 2188c2ecf20Sopenharmony_ci {{{0, 0, 0, 0} } }, /* 28: */ 2198c2ecf20Sopenharmony_ci {{{1, 0x1d00000, 0x1d10000, 0x190000} } },/* 29: MS */ 2208c2ecf20Sopenharmony_ci {{{1, 0x1e00000, 0x1e01000, 0x16a000} } },/* 30: P2NR2 */ 2218c2ecf20Sopenharmony_ci {{{1, 0x1f00000, 0x1f10000, 0x150000} } },/* 31: EPG */ 2228c2ecf20Sopenharmony_ci {{{0} } }, /* 32: PCI */ 2238c2ecf20Sopenharmony_ci {{{1, 0x2100000, 0x2102000, 0x120000}, /* 33: PCIE */ 2248c2ecf20Sopenharmony_ci {1, 0x2110000, 0x2120000, 0x130000}, 2258c2ecf20Sopenharmony_ci {1, 0x2120000, 0x2122000, 0x124000}, 2268c2ecf20Sopenharmony_ci {1, 0x2130000, 0x2132000, 0x126000}, 2278c2ecf20Sopenharmony_ci {1, 0x2140000, 0x2142000, 0x128000}, 2288c2ecf20Sopenharmony_ci {1, 0x2150000, 0x2152000, 0x12a000}, 2298c2ecf20Sopenharmony_ci {1, 0x2160000, 0x2170000, 0x110000}, 2308c2ecf20Sopenharmony_ci {1, 0x2170000, 0x2172000, 0x12e000}, 2318c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 2328c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 2338c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 2348c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 2358c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 2368c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 2378c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000}, 2388c2ecf20Sopenharmony_ci {0, 0x0000000, 0x0000000, 0x000000} } }, 2398c2ecf20Sopenharmony_ci {{{1, 0x2200000, 0x2204000, 0x1b0000} } },/* 34: CAM */ 2408c2ecf20Sopenharmony_ci {{{0} } }, /* 35: */ 2418c2ecf20Sopenharmony_ci {{{0} } }, /* 36: */ 2428c2ecf20Sopenharmony_ci {{{0} } }, /* 37: */ 2438c2ecf20Sopenharmony_ci {{{0} } }, /* 38: */ 2448c2ecf20Sopenharmony_ci {{{0} } }, /* 39: */ 2458c2ecf20Sopenharmony_ci {{{1, 0x2800000, 0x2804000, 0x1a4000} } },/* 40: TMR */ 2468c2ecf20Sopenharmony_ci {{{1, 0x2900000, 0x2901000, 0x16b000} } },/* 41: P2NR3 */ 2478c2ecf20Sopenharmony_ci {{{1, 0x2a00000, 0x2a00400, 0x1ac400} } },/* 42: RPMX1 */ 2488c2ecf20Sopenharmony_ci {{{1, 0x2b00000, 0x2b00400, 0x1ac800} } },/* 43: RPMX2 */ 2498c2ecf20Sopenharmony_ci {{{1, 0x2c00000, 0x2c00400, 0x1acc00} } },/* 44: RPMX3 */ 2508c2ecf20Sopenharmony_ci {{{1, 0x2d00000, 0x2d00400, 0x1ad000} } },/* 45: RPMX4 */ 2518c2ecf20Sopenharmony_ci {{{1, 0x2e00000, 0x2e00400, 0x1ad400} } },/* 46: RPMX5 */ 2528c2ecf20Sopenharmony_ci {{{1, 0x2f00000, 0x2f00400, 0x1ad800} } },/* 47: RPMX6 */ 2538c2ecf20Sopenharmony_ci {{{1, 0x3000000, 0x3000400, 0x1adc00} } },/* 48: RPMX7 */ 2548c2ecf20Sopenharmony_ci {{{0, 0x3100000, 0x3104000, 0x1a8000} } },/* 49: XDMA */ 2558c2ecf20Sopenharmony_ci {{{1, 0x3200000, 0x3204000, 0x1d4000} } },/* 50: I2Q */ 2568c2ecf20Sopenharmony_ci {{{1, 0x3300000, 0x3304000, 0x1a0000} } },/* 51: ROMUSB */ 2578c2ecf20Sopenharmony_ci {{{0} } }, /* 52: */ 2588c2ecf20Sopenharmony_ci {{{1, 0x3500000, 0x3500400, 0x1ac000} } },/* 53: RPMX0 */ 2598c2ecf20Sopenharmony_ci {{{1, 0x3600000, 0x3600400, 0x1ae000} } },/* 54: RPMX8 */ 2608c2ecf20Sopenharmony_ci {{{1, 0x3700000, 0x3700400, 0x1ae400} } },/* 55: RPMX9 */ 2618c2ecf20Sopenharmony_ci {{{1, 0x3800000, 0x3804000, 0x1d0000} } },/* 56: OCM0 */ 2628c2ecf20Sopenharmony_ci {{{1, 0x3900000, 0x3904000, 0x1b4000} } },/* 57: CRYPTO */ 2638c2ecf20Sopenharmony_ci {{{1, 0x3a00000, 0x3a04000, 0x1d8000} } },/* 58: SMB */ 2648c2ecf20Sopenharmony_ci {{{0} } }, /* 59: I2C0 */ 2658c2ecf20Sopenharmony_ci {{{0} } }, /* 60: I2C1 */ 2668c2ecf20Sopenharmony_ci {{{1, 0x3d00000, 0x3d04000, 0x1dc000} } },/* 61: LPC */ 2678c2ecf20Sopenharmony_ci {{{1, 0x3e00000, 0x3e01000, 0x167000} } },/* 62: P2NC */ 2688c2ecf20Sopenharmony_ci {{{1, 0x3f00000, 0x3f01000, 0x168000} } } /* 63: P2NR0 */ 2698c2ecf20Sopenharmony_ci}; 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci/* 2728c2ecf20Sopenharmony_ci * top 12 bits of crb internal address (hub, agent) 2738c2ecf20Sopenharmony_ci */ 2748c2ecf20Sopenharmony_cistatic unsigned qla4_82xx_crb_hub_agt[64] = { 2758c2ecf20Sopenharmony_ci 0, 2768c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_PS, 2778c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_MN, 2788c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_MS, 2798c2ecf20Sopenharmony_ci 0, 2808c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_SRE, 2818c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_NIU, 2828c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_QMN, 2838c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_SQN0, 2848c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_SQN1, 2858c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_SQN2, 2868c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_SQN3, 2878c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_I2Q, 2888c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_TIMR, 2898c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_ROMUSB, 2908c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_PGN4, 2918c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_XDMA, 2928c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_PGN0, 2938c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_PGN1, 2948c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_PGN2, 2958c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_PGN3, 2968c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_PGND, 2978c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_PGNI, 2988c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_PGS0, 2998c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_PGS1, 3008c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_PGS2, 3018c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_PGS3, 3028c2ecf20Sopenharmony_ci 0, 3038c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_PGSI, 3048c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_SN, 3058c2ecf20Sopenharmony_ci 0, 3068c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_EG, 3078c2ecf20Sopenharmony_ci 0, 3088c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_PS, 3098c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_CAM, 3108c2ecf20Sopenharmony_ci 0, 3118c2ecf20Sopenharmony_ci 0, 3128c2ecf20Sopenharmony_ci 0, 3138c2ecf20Sopenharmony_ci 0, 3148c2ecf20Sopenharmony_ci 0, 3158c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_TIMR, 3168c2ecf20Sopenharmony_ci 0, 3178c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX1, 3188c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX2, 3198c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX3, 3208c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX4, 3218c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX5, 3228c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX6, 3238c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX7, 3248c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_XDMA, 3258c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_I2Q, 3268c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_ROMUSB, 3278c2ecf20Sopenharmony_ci 0, 3288c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX0, 3298c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX8, 3308c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX9, 3318c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_OCM0, 3328c2ecf20Sopenharmony_ci 0, 3338c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_SMB, 3348c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_I2C0, 3358c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_I2C1, 3368c2ecf20Sopenharmony_ci 0, 3378c2ecf20Sopenharmony_ci QLA82XX_HW_CRB_HUB_AGT_ADR_PGNC, 3388c2ecf20Sopenharmony_ci 0, 3398c2ecf20Sopenharmony_ci}; 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci/* Device states */ 3428c2ecf20Sopenharmony_cistatic char *qdev_state[] = { 3438c2ecf20Sopenharmony_ci "Unknown", 3448c2ecf20Sopenharmony_ci "Cold", 3458c2ecf20Sopenharmony_ci "Initializing", 3468c2ecf20Sopenharmony_ci "Ready", 3478c2ecf20Sopenharmony_ci "Need Reset", 3488c2ecf20Sopenharmony_ci "Need Quiescent", 3498c2ecf20Sopenharmony_ci "Failed", 3508c2ecf20Sopenharmony_ci "Quiescent", 3518c2ecf20Sopenharmony_ci}; 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci/* 3548c2ecf20Sopenharmony_ci * In: 'off' is offset from CRB space in 128M pci map 3558c2ecf20Sopenharmony_ci * Out: 'off' is 2M pci map addr 3568c2ecf20Sopenharmony_ci * side effect: lock crb window 3578c2ecf20Sopenharmony_ci */ 3588c2ecf20Sopenharmony_cistatic void 3598c2ecf20Sopenharmony_ciqla4_82xx_pci_set_crbwindow_2M(struct scsi_qla_host *ha, ulong *off) 3608c2ecf20Sopenharmony_ci{ 3618c2ecf20Sopenharmony_ci u32 win_read; 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci ha->crb_win = CRB_HI(*off); 3648c2ecf20Sopenharmony_ci writel(ha->crb_win, 3658c2ecf20Sopenharmony_ci (void __iomem *)(CRB_WINDOW_2M + ha->nx_pcibase)); 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_ci /* Read back value to make sure write has gone through before trying 3688c2ecf20Sopenharmony_ci * to use it. */ 3698c2ecf20Sopenharmony_ci win_read = readl((void __iomem *)(CRB_WINDOW_2M + ha->nx_pcibase)); 3708c2ecf20Sopenharmony_ci if (win_read != ha->crb_win) { 3718c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 3728c2ecf20Sopenharmony_ci "%s: Written crbwin (0x%x) != Read crbwin (0x%x)," 3738c2ecf20Sopenharmony_ci " off=0x%lx\n", __func__, ha->crb_win, win_read, *off)); 3748c2ecf20Sopenharmony_ci } 3758c2ecf20Sopenharmony_ci *off = (*off & MASK(16)) + CRB_INDIRECT_2M + ha->nx_pcibase; 3768c2ecf20Sopenharmony_ci} 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_civoid 3798c2ecf20Sopenharmony_ciqla4_82xx_wr_32(struct scsi_qla_host *ha, ulong off, u32 data) 3808c2ecf20Sopenharmony_ci{ 3818c2ecf20Sopenharmony_ci unsigned long flags = 0; 3828c2ecf20Sopenharmony_ci int rv; 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ci rv = qla4_82xx_pci_get_crb_addr_2M(ha, &off); 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci BUG_ON(rv == -1); 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ci if (rv == 1) { 3898c2ecf20Sopenharmony_ci write_lock_irqsave(&ha->hw_lock, flags); 3908c2ecf20Sopenharmony_ci qla4_82xx_crb_win_lock(ha); 3918c2ecf20Sopenharmony_ci qla4_82xx_pci_set_crbwindow_2M(ha, &off); 3928c2ecf20Sopenharmony_ci } 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci writel(data, (void __iomem *)off); 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci if (rv == 1) { 3978c2ecf20Sopenharmony_ci qla4_82xx_crb_win_unlock(ha); 3988c2ecf20Sopenharmony_ci write_unlock_irqrestore(&ha->hw_lock, flags); 3998c2ecf20Sopenharmony_ci } 4008c2ecf20Sopenharmony_ci} 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ciuint32_t qla4_82xx_rd_32(struct scsi_qla_host *ha, ulong off) 4038c2ecf20Sopenharmony_ci{ 4048c2ecf20Sopenharmony_ci unsigned long flags = 0; 4058c2ecf20Sopenharmony_ci int rv; 4068c2ecf20Sopenharmony_ci u32 data; 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci rv = qla4_82xx_pci_get_crb_addr_2M(ha, &off); 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci BUG_ON(rv == -1); 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci if (rv == 1) { 4138c2ecf20Sopenharmony_ci write_lock_irqsave(&ha->hw_lock, flags); 4148c2ecf20Sopenharmony_ci qla4_82xx_crb_win_lock(ha); 4158c2ecf20Sopenharmony_ci qla4_82xx_pci_set_crbwindow_2M(ha, &off); 4168c2ecf20Sopenharmony_ci } 4178c2ecf20Sopenharmony_ci data = readl((void __iomem *)off); 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci if (rv == 1) { 4208c2ecf20Sopenharmony_ci qla4_82xx_crb_win_unlock(ha); 4218c2ecf20Sopenharmony_ci write_unlock_irqrestore(&ha->hw_lock, flags); 4228c2ecf20Sopenharmony_ci } 4238c2ecf20Sopenharmony_ci return data; 4248c2ecf20Sopenharmony_ci} 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci/* Minidump related functions */ 4278c2ecf20Sopenharmony_ciint qla4_82xx_md_rd_32(struct scsi_qla_host *ha, uint32_t off, uint32_t *data) 4288c2ecf20Sopenharmony_ci{ 4298c2ecf20Sopenharmony_ci uint32_t win_read, off_value; 4308c2ecf20Sopenharmony_ci int rval = QLA_SUCCESS; 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci off_value = off & 0xFFFF0000; 4338c2ecf20Sopenharmony_ci writel(off_value, (void __iomem *)(CRB_WINDOW_2M + ha->nx_pcibase)); 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci /* 4368c2ecf20Sopenharmony_ci * Read back value to make sure write has gone through before trying 4378c2ecf20Sopenharmony_ci * to use it. 4388c2ecf20Sopenharmony_ci */ 4398c2ecf20Sopenharmony_ci win_read = readl((void __iomem *)(CRB_WINDOW_2M + ha->nx_pcibase)); 4408c2ecf20Sopenharmony_ci if (win_read != off_value) { 4418c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 4428c2ecf20Sopenharmony_ci "%s: Written (0x%x) != Read (0x%x), off=0x%x\n", 4438c2ecf20Sopenharmony_ci __func__, off_value, win_read, off)); 4448c2ecf20Sopenharmony_ci rval = QLA_ERROR; 4458c2ecf20Sopenharmony_ci } else { 4468c2ecf20Sopenharmony_ci off_value = off & 0x0000FFFF; 4478c2ecf20Sopenharmony_ci *data = readl((void __iomem *)(off_value + CRB_INDIRECT_2M + 4488c2ecf20Sopenharmony_ci ha->nx_pcibase)); 4498c2ecf20Sopenharmony_ci } 4508c2ecf20Sopenharmony_ci return rval; 4518c2ecf20Sopenharmony_ci} 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ciint qla4_82xx_md_wr_32(struct scsi_qla_host *ha, uint32_t off, uint32_t data) 4548c2ecf20Sopenharmony_ci{ 4558c2ecf20Sopenharmony_ci uint32_t win_read, off_value; 4568c2ecf20Sopenharmony_ci int rval = QLA_SUCCESS; 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_ci off_value = off & 0xFFFF0000; 4598c2ecf20Sopenharmony_ci writel(off_value, (void __iomem *)(CRB_WINDOW_2M + ha->nx_pcibase)); 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci /* Read back value to make sure write has gone through before trying 4628c2ecf20Sopenharmony_ci * to use it. 4638c2ecf20Sopenharmony_ci */ 4648c2ecf20Sopenharmony_ci win_read = readl((void __iomem *)(CRB_WINDOW_2M + ha->nx_pcibase)); 4658c2ecf20Sopenharmony_ci if (win_read != off_value) { 4668c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 4678c2ecf20Sopenharmony_ci "%s: Written (0x%x) != Read (0x%x), off=0x%x\n", 4688c2ecf20Sopenharmony_ci __func__, off_value, win_read, off)); 4698c2ecf20Sopenharmony_ci rval = QLA_ERROR; 4708c2ecf20Sopenharmony_ci } else { 4718c2ecf20Sopenharmony_ci off_value = off & 0x0000FFFF; 4728c2ecf20Sopenharmony_ci writel(data, (void __iomem *)(off_value + CRB_INDIRECT_2M + 4738c2ecf20Sopenharmony_ci ha->nx_pcibase)); 4748c2ecf20Sopenharmony_ci } 4758c2ecf20Sopenharmony_ci return rval; 4768c2ecf20Sopenharmony_ci} 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_ci#define CRB_WIN_LOCK_TIMEOUT 100000000 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ciint qla4_82xx_crb_win_lock(struct scsi_qla_host *ha) 4818c2ecf20Sopenharmony_ci{ 4828c2ecf20Sopenharmony_ci int i; 4838c2ecf20Sopenharmony_ci int done = 0, timeout = 0; 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci while (!done) { 4868c2ecf20Sopenharmony_ci /* acquire semaphore3 from PCI HW block */ 4878c2ecf20Sopenharmony_ci done = qla4_82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM7_LOCK)); 4888c2ecf20Sopenharmony_ci if (done == 1) 4898c2ecf20Sopenharmony_ci break; 4908c2ecf20Sopenharmony_ci if (timeout >= CRB_WIN_LOCK_TIMEOUT) 4918c2ecf20Sopenharmony_ci return -1; 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_ci timeout++; 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci /* Yield CPU */ 4968c2ecf20Sopenharmony_ci if (!in_interrupt()) 4978c2ecf20Sopenharmony_ci schedule(); 4988c2ecf20Sopenharmony_ci else { 4998c2ecf20Sopenharmony_ci for (i = 0; i < 20; i++) 5008c2ecf20Sopenharmony_ci cpu_relax(); /*This a nop instr on i386*/ 5018c2ecf20Sopenharmony_ci } 5028c2ecf20Sopenharmony_ci } 5038c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_WIN_LOCK_ID, ha->func_num); 5048c2ecf20Sopenharmony_ci return 0; 5058c2ecf20Sopenharmony_ci} 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_civoid qla4_82xx_crb_win_unlock(struct scsi_qla_host *ha) 5088c2ecf20Sopenharmony_ci{ 5098c2ecf20Sopenharmony_ci qla4_82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM7_UNLOCK)); 5108c2ecf20Sopenharmony_ci} 5118c2ecf20Sopenharmony_ci 5128c2ecf20Sopenharmony_ci#define IDC_LOCK_TIMEOUT 100000000 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_ci/** 5158c2ecf20Sopenharmony_ci * qla4_82xx_idc_lock - hw_lock 5168c2ecf20Sopenharmony_ci * @ha: pointer to adapter structure 5178c2ecf20Sopenharmony_ci * 5188c2ecf20Sopenharmony_ci * General purpose lock used to synchronize access to 5198c2ecf20Sopenharmony_ci * CRB_DEV_STATE, CRB_DEV_REF_COUNT, etc. 5208c2ecf20Sopenharmony_ci **/ 5218c2ecf20Sopenharmony_ciint qla4_82xx_idc_lock(struct scsi_qla_host *ha) 5228c2ecf20Sopenharmony_ci{ 5238c2ecf20Sopenharmony_ci int i; 5248c2ecf20Sopenharmony_ci int done = 0, timeout = 0; 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_ci while (!done) { 5278c2ecf20Sopenharmony_ci /* acquire semaphore5 from PCI HW block */ 5288c2ecf20Sopenharmony_ci done = qla4_82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM5_LOCK)); 5298c2ecf20Sopenharmony_ci if (done == 1) 5308c2ecf20Sopenharmony_ci break; 5318c2ecf20Sopenharmony_ci if (timeout >= IDC_LOCK_TIMEOUT) 5328c2ecf20Sopenharmony_ci return -1; 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_ci timeout++; 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_ci /* Yield CPU */ 5378c2ecf20Sopenharmony_ci if (!in_interrupt()) 5388c2ecf20Sopenharmony_ci schedule(); 5398c2ecf20Sopenharmony_ci else { 5408c2ecf20Sopenharmony_ci for (i = 0; i < 20; i++) 5418c2ecf20Sopenharmony_ci cpu_relax(); /*This a nop instr on i386*/ 5428c2ecf20Sopenharmony_ci } 5438c2ecf20Sopenharmony_ci } 5448c2ecf20Sopenharmony_ci return 0; 5458c2ecf20Sopenharmony_ci} 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_civoid qla4_82xx_idc_unlock(struct scsi_qla_host *ha) 5488c2ecf20Sopenharmony_ci{ 5498c2ecf20Sopenharmony_ci qla4_82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM5_UNLOCK)); 5508c2ecf20Sopenharmony_ci} 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_ciint 5538c2ecf20Sopenharmony_ciqla4_82xx_pci_get_crb_addr_2M(struct scsi_qla_host *ha, ulong *off) 5548c2ecf20Sopenharmony_ci{ 5558c2ecf20Sopenharmony_ci struct crb_128M_2M_sub_block_map *m; 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci if (*off >= QLA82XX_CRB_MAX) 5588c2ecf20Sopenharmony_ci return -1; 5598c2ecf20Sopenharmony_ci 5608c2ecf20Sopenharmony_ci if (*off >= QLA82XX_PCI_CAMQM && (*off < QLA82XX_PCI_CAMQM_2M_END)) { 5618c2ecf20Sopenharmony_ci *off = (*off - QLA82XX_PCI_CAMQM) + 5628c2ecf20Sopenharmony_ci QLA82XX_PCI_CAMQM_2M_BASE + ha->nx_pcibase; 5638c2ecf20Sopenharmony_ci return 0; 5648c2ecf20Sopenharmony_ci } 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_ci if (*off < QLA82XX_PCI_CRBSPACE) 5678c2ecf20Sopenharmony_ci return -1; 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_ci *off -= QLA82XX_PCI_CRBSPACE; 5708c2ecf20Sopenharmony_ci /* 5718c2ecf20Sopenharmony_ci * Try direct map 5728c2ecf20Sopenharmony_ci */ 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ci m = &crb_128M_2M_map[CRB_BLK(*off)].sub_block[CRB_SUBBLK(*off)]; 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_ci if (m->valid && (m->start_128M <= *off) && (m->end_128M > *off)) { 5778c2ecf20Sopenharmony_ci *off = *off + m->start_2M - m->start_128M + ha->nx_pcibase; 5788c2ecf20Sopenharmony_ci return 0; 5798c2ecf20Sopenharmony_ci } 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_ci /* 5828c2ecf20Sopenharmony_ci * Not in direct map, use crb window 5838c2ecf20Sopenharmony_ci */ 5848c2ecf20Sopenharmony_ci return 1; 5858c2ecf20Sopenharmony_ci} 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_ci/* 5888c2ecf20Sopenharmony_ci* check memory access boundary. 5898c2ecf20Sopenharmony_ci* used by test agent. support ddr access only for now 5908c2ecf20Sopenharmony_ci*/ 5918c2ecf20Sopenharmony_cistatic unsigned long 5928c2ecf20Sopenharmony_ciqla4_82xx_pci_mem_bound_check(struct scsi_qla_host *ha, 5938c2ecf20Sopenharmony_ci unsigned long long addr, int size) 5948c2ecf20Sopenharmony_ci{ 5958c2ecf20Sopenharmony_ci if (!QLA8XXX_ADDR_IN_RANGE(addr, QLA8XXX_ADDR_DDR_NET, 5968c2ecf20Sopenharmony_ci QLA8XXX_ADDR_DDR_NET_MAX) || 5978c2ecf20Sopenharmony_ci !QLA8XXX_ADDR_IN_RANGE(addr + size - 1, 5988c2ecf20Sopenharmony_ci QLA8XXX_ADDR_DDR_NET, QLA8XXX_ADDR_DDR_NET_MAX) || 5998c2ecf20Sopenharmony_ci ((size != 1) && (size != 2) && (size != 4) && (size != 8))) { 6008c2ecf20Sopenharmony_ci return 0; 6018c2ecf20Sopenharmony_ci } 6028c2ecf20Sopenharmony_ci return 1; 6038c2ecf20Sopenharmony_ci} 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_cistatic int qla4_82xx_pci_set_window_warning_count; 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_cistatic unsigned long 6088c2ecf20Sopenharmony_ciqla4_82xx_pci_set_window(struct scsi_qla_host *ha, unsigned long long addr) 6098c2ecf20Sopenharmony_ci{ 6108c2ecf20Sopenharmony_ci int window; 6118c2ecf20Sopenharmony_ci u32 win_read; 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_ci if (QLA8XXX_ADDR_IN_RANGE(addr, QLA8XXX_ADDR_DDR_NET, 6148c2ecf20Sopenharmony_ci QLA8XXX_ADDR_DDR_NET_MAX)) { 6158c2ecf20Sopenharmony_ci /* DDR network side */ 6168c2ecf20Sopenharmony_ci window = MN_WIN(addr); 6178c2ecf20Sopenharmony_ci ha->ddr_mn_window = window; 6188c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, ha->mn_win_crb | 6198c2ecf20Sopenharmony_ci QLA82XX_PCI_CRBSPACE, window); 6208c2ecf20Sopenharmony_ci win_read = qla4_82xx_rd_32(ha, ha->mn_win_crb | 6218c2ecf20Sopenharmony_ci QLA82XX_PCI_CRBSPACE); 6228c2ecf20Sopenharmony_ci if ((win_read << 17) != window) { 6238c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, 6248c2ecf20Sopenharmony_ci "%s: Written MNwin (0x%x) != Read MNwin (0x%x)\n", 6258c2ecf20Sopenharmony_ci __func__, window, win_read); 6268c2ecf20Sopenharmony_ci } 6278c2ecf20Sopenharmony_ci addr = GET_MEM_OFFS_2M(addr) + QLA82XX_PCI_DDR_NET; 6288c2ecf20Sopenharmony_ci } else if (QLA8XXX_ADDR_IN_RANGE(addr, QLA8XXX_ADDR_OCM0, 6298c2ecf20Sopenharmony_ci QLA8XXX_ADDR_OCM0_MAX)) { 6308c2ecf20Sopenharmony_ci unsigned int temp1; 6318c2ecf20Sopenharmony_ci /* if bits 19:18&17:11 are on */ 6328c2ecf20Sopenharmony_ci if ((addr & 0x00ff800) == 0xff800) { 6338c2ecf20Sopenharmony_ci printk("%s: QM access not handled.\n", __func__); 6348c2ecf20Sopenharmony_ci addr = -1UL; 6358c2ecf20Sopenharmony_ci } 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_ci window = OCM_WIN(addr); 6388c2ecf20Sopenharmony_ci ha->ddr_mn_window = window; 6398c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, ha->mn_win_crb | 6408c2ecf20Sopenharmony_ci QLA82XX_PCI_CRBSPACE, window); 6418c2ecf20Sopenharmony_ci win_read = qla4_82xx_rd_32(ha, ha->mn_win_crb | 6428c2ecf20Sopenharmony_ci QLA82XX_PCI_CRBSPACE); 6438c2ecf20Sopenharmony_ci temp1 = ((window & 0x1FF) << 7) | 6448c2ecf20Sopenharmony_ci ((window & 0x0FFFE0000) >> 17); 6458c2ecf20Sopenharmony_ci if (win_read != temp1) { 6468c2ecf20Sopenharmony_ci printk("%s: Written OCMwin (0x%x) != Read" 6478c2ecf20Sopenharmony_ci " OCMwin (0x%x)\n", __func__, temp1, win_read); 6488c2ecf20Sopenharmony_ci } 6498c2ecf20Sopenharmony_ci addr = GET_MEM_OFFS_2M(addr) + QLA82XX_PCI_OCM0_2M; 6508c2ecf20Sopenharmony_ci 6518c2ecf20Sopenharmony_ci } else if (QLA8XXX_ADDR_IN_RANGE(addr, QLA8XXX_ADDR_QDR_NET, 6528c2ecf20Sopenharmony_ci QLA82XX_P3_ADDR_QDR_NET_MAX)) { 6538c2ecf20Sopenharmony_ci /* QDR network side */ 6548c2ecf20Sopenharmony_ci window = MS_WIN(addr); 6558c2ecf20Sopenharmony_ci ha->qdr_sn_window = window; 6568c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, ha->ms_win_crb | 6578c2ecf20Sopenharmony_ci QLA82XX_PCI_CRBSPACE, window); 6588c2ecf20Sopenharmony_ci win_read = qla4_82xx_rd_32(ha, 6598c2ecf20Sopenharmony_ci ha->ms_win_crb | QLA82XX_PCI_CRBSPACE); 6608c2ecf20Sopenharmony_ci if (win_read != window) { 6618c2ecf20Sopenharmony_ci printk("%s: Written MSwin (0x%x) != Read " 6628c2ecf20Sopenharmony_ci "MSwin (0x%x)\n", __func__, window, win_read); 6638c2ecf20Sopenharmony_ci } 6648c2ecf20Sopenharmony_ci addr = GET_MEM_OFFS_2M(addr) + QLA82XX_PCI_QDR_NET; 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci } else { 6678c2ecf20Sopenharmony_ci /* 6688c2ecf20Sopenharmony_ci * peg gdb frequently accesses memory that doesn't exist, 6698c2ecf20Sopenharmony_ci * this limits the chit chat so debugging isn't slowed down. 6708c2ecf20Sopenharmony_ci */ 6718c2ecf20Sopenharmony_ci if ((qla4_82xx_pci_set_window_warning_count++ < 8) || 6728c2ecf20Sopenharmony_ci (qla4_82xx_pci_set_window_warning_count%64 == 0)) { 6738c2ecf20Sopenharmony_ci printk("%s: Warning:%s Unknown address range!\n", 6748c2ecf20Sopenharmony_ci __func__, DRIVER_NAME); 6758c2ecf20Sopenharmony_ci } 6768c2ecf20Sopenharmony_ci addr = -1UL; 6778c2ecf20Sopenharmony_ci } 6788c2ecf20Sopenharmony_ci return addr; 6798c2ecf20Sopenharmony_ci} 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_ci/* check if address is in the same windows as the previous access */ 6828c2ecf20Sopenharmony_cistatic int qla4_82xx_pci_is_same_window(struct scsi_qla_host *ha, 6838c2ecf20Sopenharmony_ci unsigned long long addr) 6848c2ecf20Sopenharmony_ci{ 6858c2ecf20Sopenharmony_ci int window; 6868c2ecf20Sopenharmony_ci unsigned long long qdr_max; 6878c2ecf20Sopenharmony_ci 6888c2ecf20Sopenharmony_ci qdr_max = QLA82XX_P3_ADDR_QDR_NET_MAX; 6898c2ecf20Sopenharmony_ci 6908c2ecf20Sopenharmony_ci if (QLA8XXX_ADDR_IN_RANGE(addr, QLA8XXX_ADDR_DDR_NET, 6918c2ecf20Sopenharmony_ci QLA8XXX_ADDR_DDR_NET_MAX)) { 6928c2ecf20Sopenharmony_ci /* DDR network side */ 6938c2ecf20Sopenharmony_ci BUG(); /* MN access can not come here */ 6948c2ecf20Sopenharmony_ci } else if (QLA8XXX_ADDR_IN_RANGE(addr, QLA8XXX_ADDR_OCM0, 6958c2ecf20Sopenharmony_ci QLA8XXX_ADDR_OCM0_MAX)) { 6968c2ecf20Sopenharmony_ci return 1; 6978c2ecf20Sopenharmony_ci } else if (QLA8XXX_ADDR_IN_RANGE(addr, QLA8XXX_ADDR_OCM1, 6988c2ecf20Sopenharmony_ci QLA8XXX_ADDR_OCM1_MAX)) { 6998c2ecf20Sopenharmony_ci return 1; 7008c2ecf20Sopenharmony_ci } else if (QLA8XXX_ADDR_IN_RANGE(addr, QLA8XXX_ADDR_QDR_NET, 7018c2ecf20Sopenharmony_ci qdr_max)) { 7028c2ecf20Sopenharmony_ci /* QDR network side */ 7038c2ecf20Sopenharmony_ci window = ((addr - QLA8XXX_ADDR_QDR_NET) >> 22) & 0x3f; 7048c2ecf20Sopenharmony_ci if (ha->qdr_sn_window == window) 7058c2ecf20Sopenharmony_ci return 1; 7068c2ecf20Sopenharmony_ci } 7078c2ecf20Sopenharmony_ci 7088c2ecf20Sopenharmony_ci return 0; 7098c2ecf20Sopenharmony_ci} 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_cistatic int qla4_82xx_pci_mem_read_direct(struct scsi_qla_host *ha, 7128c2ecf20Sopenharmony_ci u64 off, void *data, int size) 7138c2ecf20Sopenharmony_ci{ 7148c2ecf20Sopenharmony_ci unsigned long flags; 7158c2ecf20Sopenharmony_ci void __iomem *addr; 7168c2ecf20Sopenharmony_ci int ret = 0; 7178c2ecf20Sopenharmony_ci u64 start; 7188c2ecf20Sopenharmony_ci void __iomem *mem_ptr = NULL; 7198c2ecf20Sopenharmony_ci unsigned long mem_base; 7208c2ecf20Sopenharmony_ci unsigned long mem_page; 7218c2ecf20Sopenharmony_ci 7228c2ecf20Sopenharmony_ci write_lock_irqsave(&ha->hw_lock, flags); 7238c2ecf20Sopenharmony_ci 7248c2ecf20Sopenharmony_ci /* 7258c2ecf20Sopenharmony_ci * If attempting to access unknown address or straddle hw windows, 7268c2ecf20Sopenharmony_ci * do not access. 7278c2ecf20Sopenharmony_ci */ 7288c2ecf20Sopenharmony_ci start = qla4_82xx_pci_set_window(ha, off); 7298c2ecf20Sopenharmony_ci if ((start == -1UL) || 7308c2ecf20Sopenharmony_ci (qla4_82xx_pci_is_same_window(ha, off + size - 1) == 0)) { 7318c2ecf20Sopenharmony_ci write_unlock_irqrestore(&ha->hw_lock, flags); 7328c2ecf20Sopenharmony_ci printk(KERN_ERR"%s out of bound pci memory access. " 7338c2ecf20Sopenharmony_ci "offset is 0x%llx\n", DRIVER_NAME, off); 7348c2ecf20Sopenharmony_ci return -1; 7358c2ecf20Sopenharmony_ci } 7368c2ecf20Sopenharmony_ci 7378c2ecf20Sopenharmony_ci addr = qla4_8xxx_pci_base_offsetfset(ha, start); 7388c2ecf20Sopenharmony_ci if (!addr) { 7398c2ecf20Sopenharmony_ci write_unlock_irqrestore(&ha->hw_lock, flags); 7408c2ecf20Sopenharmony_ci mem_base = pci_resource_start(ha->pdev, 0); 7418c2ecf20Sopenharmony_ci mem_page = start & PAGE_MASK; 7428c2ecf20Sopenharmony_ci /* Map two pages whenever user tries to access addresses in two 7438c2ecf20Sopenharmony_ci consecutive pages. 7448c2ecf20Sopenharmony_ci */ 7458c2ecf20Sopenharmony_ci if (mem_page != ((start + size - 1) & PAGE_MASK)) 7468c2ecf20Sopenharmony_ci mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE * 2); 7478c2ecf20Sopenharmony_ci else 7488c2ecf20Sopenharmony_ci mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE); 7498c2ecf20Sopenharmony_ci 7508c2ecf20Sopenharmony_ci if (mem_ptr == NULL) { 7518c2ecf20Sopenharmony_ci *(u8 *)data = 0; 7528c2ecf20Sopenharmony_ci return -1; 7538c2ecf20Sopenharmony_ci } 7548c2ecf20Sopenharmony_ci addr = mem_ptr; 7558c2ecf20Sopenharmony_ci addr += start & (PAGE_SIZE - 1); 7568c2ecf20Sopenharmony_ci write_lock_irqsave(&ha->hw_lock, flags); 7578c2ecf20Sopenharmony_ci } 7588c2ecf20Sopenharmony_ci 7598c2ecf20Sopenharmony_ci switch (size) { 7608c2ecf20Sopenharmony_ci case 1: 7618c2ecf20Sopenharmony_ci *(u8 *)data = readb(addr); 7628c2ecf20Sopenharmony_ci break; 7638c2ecf20Sopenharmony_ci case 2: 7648c2ecf20Sopenharmony_ci *(u16 *)data = readw(addr); 7658c2ecf20Sopenharmony_ci break; 7668c2ecf20Sopenharmony_ci case 4: 7678c2ecf20Sopenharmony_ci *(u32 *)data = readl(addr); 7688c2ecf20Sopenharmony_ci break; 7698c2ecf20Sopenharmony_ci case 8: 7708c2ecf20Sopenharmony_ci *(u64 *)data = readq(addr); 7718c2ecf20Sopenharmony_ci break; 7728c2ecf20Sopenharmony_ci default: 7738c2ecf20Sopenharmony_ci ret = -1; 7748c2ecf20Sopenharmony_ci break; 7758c2ecf20Sopenharmony_ci } 7768c2ecf20Sopenharmony_ci write_unlock_irqrestore(&ha->hw_lock, flags); 7778c2ecf20Sopenharmony_ci 7788c2ecf20Sopenharmony_ci if (mem_ptr) 7798c2ecf20Sopenharmony_ci iounmap(mem_ptr); 7808c2ecf20Sopenharmony_ci return ret; 7818c2ecf20Sopenharmony_ci} 7828c2ecf20Sopenharmony_ci 7838c2ecf20Sopenharmony_cistatic int 7848c2ecf20Sopenharmony_ciqla4_82xx_pci_mem_write_direct(struct scsi_qla_host *ha, u64 off, 7858c2ecf20Sopenharmony_ci void *data, int size) 7868c2ecf20Sopenharmony_ci{ 7878c2ecf20Sopenharmony_ci unsigned long flags; 7888c2ecf20Sopenharmony_ci void __iomem *addr; 7898c2ecf20Sopenharmony_ci int ret = 0; 7908c2ecf20Sopenharmony_ci u64 start; 7918c2ecf20Sopenharmony_ci void __iomem *mem_ptr = NULL; 7928c2ecf20Sopenharmony_ci unsigned long mem_base; 7938c2ecf20Sopenharmony_ci unsigned long mem_page; 7948c2ecf20Sopenharmony_ci 7958c2ecf20Sopenharmony_ci write_lock_irqsave(&ha->hw_lock, flags); 7968c2ecf20Sopenharmony_ci 7978c2ecf20Sopenharmony_ci /* 7988c2ecf20Sopenharmony_ci * If attempting to access unknown address or straddle hw windows, 7998c2ecf20Sopenharmony_ci * do not access. 8008c2ecf20Sopenharmony_ci */ 8018c2ecf20Sopenharmony_ci start = qla4_82xx_pci_set_window(ha, off); 8028c2ecf20Sopenharmony_ci if ((start == -1UL) || 8038c2ecf20Sopenharmony_ci (qla4_82xx_pci_is_same_window(ha, off + size - 1) == 0)) { 8048c2ecf20Sopenharmony_ci write_unlock_irqrestore(&ha->hw_lock, flags); 8058c2ecf20Sopenharmony_ci printk(KERN_ERR"%s out of bound pci memory access. " 8068c2ecf20Sopenharmony_ci "offset is 0x%llx\n", DRIVER_NAME, off); 8078c2ecf20Sopenharmony_ci return -1; 8088c2ecf20Sopenharmony_ci } 8098c2ecf20Sopenharmony_ci 8108c2ecf20Sopenharmony_ci addr = qla4_8xxx_pci_base_offsetfset(ha, start); 8118c2ecf20Sopenharmony_ci if (!addr) { 8128c2ecf20Sopenharmony_ci write_unlock_irqrestore(&ha->hw_lock, flags); 8138c2ecf20Sopenharmony_ci mem_base = pci_resource_start(ha->pdev, 0); 8148c2ecf20Sopenharmony_ci mem_page = start & PAGE_MASK; 8158c2ecf20Sopenharmony_ci /* Map two pages whenever user tries to access addresses in two 8168c2ecf20Sopenharmony_ci consecutive pages. 8178c2ecf20Sopenharmony_ci */ 8188c2ecf20Sopenharmony_ci if (mem_page != ((start + size - 1) & PAGE_MASK)) 8198c2ecf20Sopenharmony_ci mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE*2); 8208c2ecf20Sopenharmony_ci else 8218c2ecf20Sopenharmony_ci mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE); 8228c2ecf20Sopenharmony_ci if (mem_ptr == NULL) 8238c2ecf20Sopenharmony_ci return -1; 8248c2ecf20Sopenharmony_ci 8258c2ecf20Sopenharmony_ci addr = mem_ptr; 8268c2ecf20Sopenharmony_ci addr += start & (PAGE_SIZE - 1); 8278c2ecf20Sopenharmony_ci write_lock_irqsave(&ha->hw_lock, flags); 8288c2ecf20Sopenharmony_ci } 8298c2ecf20Sopenharmony_ci 8308c2ecf20Sopenharmony_ci switch (size) { 8318c2ecf20Sopenharmony_ci case 1: 8328c2ecf20Sopenharmony_ci writeb(*(u8 *)data, addr); 8338c2ecf20Sopenharmony_ci break; 8348c2ecf20Sopenharmony_ci case 2: 8358c2ecf20Sopenharmony_ci writew(*(u16 *)data, addr); 8368c2ecf20Sopenharmony_ci break; 8378c2ecf20Sopenharmony_ci case 4: 8388c2ecf20Sopenharmony_ci writel(*(u32 *)data, addr); 8398c2ecf20Sopenharmony_ci break; 8408c2ecf20Sopenharmony_ci case 8: 8418c2ecf20Sopenharmony_ci writeq(*(u64 *)data, addr); 8428c2ecf20Sopenharmony_ci break; 8438c2ecf20Sopenharmony_ci default: 8448c2ecf20Sopenharmony_ci ret = -1; 8458c2ecf20Sopenharmony_ci break; 8468c2ecf20Sopenharmony_ci } 8478c2ecf20Sopenharmony_ci write_unlock_irqrestore(&ha->hw_lock, flags); 8488c2ecf20Sopenharmony_ci if (mem_ptr) 8498c2ecf20Sopenharmony_ci iounmap(mem_ptr); 8508c2ecf20Sopenharmony_ci return ret; 8518c2ecf20Sopenharmony_ci} 8528c2ecf20Sopenharmony_ci 8538c2ecf20Sopenharmony_ci#define MTU_FUDGE_FACTOR 100 8548c2ecf20Sopenharmony_ci 8558c2ecf20Sopenharmony_cistatic unsigned long 8568c2ecf20Sopenharmony_ciqla4_82xx_decode_crb_addr(unsigned long addr) 8578c2ecf20Sopenharmony_ci{ 8588c2ecf20Sopenharmony_ci int i; 8598c2ecf20Sopenharmony_ci unsigned long base_addr, offset, pci_base; 8608c2ecf20Sopenharmony_ci 8618c2ecf20Sopenharmony_ci if (!qla4_8xxx_crb_table_initialized) 8628c2ecf20Sopenharmony_ci qla4_82xx_crb_addr_transform_setup(); 8638c2ecf20Sopenharmony_ci 8648c2ecf20Sopenharmony_ci pci_base = ADDR_ERROR; 8658c2ecf20Sopenharmony_ci base_addr = addr & 0xfff00000; 8668c2ecf20Sopenharmony_ci offset = addr & 0x000fffff; 8678c2ecf20Sopenharmony_ci 8688c2ecf20Sopenharmony_ci for (i = 0; i < MAX_CRB_XFORM; i++) { 8698c2ecf20Sopenharmony_ci if (crb_addr_xform[i] == base_addr) { 8708c2ecf20Sopenharmony_ci pci_base = i << 20; 8718c2ecf20Sopenharmony_ci break; 8728c2ecf20Sopenharmony_ci } 8738c2ecf20Sopenharmony_ci } 8748c2ecf20Sopenharmony_ci if (pci_base == ADDR_ERROR) 8758c2ecf20Sopenharmony_ci return pci_base; 8768c2ecf20Sopenharmony_ci else 8778c2ecf20Sopenharmony_ci return pci_base + offset; 8788c2ecf20Sopenharmony_ci} 8798c2ecf20Sopenharmony_ci 8808c2ecf20Sopenharmony_cistatic long rom_max_timeout = 100; 8818c2ecf20Sopenharmony_cistatic long qla4_82xx_rom_lock_timeout = 100; 8828c2ecf20Sopenharmony_ci 8838c2ecf20Sopenharmony_cistatic int 8848c2ecf20Sopenharmony_ciqla4_82xx_rom_lock(struct scsi_qla_host *ha) 8858c2ecf20Sopenharmony_ci{ 8868c2ecf20Sopenharmony_ci int i; 8878c2ecf20Sopenharmony_ci int done = 0, timeout = 0; 8888c2ecf20Sopenharmony_ci 8898c2ecf20Sopenharmony_ci while (!done) { 8908c2ecf20Sopenharmony_ci /* acquire semaphore2 from PCI HW block */ 8918c2ecf20Sopenharmony_ci 8928c2ecf20Sopenharmony_ci done = qla4_82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM2_LOCK)); 8938c2ecf20Sopenharmony_ci if (done == 1) 8948c2ecf20Sopenharmony_ci break; 8958c2ecf20Sopenharmony_ci if (timeout >= qla4_82xx_rom_lock_timeout) 8968c2ecf20Sopenharmony_ci return -1; 8978c2ecf20Sopenharmony_ci 8988c2ecf20Sopenharmony_ci timeout++; 8998c2ecf20Sopenharmony_ci 9008c2ecf20Sopenharmony_ci /* Yield CPU */ 9018c2ecf20Sopenharmony_ci if (!in_interrupt()) 9028c2ecf20Sopenharmony_ci schedule(); 9038c2ecf20Sopenharmony_ci else { 9048c2ecf20Sopenharmony_ci for (i = 0; i < 20; i++) 9058c2ecf20Sopenharmony_ci cpu_relax(); /*This a nop instr on i386*/ 9068c2ecf20Sopenharmony_ci } 9078c2ecf20Sopenharmony_ci } 9088c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_ROM_LOCK_ID, ROM_LOCK_DRIVER); 9098c2ecf20Sopenharmony_ci return 0; 9108c2ecf20Sopenharmony_ci} 9118c2ecf20Sopenharmony_ci 9128c2ecf20Sopenharmony_cistatic void 9138c2ecf20Sopenharmony_ciqla4_82xx_rom_unlock(struct scsi_qla_host *ha) 9148c2ecf20Sopenharmony_ci{ 9158c2ecf20Sopenharmony_ci qla4_82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM2_UNLOCK)); 9168c2ecf20Sopenharmony_ci} 9178c2ecf20Sopenharmony_ci 9188c2ecf20Sopenharmony_cistatic int 9198c2ecf20Sopenharmony_ciqla4_82xx_wait_rom_done(struct scsi_qla_host *ha) 9208c2ecf20Sopenharmony_ci{ 9218c2ecf20Sopenharmony_ci long timeout = 0; 9228c2ecf20Sopenharmony_ci long done = 0 ; 9238c2ecf20Sopenharmony_ci 9248c2ecf20Sopenharmony_ci while (done == 0) { 9258c2ecf20Sopenharmony_ci done = qla4_82xx_rd_32(ha, QLA82XX_ROMUSB_GLB_STATUS); 9268c2ecf20Sopenharmony_ci done &= 2; 9278c2ecf20Sopenharmony_ci timeout++; 9288c2ecf20Sopenharmony_ci if (timeout >= rom_max_timeout) { 9298c2ecf20Sopenharmony_ci printk("%s: Timeout reached waiting for rom done", 9308c2ecf20Sopenharmony_ci DRIVER_NAME); 9318c2ecf20Sopenharmony_ci return -1; 9328c2ecf20Sopenharmony_ci } 9338c2ecf20Sopenharmony_ci } 9348c2ecf20Sopenharmony_ci return 0; 9358c2ecf20Sopenharmony_ci} 9368c2ecf20Sopenharmony_ci 9378c2ecf20Sopenharmony_cistatic int 9388c2ecf20Sopenharmony_ciqla4_82xx_do_rom_fast_read(struct scsi_qla_host *ha, int addr, int *valp) 9398c2ecf20Sopenharmony_ci{ 9408c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_ADDRESS, addr); 9418c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_DUMMY_BYTE_CNT, 0); 9428c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_ABYTE_CNT, 3); 9438c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, 0xb); 9448c2ecf20Sopenharmony_ci if (qla4_82xx_wait_rom_done(ha)) { 9458c2ecf20Sopenharmony_ci printk("%s: Error waiting for rom done\n", DRIVER_NAME); 9468c2ecf20Sopenharmony_ci return -1; 9478c2ecf20Sopenharmony_ci } 9488c2ecf20Sopenharmony_ci /* reset abyte_cnt and dummy_byte_cnt */ 9498c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_DUMMY_BYTE_CNT, 0); 9508c2ecf20Sopenharmony_ci udelay(10); 9518c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_ABYTE_CNT, 0); 9528c2ecf20Sopenharmony_ci 9538c2ecf20Sopenharmony_ci *valp = qla4_82xx_rd_32(ha, QLA82XX_ROMUSB_ROM_RDATA); 9548c2ecf20Sopenharmony_ci return 0; 9558c2ecf20Sopenharmony_ci} 9568c2ecf20Sopenharmony_ci 9578c2ecf20Sopenharmony_cistatic int 9588c2ecf20Sopenharmony_ciqla4_82xx_rom_fast_read(struct scsi_qla_host *ha, int addr, int *valp) 9598c2ecf20Sopenharmony_ci{ 9608c2ecf20Sopenharmony_ci int ret, loops = 0; 9618c2ecf20Sopenharmony_ci 9628c2ecf20Sopenharmony_ci while ((qla4_82xx_rom_lock(ha) != 0) && (loops < 50000)) { 9638c2ecf20Sopenharmony_ci udelay(100); 9648c2ecf20Sopenharmony_ci loops++; 9658c2ecf20Sopenharmony_ci } 9668c2ecf20Sopenharmony_ci if (loops >= 50000) { 9678c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, "%s: qla4_82xx_rom_lock failed\n", 9688c2ecf20Sopenharmony_ci DRIVER_NAME); 9698c2ecf20Sopenharmony_ci return -1; 9708c2ecf20Sopenharmony_ci } 9718c2ecf20Sopenharmony_ci ret = qla4_82xx_do_rom_fast_read(ha, addr, valp); 9728c2ecf20Sopenharmony_ci qla4_82xx_rom_unlock(ha); 9738c2ecf20Sopenharmony_ci return ret; 9748c2ecf20Sopenharmony_ci} 9758c2ecf20Sopenharmony_ci 9768c2ecf20Sopenharmony_ci/* 9778c2ecf20Sopenharmony_ci * This routine does CRB initialize sequence 9788c2ecf20Sopenharmony_ci * to put the ISP into operational state 9798c2ecf20Sopenharmony_ci */ 9808c2ecf20Sopenharmony_cistatic int 9818c2ecf20Sopenharmony_ciqla4_82xx_pinit_from_rom(struct scsi_qla_host *ha, int verbose) 9828c2ecf20Sopenharmony_ci{ 9838c2ecf20Sopenharmony_ci int addr, val; 9848c2ecf20Sopenharmony_ci int i ; 9858c2ecf20Sopenharmony_ci struct crb_addr_pair *buf; 9868c2ecf20Sopenharmony_ci unsigned long off; 9878c2ecf20Sopenharmony_ci unsigned offset, n; 9888c2ecf20Sopenharmony_ci 9898c2ecf20Sopenharmony_ci struct crb_addr_pair { 9908c2ecf20Sopenharmony_ci long addr; 9918c2ecf20Sopenharmony_ci long data; 9928c2ecf20Sopenharmony_ci }; 9938c2ecf20Sopenharmony_ci 9948c2ecf20Sopenharmony_ci /* Halt all the indiviual PEGs and other blocks of the ISP */ 9958c2ecf20Sopenharmony_ci qla4_82xx_rom_lock(ha); 9968c2ecf20Sopenharmony_ci 9978c2ecf20Sopenharmony_ci /* disable all I2Q */ 9988c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_I2Q + 0x10, 0x0); 9998c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_I2Q + 0x14, 0x0); 10008c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_I2Q + 0x18, 0x0); 10018c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_I2Q + 0x1c, 0x0); 10028c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_I2Q + 0x20, 0x0); 10038c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_I2Q + 0x24, 0x0); 10048c2ecf20Sopenharmony_ci 10058c2ecf20Sopenharmony_ci /* disable all niu interrupts */ 10068c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_NIU + 0x40, 0xff); 10078c2ecf20Sopenharmony_ci /* disable xge rx/tx */ 10088c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_NIU + 0x70000, 0x00); 10098c2ecf20Sopenharmony_ci /* disable xg1 rx/tx */ 10108c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_NIU + 0x80000, 0x00); 10118c2ecf20Sopenharmony_ci /* disable sideband mac */ 10128c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_NIU + 0x90000, 0x00); 10138c2ecf20Sopenharmony_ci /* disable ap0 mac */ 10148c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_NIU + 0xa0000, 0x00); 10158c2ecf20Sopenharmony_ci /* disable ap1 mac */ 10168c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_NIU + 0xb0000, 0x00); 10178c2ecf20Sopenharmony_ci 10188c2ecf20Sopenharmony_ci /* halt sre */ 10198c2ecf20Sopenharmony_ci val = qla4_82xx_rd_32(ha, QLA82XX_CRB_SRE + 0x1000); 10208c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_SRE + 0x1000, val & (~(0x1))); 10218c2ecf20Sopenharmony_ci 10228c2ecf20Sopenharmony_ci /* halt epg */ 10238c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_EPG + 0x1300, 0x1); 10248c2ecf20Sopenharmony_ci 10258c2ecf20Sopenharmony_ci /* halt timers */ 10268c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_TIMER + 0x0, 0x0); 10278c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_TIMER + 0x8, 0x0); 10288c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_TIMER + 0x10, 0x0); 10298c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_TIMER + 0x18, 0x0); 10308c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_TIMER + 0x100, 0x0); 10318c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_TIMER + 0x200, 0x0); 10328c2ecf20Sopenharmony_ci 10338c2ecf20Sopenharmony_ci /* halt pegs */ 10348c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_0 + 0x3c, 1); 10358c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_1 + 0x3c, 1); 10368c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_2 + 0x3c, 1); 10378c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_3 + 0x3c, 1); 10388c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_4 + 0x3c, 1); 10398c2ecf20Sopenharmony_ci msleep(5); 10408c2ecf20Sopenharmony_ci 10418c2ecf20Sopenharmony_ci /* big hammer */ 10428c2ecf20Sopenharmony_ci if (test_bit(DPC_RESET_HA, &ha->dpc_flags)) 10438c2ecf20Sopenharmony_ci /* don't reset CAM block on reset */ 10448c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0xfeffffff); 10458c2ecf20Sopenharmony_ci else 10468c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0xffffffff); 10478c2ecf20Sopenharmony_ci 10488c2ecf20Sopenharmony_ci qla4_82xx_rom_unlock(ha); 10498c2ecf20Sopenharmony_ci 10508c2ecf20Sopenharmony_ci /* Read the signature value from the flash. 10518c2ecf20Sopenharmony_ci * Offset 0: Contain signature (0xcafecafe) 10528c2ecf20Sopenharmony_ci * Offset 4: Offset and number of addr/value pairs 10538c2ecf20Sopenharmony_ci * that present in CRB initialize sequence 10548c2ecf20Sopenharmony_ci */ 10558c2ecf20Sopenharmony_ci if (qla4_82xx_rom_fast_read(ha, 0, &n) != 0 || n != 0xcafecafeUL || 10568c2ecf20Sopenharmony_ci qla4_82xx_rom_fast_read(ha, 4, &n) != 0) { 10578c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, 10588c2ecf20Sopenharmony_ci "[ERROR] Reading crb_init area: n: %08x\n", n); 10598c2ecf20Sopenharmony_ci return -1; 10608c2ecf20Sopenharmony_ci } 10618c2ecf20Sopenharmony_ci 10628c2ecf20Sopenharmony_ci /* Offset in flash = lower 16 bits 10638c2ecf20Sopenharmony_ci * Number of enteries = upper 16 bits 10648c2ecf20Sopenharmony_ci */ 10658c2ecf20Sopenharmony_ci offset = n & 0xffffU; 10668c2ecf20Sopenharmony_ci n = (n >> 16) & 0xffffU; 10678c2ecf20Sopenharmony_ci 10688c2ecf20Sopenharmony_ci /* number of addr/value pair should not exceed 1024 enteries */ 10698c2ecf20Sopenharmony_ci if (n >= 1024) { 10708c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, 10718c2ecf20Sopenharmony_ci "%s: %s:n=0x%x [ERROR] Card flash not initialized.\n", 10728c2ecf20Sopenharmony_ci DRIVER_NAME, __func__, n); 10738c2ecf20Sopenharmony_ci return -1; 10748c2ecf20Sopenharmony_ci } 10758c2ecf20Sopenharmony_ci 10768c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, 10778c2ecf20Sopenharmony_ci "%s: %d CRB init values found in ROM.\n", DRIVER_NAME, n); 10788c2ecf20Sopenharmony_ci 10798c2ecf20Sopenharmony_ci buf = kmalloc_array(n, sizeof(struct crb_addr_pair), GFP_KERNEL); 10808c2ecf20Sopenharmony_ci if (buf == NULL) { 10818c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, 10828c2ecf20Sopenharmony_ci "%s: [ERROR] Unable to malloc memory.\n", DRIVER_NAME); 10838c2ecf20Sopenharmony_ci return -1; 10848c2ecf20Sopenharmony_ci } 10858c2ecf20Sopenharmony_ci 10868c2ecf20Sopenharmony_ci for (i = 0; i < n; i++) { 10878c2ecf20Sopenharmony_ci if (qla4_82xx_rom_fast_read(ha, 8*i + 4*offset, &val) != 0 || 10888c2ecf20Sopenharmony_ci qla4_82xx_rom_fast_read(ha, 8*i + 4*offset + 4, &addr) != 10898c2ecf20Sopenharmony_ci 0) { 10908c2ecf20Sopenharmony_ci kfree(buf); 10918c2ecf20Sopenharmony_ci return -1; 10928c2ecf20Sopenharmony_ci } 10938c2ecf20Sopenharmony_ci 10948c2ecf20Sopenharmony_ci buf[i].addr = addr; 10958c2ecf20Sopenharmony_ci buf[i].data = val; 10968c2ecf20Sopenharmony_ci } 10978c2ecf20Sopenharmony_ci 10988c2ecf20Sopenharmony_ci for (i = 0; i < n; i++) { 10998c2ecf20Sopenharmony_ci /* Translate internal CRB initialization 11008c2ecf20Sopenharmony_ci * address to PCI bus address 11018c2ecf20Sopenharmony_ci */ 11028c2ecf20Sopenharmony_ci off = qla4_82xx_decode_crb_addr((unsigned long)buf[i].addr) + 11038c2ecf20Sopenharmony_ci QLA82XX_PCI_CRBSPACE; 11048c2ecf20Sopenharmony_ci /* Not all CRB addr/value pair to be written, 11058c2ecf20Sopenharmony_ci * some of them are skipped 11068c2ecf20Sopenharmony_ci */ 11078c2ecf20Sopenharmony_ci 11088c2ecf20Sopenharmony_ci /* skip if LS bit is set*/ 11098c2ecf20Sopenharmony_ci if (off & 0x1) { 11108c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_WARNING, ha, 11118c2ecf20Sopenharmony_ci "Skip CRB init replay for offset = 0x%lx\n", off)); 11128c2ecf20Sopenharmony_ci continue; 11138c2ecf20Sopenharmony_ci } 11148c2ecf20Sopenharmony_ci 11158c2ecf20Sopenharmony_ci /* skipping cold reboot MAGIC */ 11168c2ecf20Sopenharmony_ci if (off == QLA82XX_CAM_RAM(0x1fc)) 11178c2ecf20Sopenharmony_ci continue; 11188c2ecf20Sopenharmony_ci 11198c2ecf20Sopenharmony_ci /* do not reset PCI */ 11208c2ecf20Sopenharmony_ci if (off == (ROMUSB_GLB + 0xbc)) 11218c2ecf20Sopenharmony_ci continue; 11228c2ecf20Sopenharmony_ci 11238c2ecf20Sopenharmony_ci /* skip core clock, so that firmware can increase the clock */ 11248c2ecf20Sopenharmony_ci if (off == (ROMUSB_GLB + 0xc8)) 11258c2ecf20Sopenharmony_ci continue; 11268c2ecf20Sopenharmony_ci 11278c2ecf20Sopenharmony_ci /* skip the function enable register */ 11288c2ecf20Sopenharmony_ci if (off == QLA82XX_PCIE_REG(PCIE_SETUP_FUNCTION)) 11298c2ecf20Sopenharmony_ci continue; 11308c2ecf20Sopenharmony_ci 11318c2ecf20Sopenharmony_ci if (off == QLA82XX_PCIE_REG(PCIE_SETUP_FUNCTION2)) 11328c2ecf20Sopenharmony_ci continue; 11338c2ecf20Sopenharmony_ci 11348c2ecf20Sopenharmony_ci if ((off & 0x0ff00000) == QLA82XX_CRB_SMB) 11358c2ecf20Sopenharmony_ci continue; 11368c2ecf20Sopenharmony_ci 11378c2ecf20Sopenharmony_ci if ((off & 0x0ff00000) == QLA82XX_CRB_DDR_NET) 11388c2ecf20Sopenharmony_ci continue; 11398c2ecf20Sopenharmony_ci 11408c2ecf20Sopenharmony_ci if (off == ADDR_ERROR) { 11418c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, 11428c2ecf20Sopenharmony_ci "%s: [ERROR] Unknown addr: 0x%08lx\n", 11438c2ecf20Sopenharmony_ci DRIVER_NAME, buf[i].addr); 11448c2ecf20Sopenharmony_ci continue; 11458c2ecf20Sopenharmony_ci } 11468c2ecf20Sopenharmony_ci 11478c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, off, buf[i].data); 11488c2ecf20Sopenharmony_ci 11498c2ecf20Sopenharmony_ci /* ISP requires much bigger delay to settle down, 11508c2ecf20Sopenharmony_ci * else crb_window returns 0xffffffff 11518c2ecf20Sopenharmony_ci */ 11528c2ecf20Sopenharmony_ci if (off == QLA82XX_ROMUSB_GLB_SW_RESET) 11538c2ecf20Sopenharmony_ci msleep(1000); 11548c2ecf20Sopenharmony_ci 11558c2ecf20Sopenharmony_ci /* ISP requires millisec delay between 11568c2ecf20Sopenharmony_ci * successive CRB register updation 11578c2ecf20Sopenharmony_ci */ 11588c2ecf20Sopenharmony_ci msleep(1); 11598c2ecf20Sopenharmony_ci } 11608c2ecf20Sopenharmony_ci 11618c2ecf20Sopenharmony_ci kfree(buf); 11628c2ecf20Sopenharmony_ci 11638c2ecf20Sopenharmony_ci /* Resetting the data and instruction cache */ 11648c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_D+0xec, 0x1e); 11658c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_D+0x4c, 8); 11668c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_I+0x4c, 8); 11678c2ecf20Sopenharmony_ci 11688c2ecf20Sopenharmony_ci /* Clear all protocol processing engines */ 11698c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_0+0x8, 0); 11708c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_0+0xc, 0); 11718c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_1+0x8, 0); 11728c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_1+0xc, 0); 11738c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_2+0x8, 0); 11748c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_2+0xc, 0); 11758c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_3+0x8, 0); 11768c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_3+0xc, 0); 11778c2ecf20Sopenharmony_ci 11788c2ecf20Sopenharmony_ci return 0; 11798c2ecf20Sopenharmony_ci} 11808c2ecf20Sopenharmony_ci 11818c2ecf20Sopenharmony_ci/** 11828c2ecf20Sopenharmony_ci * qla4_8xxx_ms_mem_write_128b - Writes data to MS/off-chip memory 11838c2ecf20Sopenharmony_ci * @ha: Pointer to adapter structure 11848c2ecf20Sopenharmony_ci * @addr: Flash address to write to 11858c2ecf20Sopenharmony_ci * @data: Data to be written 11868c2ecf20Sopenharmony_ci * @count: word_count to be written 11878c2ecf20Sopenharmony_ci * 11888c2ecf20Sopenharmony_ci * Return: On success return QLA_SUCCESS 11898c2ecf20Sopenharmony_ci * On error return QLA_ERROR 11908c2ecf20Sopenharmony_ci **/ 11918c2ecf20Sopenharmony_ciint qla4_8xxx_ms_mem_write_128b(struct scsi_qla_host *ha, uint64_t addr, 11928c2ecf20Sopenharmony_ci uint32_t *data, uint32_t count) 11938c2ecf20Sopenharmony_ci{ 11948c2ecf20Sopenharmony_ci int i, j; 11958c2ecf20Sopenharmony_ci uint32_t agt_ctrl; 11968c2ecf20Sopenharmony_ci unsigned long flags; 11978c2ecf20Sopenharmony_ci int ret_val = QLA_SUCCESS; 11988c2ecf20Sopenharmony_ci 11998c2ecf20Sopenharmony_ci /* Only 128-bit aligned access */ 12008c2ecf20Sopenharmony_ci if (addr & 0xF) { 12018c2ecf20Sopenharmony_ci ret_val = QLA_ERROR; 12028c2ecf20Sopenharmony_ci goto exit_ms_mem_write; 12038c2ecf20Sopenharmony_ci } 12048c2ecf20Sopenharmony_ci 12058c2ecf20Sopenharmony_ci write_lock_irqsave(&ha->hw_lock, flags); 12068c2ecf20Sopenharmony_ci 12078c2ecf20Sopenharmony_ci /* Write address */ 12088c2ecf20Sopenharmony_ci ret_val = ha->isp_ops->wr_reg_indirect(ha, MD_MIU_TEST_AGT_ADDR_HI, 0); 12098c2ecf20Sopenharmony_ci if (ret_val == QLA_ERROR) { 12108c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: write to AGT_ADDR_HI failed\n", 12118c2ecf20Sopenharmony_ci __func__); 12128c2ecf20Sopenharmony_ci goto exit_ms_mem_write_unlock; 12138c2ecf20Sopenharmony_ci } 12148c2ecf20Sopenharmony_ci 12158c2ecf20Sopenharmony_ci for (i = 0; i < count; i++, addr += 16) { 12168c2ecf20Sopenharmony_ci if (!((QLA8XXX_ADDR_IN_RANGE(addr, QLA8XXX_ADDR_QDR_NET, 12178c2ecf20Sopenharmony_ci QLA8XXX_ADDR_QDR_NET_MAX)) || 12188c2ecf20Sopenharmony_ci (QLA8XXX_ADDR_IN_RANGE(addr, QLA8XXX_ADDR_DDR_NET, 12198c2ecf20Sopenharmony_ci QLA8XXX_ADDR_DDR_NET_MAX)))) { 12208c2ecf20Sopenharmony_ci ret_val = QLA_ERROR; 12218c2ecf20Sopenharmony_ci goto exit_ms_mem_write_unlock; 12228c2ecf20Sopenharmony_ci } 12238c2ecf20Sopenharmony_ci 12248c2ecf20Sopenharmony_ci ret_val = ha->isp_ops->wr_reg_indirect(ha, 12258c2ecf20Sopenharmony_ci MD_MIU_TEST_AGT_ADDR_LO, 12268c2ecf20Sopenharmony_ci addr); 12278c2ecf20Sopenharmony_ci /* Write data */ 12288c2ecf20Sopenharmony_ci ret_val |= ha->isp_ops->wr_reg_indirect(ha, 12298c2ecf20Sopenharmony_ci MD_MIU_TEST_AGT_WRDATA_LO, 12308c2ecf20Sopenharmony_ci *data++); 12318c2ecf20Sopenharmony_ci ret_val |= ha->isp_ops->wr_reg_indirect(ha, 12328c2ecf20Sopenharmony_ci MD_MIU_TEST_AGT_WRDATA_HI, 12338c2ecf20Sopenharmony_ci *data++); 12348c2ecf20Sopenharmony_ci ret_val |= ha->isp_ops->wr_reg_indirect(ha, 12358c2ecf20Sopenharmony_ci MD_MIU_TEST_AGT_WRDATA_ULO, 12368c2ecf20Sopenharmony_ci *data++); 12378c2ecf20Sopenharmony_ci ret_val |= ha->isp_ops->wr_reg_indirect(ha, 12388c2ecf20Sopenharmony_ci MD_MIU_TEST_AGT_WRDATA_UHI, 12398c2ecf20Sopenharmony_ci *data++); 12408c2ecf20Sopenharmony_ci if (ret_val == QLA_ERROR) { 12418c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: write to AGT_WRDATA failed\n", 12428c2ecf20Sopenharmony_ci __func__); 12438c2ecf20Sopenharmony_ci goto exit_ms_mem_write_unlock; 12448c2ecf20Sopenharmony_ci } 12458c2ecf20Sopenharmony_ci 12468c2ecf20Sopenharmony_ci /* Check write status */ 12478c2ecf20Sopenharmony_ci ret_val = ha->isp_ops->wr_reg_indirect(ha, MD_MIU_TEST_AGT_CTRL, 12488c2ecf20Sopenharmony_ci MIU_TA_CTL_WRITE_ENABLE); 12498c2ecf20Sopenharmony_ci ret_val |= ha->isp_ops->wr_reg_indirect(ha, 12508c2ecf20Sopenharmony_ci MD_MIU_TEST_AGT_CTRL, 12518c2ecf20Sopenharmony_ci MIU_TA_CTL_WRITE_START); 12528c2ecf20Sopenharmony_ci if (ret_val == QLA_ERROR) { 12538c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: write to AGT_CTRL failed\n", 12548c2ecf20Sopenharmony_ci __func__); 12558c2ecf20Sopenharmony_ci goto exit_ms_mem_write_unlock; 12568c2ecf20Sopenharmony_ci } 12578c2ecf20Sopenharmony_ci 12588c2ecf20Sopenharmony_ci for (j = 0; j < MAX_CTL_CHECK; j++) { 12598c2ecf20Sopenharmony_ci ret_val = ha->isp_ops->rd_reg_indirect(ha, 12608c2ecf20Sopenharmony_ci MD_MIU_TEST_AGT_CTRL, 12618c2ecf20Sopenharmony_ci &agt_ctrl); 12628c2ecf20Sopenharmony_ci if (ret_val == QLA_ERROR) { 12638c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: failed to read MD_MIU_TEST_AGT_CTRL\n", 12648c2ecf20Sopenharmony_ci __func__); 12658c2ecf20Sopenharmony_ci goto exit_ms_mem_write_unlock; 12668c2ecf20Sopenharmony_ci } 12678c2ecf20Sopenharmony_ci if ((agt_ctrl & MIU_TA_CTL_BUSY) == 0) 12688c2ecf20Sopenharmony_ci break; 12698c2ecf20Sopenharmony_ci } 12708c2ecf20Sopenharmony_ci 12718c2ecf20Sopenharmony_ci /* Status check failed */ 12728c2ecf20Sopenharmony_ci if (j >= MAX_CTL_CHECK) { 12738c2ecf20Sopenharmony_ci printk_ratelimited(KERN_ERR "%s: MS memory write failed!\n", 12748c2ecf20Sopenharmony_ci __func__); 12758c2ecf20Sopenharmony_ci ret_val = QLA_ERROR; 12768c2ecf20Sopenharmony_ci goto exit_ms_mem_write_unlock; 12778c2ecf20Sopenharmony_ci } 12788c2ecf20Sopenharmony_ci } 12798c2ecf20Sopenharmony_ci 12808c2ecf20Sopenharmony_ciexit_ms_mem_write_unlock: 12818c2ecf20Sopenharmony_ci write_unlock_irqrestore(&ha->hw_lock, flags); 12828c2ecf20Sopenharmony_ci 12838c2ecf20Sopenharmony_ciexit_ms_mem_write: 12848c2ecf20Sopenharmony_ci return ret_val; 12858c2ecf20Sopenharmony_ci} 12868c2ecf20Sopenharmony_ci 12878c2ecf20Sopenharmony_cistatic int 12888c2ecf20Sopenharmony_ciqla4_82xx_load_from_flash(struct scsi_qla_host *ha, uint32_t image_start) 12898c2ecf20Sopenharmony_ci{ 12908c2ecf20Sopenharmony_ci int i, rval = 0; 12918c2ecf20Sopenharmony_ci long size = 0; 12928c2ecf20Sopenharmony_ci long flashaddr, memaddr; 12938c2ecf20Sopenharmony_ci u64 data; 12948c2ecf20Sopenharmony_ci u32 high, low; 12958c2ecf20Sopenharmony_ci 12968c2ecf20Sopenharmony_ci flashaddr = memaddr = ha->hw.flt_region_bootload; 12978c2ecf20Sopenharmony_ci size = (image_start - flashaddr) / 8; 12988c2ecf20Sopenharmony_ci 12998c2ecf20Sopenharmony_ci DEBUG2(printk("scsi%ld: %s: bootldr=0x%lx, fw_image=0x%x\n", 13008c2ecf20Sopenharmony_ci ha->host_no, __func__, flashaddr, image_start)); 13018c2ecf20Sopenharmony_ci 13028c2ecf20Sopenharmony_ci for (i = 0; i < size; i++) { 13038c2ecf20Sopenharmony_ci if ((qla4_82xx_rom_fast_read(ha, flashaddr, (int *)&low)) || 13048c2ecf20Sopenharmony_ci (qla4_82xx_rom_fast_read(ha, flashaddr + 4, 13058c2ecf20Sopenharmony_ci (int *)&high))) { 13068c2ecf20Sopenharmony_ci rval = -1; 13078c2ecf20Sopenharmony_ci goto exit_load_from_flash; 13088c2ecf20Sopenharmony_ci } 13098c2ecf20Sopenharmony_ci data = ((u64)high << 32) | low ; 13108c2ecf20Sopenharmony_ci rval = qla4_82xx_pci_mem_write_2M(ha, memaddr, &data, 8); 13118c2ecf20Sopenharmony_ci if (rval) 13128c2ecf20Sopenharmony_ci goto exit_load_from_flash; 13138c2ecf20Sopenharmony_ci 13148c2ecf20Sopenharmony_ci flashaddr += 8; 13158c2ecf20Sopenharmony_ci memaddr += 8; 13168c2ecf20Sopenharmony_ci 13178c2ecf20Sopenharmony_ci if (i % 0x1000 == 0) 13188c2ecf20Sopenharmony_ci msleep(1); 13198c2ecf20Sopenharmony_ci 13208c2ecf20Sopenharmony_ci } 13218c2ecf20Sopenharmony_ci 13228c2ecf20Sopenharmony_ci udelay(100); 13238c2ecf20Sopenharmony_ci 13248c2ecf20Sopenharmony_ci read_lock(&ha->hw_lock); 13258c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_0 + 0x18, 0x1020); 13268c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0x80001e); 13278c2ecf20Sopenharmony_ci read_unlock(&ha->hw_lock); 13288c2ecf20Sopenharmony_ci 13298c2ecf20Sopenharmony_ciexit_load_from_flash: 13308c2ecf20Sopenharmony_ci return rval; 13318c2ecf20Sopenharmony_ci} 13328c2ecf20Sopenharmony_ci 13338c2ecf20Sopenharmony_cistatic int qla4_82xx_load_fw(struct scsi_qla_host *ha, uint32_t image_start) 13348c2ecf20Sopenharmony_ci{ 13358c2ecf20Sopenharmony_ci u32 rst; 13368c2ecf20Sopenharmony_ci 13378c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, CRB_CMDPEG_STATE, 0); 13388c2ecf20Sopenharmony_ci if (qla4_82xx_pinit_from_rom(ha, 0) != QLA_SUCCESS) { 13398c2ecf20Sopenharmony_ci printk(KERN_WARNING "%s: Error during CRB Initialization\n", 13408c2ecf20Sopenharmony_ci __func__); 13418c2ecf20Sopenharmony_ci return QLA_ERROR; 13428c2ecf20Sopenharmony_ci } 13438c2ecf20Sopenharmony_ci 13448c2ecf20Sopenharmony_ci udelay(500); 13458c2ecf20Sopenharmony_ci 13468c2ecf20Sopenharmony_ci /* at this point, QM is in reset. This could be a problem if there are 13478c2ecf20Sopenharmony_ci * incoming d* transition queue messages. QM/PCIE could wedge. 13488c2ecf20Sopenharmony_ci * To get around this, QM is brought out of reset. 13498c2ecf20Sopenharmony_ci */ 13508c2ecf20Sopenharmony_ci 13518c2ecf20Sopenharmony_ci rst = qla4_82xx_rd_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET); 13528c2ecf20Sopenharmony_ci /* unreset qm */ 13538c2ecf20Sopenharmony_ci rst &= ~(1 << 28); 13548c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, rst); 13558c2ecf20Sopenharmony_ci 13568c2ecf20Sopenharmony_ci if (qla4_82xx_load_from_flash(ha, image_start)) { 13578c2ecf20Sopenharmony_ci printk("%s: Error trying to load fw from flash!\n", __func__); 13588c2ecf20Sopenharmony_ci return QLA_ERROR; 13598c2ecf20Sopenharmony_ci } 13608c2ecf20Sopenharmony_ci 13618c2ecf20Sopenharmony_ci return QLA_SUCCESS; 13628c2ecf20Sopenharmony_ci} 13638c2ecf20Sopenharmony_ci 13648c2ecf20Sopenharmony_ciint 13658c2ecf20Sopenharmony_ciqla4_82xx_pci_mem_read_2M(struct scsi_qla_host *ha, 13668c2ecf20Sopenharmony_ci u64 off, void *data, int size) 13678c2ecf20Sopenharmony_ci{ 13688c2ecf20Sopenharmony_ci int i, j = 0, k, start, end, loop, sz[2], off0[2]; 13698c2ecf20Sopenharmony_ci int shift_amount; 13708c2ecf20Sopenharmony_ci uint32_t temp; 13718c2ecf20Sopenharmony_ci uint64_t off8, val, mem_crb, word[2] = {0, 0}; 13728c2ecf20Sopenharmony_ci 13738c2ecf20Sopenharmony_ci /* 13748c2ecf20Sopenharmony_ci * If not MN, go check for MS or invalid. 13758c2ecf20Sopenharmony_ci */ 13768c2ecf20Sopenharmony_ci 13778c2ecf20Sopenharmony_ci if (off >= QLA8XXX_ADDR_QDR_NET && off <= QLA82XX_P3_ADDR_QDR_NET_MAX) 13788c2ecf20Sopenharmony_ci mem_crb = QLA82XX_CRB_QDR_NET; 13798c2ecf20Sopenharmony_ci else { 13808c2ecf20Sopenharmony_ci mem_crb = QLA82XX_CRB_DDR_NET; 13818c2ecf20Sopenharmony_ci if (qla4_82xx_pci_mem_bound_check(ha, off, size) == 0) 13828c2ecf20Sopenharmony_ci return qla4_82xx_pci_mem_read_direct(ha, 13838c2ecf20Sopenharmony_ci off, data, size); 13848c2ecf20Sopenharmony_ci } 13858c2ecf20Sopenharmony_ci 13868c2ecf20Sopenharmony_ci 13878c2ecf20Sopenharmony_ci off8 = off & 0xfffffff0; 13888c2ecf20Sopenharmony_ci off0[0] = off & 0xf; 13898c2ecf20Sopenharmony_ci sz[0] = (size < (16 - off0[0])) ? size : (16 - off0[0]); 13908c2ecf20Sopenharmony_ci shift_amount = 4; 13918c2ecf20Sopenharmony_ci 13928c2ecf20Sopenharmony_ci loop = ((off0[0] + size - 1) >> shift_amount) + 1; 13938c2ecf20Sopenharmony_ci off0[1] = 0; 13948c2ecf20Sopenharmony_ci sz[1] = size - sz[0]; 13958c2ecf20Sopenharmony_ci 13968c2ecf20Sopenharmony_ci for (i = 0; i < loop; i++) { 13978c2ecf20Sopenharmony_ci temp = off8 + (i << shift_amount); 13988c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_ADDR_LO, temp); 13998c2ecf20Sopenharmony_ci temp = 0; 14008c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_ADDR_HI, temp); 14018c2ecf20Sopenharmony_ci temp = MIU_TA_CTL_ENABLE; 14028c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp); 14038c2ecf20Sopenharmony_ci temp = MIU_TA_CTL_START_ENABLE; 14048c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp); 14058c2ecf20Sopenharmony_ci 14068c2ecf20Sopenharmony_ci for (j = 0; j < MAX_CTL_CHECK; j++) { 14078c2ecf20Sopenharmony_ci temp = qla4_82xx_rd_32(ha, mem_crb + MIU_TEST_AGT_CTRL); 14088c2ecf20Sopenharmony_ci if ((temp & MIU_TA_CTL_BUSY) == 0) 14098c2ecf20Sopenharmony_ci break; 14108c2ecf20Sopenharmony_ci } 14118c2ecf20Sopenharmony_ci 14128c2ecf20Sopenharmony_ci if (j >= MAX_CTL_CHECK) { 14138c2ecf20Sopenharmony_ci printk_ratelimited(KERN_ERR 14148c2ecf20Sopenharmony_ci "%s: failed to read through agent\n", 14158c2ecf20Sopenharmony_ci __func__); 14168c2ecf20Sopenharmony_ci break; 14178c2ecf20Sopenharmony_ci } 14188c2ecf20Sopenharmony_ci 14198c2ecf20Sopenharmony_ci start = off0[i] >> 2; 14208c2ecf20Sopenharmony_ci end = (off0[i] + sz[i] - 1) >> 2; 14218c2ecf20Sopenharmony_ci for (k = start; k <= end; k++) { 14228c2ecf20Sopenharmony_ci temp = qla4_82xx_rd_32(ha, 14238c2ecf20Sopenharmony_ci mem_crb + MIU_TEST_AGT_RDDATA(k)); 14248c2ecf20Sopenharmony_ci word[i] |= ((uint64_t)temp << (32 * (k & 1))); 14258c2ecf20Sopenharmony_ci } 14268c2ecf20Sopenharmony_ci } 14278c2ecf20Sopenharmony_ci 14288c2ecf20Sopenharmony_ci if (j >= MAX_CTL_CHECK) 14298c2ecf20Sopenharmony_ci return -1; 14308c2ecf20Sopenharmony_ci 14318c2ecf20Sopenharmony_ci if ((off0[0] & 7) == 0) { 14328c2ecf20Sopenharmony_ci val = word[0]; 14338c2ecf20Sopenharmony_ci } else { 14348c2ecf20Sopenharmony_ci val = ((word[0] >> (off0[0] * 8)) & (~(~0ULL << (sz[0] * 8)))) | 14358c2ecf20Sopenharmony_ci ((word[1] & (~(~0ULL << (sz[1] * 8)))) << (sz[0] * 8)); 14368c2ecf20Sopenharmony_ci } 14378c2ecf20Sopenharmony_ci 14388c2ecf20Sopenharmony_ci switch (size) { 14398c2ecf20Sopenharmony_ci case 1: 14408c2ecf20Sopenharmony_ci *(uint8_t *)data = val; 14418c2ecf20Sopenharmony_ci break; 14428c2ecf20Sopenharmony_ci case 2: 14438c2ecf20Sopenharmony_ci *(uint16_t *)data = val; 14448c2ecf20Sopenharmony_ci break; 14458c2ecf20Sopenharmony_ci case 4: 14468c2ecf20Sopenharmony_ci *(uint32_t *)data = val; 14478c2ecf20Sopenharmony_ci break; 14488c2ecf20Sopenharmony_ci case 8: 14498c2ecf20Sopenharmony_ci *(uint64_t *)data = val; 14508c2ecf20Sopenharmony_ci break; 14518c2ecf20Sopenharmony_ci } 14528c2ecf20Sopenharmony_ci return 0; 14538c2ecf20Sopenharmony_ci} 14548c2ecf20Sopenharmony_ci 14558c2ecf20Sopenharmony_ciint 14568c2ecf20Sopenharmony_ciqla4_82xx_pci_mem_write_2M(struct scsi_qla_host *ha, 14578c2ecf20Sopenharmony_ci u64 off, void *data, int size) 14588c2ecf20Sopenharmony_ci{ 14598c2ecf20Sopenharmony_ci int i, j, ret = 0, loop, sz[2], off0; 14608c2ecf20Sopenharmony_ci int scale, shift_amount, startword; 14618c2ecf20Sopenharmony_ci uint32_t temp; 14628c2ecf20Sopenharmony_ci uint64_t off8, mem_crb, tmpw, word[2] = {0, 0}; 14638c2ecf20Sopenharmony_ci 14648c2ecf20Sopenharmony_ci /* 14658c2ecf20Sopenharmony_ci * If not MN, go check for MS or invalid. 14668c2ecf20Sopenharmony_ci */ 14678c2ecf20Sopenharmony_ci if (off >= QLA8XXX_ADDR_QDR_NET && off <= QLA82XX_P3_ADDR_QDR_NET_MAX) 14688c2ecf20Sopenharmony_ci mem_crb = QLA82XX_CRB_QDR_NET; 14698c2ecf20Sopenharmony_ci else { 14708c2ecf20Sopenharmony_ci mem_crb = QLA82XX_CRB_DDR_NET; 14718c2ecf20Sopenharmony_ci if (qla4_82xx_pci_mem_bound_check(ha, off, size) == 0) 14728c2ecf20Sopenharmony_ci return qla4_82xx_pci_mem_write_direct(ha, 14738c2ecf20Sopenharmony_ci off, data, size); 14748c2ecf20Sopenharmony_ci } 14758c2ecf20Sopenharmony_ci 14768c2ecf20Sopenharmony_ci off0 = off & 0x7; 14778c2ecf20Sopenharmony_ci sz[0] = (size < (8 - off0)) ? size : (8 - off0); 14788c2ecf20Sopenharmony_ci sz[1] = size - sz[0]; 14798c2ecf20Sopenharmony_ci 14808c2ecf20Sopenharmony_ci off8 = off & 0xfffffff0; 14818c2ecf20Sopenharmony_ci loop = (((off & 0xf) + size - 1) >> 4) + 1; 14828c2ecf20Sopenharmony_ci shift_amount = 4; 14838c2ecf20Sopenharmony_ci scale = 2; 14848c2ecf20Sopenharmony_ci startword = (off & 0xf)/8; 14858c2ecf20Sopenharmony_ci 14868c2ecf20Sopenharmony_ci for (i = 0; i < loop; i++) { 14878c2ecf20Sopenharmony_ci if (qla4_82xx_pci_mem_read_2M(ha, off8 + 14888c2ecf20Sopenharmony_ci (i << shift_amount), &word[i * scale], 8)) 14898c2ecf20Sopenharmony_ci return -1; 14908c2ecf20Sopenharmony_ci } 14918c2ecf20Sopenharmony_ci 14928c2ecf20Sopenharmony_ci switch (size) { 14938c2ecf20Sopenharmony_ci case 1: 14948c2ecf20Sopenharmony_ci tmpw = *((uint8_t *)data); 14958c2ecf20Sopenharmony_ci break; 14968c2ecf20Sopenharmony_ci case 2: 14978c2ecf20Sopenharmony_ci tmpw = *((uint16_t *)data); 14988c2ecf20Sopenharmony_ci break; 14998c2ecf20Sopenharmony_ci case 4: 15008c2ecf20Sopenharmony_ci tmpw = *((uint32_t *)data); 15018c2ecf20Sopenharmony_ci break; 15028c2ecf20Sopenharmony_ci case 8: 15038c2ecf20Sopenharmony_ci default: 15048c2ecf20Sopenharmony_ci tmpw = *((uint64_t *)data); 15058c2ecf20Sopenharmony_ci break; 15068c2ecf20Sopenharmony_ci } 15078c2ecf20Sopenharmony_ci 15088c2ecf20Sopenharmony_ci if (sz[0] == 8) 15098c2ecf20Sopenharmony_ci word[startword] = tmpw; 15108c2ecf20Sopenharmony_ci else { 15118c2ecf20Sopenharmony_ci word[startword] &= 15128c2ecf20Sopenharmony_ci ~((~(~0ULL << (sz[0] * 8))) << (off0 * 8)); 15138c2ecf20Sopenharmony_ci word[startword] |= tmpw << (off0 * 8); 15148c2ecf20Sopenharmony_ci } 15158c2ecf20Sopenharmony_ci 15168c2ecf20Sopenharmony_ci if (sz[1] != 0) { 15178c2ecf20Sopenharmony_ci word[startword+1] &= ~(~0ULL << (sz[1] * 8)); 15188c2ecf20Sopenharmony_ci word[startword+1] |= tmpw >> (sz[0] * 8); 15198c2ecf20Sopenharmony_ci } 15208c2ecf20Sopenharmony_ci 15218c2ecf20Sopenharmony_ci for (i = 0; i < loop; i++) { 15228c2ecf20Sopenharmony_ci temp = off8 + (i << shift_amount); 15238c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_ADDR_LO, temp); 15248c2ecf20Sopenharmony_ci temp = 0; 15258c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_ADDR_HI, temp); 15268c2ecf20Sopenharmony_ci temp = word[i * scale] & 0xffffffff; 15278c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_WRDATA_LO, temp); 15288c2ecf20Sopenharmony_ci temp = (word[i * scale] >> 32) & 0xffffffff; 15298c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_WRDATA_HI, temp); 15308c2ecf20Sopenharmony_ci temp = word[i*scale + 1] & 0xffffffff; 15318c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_WRDATA_UPPER_LO, 15328c2ecf20Sopenharmony_ci temp); 15338c2ecf20Sopenharmony_ci temp = (word[i*scale + 1] >> 32) & 0xffffffff; 15348c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_WRDATA_UPPER_HI, 15358c2ecf20Sopenharmony_ci temp); 15368c2ecf20Sopenharmony_ci 15378c2ecf20Sopenharmony_ci temp = MIU_TA_CTL_WRITE_ENABLE; 15388c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_CTRL, temp); 15398c2ecf20Sopenharmony_ci temp = MIU_TA_CTL_WRITE_START; 15408c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_CTRL, temp); 15418c2ecf20Sopenharmony_ci 15428c2ecf20Sopenharmony_ci for (j = 0; j < MAX_CTL_CHECK; j++) { 15438c2ecf20Sopenharmony_ci temp = qla4_82xx_rd_32(ha, mem_crb + MIU_TEST_AGT_CTRL); 15448c2ecf20Sopenharmony_ci if ((temp & MIU_TA_CTL_BUSY) == 0) 15458c2ecf20Sopenharmony_ci break; 15468c2ecf20Sopenharmony_ci } 15478c2ecf20Sopenharmony_ci 15488c2ecf20Sopenharmony_ci if (j >= MAX_CTL_CHECK) { 15498c2ecf20Sopenharmony_ci if (printk_ratelimit()) 15508c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, 15518c2ecf20Sopenharmony_ci "%s: failed to read through agent\n", 15528c2ecf20Sopenharmony_ci __func__); 15538c2ecf20Sopenharmony_ci ret = -1; 15548c2ecf20Sopenharmony_ci break; 15558c2ecf20Sopenharmony_ci } 15568c2ecf20Sopenharmony_ci } 15578c2ecf20Sopenharmony_ci 15588c2ecf20Sopenharmony_ci return ret; 15598c2ecf20Sopenharmony_ci} 15608c2ecf20Sopenharmony_ci 15618c2ecf20Sopenharmony_cistatic int qla4_82xx_cmdpeg_ready(struct scsi_qla_host *ha, int pegtune_val) 15628c2ecf20Sopenharmony_ci{ 15638c2ecf20Sopenharmony_ci u32 val = 0; 15648c2ecf20Sopenharmony_ci int retries = 60; 15658c2ecf20Sopenharmony_ci 15668c2ecf20Sopenharmony_ci if (!pegtune_val) { 15678c2ecf20Sopenharmony_ci do { 15688c2ecf20Sopenharmony_ci val = qla4_82xx_rd_32(ha, CRB_CMDPEG_STATE); 15698c2ecf20Sopenharmony_ci if ((val == PHAN_INITIALIZE_COMPLETE) || 15708c2ecf20Sopenharmony_ci (val == PHAN_INITIALIZE_ACK)) 15718c2ecf20Sopenharmony_ci return 0; 15728c2ecf20Sopenharmony_ci set_current_state(TASK_UNINTERRUPTIBLE); 15738c2ecf20Sopenharmony_ci schedule_timeout(500); 15748c2ecf20Sopenharmony_ci 15758c2ecf20Sopenharmony_ci } while (--retries); 15768c2ecf20Sopenharmony_ci 15778c2ecf20Sopenharmony_ci if (!retries) { 15788c2ecf20Sopenharmony_ci pegtune_val = qla4_82xx_rd_32(ha, 15798c2ecf20Sopenharmony_ci QLA82XX_ROMUSB_GLB_PEGTUNE_DONE); 15808c2ecf20Sopenharmony_ci printk(KERN_WARNING "%s: init failed, " 15818c2ecf20Sopenharmony_ci "pegtune_val = %x\n", __func__, pegtune_val); 15828c2ecf20Sopenharmony_ci return -1; 15838c2ecf20Sopenharmony_ci } 15848c2ecf20Sopenharmony_ci } 15858c2ecf20Sopenharmony_ci return 0; 15868c2ecf20Sopenharmony_ci} 15878c2ecf20Sopenharmony_ci 15888c2ecf20Sopenharmony_cistatic int qla4_82xx_rcvpeg_ready(struct scsi_qla_host *ha) 15898c2ecf20Sopenharmony_ci{ 15908c2ecf20Sopenharmony_ci uint32_t state = 0; 15918c2ecf20Sopenharmony_ci int loops = 0; 15928c2ecf20Sopenharmony_ci 15938c2ecf20Sopenharmony_ci /* Window 1 call */ 15948c2ecf20Sopenharmony_ci read_lock(&ha->hw_lock); 15958c2ecf20Sopenharmony_ci state = qla4_82xx_rd_32(ha, CRB_RCVPEG_STATE); 15968c2ecf20Sopenharmony_ci read_unlock(&ha->hw_lock); 15978c2ecf20Sopenharmony_ci 15988c2ecf20Sopenharmony_ci while ((state != PHAN_PEG_RCV_INITIALIZED) && (loops < 30000)) { 15998c2ecf20Sopenharmony_ci udelay(100); 16008c2ecf20Sopenharmony_ci /* Window 1 call */ 16018c2ecf20Sopenharmony_ci read_lock(&ha->hw_lock); 16028c2ecf20Sopenharmony_ci state = qla4_82xx_rd_32(ha, CRB_RCVPEG_STATE); 16038c2ecf20Sopenharmony_ci read_unlock(&ha->hw_lock); 16048c2ecf20Sopenharmony_ci 16058c2ecf20Sopenharmony_ci loops++; 16068c2ecf20Sopenharmony_ci } 16078c2ecf20Sopenharmony_ci 16088c2ecf20Sopenharmony_ci if (loops >= 30000) { 16098c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 16108c2ecf20Sopenharmony_ci "Receive Peg initialization not complete: 0x%x.\n", state)); 16118c2ecf20Sopenharmony_ci return QLA_ERROR; 16128c2ecf20Sopenharmony_ci } 16138c2ecf20Sopenharmony_ci 16148c2ecf20Sopenharmony_ci return QLA_SUCCESS; 16158c2ecf20Sopenharmony_ci} 16168c2ecf20Sopenharmony_ci 16178c2ecf20Sopenharmony_civoid 16188c2ecf20Sopenharmony_ciqla4_8xxx_set_drv_active(struct scsi_qla_host *ha) 16198c2ecf20Sopenharmony_ci{ 16208c2ecf20Sopenharmony_ci uint32_t drv_active; 16218c2ecf20Sopenharmony_ci 16228c2ecf20Sopenharmony_ci drv_active = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_ACTIVE); 16238c2ecf20Sopenharmony_ci 16248c2ecf20Sopenharmony_ci /* 16258c2ecf20Sopenharmony_ci * For ISP8324 and ISP8042, drv_active register has 1 bit per function, 16268c2ecf20Sopenharmony_ci * shift 1 by func_num to set a bit for the function. 16278c2ecf20Sopenharmony_ci * For ISP8022, drv_active has 4 bits per function 16288c2ecf20Sopenharmony_ci */ 16298c2ecf20Sopenharmony_ci if (is_qla8032(ha) || is_qla8042(ha)) 16308c2ecf20Sopenharmony_ci drv_active |= (1 << ha->func_num); 16318c2ecf20Sopenharmony_ci else 16328c2ecf20Sopenharmony_ci drv_active |= (1 << (ha->func_num * 4)); 16338c2ecf20Sopenharmony_ci 16348c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "%s(%ld): drv_active: 0x%08x\n", 16358c2ecf20Sopenharmony_ci __func__, ha->host_no, drv_active); 16368c2ecf20Sopenharmony_ci qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DRV_ACTIVE, drv_active); 16378c2ecf20Sopenharmony_ci} 16388c2ecf20Sopenharmony_ci 16398c2ecf20Sopenharmony_civoid 16408c2ecf20Sopenharmony_ciqla4_8xxx_clear_drv_active(struct scsi_qla_host *ha) 16418c2ecf20Sopenharmony_ci{ 16428c2ecf20Sopenharmony_ci uint32_t drv_active; 16438c2ecf20Sopenharmony_ci 16448c2ecf20Sopenharmony_ci drv_active = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_ACTIVE); 16458c2ecf20Sopenharmony_ci 16468c2ecf20Sopenharmony_ci /* 16478c2ecf20Sopenharmony_ci * For ISP8324 and ISP8042, drv_active register has 1 bit per function, 16488c2ecf20Sopenharmony_ci * shift 1 by func_num to set a bit for the function. 16498c2ecf20Sopenharmony_ci * For ISP8022, drv_active has 4 bits per function 16508c2ecf20Sopenharmony_ci */ 16518c2ecf20Sopenharmony_ci if (is_qla8032(ha) || is_qla8042(ha)) 16528c2ecf20Sopenharmony_ci drv_active &= ~(1 << (ha->func_num)); 16538c2ecf20Sopenharmony_ci else 16548c2ecf20Sopenharmony_ci drv_active &= ~(1 << (ha->func_num * 4)); 16558c2ecf20Sopenharmony_ci 16568c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "%s(%ld): drv_active: 0x%08x\n", 16578c2ecf20Sopenharmony_ci __func__, ha->host_no, drv_active); 16588c2ecf20Sopenharmony_ci qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DRV_ACTIVE, drv_active); 16598c2ecf20Sopenharmony_ci} 16608c2ecf20Sopenharmony_ci 16618c2ecf20Sopenharmony_ciinline int qla4_8xxx_need_reset(struct scsi_qla_host *ha) 16628c2ecf20Sopenharmony_ci{ 16638c2ecf20Sopenharmony_ci uint32_t drv_state, drv_active; 16648c2ecf20Sopenharmony_ci int rval; 16658c2ecf20Sopenharmony_ci 16668c2ecf20Sopenharmony_ci drv_active = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_ACTIVE); 16678c2ecf20Sopenharmony_ci drv_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_STATE); 16688c2ecf20Sopenharmony_ci 16698c2ecf20Sopenharmony_ci /* 16708c2ecf20Sopenharmony_ci * For ISP8324 and ISP8042, drv_active register has 1 bit per function, 16718c2ecf20Sopenharmony_ci * shift 1 by func_num to set a bit for the function. 16728c2ecf20Sopenharmony_ci * For ISP8022, drv_active has 4 bits per function 16738c2ecf20Sopenharmony_ci */ 16748c2ecf20Sopenharmony_ci if (is_qla8032(ha) || is_qla8042(ha)) 16758c2ecf20Sopenharmony_ci rval = drv_state & (1 << ha->func_num); 16768c2ecf20Sopenharmony_ci else 16778c2ecf20Sopenharmony_ci rval = drv_state & (1 << (ha->func_num * 4)); 16788c2ecf20Sopenharmony_ci 16798c2ecf20Sopenharmony_ci if ((test_bit(AF_EEH_BUSY, &ha->flags)) && drv_active) 16808c2ecf20Sopenharmony_ci rval = 1; 16818c2ecf20Sopenharmony_ci 16828c2ecf20Sopenharmony_ci return rval; 16838c2ecf20Sopenharmony_ci} 16848c2ecf20Sopenharmony_ci 16858c2ecf20Sopenharmony_civoid qla4_8xxx_set_rst_ready(struct scsi_qla_host *ha) 16868c2ecf20Sopenharmony_ci{ 16878c2ecf20Sopenharmony_ci uint32_t drv_state; 16888c2ecf20Sopenharmony_ci 16898c2ecf20Sopenharmony_ci drv_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_STATE); 16908c2ecf20Sopenharmony_ci 16918c2ecf20Sopenharmony_ci /* 16928c2ecf20Sopenharmony_ci * For ISP8324 and ISP8042, drv_active register has 1 bit per function, 16938c2ecf20Sopenharmony_ci * shift 1 by func_num to set a bit for the function. 16948c2ecf20Sopenharmony_ci * For ISP8022, drv_active has 4 bits per function 16958c2ecf20Sopenharmony_ci */ 16968c2ecf20Sopenharmony_ci if (is_qla8032(ha) || is_qla8042(ha)) 16978c2ecf20Sopenharmony_ci drv_state |= (1 << ha->func_num); 16988c2ecf20Sopenharmony_ci else 16998c2ecf20Sopenharmony_ci drv_state |= (1 << (ha->func_num * 4)); 17008c2ecf20Sopenharmony_ci 17018c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "%s(%ld): drv_state: 0x%08x\n", 17028c2ecf20Sopenharmony_ci __func__, ha->host_no, drv_state); 17038c2ecf20Sopenharmony_ci qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DRV_STATE, drv_state); 17048c2ecf20Sopenharmony_ci} 17058c2ecf20Sopenharmony_ci 17068c2ecf20Sopenharmony_civoid qla4_8xxx_clear_rst_ready(struct scsi_qla_host *ha) 17078c2ecf20Sopenharmony_ci{ 17088c2ecf20Sopenharmony_ci uint32_t drv_state; 17098c2ecf20Sopenharmony_ci 17108c2ecf20Sopenharmony_ci drv_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_STATE); 17118c2ecf20Sopenharmony_ci 17128c2ecf20Sopenharmony_ci /* 17138c2ecf20Sopenharmony_ci * For ISP8324 and ISP8042, drv_active register has 1 bit per function, 17148c2ecf20Sopenharmony_ci * shift 1 by func_num to set a bit for the function. 17158c2ecf20Sopenharmony_ci * For ISP8022, drv_active has 4 bits per function 17168c2ecf20Sopenharmony_ci */ 17178c2ecf20Sopenharmony_ci if (is_qla8032(ha) || is_qla8042(ha)) 17188c2ecf20Sopenharmony_ci drv_state &= ~(1 << ha->func_num); 17198c2ecf20Sopenharmony_ci else 17208c2ecf20Sopenharmony_ci drv_state &= ~(1 << (ha->func_num * 4)); 17218c2ecf20Sopenharmony_ci 17228c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "%s(%ld): drv_state: 0x%08x\n", 17238c2ecf20Sopenharmony_ci __func__, ha->host_no, drv_state); 17248c2ecf20Sopenharmony_ci qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DRV_STATE, drv_state); 17258c2ecf20Sopenharmony_ci} 17268c2ecf20Sopenharmony_ci 17278c2ecf20Sopenharmony_cistatic inline void 17288c2ecf20Sopenharmony_ciqla4_8xxx_set_qsnt_ready(struct scsi_qla_host *ha) 17298c2ecf20Sopenharmony_ci{ 17308c2ecf20Sopenharmony_ci uint32_t qsnt_state; 17318c2ecf20Sopenharmony_ci 17328c2ecf20Sopenharmony_ci qsnt_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_STATE); 17338c2ecf20Sopenharmony_ci 17348c2ecf20Sopenharmony_ci /* 17358c2ecf20Sopenharmony_ci * For ISP8324 and ISP8042, drv_active register has 1 bit per function, 17368c2ecf20Sopenharmony_ci * shift 1 by func_num to set a bit for the function. 17378c2ecf20Sopenharmony_ci * For ISP8022, drv_active has 4 bits per function. 17388c2ecf20Sopenharmony_ci */ 17398c2ecf20Sopenharmony_ci if (is_qla8032(ha) || is_qla8042(ha)) 17408c2ecf20Sopenharmony_ci qsnt_state |= (1 << ha->func_num); 17418c2ecf20Sopenharmony_ci else 17428c2ecf20Sopenharmony_ci qsnt_state |= (2 << (ha->func_num * 4)); 17438c2ecf20Sopenharmony_ci 17448c2ecf20Sopenharmony_ci qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DRV_STATE, qsnt_state); 17458c2ecf20Sopenharmony_ci} 17468c2ecf20Sopenharmony_ci 17478c2ecf20Sopenharmony_ci 17488c2ecf20Sopenharmony_cistatic int 17498c2ecf20Sopenharmony_ciqla4_82xx_start_firmware(struct scsi_qla_host *ha, uint32_t image_start) 17508c2ecf20Sopenharmony_ci{ 17518c2ecf20Sopenharmony_ci uint16_t lnk; 17528c2ecf20Sopenharmony_ci 17538c2ecf20Sopenharmony_ci /* scrub dma mask expansion register */ 17548c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, CRB_DMA_SHIFT, 0x55555555); 17558c2ecf20Sopenharmony_ci 17568c2ecf20Sopenharmony_ci /* Overwrite stale initialization register values */ 17578c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, CRB_CMDPEG_STATE, 0); 17588c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, CRB_RCVPEG_STATE, 0); 17598c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_PEG_HALT_STATUS1, 0); 17608c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_PEG_HALT_STATUS2, 0); 17618c2ecf20Sopenharmony_ci 17628c2ecf20Sopenharmony_ci if (qla4_82xx_load_fw(ha, image_start) != QLA_SUCCESS) { 17638c2ecf20Sopenharmony_ci printk("%s: Error trying to start fw!\n", __func__); 17648c2ecf20Sopenharmony_ci return QLA_ERROR; 17658c2ecf20Sopenharmony_ci } 17668c2ecf20Sopenharmony_ci 17678c2ecf20Sopenharmony_ci /* Handshake with the card before we register the devices. */ 17688c2ecf20Sopenharmony_ci if (qla4_82xx_cmdpeg_ready(ha, 0) != QLA_SUCCESS) { 17698c2ecf20Sopenharmony_ci printk("%s: Error during card handshake!\n", __func__); 17708c2ecf20Sopenharmony_ci return QLA_ERROR; 17718c2ecf20Sopenharmony_ci } 17728c2ecf20Sopenharmony_ci 17738c2ecf20Sopenharmony_ci /* Negotiated Link width */ 17748c2ecf20Sopenharmony_ci pcie_capability_read_word(ha->pdev, PCI_EXP_LNKSTA, &lnk); 17758c2ecf20Sopenharmony_ci ha->link_width = (lnk >> 4) & 0x3f; 17768c2ecf20Sopenharmony_ci 17778c2ecf20Sopenharmony_ci /* Synchronize with Receive peg */ 17788c2ecf20Sopenharmony_ci return qla4_82xx_rcvpeg_ready(ha); 17798c2ecf20Sopenharmony_ci} 17808c2ecf20Sopenharmony_ci 17818c2ecf20Sopenharmony_ciint qla4_82xx_try_start_fw(struct scsi_qla_host *ha) 17828c2ecf20Sopenharmony_ci{ 17838c2ecf20Sopenharmony_ci int rval = QLA_ERROR; 17848c2ecf20Sopenharmony_ci 17858c2ecf20Sopenharmony_ci /* 17868c2ecf20Sopenharmony_ci * FW Load priority: 17878c2ecf20Sopenharmony_ci * 1) Operational firmware residing in flash. 17888c2ecf20Sopenharmony_ci * 2) Fail 17898c2ecf20Sopenharmony_ci */ 17908c2ecf20Sopenharmony_ci 17918c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, 17928c2ecf20Sopenharmony_ci "FW: Retrieving flash offsets from FLT/FDT ...\n"); 17938c2ecf20Sopenharmony_ci rval = qla4_8xxx_get_flash_info(ha); 17948c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) 17958c2ecf20Sopenharmony_ci return rval; 17968c2ecf20Sopenharmony_ci 17978c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, 17988c2ecf20Sopenharmony_ci "FW: Attempting to load firmware from flash...\n"); 17998c2ecf20Sopenharmony_ci rval = qla4_82xx_start_firmware(ha, ha->hw.flt_region_fw); 18008c2ecf20Sopenharmony_ci 18018c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) { 18028c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "FW: Load firmware from flash" 18038c2ecf20Sopenharmony_ci " FAILED...\n"); 18048c2ecf20Sopenharmony_ci return rval; 18058c2ecf20Sopenharmony_ci } 18068c2ecf20Sopenharmony_ci 18078c2ecf20Sopenharmony_ci return rval; 18088c2ecf20Sopenharmony_ci} 18098c2ecf20Sopenharmony_ci 18108c2ecf20Sopenharmony_civoid qla4_82xx_rom_lock_recovery(struct scsi_qla_host *ha) 18118c2ecf20Sopenharmony_ci{ 18128c2ecf20Sopenharmony_ci if (qla4_82xx_rom_lock(ha)) { 18138c2ecf20Sopenharmony_ci /* Someone else is holding the lock. */ 18148c2ecf20Sopenharmony_ci dev_info(&ha->pdev->dev, "Resetting rom_lock\n"); 18158c2ecf20Sopenharmony_ci } 18168c2ecf20Sopenharmony_ci 18178c2ecf20Sopenharmony_ci /* 18188c2ecf20Sopenharmony_ci * Either we got the lock, or someone 18198c2ecf20Sopenharmony_ci * else died while holding it. 18208c2ecf20Sopenharmony_ci * In either case, unlock. 18218c2ecf20Sopenharmony_ci */ 18228c2ecf20Sopenharmony_ci qla4_82xx_rom_unlock(ha); 18238c2ecf20Sopenharmony_ci} 18248c2ecf20Sopenharmony_ci 18258c2ecf20Sopenharmony_cistatic uint32_t ql4_84xx_poll_wait_for_ready(struct scsi_qla_host *ha, 18268c2ecf20Sopenharmony_ci uint32_t addr1, uint32_t mask) 18278c2ecf20Sopenharmony_ci{ 18288c2ecf20Sopenharmony_ci unsigned long timeout; 18298c2ecf20Sopenharmony_ci uint32_t rval = QLA_SUCCESS; 18308c2ecf20Sopenharmony_ci uint32_t temp; 18318c2ecf20Sopenharmony_ci 18328c2ecf20Sopenharmony_ci timeout = jiffies + msecs_to_jiffies(TIMEOUT_100_MS); 18338c2ecf20Sopenharmony_ci do { 18348c2ecf20Sopenharmony_ci ha->isp_ops->rd_reg_indirect(ha, addr1, &temp); 18358c2ecf20Sopenharmony_ci if ((temp & mask) != 0) 18368c2ecf20Sopenharmony_ci break; 18378c2ecf20Sopenharmony_ci 18388c2ecf20Sopenharmony_ci if (time_after_eq(jiffies, timeout)) { 18398c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "Error in processing rdmdio entry\n"); 18408c2ecf20Sopenharmony_ci return QLA_ERROR; 18418c2ecf20Sopenharmony_ci } 18428c2ecf20Sopenharmony_ci } while (1); 18438c2ecf20Sopenharmony_ci 18448c2ecf20Sopenharmony_ci return rval; 18458c2ecf20Sopenharmony_ci} 18468c2ecf20Sopenharmony_ci 18478c2ecf20Sopenharmony_cistatic uint32_t ql4_84xx_ipmdio_rd_reg(struct scsi_qla_host *ha, uint32_t addr1, 18488c2ecf20Sopenharmony_ci uint32_t addr3, uint32_t mask, uint32_t addr, 18498c2ecf20Sopenharmony_ci uint32_t *data_ptr) 18508c2ecf20Sopenharmony_ci{ 18518c2ecf20Sopenharmony_ci int rval = QLA_SUCCESS; 18528c2ecf20Sopenharmony_ci uint32_t temp; 18538c2ecf20Sopenharmony_ci uint32_t data; 18548c2ecf20Sopenharmony_ci 18558c2ecf20Sopenharmony_ci rval = ql4_84xx_poll_wait_for_ready(ha, addr1, mask); 18568c2ecf20Sopenharmony_ci if (rval) 18578c2ecf20Sopenharmony_ci goto exit_ipmdio_rd_reg; 18588c2ecf20Sopenharmony_ci 18598c2ecf20Sopenharmony_ci temp = (0x40000000 | addr); 18608c2ecf20Sopenharmony_ci ha->isp_ops->wr_reg_indirect(ha, addr1, temp); 18618c2ecf20Sopenharmony_ci 18628c2ecf20Sopenharmony_ci rval = ql4_84xx_poll_wait_for_ready(ha, addr1, mask); 18638c2ecf20Sopenharmony_ci if (rval) 18648c2ecf20Sopenharmony_ci goto exit_ipmdio_rd_reg; 18658c2ecf20Sopenharmony_ci 18668c2ecf20Sopenharmony_ci ha->isp_ops->rd_reg_indirect(ha, addr3, &data); 18678c2ecf20Sopenharmony_ci *data_ptr = data; 18688c2ecf20Sopenharmony_ci 18698c2ecf20Sopenharmony_ciexit_ipmdio_rd_reg: 18708c2ecf20Sopenharmony_ci return rval; 18718c2ecf20Sopenharmony_ci} 18728c2ecf20Sopenharmony_ci 18738c2ecf20Sopenharmony_ci 18748c2ecf20Sopenharmony_cistatic uint32_t ql4_84xx_poll_wait_ipmdio_bus_idle(struct scsi_qla_host *ha, 18758c2ecf20Sopenharmony_ci uint32_t addr1, 18768c2ecf20Sopenharmony_ci uint32_t addr2, 18778c2ecf20Sopenharmony_ci uint32_t addr3, 18788c2ecf20Sopenharmony_ci uint32_t mask) 18798c2ecf20Sopenharmony_ci{ 18808c2ecf20Sopenharmony_ci unsigned long timeout; 18818c2ecf20Sopenharmony_ci uint32_t temp; 18828c2ecf20Sopenharmony_ci uint32_t rval = QLA_SUCCESS; 18838c2ecf20Sopenharmony_ci 18848c2ecf20Sopenharmony_ci timeout = jiffies + msecs_to_jiffies(TIMEOUT_100_MS); 18858c2ecf20Sopenharmony_ci do { 18868c2ecf20Sopenharmony_ci ql4_84xx_ipmdio_rd_reg(ha, addr1, addr3, mask, addr2, &temp); 18878c2ecf20Sopenharmony_ci if ((temp & 0x1) != 1) 18888c2ecf20Sopenharmony_ci break; 18898c2ecf20Sopenharmony_ci if (time_after_eq(jiffies, timeout)) { 18908c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "Error in processing mdiobus idle\n"); 18918c2ecf20Sopenharmony_ci return QLA_ERROR; 18928c2ecf20Sopenharmony_ci } 18938c2ecf20Sopenharmony_ci } while (1); 18948c2ecf20Sopenharmony_ci 18958c2ecf20Sopenharmony_ci return rval; 18968c2ecf20Sopenharmony_ci} 18978c2ecf20Sopenharmony_ci 18988c2ecf20Sopenharmony_cistatic int ql4_84xx_ipmdio_wr_reg(struct scsi_qla_host *ha, 18998c2ecf20Sopenharmony_ci uint32_t addr1, uint32_t addr3, 19008c2ecf20Sopenharmony_ci uint32_t mask, uint32_t addr, 19018c2ecf20Sopenharmony_ci uint32_t value) 19028c2ecf20Sopenharmony_ci{ 19038c2ecf20Sopenharmony_ci int rval = QLA_SUCCESS; 19048c2ecf20Sopenharmony_ci 19058c2ecf20Sopenharmony_ci rval = ql4_84xx_poll_wait_for_ready(ha, addr1, mask); 19068c2ecf20Sopenharmony_ci if (rval) 19078c2ecf20Sopenharmony_ci goto exit_ipmdio_wr_reg; 19088c2ecf20Sopenharmony_ci 19098c2ecf20Sopenharmony_ci ha->isp_ops->wr_reg_indirect(ha, addr3, value); 19108c2ecf20Sopenharmony_ci ha->isp_ops->wr_reg_indirect(ha, addr1, addr); 19118c2ecf20Sopenharmony_ci 19128c2ecf20Sopenharmony_ci rval = ql4_84xx_poll_wait_for_ready(ha, addr1, mask); 19138c2ecf20Sopenharmony_ci if (rval) 19148c2ecf20Sopenharmony_ci goto exit_ipmdio_wr_reg; 19158c2ecf20Sopenharmony_ci 19168c2ecf20Sopenharmony_ciexit_ipmdio_wr_reg: 19178c2ecf20Sopenharmony_ci return rval; 19188c2ecf20Sopenharmony_ci} 19198c2ecf20Sopenharmony_ci 19208c2ecf20Sopenharmony_cistatic void qla4_8xxx_minidump_process_rdcrb(struct scsi_qla_host *ha, 19218c2ecf20Sopenharmony_ci struct qla8xxx_minidump_entry_hdr *entry_hdr, 19228c2ecf20Sopenharmony_ci uint32_t **d_ptr) 19238c2ecf20Sopenharmony_ci{ 19248c2ecf20Sopenharmony_ci uint32_t r_addr, r_stride, loop_cnt, i, r_value; 19258c2ecf20Sopenharmony_ci struct qla8xxx_minidump_entry_crb *crb_hdr; 19268c2ecf20Sopenharmony_ci uint32_t *data_ptr = *d_ptr; 19278c2ecf20Sopenharmony_ci 19288c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__)); 19298c2ecf20Sopenharmony_ci crb_hdr = (struct qla8xxx_minidump_entry_crb *)entry_hdr; 19308c2ecf20Sopenharmony_ci r_addr = crb_hdr->addr; 19318c2ecf20Sopenharmony_ci r_stride = crb_hdr->crb_strd.addr_stride; 19328c2ecf20Sopenharmony_ci loop_cnt = crb_hdr->op_count; 19338c2ecf20Sopenharmony_ci 19348c2ecf20Sopenharmony_ci for (i = 0; i < loop_cnt; i++) { 19358c2ecf20Sopenharmony_ci ha->isp_ops->rd_reg_indirect(ha, r_addr, &r_value); 19368c2ecf20Sopenharmony_ci *data_ptr++ = cpu_to_le32(r_addr); 19378c2ecf20Sopenharmony_ci *data_ptr++ = cpu_to_le32(r_value); 19388c2ecf20Sopenharmony_ci r_addr += r_stride; 19398c2ecf20Sopenharmony_ci } 19408c2ecf20Sopenharmony_ci *d_ptr = data_ptr; 19418c2ecf20Sopenharmony_ci} 19428c2ecf20Sopenharmony_ci 19438c2ecf20Sopenharmony_cistatic int qla4_83xx_check_dma_engine_state(struct scsi_qla_host *ha) 19448c2ecf20Sopenharmony_ci{ 19458c2ecf20Sopenharmony_ci int rval = QLA_SUCCESS; 19468c2ecf20Sopenharmony_ci uint32_t dma_eng_num = 0, cmd_sts_and_cntrl = 0; 19478c2ecf20Sopenharmony_ci uint64_t dma_base_addr = 0; 19488c2ecf20Sopenharmony_ci struct qla4_8xxx_minidump_template_hdr *tmplt_hdr = NULL; 19498c2ecf20Sopenharmony_ci 19508c2ecf20Sopenharmony_ci tmplt_hdr = (struct qla4_8xxx_minidump_template_hdr *) 19518c2ecf20Sopenharmony_ci ha->fw_dump_tmplt_hdr; 19528c2ecf20Sopenharmony_ci dma_eng_num = 19538c2ecf20Sopenharmony_ci tmplt_hdr->saved_state_array[QLA83XX_PEX_DMA_ENGINE_INDEX]; 19548c2ecf20Sopenharmony_ci dma_base_addr = QLA83XX_PEX_DMA_BASE_ADDRESS + 19558c2ecf20Sopenharmony_ci (dma_eng_num * QLA83XX_PEX_DMA_NUM_OFFSET); 19568c2ecf20Sopenharmony_ci 19578c2ecf20Sopenharmony_ci /* Read the pex-dma's command-status-and-control register. */ 19588c2ecf20Sopenharmony_ci rval = ha->isp_ops->rd_reg_indirect(ha, 19598c2ecf20Sopenharmony_ci (dma_base_addr + QLA83XX_PEX_DMA_CMD_STS_AND_CNTRL), 19608c2ecf20Sopenharmony_ci &cmd_sts_and_cntrl); 19618c2ecf20Sopenharmony_ci 19628c2ecf20Sopenharmony_ci if (rval) 19638c2ecf20Sopenharmony_ci return QLA_ERROR; 19648c2ecf20Sopenharmony_ci 19658c2ecf20Sopenharmony_ci /* Check if requested pex-dma engine is available. */ 19668c2ecf20Sopenharmony_ci if (cmd_sts_and_cntrl & BIT_31) 19678c2ecf20Sopenharmony_ci return QLA_SUCCESS; 19688c2ecf20Sopenharmony_ci else 19698c2ecf20Sopenharmony_ci return QLA_ERROR; 19708c2ecf20Sopenharmony_ci} 19718c2ecf20Sopenharmony_ci 19728c2ecf20Sopenharmony_cistatic int qla4_83xx_start_pex_dma(struct scsi_qla_host *ha, 19738c2ecf20Sopenharmony_ci struct qla4_83xx_minidump_entry_rdmem_pex_dma *m_hdr) 19748c2ecf20Sopenharmony_ci{ 19758c2ecf20Sopenharmony_ci int rval = QLA_SUCCESS, wait = 0; 19768c2ecf20Sopenharmony_ci uint32_t dma_eng_num = 0, cmd_sts_and_cntrl = 0; 19778c2ecf20Sopenharmony_ci uint64_t dma_base_addr = 0; 19788c2ecf20Sopenharmony_ci struct qla4_8xxx_minidump_template_hdr *tmplt_hdr = NULL; 19798c2ecf20Sopenharmony_ci 19808c2ecf20Sopenharmony_ci tmplt_hdr = (struct qla4_8xxx_minidump_template_hdr *) 19818c2ecf20Sopenharmony_ci ha->fw_dump_tmplt_hdr; 19828c2ecf20Sopenharmony_ci dma_eng_num = 19838c2ecf20Sopenharmony_ci tmplt_hdr->saved_state_array[QLA83XX_PEX_DMA_ENGINE_INDEX]; 19848c2ecf20Sopenharmony_ci dma_base_addr = QLA83XX_PEX_DMA_BASE_ADDRESS + 19858c2ecf20Sopenharmony_ci (dma_eng_num * QLA83XX_PEX_DMA_NUM_OFFSET); 19868c2ecf20Sopenharmony_ci 19878c2ecf20Sopenharmony_ci rval = ha->isp_ops->wr_reg_indirect(ha, 19888c2ecf20Sopenharmony_ci dma_base_addr + QLA83XX_PEX_DMA_CMD_ADDR_LOW, 19898c2ecf20Sopenharmony_ci m_hdr->desc_card_addr); 19908c2ecf20Sopenharmony_ci if (rval) 19918c2ecf20Sopenharmony_ci goto error_exit; 19928c2ecf20Sopenharmony_ci 19938c2ecf20Sopenharmony_ci rval = ha->isp_ops->wr_reg_indirect(ha, 19948c2ecf20Sopenharmony_ci dma_base_addr + QLA83XX_PEX_DMA_CMD_ADDR_HIGH, 0); 19958c2ecf20Sopenharmony_ci if (rval) 19968c2ecf20Sopenharmony_ci goto error_exit; 19978c2ecf20Sopenharmony_ci 19988c2ecf20Sopenharmony_ci rval = ha->isp_ops->wr_reg_indirect(ha, 19998c2ecf20Sopenharmony_ci dma_base_addr + QLA83XX_PEX_DMA_CMD_STS_AND_CNTRL, 20008c2ecf20Sopenharmony_ci m_hdr->start_dma_cmd); 20018c2ecf20Sopenharmony_ci if (rval) 20028c2ecf20Sopenharmony_ci goto error_exit; 20038c2ecf20Sopenharmony_ci 20048c2ecf20Sopenharmony_ci /* Wait for dma operation to complete. */ 20058c2ecf20Sopenharmony_ci for (wait = 0; wait < QLA83XX_PEX_DMA_MAX_WAIT; wait++) { 20068c2ecf20Sopenharmony_ci rval = ha->isp_ops->rd_reg_indirect(ha, 20078c2ecf20Sopenharmony_ci (dma_base_addr + QLA83XX_PEX_DMA_CMD_STS_AND_CNTRL), 20088c2ecf20Sopenharmony_ci &cmd_sts_and_cntrl); 20098c2ecf20Sopenharmony_ci if (rval) 20108c2ecf20Sopenharmony_ci goto error_exit; 20118c2ecf20Sopenharmony_ci 20128c2ecf20Sopenharmony_ci if ((cmd_sts_and_cntrl & BIT_1) == 0) 20138c2ecf20Sopenharmony_ci break; 20148c2ecf20Sopenharmony_ci else 20158c2ecf20Sopenharmony_ci udelay(10); 20168c2ecf20Sopenharmony_ci } 20178c2ecf20Sopenharmony_ci 20188c2ecf20Sopenharmony_ci /* Wait a max of 100 ms, otherwise fallback to rdmem entry read */ 20198c2ecf20Sopenharmony_ci if (wait >= QLA83XX_PEX_DMA_MAX_WAIT) { 20208c2ecf20Sopenharmony_ci rval = QLA_ERROR; 20218c2ecf20Sopenharmony_ci goto error_exit; 20228c2ecf20Sopenharmony_ci } 20238c2ecf20Sopenharmony_ci 20248c2ecf20Sopenharmony_cierror_exit: 20258c2ecf20Sopenharmony_ci return rval; 20268c2ecf20Sopenharmony_ci} 20278c2ecf20Sopenharmony_ci 20288c2ecf20Sopenharmony_cistatic int qla4_8xxx_minidump_pex_dma_read(struct scsi_qla_host *ha, 20298c2ecf20Sopenharmony_ci struct qla8xxx_minidump_entry_hdr *entry_hdr, 20308c2ecf20Sopenharmony_ci uint32_t **d_ptr) 20318c2ecf20Sopenharmony_ci{ 20328c2ecf20Sopenharmony_ci int rval = QLA_SUCCESS; 20338c2ecf20Sopenharmony_ci struct qla4_83xx_minidump_entry_rdmem_pex_dma *m_hdr = NULL; 20348c2ecf20Sopenharmony_ci uint32_t size, read_size; 20358c2ecf20Sopenharmony_ci uint8_t *data_ptr = (uint8_t *)*d_ptr; 20368c2ecf20Sopenharmony_ci void *rdmem_buffer = NULL; 20378c2ecf20Sopenharmony_ci dma_addr_t rdmem_dma; 20388c2ecf20Sopenharmony_ci struct qla4_83xx_pex_dma_descriptor dma_desc; 20398c2ecf20Sopenharmony_ci 20408c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__)); 20418c2ecf20Sopenharmony_ci 20428c2ecf20Sopenharmony_ci rval = qla4_83xx_check_dma_engine_state(ha); 20438c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) { 20448c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 20458c2ecf20Sopenharmony_ci "%s: DMA engine not available. Fallback to rdmem-read.\n", 20468c2ecf20Sopenharmony_ci __func__)); 20478c2ecf20Sopenharmony_ci return QLA_ERROR; 20488c2ecf20Sopenharmony_ci } 20498c2ecf20Sopenharmony_ci 20508c2ecf20Sopenharmony_ci m_hdr = (struct qla4_83xx_minidump_entry_rdmem_pex_dma *)entry_hdr; 20518c2ecf20Sopenharmony_ci rdmem_buffer = dma_alloc_coherent(&ha->pdev->dev, 20528c2ecf20Sopenharmony_ci QLA83XX_PEX_DMA_READ_SIZE, 20538c2ecf20Sopenharmony_ci &rdmem_dma, GFP_KERNEL); 20548c2ecf20Sopenharmony_ci if (!rdmem_buffer) { 20558c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 20568c2ecf20Sopenharmony_ci "%s: Unable to allocate rdmem dma buffer\n", 20578c2ecf20Sopenharmony_ci __func__)); 20588c2ecf20Sopenharmony_ci return QLA_ERROR; 20598c2ecf20Sopenharmony_ci } 20608c2ecf20Sopenharmony_ci 20618c2ecf20Sopenharmony_ci /* Prepare pex-dma descriptor to be written to MS memory. */ 20628c2ecf20Sopenharmony_ci /* dma-desc-cmd layout: 20638c2ecf20Sopenharmony_ci * 0-3: dma-desc-cmd 0-3 20648c2ecf20Sopenharmony_ci * 4-7: pcid function number 20658c2ecf20Sopenharmony_ci * 8-15: dma-desc-cmd 8-15 20668c2ecf20Sopenharmony_ci */ 20678c2ecf20Sopenharmony_ci dma_desc.cmd.dma_desc_cmd = (m_hdr->dma_desc_cmd & 0xff0f); 20688c2ecf20Sopenharmony_ci dma_desc.cmd.dma_desc_cmd |= ((PCI_FUNC(ha->pdev->devfn) & 0xf) << 0x4); 20698c2ecf20Sopenharmony_ci dma_desc.dma_bus_addr = rdmem_dma; 20708c2ecf20Sopenharmony_ci 20718c2ecf20Sopenharmony_ci size = 0; 20728c2ecf20Sopenharmony_ci read_size = 0; 20738c2ecf20Sopenharmony_ci /* 20748c2ecf20Sopenharmony_ci * Perform rdmem operation using pex-dma. 20758c2ecf20Sopenharmony_ci * Prepare dma in chunks of QLA83XX_PEX_DMA_READ_SIZE. 20768c2ecf20Sopenharmony_ci */ 20778c2ecf20Sopenharmony_ci while (read_size < m_hdr->read_data_size) { 20788c2ecf20Sopenharmony_ci if (m_hdr->read_data_size - read_size >= 20798c2ecf20Sopenharmony_ci QLA83XX_PEX_DMA_READ_SIZE) 20808c2ecf20Sopenharmony_ci size = QLA83XX_PEX_DMA_READ_SIZE; 20818c2ecf20Sopenharmony_ci else { 20828c2ecf20Sopenharmony_ci size = (m_hdr->read_data_size - read_size); 20838c2ecf20Sopenharmony_ci 20848c2ecf20Sopenharmony_ci if (rdmem_buffer) 20858c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, 20868c2ecf20Sopenharmony_ci QLA83XX_PEX_DMA_READ_SIZE, 20878c2ecf20Sopenharmony_ci rdmem_buffer, rdmem_dma); 20888c2ecf20Sopenharmony_ci 20898c2ecf20Sopenharmony_ci rdmem_buffer = dma_alloc_coherent(&ha->pdev->dev, size, 20908c2ecf20Sopenharmony_ci &rdmem_dma, 20918c2ecf20Sopenharmony_ci GFP_KERNEL); 20928c2ecf20Sopenharmony_ci if (!rdmem_buffer) { 20938c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 20948c2ecf20Sopenharmony_ci "%s: Unable to allocate rdmem dma buffer\n", 20958c2ecf20Sopenharmony_ci __func__)); 20968c2ecf20Sopenharmony_ci return QLA_ERROR; 20978c2ecf20Sopenharmony_ci } 20988c2ecf20Sopenharmony_ci dma_desc.dma_bus_addr = rdmem_dma; 20998c2ecf20Sopenharmony_ci } 21008c2ecf20Sopenharmony_ci 21018c2ecf20Sopenharmony_ci dma_desc.src_addr = m_hdr->read_addr + read_size; 21028c2ecf20Sopenharmony_ci dma_desc.cmd.read_data_size = size; 21038c2ecf20Sopenharmony_ci 21048c2ecf20Sopenharmony_ci /* Prepare: Write pex-dma descriptor to MS memory. */ 21058c2ecf20Sopenharmony_ci rval = qla4_8xxx_ms_mem_write_128b(ha, 21068c2ecf20Sopenharmony_ci (uint64_t)m_hdr->desc_card_addr, 21078c2ecf20Sopenharmony_ci (uint32_t *)&dma_desc, 21088c2ecf20Sopenharmony_ci (sizeof(struct qla4_83xx_pex_dma_descriptor)/16)); 21098c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) { 21108c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, 21118c2ecf20Sopenharmony_ci "%s: Error writing rdmem-dma-init to MS !!!\n", 21128c2ecf20Sopenharmony_ci __func__); 21138c2ecf20Sopenharmony_ci goto error_exit; 21148c2ecf20Sopenharmony_ci } 21158c2ecf20Sopenharmony_ci 21168c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 21178c2ecf20Sopenharmony_ci "%s: Dma-desc: Instruct for rdmem dma (size 0x%x).\n", 21188c2ecf20Sopenharmony_ci __func__, size)); 21198c2ecf20Sopenharmony_ci /* Execute: Start pex-dma operation. */ 21208c2ecf20Sopenharmony_ci rval = qla4_83xx_start_pex_dma(ha, m_hdr); 21218c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) { 21228c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 21238c2ecf20Sopenharmony_ci "scsi(%ld): start-pex-dma failed rval=0x%x\n", 21248c2ecf20Sopenharmony_ci ha->host_no, rval)); 21258c2ecf20Sopenharmony_ci goto error_exit; 21268c2ecf20Sopenharmony_ci } 21278c2ecf20Sopenharmony_ci 21288c2ecf20Sopenharmony_ci memcpy(data_ptr, rdmem_buffer, size); 21298c2ecf20Sopenharmony_ci data_ptr += size; 21308c2ecf20Sopenharmony_ci read_size += size; 21318c2ecf20Sopenharmony_ci } 21328c2ecf20Sopenharmony_ci 21338c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "Leaving fn: %s\n", __func__)); 21348c2ecf20Sopenharmony_ci 21358c2ecf20Sopenharmony_ci *d_ptr = (uint32_t *)data_ptr; 21368c2ecf20Sopenharmony_ci 21378c2ecf20Sopenharmony_cierror_exit: 21388c2ecf20Sopenharmony_ci if (rdmem_buffer) 21398c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, size, rdmem_buffer, 21408c2ecf20Sopenharmony_ci rdmem_dma); 21418c2ecf20Sopenharmony_ci 21428c2ecf20Sopenharmony_ci return rval; 21438c2ecf20Sopenharmony_ci} 21448c2ecf20Sopenharmony_ci 21458c2ecf20Sopenharmony_cistatic int qla4_8xxx_minidump_process_l2tag(struct scsi_qla_host *ha, 21468c2ecf20Sopenharmony_ci struct qla8xxx_minidump_entry_hdr *entry_hdr, 21478c2ecf20Sopenharmony_ci uint32_t **d_ptr) 21488c2ecf20Sopenharmony_ci{ 21498c2ecf20Sopenharmony_ci uint32_t addr, r_addr, c_addr, t_r_addr; 21508c2ecf20Sopenharmony_ci uint32_t i, k, loop_count, t_value, r_cnt, r_value; 21518c2ecf20Sopenharmony_ci unsigned long p_wait, w_time, p_mask; 21528c2ecf20Sopenharmony_ci uint32_t c_value_w, c_value_r; 21538c2ecf20Sopenharmony_ci struct qla8xxx_minidump_entry_cache *cache_hdr; 21548c2ecf20Sopenharmony_ci int rval = QLA_ERROR; 21558c2ecf20Sopenharmony_ci uint32_t *data_ptr = *d_ptr; 21568c2ecf20Sopenharmony_ci 21578c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__)); 21588c2ecf20Sopenharmony_ci cache_hdr = (struct qla8xxx_minidump_entry_cache *)entry_hdr; 21598c2ecf20Sopenharmony_ci 21608c2ecf20Sopenharmony_ci loop_count = cache_hdr->op_count; 21618c2ecf20Sopenharmony_ci r_addr = cache_hdr->read_addr; 21628c2ecf20Sopenharmony_ci c_addr = cache_hdr->control_addr; 21638c2ecf20Sopenharmony_ci c_value_w = cache_hdr->cache_ctrl.write_value; 21648c2ecf20Sopenharmony_ci 21658c2ecf20Sopenharmony_ci t_r_addr = cache_hdr->tag_reg_addr; 21668c2ecf20Sopenharmony_ci t_value = cache_hdr->addr_ctrl.init_tag_value; 21678c2ecf20Sopenharmony_ci r_cnt = cache_hdr->read_ctrl.read_addr_cnt; 21688c2ecf20Sopenharmony_ci p_wait = cache_hdr->cache_ctrl.poll_wait; 21698c2ecf20Sopenharmony_ci p_mask = cache_hdr->cache_ctrl.poll_mask; 21708c2ecf20Sopenharmony_ci 21718c2ecf20Sopenharmony_ci for (i = 0; i < loop_count; i++) { 21728c2ecf20Sopenharmony_ci ha->isp_ops->wr_reg_indirect(ha, t_r_addr, t_value); 21738c2ecf20Sopenharmony_ci 21748c2ecf20Sopenharmony_ci if (c_value_w) 21758c2ecf20Sopenharmony_ci ha->isp_ops->wr_reg_indirect(ha, c_addr, c_value_w); 21768c2ecf20Sopenharmony_ci 21778c2ecf20Sopenharmony_ci if (p_mask) { 21788c2ecf20Sopenharmony_ci w_time = jiffies + p_wait; 21798c2ecf20Sopenharmony_ci do { 21808c2ecf20Sopenharmony_ci ha->isp_ops->rd_reg_indirect(ha, c_addr, 21818c2ecf20Sopenharmony_ci &c_value_r); 21828c2ecf20Sopenharmony_ci if ((c_value_r & p_mask) == 0) { 21838c2ecf20Sopenharmony_ci break; 21848c2ecf20Sopenharmony_ci } else if (time_after_eq(jiffies, w_time)) { 21858c2ecf20Sopenharmony_ci /* capturing dump failed */ 21868c2ecf20Sopenharmony_ci return rval; 21878c2ecf20Sopenharmony_ci } 21888c2ecf20Sopenharmony_ci } while (1); 21898c2ecf20Sopenharmony_ci } 21908c2ecf20Sopenharmony_ci 21918c2ecf20Sopenharmony_ci addr = r_addr; 21928c2ecf20Sopenharmony_ci for (k = 0; k < r_cnt; k++) { 21938c2ecf20Sopenharmony_ci ha->isp_ops->rd_reg_indirect(ha, addr, &r_value); 21948c2ecf20Sopenharmony_ci *data_ptr++ = cpu_to_le32(r_value); 21958c2ecf20Sopenharmony_ci addr += cache_hdr->read_ctrl.read_addr_stride; 21968c2ecf20Sopenharmony_ci } 21978c2ecf20Sopenharmony_ci 21988c2ecf20Sopenharmony_ci t_value += cache_hdr->addr_ctrl.tag_value_stride; 21998c2ecf20Sopenharmony_ci } 22008c2ecf20Sopenharmony_ci *d_ptr = data_ptr; 22018c2ecf20Sopenharmony_ci return QLA_SUCCESS; 22028c2ecf20Sopenharmony_ci} 22038c2ecf20Sopenharmony_ci 22048c2ecf20Sopenharmony_cistatic int qla4_8xxx_minidump_process_control(struct scsi_qla_host *ha, 22058c2ecf20Sopenharmony_ci struct qla8xxx_minidump_entry_hdr *entry_hdr) 22068c2ecf20Sopenharmony_ci{ 22078c2ecf20Sopenharmony_ci struct qla8xxx_minidump_entry_crb *crb_entry; 22088c2ecf20Sopenharmony_ci uint32_t read_value, opcode, poll_time, addr, index, rval = QLA_SUCCESS; 22098c2ecf20Sopenharmony_ci uint32_t crb_addr; 22108c2ecf20Sopenharmony_ci unsigned long wtime; 22118c2ecf20Sopenharmony_ci struct qla4_8xxx_minidump_template_hdr *tmplt_hdr; 22128c2ecf20Sopenharmony_ci int i; 22138c2ecf20Sopenharmony_ci 22148c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__)); 22158c2ecf20Sopenharmony_ci tmplt_hdr = (struct qla4_8xxx_minidump_template_hdr *) 22168c2ecf20Sopenharmony_ci ha->fw_dump_tmplt_hdr; 22178c2ecf20Sopenharmony_ci crb_entry = (struct qla8xxx_minidump_entry_crb *)entry_hdr; 22188c2ecf20Sopenharmony_ci 22198c2ecf20Sopenharmony_ci crb_addr = crb_entry->addr; 22208c2ecf20Sopenharmony_ci for (i = 0; i < crb_entry->op_count; i++) { 22218c2ecf20Sopenharmony_ci opcode = crb_entry->crb_ctrl.opcode; 22228c2ecf20Sopenharmony_ci if (opcode & QLA8XXX_DBG_OPCODE_WR) { 22238c2ecf20Sopenharmony_ci ha->isp_ops->wr_reg_indirect(ha, crb_addr, 22248c2ecf20Sopenharmony_ci crb_entry->value_1); 22258c2ecf20Sopenharmony_ci opcode &= ~QLA8XXX_DBG_OPCODE_WR; 22268c2ecf20Sopenharmony_ci } 22278c2ecf20Sopenharmony_ci if (opcode & QLA8XXX_DBG_OPCODE_RW) { 22288c2ecf20Sopenharmony_ci ha->isp_ops->rd_reg_indirect(ha, crb_addr, &read_value); 22298c2ecf20Sopenharmony_ci ha->isp_ops->wr_reg_indirect(ha, crb_addr, read_value); 22308c2ecf20Sopenharmony_ci opcode &= ~QLA8XXX_DBG_OPCODE_RW; 22318c2ecf20Sopenharmony_ci } 22328c2ecf20Sopenharmony_ci if (opcode & QLA8XXX_DBG_OPCODE_AND) { 22338c2ecf20Sopenharmony_ci ha->isp_ops->rd_reg_indirect(ha, crb_addr, &read_value); 22348c2ecf20Sopenharmony_ci read_value &= crb_entry->value_2; 22358c2ecf20Sopenharmony_ci opcode &= ~QLA8XXX_DBG_OPCODE_AND; 22368c2ecf20Sopenharmony_ci if (opcode & QLA8XXX_DBG_OPCODE_OR) { 22378c2ecf20Sopenharmony_ci read_value |= crb_entry->value_3; 22388c2ecf20Sopenharmony_ci opcode &= ~QLA8XXX_DBG_OPCODE_OR; 22398c2ecf20Sopenharmony_ci } 22408c2ecf20Sopenharmony_ci ha->isp_ops->wr_reg_indirect(ha, crb_addr, read_value); 22418c2ecf20Sopenharmony_ci } 22428c2ecf20Sopenharmony_ci if (opcode & QLA8XXX_DBG_OPCODE_OR) { 22438c2ecf20Sopenharmony_ci ha->isp_ops->rd_reg_indirect(ha, crb_addr, &read_value); 22448c2ecf20Sopenharmony_ci read_value |= crb_entry->value_3; 22458c2ecf20Sopenharmony_ci ha->isp_ops->wr_reg_indirect(ha, crb_addr, read_value); 22468c2ecf20Sopenharmony_ci opcode &= ~QLA8XXX_DBG_OPCODE_OR; 22478c2ecf20Sopenharmony_ci } 22488c2ecf20Sopenharmony_ci if (opcode & QLA8XXX_DBG_OPCODE_POLL) { 22498c2ecf20Sopenharmony_ci poll_time = crb_entry->crb_strd.poll_timeout; 22508c2ecf20Sopenharmony_ci wtime = jiffies + poll_time; 22518c2ecf20Sopenharmony_ci ha->isp_ops->rd_reg_indirect(ha, crb_addr, &read_value); 22528c2ecf20Sopenharmony_ci 22538c2ecf20Sopenharmony_ci do { 22548c2ecf20Sopenharmony_ci if ((read_value & crb_entry->value_2) == 22558c2ecf20Sopenharmony_ci crb_entry->value_1) { 22568c2ecf20Sopenharmony_ci break; 22578c2ecf20Sopenharmony_ci } else if (time_after_eq(jiffies, wtime)) { 22588c2ecf20Sopenharmony_ci /* capturing dump failed */ 22598c2ecf20Sopenharmony_ci rval = QLA_ERROR; 22608c2ecf20Sopenharmony_ci break; 22618c2ecf20Sopenharmony_ci } else { 22628c2ecf20Sopenharmony_ci ha->isp_ops->rd_reg_indirect(ha, 22638c2ecf20Sopenharmony_ci crb_addr, &read_value); 22648c2ecf20Sopenharmony_ci } 22658c2ecf20Sopenharmony_ci } while (1); 22668c2ecf20Sopenharmony_ci opcode &= ~QLA8XXX_DBG_OPCODE_POLL; 22678c2ecf20Sopenharmony_ci } 22688c2ecf20Sopenharmony_ci 22698c2ecf20Sopenharmony_ci if (opcode & QLA8XXX_DBG_OPCODE_RDSTATE) { 22708c2ecf20Sopenharmony_ci if (crb_entry->crb_strd.state_index_a) { 22718c2ecf20Sopenharmony_ci index = crb_entry->crb_strd.state_index_a; 22728c2ecf20Sopenharmony_ci addr = tmplt_hdr->saved_state_array[index]; 22738c2ecf20Sopenharmony_ci } else { 22748c2ecf20Sopenharmony_ci addr = crb_addr; 22758c2ecf20Sopenharmony_ci } 22768c2ecf20Sopenharmony_ci 22778c2ecf20Sopenharmony_ci ha->isp_ops->rd_reg_indirect(ha, addr, &read_value); 22788c2ecf20Sopenharmony_ci index = crb_entry->crb_ctrl.state_index_v; 22798c2ecf20Sopenharmony_ci tmplt_hdr->saved_state_array[index] = read_value; 22808c2ecf20Sopenharmony_ci opcode &= ~QLA8XXX_DBG_OPCODE_RDSTATE; 22818c2ecf20Sopenharmony_ci } 22828c2ecf20Sopenharmony_ci 22838c2ecf20Sopenharmony_ci if (opcode & QLA8XXX_DBG_OPCODE_WRSTATE) { 22848c2ecf20Sopenharmony_ci if (crb_entry->crb_strd.state_index_a) { 22858c2ecf20Sopenharmony_ci index = crb_entry->crb_strd.state_index_a; 22868c2ecf20Sopenharmony_ci addr = tmplt_hdr->saved_state_array[index]; 22878c2ecf20Sopenharmony_ci } else { 22888c2ecf20Sopenharmony_ci addr = crb_addr; 22898c2ecf20Sopenharmony_ci } 22908c2ecf20Sopenharmony_ci 22918c2ecf20Sopenharmony_ci if (crb_entry->crb_ctrl.state_index_v) { 22928c2ecf20Sopenharmony_ci index = crb_entry->crb_ctrl.state_index_v; 22938c2ecf20Sopenharmony_ci read_value = 22948c2ecf20Sopenharmony_ci tmplt_hdr->saved_state_array[index]; 22958c2ecf20Sopenharmony_ci } else { 22968c2ecf20Sopenharmony_ci read_value = crb_entry->value_1; 22978c2ecf20Sopenharmony_ci } 22988c2ecf20Sopenharmony_ci 22998c2ecf20Sopenharmony_ci ha->isp_ops->wr_reg_indirect(ha, addr, read_value); 23008c2ecf20Sopenharmony_ci opcode &= ~QLA8XXX_DBG_OPCODE_WRSTATE; 23018c2ecf20Sopenharmony_ci } 23028c2ecf20Sopenharmony_ci 23038c2ecf20Sopenharmony_ci if (opcode & QLA8XXX_DBG_OPCODE_MDSTATE) { 23048c2ecf20Sopenharmony_ci index = crb_entry->crb_ctrl.state_index_v; 23058c2ecf20Sopenharmony_ci read_value = tmplt_hdr->saved_state_array[index]; 23068c2ecf20Sopenharmony_ci read_value <<= crb_entry->crb_ctrl.shl; 23078c2ecf20Sopenharmony_ci read_value >>= crb_entry->crb_ctrl.shr; 23088c2ecf20Sopenharmony_ci if (crb_entry->value_2) 23098c2ecf20Sopenharmony_ci read_value &= crb_entry->value_2; 23108c2ecf20Sopenharmony_ci read_value |= crb_entry->value_3; 23118c2ecf20Sopenharmony_ci read_value += crb_entry->value_1; 23128c2ecf20Sopenharmony_ci tmplt_hdr->saved_state_array[index] = read_value; 23138c2ecf20Sopenharmony_ci opcode &= ~QLA8XXX_DBG_OPCODE_MDSTATE; 23148c2ecf20Sopenharmony_ci } 23158c2ecf20Sopenharmony_ci crb_addr += crb_entry->crb_strd.addr_stride; 23168c2ecf20Sopenharmony_ci } 23178c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "Leaving fn: %s\n", __func__)); 23188c2ecf20Sopenharmony_ci return rval; 23198c2ecf20Sopenharmony_ci} 23208c2ecf20Sopenharmony_ci 23218c2ecf20Sopenharmony_cistatic void qla4_8xxx_minidump_process_rdocm(struct scsi_qla_host *ha, 23228c2ecf20Sopenharmony_ci struct qla8xxx_minidump_entry_hdr *entry_hdr, 23238c2ecf20Sopenharmony_ci uint32_t **d_ptr) 23248c2ecf20Sopenharmony_ci{ 23258c2ecf20Sopenharmony_ci uint32_t r_addr, r_stride, loop_cnt, i, r_value; 23268c2ecf20Sopenharmony_ci struct qla8xxx_minidump_entry_rdocm *ocm_hdr; 23278c2ecf20Sopenharmony_ci uint32_t *data_ptr = *d_ptr; 23288c2ecf20Sopenharmony_ci 23298c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__)); 23308c2ecf20Sopenharmony_ci ocm_hdr = (struct qla8xxx_minidump_entry_rdocm *)entry_hdr; 23318c2ecf20Sopenharmony_ci r_addr = ocm_hdr->read_addr; 23328c2ecf20Sopenharmony_ci r_stride = ocm_hdr->read_addr_stride; 23338c2ecf20Sopenharmony_ci loop_cnt = ocm_hdr->op_count; 23348c2ecf20Sopenharmony_ci 23358c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 23368c2ecf20Sopenharmony_ci "[%s]: r_addr: 0x%x, r_stride: 0x%x, loop_cnt: 0x%x\n", 23378c2ecf20Sopenharmony_ci __func__, r_addr, r_stride, loop_cnt)); 23388c2ecf20Sopenharmony_ci 23398c2ecf20Sopenharmony_ci for (i = 0; i < loop_cnt; i++) { 23408c2ecf20Sopenharmony_ci r_value = readl((void __iomem *)(r_addr + ha->nx_pcibase)); 23418c2ecf20Sopenharmony_ci *data_ptr++ = cpu_to_le32(r_value); 23428c2ecf20Sopenharmony_ci r_addr += r_stride; 23438c2ecf20Sopenharmony_ci } 23448c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "Leaving fn: %s datacount: 0x%lx\n", 23458c2ecf20Sopenharmony_ci __func__, (long unsigned int) (loop_cnt * sizeof(uint32_t)))); 23468c2ecf20Sopenharmony_ci *d_ptr = data_ptr; 23478c2ecf20Sopenharmony_ci} 23488c2ecf20Sopenharmony_ci 23498c2ecf20Sopenharmony_cistatic void qla4_8xxx_minidump_process_rdmux(struct scsi_qla_host *ha, 23508c2ecf20Sopenharmony_ci struct qla8xxx_minidump_entry_hdr *entry_hdr, 23518c2ecf20Sopenharmony_ci uint32_t **d_ptr) 23528c2ecf20Sopenharmony_ci{ 23538c2ecf20Sopenharmony_ci uint32_t r_addr, s_stride, s_addr, s_value, loop_cnt, i, r_value; 23548c2ecf20Sopenharmony_ci struct qla8xxx_minidump_entry_mux *mux_hdr; 23558c2ecf20Sopenharmony_ci uint32_t *data_ptr = *d_ptr; 23568c2ecf20Sopenharmony_ci 23578c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__)); 23588c2ecf20Sopenharmony_ci mux_hdr = (struct qla8xxx_minidump_entry_mux *)entry_hdr; 23598c2ecf20Sopenharmony_ci r_addr = mux_hdr->read_addr; 23608c2ecf20Sopenharmony_ci s_addr = mux_hdr->select_addr; 23618c2ecf20Sopenharmony_ci s_stride = mux_hdr->select_value_stride; 23628c2ecf20Sopenharmony_ci s_value = mux_hdr->select_value; 23638c2ecf20Sopenharmony_ci loop_cnt = mux_hdr->op_count; 23648c2ecf20Sopenharmony_ci 23658c2ecf20Sopenharmony_ci for (i = 0; i < loop_cnt; i++) { 23668c2ecf20Sopenharmony_ci ha->isp_ops->wr_reg_indirect(ha, s_addr, s_value); 23678c2ecf20Sopenharmony_ci ha->isp_ops->rd_reg_indirect(ha, r_addr, &r_value); 23688c2ecf20Sopenharmony_ci *data_ptr++ = cpu_to_le32(s_value); 23698c2ecf20Sopenharmony_ci *data_ptr++ = cpu_to_le32(r_value); 23708c2ecf20Sopenharmony_ci s_value += s_stride; 23718c2ecf20Sopenharmony_ci } 23728c2ecf20Sopenharmony_ci *d_ptr = data_ptr; 23738c2ecf20Sopenharmony_ci} 23748c2ecf20Sopenharmony_ci 23758c2ecf20Sopenharmony_cistatic void qla4_8xxx_minidump_process_l1cache(struct scsi_qla_host *ha, 23768c2ecf20Sopenharmony_ci struct qla8xxx_minidump_entry_hdr *entry_hdr, 23778c2ecf20Sopenharmony_ci uint32_t **d_ptr) 23788c2ecf20Sopenharmony_ci{ 23798c2ecf20Sopenharmony_ci uint32_t addr, r_addr, c_addr, t_r_addr; 23808c2ecf20Sopenharmony_ci uint32_t i, k, loop_count, t_value, r_cnt, r_value; 23818c2ecf20Sopenharmony_ci uint32_t c_value_w; 23828c2ecf20Sopenharmony_ci struct qla8xxx_minidump_entry_cache *cache_hdr; 23838c2ecf20Sopenharmony_ci uint32_t *data_ptr = *d_ptr; 23848c2ecf20Sopenharmony_ci 23858c2ecf20Sopenharmony_ci cache_hdr = (struct qla8xxx_minidump_entry_cache *)entry_hdr; 23868c2ecf20Sopenharmony_ci loop_count = cache_hdr->op_count; 23878c2ecf20Sopenharmony_ci r_addr = cache_hdr->read_addr; 23888c2ecf20Sopenharmony_ci c_addr = cache_hdr->control_addr; 23898c2ecf20Sopenharmony_ci c_value_w = cache_hdr->cache_ctrl.write_value; 23908c2ecf20Sopenharmony_ci 23918c2ecf20Sopenharmony_ci t_r_addr = cache_hdr->tag_reg_addr; 23928c2ecf20Sopenharmony_ci t_value = cache_hdr->addr_ctrl.init_tag_value; 23938c2ecf20Sopenharmony_ci r_cnt = cache_hdr->read_ctrl.read_addr_cnt; 23948c2ecf20Sopenharmony_ci 23958c2ecf20Sopenharmony_ci for (i = 0; i < loop_count; i++) { 23968c2ecf20Sopenharmony_ci ha->isp_ops->wr_reg_indirect(ha, t_r_addr, t_value); 23978c2ecf20Sopenharmony_ci ha->isp_ops->wr_reg_indirect(ha, c_addr, c_value_w); 23988c2ecf20Sopenharmony_ci addr = r_addr; 23998c2ecf20Sopenharmony_ci for (k = 0; k < r_cnt; k++) { 24008c2ecf20Sopenharmony_ci ha->isp_ops->rd_reg_indirect(ha, addr, &r_value); 24018c2ecf20Sopenharmony_ci *data_ptr++ = cpu_to_le32(r_value); 24028c2ecf20Sopenharmony_ci addr += cache_hdr->read_ctrl.read_addr_stride; 24038c2ecf20Sopenharmony_ci } 24048c2ecf20Sopenharmony_ci t_value += cache_hdr->addr_ctrl.tag_value_stride; 24058c2ecf20Sopenharmony_ci } 24068c2ecf20Sopenharmony_ci *d_ptr = data_ptr; 24078c2ecf20Sopenharmony_ci} 24088c2ecf20Sopenharmony_ci 24098c2ecf20Sopenharmony_cistatic void qla4_8xxx_minidump_process_queue(struct scsi_qla_host *ha, 24108c2ecf20Sopenharmony_ci struct qla8xxx_minidump_entry_hdr *entry_hdr, 24118c2ecf20Sopenharmony_ci uint32_t **d_ptr) 24128c2ecf20Sopenharmony_ci{ 24138c2ecf20Sopenharmony_ci uint32_t s_addr, r_addr; 24148c2ecf20Sopenharmony_ci uint32_t r_stride, r_value, r_cnt, qid = 0; 24158c2ecf20Sopenharmony_ci uint32_t i, k, loop_cnt; 24168c2ecf20Sopenharmony_ci struct qla8xxx_minidump_entry_queue *q_hdr; 24178c2ecf20Sopenharmony_ci uint32_t *data_ptr = *d_ptr; 24188c2ecf20Sopenharmony_ci 24198c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__)); 24208c2ecf20Sopenharmony_ci q_hdr = (struct qla8xxx_minidump_entry_queue *)entry_hdr; 24218c2ecf20Sopenharmony_ci s_addr = q_hdr->select_addr; 24228c2ecf20Sopenharmony_ci r_cnt = q_hdr->rd_strd.read_addr_cnt; 24238c2ecf20Sopenharmony_ci r_stride = q_hdr->rd_strd.read_addr_stride; 24248c2ecf20Sopenharmony_ci loop_cnt = q_hdr->op_count; 24258c2ecf20Sopenharmony_ci 24268c2ecf20Sopenharmony_ci for (i = 0; i < loop_cnt; i++) { 24278c2ecf20Sopenharmony_ci ha->isp_ops->wr_reg_indirect(ha, s_addr, qid); 24288c2ecf20Sopenharmony_ci r_addr = q_hdr->read_addr; 24298c2ecf20Sopenharmony_ci for (k = 0; k < r_cnt; k++) { 24308c2ecf20Sopenharmony_ci ha->isp_ops->rd_reg_indirect(ha, r_addr, &r_value); 24318c2ecf20Sopenharmony_ci *data_ptr++ = cpu_to_le32(r_value); 24328c2ecf20Sopenharmony_ci r_addr += r_stride; 24338c2ecf20Sopenharmony_ci } 24348c2ecf20Sopenharmony_ci qid += q_hdr->q_strd.queue_id_stride; 24358c2ecf20Sopenharmony_ci } 24368c2ecf20Sopenharmony_ci *d_ptr = data_ptr; 24378c2ecf20Sopenharmony_ci} 24388c2ecf20Sopenharmony_ci 24398c2ecf20Sopenharmony_ci#define MD_DIRECT_ROM_WINDOW 0x42110030 24408c2ecf20Sopenharmony_ci#define MD_DIRECT_ROM_READ_BASE 0x42150000 24418c2ecf20Sopenharmony_ci 24428c2ecf20Sopenharmony_cistatic void qla4_82xx_minidump_process_rdrom(struct scsi_qla_host *ha, 24438c2ecf20Sopenharmony_ci struct qla8xxx_minidump_entry_hdr *entry_hdr, 24448c2ecf20Sopenharmony_ci uint32_t **d_ptr) 24458c2ecf20Sopenharmony_ci{ 24468c2ecf20Sopenharmony_ci uint32_t r_addr, r_value; 24478c2ecf20Sopenharmony_ci uint32_t i, loop_cnt; 24488c2ecf20Sopenharmony_ci struct qla8xxx_minidump_entry_rdrom *rom_hdr; 24498c2ecf20Sopenharmony_ci uint32_t *data_ptr = *d_ptr; 24508c2ecf20Sopenharmony_ci 24518c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__)); 24528c2ecf20Sopenharmony_ci rom_hdr = (struct qla8xxx_minidump_entry_rdrom *)entry_hdr; 24538c2ecf20Sopenharmony_ci r_addr = rom_hdr->read_addr; 24548c2ecf20Sopenharmony_ci loop_cnt = rom_hdr->read_data_size/sizeof(uint32_t); 24558c2ecf20Sopenharmony_ci 24568c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 24578c2ecf20Sopenharmony_ci "[%s]: flash_addr: 0x%x, read_data_size: 0x%x\n", 24588c2ecf20Sopenharmony_ci __func__, r_addr, loop_cnt)); 24598c2ecf20Sopenharmony_ci 24608c2ecf20Sopenharmony_ci for (i = 0; i < loop_cnt; i++) { 24618c2ecf20Sopenharmony_ci ha->isp_ops->wr_reg_indirect(ha, MD_DIRECT_ROM_WINDOW, 24628c2ecf20Sopenharmony_ci (r_addr & 0xFFFF0000)); 24638c2ecf20Sopenharmony_ci ha->isp_ops->rd_reg_indirect(ha, 24648c2ecf20Sopenharmony_ci MD_DIRECT_ROM_READ_BASE + (r_addr & 0x0000FFFF), 24658c2ecf20Sopenharmony_ci &r_value); 24668c2ecf20Sopenharmony_ci *data_ptr++ = cpu_to_le32(r_value); 24678c2ecf20Sopenharmony_ci r_addr += sizeof(uint32_t); 24688c2ecf20Sopenharmony_ci } 24698c2ecf20Sopenharmony_ci *d_ptr = data_ptr; 24708c2ecf20Sopenharmony_ci} 24718c2ecf20Sopenharmony_ci 24728c2ecf20Sopenharmony_ci#define MD_MIU_TEST_AGT_CTRL 0x41000090 24738c2ecf20Sopenharmony_ci#define MD_MIU_TEST_AGT_ADDR_LO 0x41000094 24748c2ecf20Sopenharmony_ci#define MD_MIU_TEST_AGT_ADDR_HI 0x41000098 24758c2ecf20Sopenharmony_ci 24768c2ecf20Sopenharmony_cistatic int __qla4_8xxx_minidump_process_rdmem(struct scsi_qla_host *ha, 24778c2ecf20Sopenharmony_ci struct qla8xxx_minidump_entry_hdr *entry_hdr, 24788c2ecf20Sopenharmony_ci uint32_t **d_ptr) 24798c2ecf20Sopenharmony_ci{ 24808c2ecf20Sopenharmony_ci uint32_t r_addr, r_value, r_data; 24818c2ecf20Sopenharmony_ci uint32_t i, j, loop_cnt; 24828c2ecf20Sopenharmony_ci struct qla8xxx_minidump_entry_rdmem *m_hdr; 24838c2ecf20Sopenharmony_ci unsigned long flags; 24848c2ecf20Sopenharmony_ci uint32_t *data_ptr = *d_ptr; 24858c2ecf20Sopenharmony_ci 24868c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__)); 24878c2ecf20Sopenharmony_ci m_hdr = (struct qla8xxx_minidump_entry_rdmem *)entry_hdr; 24888c2ecf20Sopenharmony_ci r_addr = m_hdr->read_addr; 24898c2ecf20Sopenharmony_ci loop_cnt = m_hdr->read_data_size/16; 24908c2ecf20Sopenharmony_ci 24918c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 24928c2ecf20Sopenharmony_ci "[%s]: Read addr: 0x%x, read_data_size: 0x%x\n", 24938c2ecf20Sopenharmony_ci __func__, r_addr, m_hdr->read_data_size)); 24948c2ecf20Sopenharmony_ci 24958c2ecf20Sopenharmony_ci if (r_addr & 0xf) { 24968c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 24978c2ecf20Sopenharmony_ci "[%s]: Read addr 0x%x not 16 bytes aligned\n", 24988c2ecf20Sopenharmony_ci __func__, r_addr)); 24998c2ecf20Sopenharmony_ci return QLA_ERROR; 25008c2ecf20Sopenharmony_ci } 25018c2ecf20Sopenharmony_ci 25028c2ecf20Sopenharmony_ci if (m_hdr->read_data_size % 16) { 25038c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 25048c2ecf20Sopenharmony_ci "[%s]: Read data[0x%x] not multiple of 16 bytes\n", 25058c2ecf20Sopenharmony_ci __func__, m_hdr->read_data_size)); 25068c2ecf20Sopenharmony_ci return QLA_ERROR; 25078c2ecf20Sopenharmony_ci } 25088c2ecf20Sopenharmony_ci 25098c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 25108c2ecf20Sopenharmony_ci "[%s]: rdmem_addr: 0x%x, read_data_size: 0x%x, loop_cnt: 0x%x\n", 25118c2ecf20Sopenharmony_ci __func__, r_addr, m_hdr->read_data_size, loop_cnt)); 25128c2ecf20Sopenharmony_ci 25138c2ecf20Sopenharmony_ci write_lock_irqsave(&ha->hw_lock, flags); 25148c2ecf20Sopenharmony_ci for (i = 0; i < loop_cnt; i++) { 25158c2ecf20Sopenharmony_ci ha->isp_ops->wr_reg_indirect(ha, MD_MIU_TEST_AGT_ADDR_LO, 25168c2ecf20Sopenharmony_ci r_addr); 25178c2ecf20Sopenharmony_ci r_value = 0; 25188c2ecf20Sopenharmony_ci ha->isp_ops->wr_reg_indirect(ha, MD_MIU_TEST_AGT_ADDR_HI, 25198c2ecf20Sopenharmony_ci r_value); 25208c2ecf20Sopenharmony_ci r_value = MIU_TA_CTL_ENABLE; 25218c2ecf20Sopenharmony_ci ha->isp_ops->wr_reg_indirect(ha, MD_MIU_TEST_AGT_CTRL, r_value); 25228c2ecf20Sopenharmony_ci r_value = MIU_TA_CTL_START_ENABLE; 25238c2ecf20Sopenharmony_ci ha->isp_ops->wr_reg_indirect(ha, MD_MIU_TEST_AGT_CTRL, r_value); 25248c2ecf20Sopenharmony_ci 25258c2ecf20Sopenharmony_ci for (j = 0; j < MAX_CTL_CHECK; j++) { 25268c2ecf20Sopenharmony_ci ha->isp_ops->rd_reg_indirect(ha, MD_MIU_TEST_AGT_CTRL, 25278c2ecf20Sopenharmony_ci &r_value); 25288c2ecf20Sopenharmony_ci if ((r_value & MIU_TA_CTL_BUSY) == 0) 25298c2ecf20Sopenharmony_ci break; 25308c2ecf20Sopenharmony_ci } 25318c2ecf20Sopenharmony_ci 25328c2ecf20Sopenharmony_ci if (j >= MAX_CTL_CHECK) { 25338c2ecf20Sopenharmony_ci printk_ratelimited(KERN_ERR 25348c2ecf20Sopenharmony_ci "%s: failed to read through agent\n", 25358c2ecf20Sopenharmony_ci __func__); 25368c2ecf20Sopenharmony_ci write_unlock_irqrestore(&ha->hw_lock, flags); 25378c2ecf20Sopenharmony_ci return QLA_SUCCESS; 25388c2ecf20Sopenharmony_ci } 25398c2ecf20Sopenharmony_ci 25408c2ecf20Sopenharmony_ci for (j = 0; j < 4; j++) { 25418c2ecf20Sopenharmony_ci ha->isp_ops->rd_reg_indirect(ha, 25428c2ecf20Sopenharmony_ci MD_MIU_TEST_AGT_RDDATA[j], 25438c2ecf20Sopenharmony_ci &r_data); 25448c2ecf20Sopenharmony_ci *data_ptr++ = cpu_to_le32(r_data); 25458c2ecf20Sopenharmony_ci } 25468c2ecf20Sopenharmony_ci 25478c2ecf20Sopenharmony_ci r_addr += 16; 25488c2ecf20Sopenharmony_ci } 25498c2ecf20Sopenharmony_ci write_unlock_irqrestore(&ha->hw_lock, flags); 25508c2ecf20Sopenharmony_ci 25518c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "Leaving fn: %s datacount: 0x%x\n", 25528c2ecf20Sopenharmony_ci __func__, (loop_cnt * 16))); 25538c2ecf20Sopenharmony_ci 25548c2ecf20Sopenharmony_ci *d_ptr = data_ptr; 25558c2ecf20Sopenharmony_ci return QLA_SUCCESS; 25568c2ecf20Sopenharmony_ci} 25578c2ecf20Sopenharmony_ci 25588c2ecf20Sopenharmony_cistatic int qla4_8xxx_minidump_process_rdmem(struct scsi_qla_host *ha, 25598c2ecf20Sopenharmony_ci struct qla8xxx_minidump_entry_hdr *entry_hdr, 25608c2ecf20Sopenharmony_ci uint32_t **d_ptr) 25618c2ecf20Sopenharmony_ci{ 25628c2ecf20Sopenharmony_ci uint32_t *data_ptr = *d_ptr; 25638c2ecf20Sopenharmony_ci int rval = QLA_SUCCESS; 25648c2ecf20Sopenharmony_ci 25658c2ecf20Sopenharmony_ci rval = qla4_8xxx_minidump_pex_dma_read(ha, entry_hdr, &data_ptr); 25668c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) 25678c2ecf20Sopenharmony_ci rval = __qla4_8xxx_minidump_process_rdmem(ha, entry_hdr, 25688c2ecf20Sopenharmony_ci &data_ptr); 25698c2ecf20Sopenharmony_ci *d_ptr = data_ptr; 25708c2ecf20Sopenharmony_ci return rval; 25718c2ecf20Sopenharmony_ci} 25728c2ecf20Sopenharmony_ci 25738c2ecf20Sopenharmony_cistatic void qla4_8xxx_mark_entry_skipped(struct scsi_qla_host *ha, 25748c2ecf20Sopenharmony_ci struct qla8xxx_minidump_entry_hdr *entry_hdr, 25758c2ecf20Sopenharmony_ci int index) 25768c2ecf20Sopenharmony_ci{ 25778c2ecf20Sopenharmony_ci entry_hdr->d_ctrl.driver_flags |= QLA8XXX_DBG_SKIPPED_FLAG; 25788c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 25798c2ecf20Sopenharmony_ci "scsi(%ld): Skipping entry[%d]: ETYPE[0x%x]-ELEVEL[0x%x]\n", 25808c2ecf20Sopenharmony_ci ha->host_no, index, entry_hdr->entry_type, 25818c2ecf20Sopenharmony_ci entry_hdr->d_ctrl.entry_capture_mask)); 25828c2ecf20Sopenharmony_ci /* If driver encounters a new entry type that it cannot process, 25838c2ecf20Sopenharmony_ci * it should just skip the entry and adjust the total buffer size by 25848c2ecf20Sopenharmony_ci * from subtracting the skipped bytes from it 25858c2ecf20Sopenharmony_ci */ 25868c2ecf20Sopenharmony_ci ha->fw_dump_skip_size += entry_hdr->entry_capture_size; 25878c2ecf20Sopenharmony_ci} 25888c2ecf20Sopenharmony_ci 25898c2ecf20Sopenharmony_ci/* ISP83xx functions to process new minidump entries... */ 25908c2ecf20Sopenharmony_cistatic uint32_t qla83xx_minidump_process_pollrd(struct scsi_qla_host *ha, 25918c2ecf20Sopenharmony_ci struct qla8xxx_minidump_entry_hdr *entry_hdr, 25928c2ecf20Sopenharmony_ci uint32_t **d_ptr) 25938c2ecf20Sopenharmony_ci{ 25948c2ecf20Sopenharmony_ci uint32_t r_addr, s_addr, s_value, r_value, poll_wait, poll_mask; 25958c2ecf20Sopenharmony_ci uint16_t s_stride, i; 25968c2ecf20Sopenharmony_ci uint32_t *data_ptr = *d_ptr; 25978c2ecf20Sopenharmony_ci uint32_t rval = QLA_SUCCESS; 25988c2ecf20Sopenharmony_ci struct qla83xx_minidump_entry_pollrd *pollrd_hdr; 25998c2ecf20Sopenharmony_ci 26008c2ecf20Sopenharmony_ci pollrd_hdr = (struct qla83xx_minidump_entry_pollrd *)entry_hdr; 26018c2ecf20Sopenharmony_ci s_addr = le32_to_cpu(pollrd_hdr->select_addr); 26028c2ecf20Sopenharmony_ci r_addr = le32_to_cpu(pollrd_hdr->read_addr); 26038c2ecf20Sopenharmony_ci s_value = le32_to_cpu(pollrd_hdr->select_value); 26048c2ecf20Sopenharmony_ci s_stride = le32_to_cpu(pollrd_hdr->select_value_stride); 26058c2ecf20Sopenharmony_ci 26068c2ecf20Sopenharmony_ci poll_wait = le32_to_cpu(pollrd_hdr->poll_wait); 26078c2ecf20Sopenharmony_ci poll_mask = le32_to_cpu(pollrd_hdr->poll_mask); 26088c2ecf20Sopenharmony_ci 26098c2ecf20Sopenharmony_ci for (i = 0; i < le32_to_cpu(pollrd_hdr->op_count); i++) { 26108c2ecf20Sopenharmony_ci ha->isp_ops->wr_reg_indirect(ha, s_addr, s_value); 26118c2ecf20Sopenharmony_ci poll_wait = le32_to_cpu(pollrd_hdr->poll_wait); 26128c2ecf20Sopenharmony_ci while (1) { 26138c2ecf20Sopenharmony_ci ha->isp_ops->rd_reg_indirect(ha, s_addr, &r_value); 26148c2ecf20Sopenharmony_ci 26158c2ecf20Sopenharmony_ci if ((r_value & poll_mask) != 0) { 26168c2ecf20Sopenharmony_ci break; 26178c2ecf20Sopenharmony_ci } else { 26188c2ecf20Sopenharmony_ci msleep(1); 26198c2ecf20Sopenharmony_ci if (--poll_wait == 0) { 26208c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: TIMEOUT\n", 26218c2ecf20Sopenharmony_ci __func__); 26228c2ecf20Sopenharmony_ci rval = QLA_ERROR; 26238c2ecf20Sopenharmony_ci goto exit_process_pollrd; 26248c2ecf20Sopenharmony_ci } 26258c2ecf20Sopenharmony_ci } 26268c2ecf20Sopenharmony_ci } 26278c2ecf20Sopenharmony_ci ha->isp_ops->rd_reg_indirect(ha, r_addr, &r_value); 26288c2ecf20Sopenharmony_ci *data_ptr++ = cpu_to_le32(s_value); 26298c2ecf20Sopenharmony_ci *data_ptr++ = cpu_to_le32(r_value); 26308c2ecf20Sopenharmony_ci s_value += s_stride; 26318c2ecf20Sopenharmony_ci } 26328c2ecf20Sopenharmony_ci 26338c2ecf20Sopenharmony_ci *d_ptr = data_ptr; 26348c2ecf20Sopenharmony_ci 26358c2ecf20Sopenharmony_ciexit_process_pollrd: 26368c2ecf20Sopenharmony_ci return rval; 26378c2ecf20Sopenharmony_ci} 26388c2ecf20Sopenharmony_ci 26398c2ecf20Sopenharmony_cistatic uint32_t qla4_84xx_minidump_process_rddfe(struct scsi_qla_host *ha, 26408c2ecf20Sopenharmony_ci struct qla8xxx_minidump_entry_hdr *entry_hdr, 26418c2ecf20Sopenharmony_ci uint32_t **d_ptr) 26428c2ecf20Sopenharmony_ci{ 26438c2ecf20Sopenharmony_ci int loop_cnt; 26448c2ecf20Sopenharmony_ci uint32_t addr1, addr2, value, data, temp, wrval; 26458c2ecf20Sopenharmony_ci uint8_t stride, stride2; 26468c2ecf20Sopenharmony_ci uint16_t count; 26478c2ecf20Sopenharmony_ci uint32_t poll, mask, modify_mask; 26488c2ecf20Sopenharmony_ci uint32_t wait_count = 0; 26498c2ecf20Sopenharmony_ci uint32_t *data_ptr = *d_ptr; 26508c2ecf20Sopenharmony_ci struct qla8044_minidump_entry_rddfe *rddfe; 26518c2ecf20Sopenharmony_ci uint32_t rval = QLA_SUCCESS; 26528c2ecf20Sopenharmony_ci 26538c2ecf20Sopenharmony_ci rddfe = (struct qla8044_minidump_entry_rddfe *)entry_hdr; 26548c2ecf20Sopenharmony_ci addr1 = le32_to_cpu(rddfe->addr_1); 26558c2ecf20Sopenharmony_ci value = le32_to_cpu(rddfe->value); 26568c2ecf20Sopenharmony_ci stride = le32_to_cpu(rddfe->stride); 26578c2ecf20Sopenharmony_ci stride2 = le32_to_cpu(rddfe->stride2); 26588c2ecf20Sopenharmony_ci count = le32_to_cpu(rddfe->count); 26598c2ecf20Sopenharmony_ci 26608c2ecf20Sopenharmony_ci poll = le32_to_cpu(rddfe->poll); 26618c2ecf20Sopenharmony_ci mask = le32_to_cpu(rddfe->mask); 26628c2ecf20Sopenharmony_ci modify_mask = le32_to_cpu(rddfe->modify_mask); 26638c2ecf20Sopenharmony_ci 26648c2ecf20Sopenharmony_ci addr2 = addr1 + stride; 26658c2ecf20Sopenharmony_ci 26668c2ecf20Sopenharmony_ci for (loop_cnt = 0x0; loop_cnt < count; loop_cnt++) { 26678c2ecf20Sopenharmony_ci ha->isp_ops->wr_reg_indirect(ha, addr1, (0x40000000 | value)); 26688c2ecf20Sopenharmony_ci 26698c2ecf20Sopenharmony_ci wait_count = 0; 26708c2ecf20Sopenharmony_ci while (wait_count < poll) { 26718c2ecf20Sopenharmony_ci ha->isp_ops->rd_reg_indirect(ha, addr1, &temp); 26728c2ecf20Sopenharmony_ci if ((temp & mask) != 0) 26738c2ecf20Sopenharmony_ci break; 26748c2ecf20Sopenharmony_ci wait_count++; 26758c2ecf20Sopenharmony_ci } 26768c2ecf20Sopenharmony_ci 26778c2ecf20Sopenharmony_ci if (wait_count == poll) { 26788c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: TIMEOUT\n", __func__); 26798c2ecf20Sopenharmony_ci rval = QLA_ERROR; 26808c2ecf20Sopenharmony_ci goto exit_process_rddfe; 26818c2ecf20Sopenharmony_ci } else { 26828c2ecf20Sopenharmony_ci ha->isp_ops->rd_reg_indirect(ha, addr2, &temp); 26838c2ecf20Sopenharmony_ci temp = temp & modify_mask; 26848c2ecf20Sopenharmony_ci temp = (temp | ((loop_cnt << 16) | loop_cnt)); 26858c2ecf20Sopenharmony_ci wrval = ((temp << 16) | temp); 26868c2ecf20Sopenharmony_ci 26878c2ecf20Sopenharmony_ci ha->isp_ops->wr_reg_indirect(ha, addr2, wrval); 26888c2ecf20Sopenharmony_ci ha->isp_ops->wr_reg_indirect(ha, addr1, value); 26898c2ecf20Sopenharmony_ci 26908c2ecf20Sopenharmony_ci wait_count = 0; 26918c2ecf20Sopenharmony_ci while (wait_count < poll) { 26928c2ecf20Sopenharmony_ci ha->isp_ops->rd_reg_indirect(ha, addr1, &temp); 26938c2ecf20Sopenharmony_ci if ((temp & mask) != 0) 26948c2ecf20Sopenharmony_ci break; 26958c2ecf20Sopenharmony_ci wait_count++; 26968c2ecf20Sopenharmony_ci } 26978c2ecf20Sopenharmony_ci if (wait_count == poll) { 26988c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: TIMEOUT\n", 26998c2ecf20Sopenharmony_ci __func__); 27008c2ecf20Sopenharmony_ci rval = QLA_ERROR; 27018c2ecf20Sopenharmony_ci goto exit_process_rddfe; 27028c2ecf20Sopenharmony_ci } 27038c2ecf20Sopenharmony_ci 27048c2ecf20Sopenharmony_ci ha->isp_ops->wr_reg_indirect(ha, addr1, 27058c2ecf20Sopenharmony_ci ((0x40000000 | value) + 27068c2ecf20Sopenharmony_ci stride2)); 27078c2ecf20Sopenharmony_ci wait_count = 0; 27088c2ecf20Sopenharmony_ci while (wait_count < poll) { 27098c2ecf20Sopenharmony_ci ha->isp_ops->rd_reg_indirect(ha, addr1, &temp); 27108c2ecf20Sopenharmony_ci if ((temp & mask) != 0) 27118c2ecf20Sopenharmony_ci break; 27128c2ecf20Sopenharmony_ci wait_count++; 27138c2ecf20Sopenharmony_ci } 27148c2ecf20Sopenharmony_ci 27158c2ecf20Sopenharmony_ci if (wait_count == poll) { 27168c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: TIMEOUT\n", 27178c2ecf20Sopenharmony_ci __func__); 27188c2ecf20Sopenharmony_ci rval = QLA_ERROR; 27198c2ecf20Sopenharmony_ci goto exit_process_rddfe; 27208c2ecf20Sopenharmony_ci } 27218c2ecf20Sopenharmony_ci 27228c2ecf20Sopenharmony_ci ha->isp_ops->rd_reg_indirect(ha, addr2, &data); 27238c2ecf20Sopenharmony_ci 27248c2ecf20Sopenharmony_ci *data_ptr++ = cpu_to_le32(wrval); 27258c2ecf20Sopenharmony_ci *data_ptr++ = cpu_to_le32(data); 27268c2ecf20Sopenharmony_ci } 27278c2ecf20Sopenharmony_ci } 27288c2ecf20Sopenharmony_ci 27298c2ecf20Sopenharmony_ci *d_ptr = data_ptr; 27308c2ecf20Sopenharmony_ciexit_process_rddfe: 27318c2ecf20Sopenharmony_ci return rval; 27328c2ecf20Sopenharmony_ci} 27338c2ecf20Sopenharmony_ci 27348c2ecf20Sopenharmony_cistatic uint32_t qla4_84xx_minidump_process_rdmdio(struct scsi_qla_host *ha, 27358c2ecf20Sopenharmony_ci struct qla8xxx_minidump_entry_hdr *entry_hdr, 27368c2ecf20Sopenharmony_ci uint32_t **d_ptr) 27378c2ecf20Sopenharmony_ci{ 27388c2ecf20Sopenharmony_ci int rval = QLA_SUCCESS; 27398c2ecf20Sopenharmony_ci uint32_t addr1, addr2, value1, value2, data, selval; 27408c2ecf20Sopenharmony_ci uint8_t stride1, stride2; 27418c2ecf20Sopenharmony_ci uint32_t addr3, addr4, addr5, addr6, addr7; 27428c2ecf20Sopenharmony_ci uint16_t count, loop_cnt; 27438c2ecf20Sopenharmony_ci uint32_t mask; 27448c2ecf20Sopenharmony_ci uint32_t *data_ptr = *d_ptr; 27458c2ecf20Sopenharmony_ci struct qla8044_minidump_entry_rdmdio *rdmdio; 27468c2ecf20Sopenharmony_ci 27478c2ecf20Sopenharmony_ci rdmdio = (struct qla8044_minidump_entry_rdmdio *)entry_hdr; 27488c2ecf20Sopenharmony_ci addr1 = le32_to_cpu(rdmdio->addr_1); 27498c2ecf20Sopenharmony_ci addr2 = le32_to_cpu(rdmdio->addr_2); 27508c2ecf20Sopenharmony_ci value1 = le32_to_cpu(rdmdio->value_1); 27518c2ecf20Sopenharmony_ci stride1 = le32_to_cpu(rdmdio->stride_1); 27528c2ecf20Sopenharmony_ci stride2 = le32_to_cpu(rdmdio->stride_2); 27538c2ecf20Sopenharmony_ci count = le32_to_cpu(rdmdio->count); 27548c2ecf20Sopenharmony_ci 27558c2ecf20Sopenharmony_ci mask = le32_to_cpu(rdmdio->mask); 27568c2ecf20Sopenharmony_ci value2 = le32_to_cpu(rdmdio->value_2); 27578c2ecf20Sopenharmony_ci 27588c2ecf20Sopenharmony_ci addr3 = addr1 + stride1; 27598c2ecf20Sopenharmony_ci 27608c2ecf20Sopenharmony_ci for (loop_cnt = 0; loop_cnt < count; loop_cnt++) { 27618c2ecf20Sopenharmony_ci rval = ql4_84xx_poll_wait_ipmdio_bus_idle(ha, addr1, addr2, 27628c2ecf20Sopenharmony_ci addr3, mask); 27638c2ecf20Sopenharmony_ci if (rval) 27648c2ecf20Sopenharmony_ci goto exit_process_rdmdio; 27658c2ecf20Sopenharmony_ci 27668c2ecf20Sopenharmony_ci addr4 = addr2 - stride1; 27678c2ecf20Sopenharmony_ci rval = ql4_84xx_ipmdio_wr_reg(ha, addr1, addr3, mask, addr4, 27688c2ecf20Sopenharmony_ci value2); 27698c2ecf20Sopenharmony_ci if (rval) 27708c2ecf20Sopenharmony_ci goto exit_process_rdmdio; 27718c2ecf20Sopenharmony_ci 27728c2ecf20Sopenharmony_ci addr5 = addr2 - (2 * stride1); 27738c2ecf20Sopenharmony_ci rval = ql4_84xx_ipmdio_wr_reg(ha, addr1, addr3, mask, addr5, 27748c2ecf20Sopenharmony_ci value1); 27758c2ecf20Sopenharmony_ci if (rval) 27768c2ecf20Sopenharmony_ci goto exit_process_rdmdio; 27778c2ecf20Sopenharmony_ci 27788c2ecf20Sopenharmony_ci addr6 = addr2 - (3 * stride1); 27798c2ecf20Sopenharmony_ci rval = ql4_84xx_ipmdio_wr_reg(ha, addr1, addr3, mask, 27808c2ecf20Sopenharmony_ci addr6, 0x2); 27818c2ecf20Sopenharmony_ci if (rval) 27828c2ecf20Sopenharmony_ci goto exit_process_rdmdio; 27838c2ecf20Sopenharmony_ci 27848c2ecf20Sopenharmony_ci rval = ql4_84xx_poll_wait_ipmdio_bus_idle(ha, addr1, addr2, 27858c2ecf20Sopenharmony_ci addr3, mask); 27868c2ecf20Sopenharmony_ci if (rval) 27878c2ecf20Sopenharmony_ci goto exit_process_rdmdio; 27888c2ecf20Sopenharmony_ci 27898c2ecf20Sopenharmony_ci addr7 = addr2 - (4 * stride1); 27908c2ecf20Sopenharmony_ci rval = ql4_84xx_ipmdio_rd_reg(ha, addr1, addr3, 27918c2ecf20Sopenharmony_ci mask, addr7, &data); 27928c2ecf20Sopenharmony_ci if (rval) 27938c2ecf20Sopenharmony_ci goto exit_process_rdmdio; 27948c2ecf20Sopenharmony_ci 27958c2ecf20Sopenharmony_ci selval = (value2 << 18) | (value1 << 2) | 2; 27968c2ecf20Sopenharmony_ci 27978c2ecf20Sopenharmony_ci stride2 = le32_to_cpu(rdmdio->stride_2); 27988c2ecf20Sopenharmony_ci *data_ptr++ = cpu_to_le32(selval); 27998c2ecf20Sopenharmony_ci *data_ptr++ = cpu_to_le32(data); 28008c2ecf20Sopenharmony_ci 28018c2ecf20Sopenharmony_ci value1 = value1 + stride2; 28028c2ecf20Sopenharmony_ci *d_ptr = data_ptr; 28038c2ecf20Sopenharmony_ci } 28048c2ecf20Sopenharmony_ci 28058c2ecf20Sopenharmony_ciexit_process_rdmdio: 28068c2ecf20Sopenharmony_ci return rval; 28078c2ecf20Sopenharmony_ci} 28088c2ecf20Sopenharmony_ci 28098c2ecf20Sopenharmony_cistatic uint32_t qla4_84xx_minidump_process_pollwr(struct scsi_qla_host *ha, 28108c2ecf20Sopenharmony_ci struct qla8xxx_minidump_entry_hdr *entry_hdr, 28118c2ecf20Sopenharmony_ci uint32_t **d_ptr) 28128c2ecf20Sopenharmony_ci{ 28138c2ecf20Sopenharmony_ci uint32_t addr1, addr2, value1, value2, poll, r_value; 28148c2ecf20Sopenharmony_ci struct qla8044_minidump_entry_pollwr *pollwr_hdr; 28158c2ecf20Sopenharmony_ci uint32_t wait_count = 0; 28168c2ecf20Sopenharmony_ci uint32_t rval = QLA_SUCCESS; 28178c2ecf20Sopenharmony_ci 28188c2ecf20Sopenharmony_ci pollwr_hdr = (struct qla8044_minidump_entry_pollwr *)entry_hdr; 28198c2ecf20Sopenharmony_ci addr1 = le32_to_cpu(pollwr_hdr->addr_1); 28208c2ecf20Sopenharmony_ci addr2 = le32_to_cpu(pollwr_hdr->addr_2); 28218c2ecf20Sopenharmony_ci value1 = le32_to_cpu(pollwr_hdr->value_1); 28228c2ecf20Sopenharmony_ci value2 = le32_to_cpu(pollwr_hdr->value_2); 28238c2ecf20Sopenharmony_ci 28248c2ecf20Sopenharmony_ci poll = le32_to_cpu(pollwr_hdr->poll); 28258c2ecf20Sopenharmony_ci 28268c2ecf20Sopenharmony_ci while (wait_count < poll) { 28278c2ecf20Sopenharmony_ci ha->isp_ops->rd_reg_indirect(ha, addr1, &r_value); 28288c2ecf20Sopenharmony_ci 28298c2ecf20Sopenharmony_ci if ((r_value & poll) != 0) 28308c2ecf20Sopenharmony_ci break; 28318c2ecf20Sopenharmony_ci 28328c2ecf20Sopenharmony_ci wait_count++; 28338c2ecf20Sopenharmony_ci } 28348c2ecf20Sopenharmony_ci 28358c2ecf20Sopenharmony_ci if (wait_count == poll) { 28368c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: TIMEOUT\n", __func__); 28378c2ecf20Sopenharmony_ci rval = QLA_ERROR; 28388c2ecf20Sopenharmony_ci goto exit_process_pollwr; 28398c2ecf20Sopenharmony_ci } 28408c2ecf20Sopenharmony_ci 28418c2ecf20Sopenharmony_ci ha->isp_ops->wr_reg_indirect(ha, addr2, value2); 28428c2ecf20Sopenharmony_ci ha->isp_ops->wr_reg_indirect(ha, addr1, value1); 28438c2ecf20Sopenharmony_ci 28448c2ecf20Sopenharmony_ci wait_count = 0; 28458c2ecf20Sopenharmony_ci while (wait_count < poll) { 28468c2ecf20Sopenharmony_ci ha->isp_ops->rd_reg_indirect(ha, addr1, &r_value); 28478c2ecf20Sopenharmony_ci 28488c2ecf20Sopenharmony_ci if ((r_value & poll) != 0) 28498c2ecf20Sopenharmony_ci break; 28508c2ecf20Sopenharmony_ci wait_count++; 28518c2ecf20Sopenharmony_ci } 28528c2ecf20Sopenharmony_ci 28538c2ecf20Sopenharmony_ciexit_process_pollwr: 28548c2ecf20Sopenharmony_ci return rval; 28558c2ecf20Sopenharmony_ci} 28568c2ecf20Sopenharmony_ci 28578c2ecf20Sopenharmony_cistatic void qla83xx_minidump_process_rdmux2(struct scsi_qla_host *ha, 28588c2ecf20Sopenharmony_ci struct qla8xxx_minidump_entry_hdr *entry_hdr, 28598c2ecf20Sopenharmony_ci uint32_t **d_ptr) 28608c2ecf20Sopenharmony_ci{ 28618c2ecf20Sopenharmony_ci uint32_t sel_val1, sel_val2, t_sel_val, data, i; 28628c2ecf20Sopenharmony_ci uint32_t sel_addr1, sel_addr2, sel_val_mask, read_addr; 28638c2ecf20Sopenharmony_ci struct qla83xx_minidump_entry_rdmux2 *rdmux2_hdr; 28648c2ecf20Sopenharmony_ci uint32_t *data_ptr = *d_ptr; 28658c2ecf20Sopenharmony_ci 28668c2ecf20Sopenharmony_ci rdmux2_hdr = (struct qla83xx_minidump_entry_rdmux2 *)entry_hdr; 28678c2ecf20Sopenharmony_ci sel_val1 = le32_to_cpu(rdmux2_hdr->select_value_1); 28688c2ecf20Sopenharmony_ci sel_val2 = le32_to_cpu(rdmux2_hdr->select_value_2); 28698c2ecf20Sopenharmony_ci sel_addr1 = le32_to_cpu(rdmux2_hdr->select_addr_1); 28708c2ecf20Sopenharmony_ci sel_addr2 = le32_to_cpu(rdmux2_hdr->select_addr_2); 28718c2ecf20Sopenharmony_ci sel_val_mask = le32_to_cpu(rdmux2_hdr->select_value_mask); 28728c2ecf20Sopenharmony_ci read_addr = le32_to_cpu(rdmux2_hdr->read_addr); 28738c2ecf20Sopenharmony_ci 28748c2ecf20Sopenharmony_ci for (i = 0; i < rdmux2_hdr->op_count; i++) { 28758c2ecf20Sopenharmony_ci ha->isp_ops->wr_reg_indirect(ha, sel_addr1, sel_val1); 28768c2ecf20Sopenharmony_ci t_sel_val = sel_val1 & sel_val_mask; 28778c2ecf20Sopenharmony_ci *data_ptr++ = cpu_to_le32(t_sel_val); 28788c2ecf20Sopenharmony_ci 28798c2ecf20Sopenharmony_ci ha->isp_ops->wr_reg_indirect(ha, sel_addr2, t_sel_val); 28808c2ecf20Sopenharmony_ci ha->isp_ops->rd_reg_indirect(ha, read_addr, &data); 28818c2ecf20Sopenharmony_ci 28828c2ecf20Sopenharmony_ci *data_ptr++ = cpu_to_le32(data); 28838c2ecf20Sopenharmony_ci 28848c2ecf20Sopenharmony_ci ha->isp_ops->wr_reg_indirect(ha, sel_addr1, sel_val2); 28858c2ecf20Sopenharmony_ci t_sel_val = sel_val2 & sel_val_mask; 28868c2ecf20Sopenharmony_ci *data_ptr++ = cpu_to_le32(t_sel_val); 28878c2ecf20Sopenharmony_ci 28888c2ecf20Sopenharmony_ci ha->isp_ops->wr_reg_indirect(ha, sel_addr2, t_sel_val); 28898c2ecf20Sopenharmony_ci ha->isp_ops->rd_reg_indirect(ha, read_addr, &data); 28908c2ecf20Sopenharmony_ci 28918c2ecf20Sopenharmony_ci *data_ptr++ = cpu_to_le32(data); 28928c2ecf20Sopenharmony_ci 28938c2ecf20Sopenharmony_ci sel_val1 += rdmux2_hdr->select_value_stride; 28948c2ecf20Sopenharmony_ci sel_val2 += rdmux2_hdr->select_value_stride; 28958c2ecf20Sopenharmony_ci } 28968c2ecf20Sopenharmony_ci 28978c2ecf20Sopenharmony_ci *d_ptr = data_ptr; 28988c2ecf20Sopenharmony_ci} 28998c2ecf20Sopenharmony_ci 29008c2ecf20Sopenharmony_cistatic uint32_t qla83xx_minidump_process_pollrdmwr(struct scsi_qla_host *ha, 29018c2ecf20Sopenharmony_ci struct qla8xxx_minidump_entry_hdr *entry_hdr, 29028c2ecf20Sopenharmony_ci uint32_t **d_ptr) 29038c2ecf20Sopenharmony_ci{ 29048c2ecf20Sopenharmony_ci uint32_t poll_wait, poll_mask, r_value, data; 29058c2ecf20Sopenharmony_ci uint32_t addr_1, addr_2, value_1, value_2; 29068c2ecf20Sopenharmony_ci uint32_t *data_ptr = *d_ptr; 29078c2ecf20Sopenharmony_ci uint32_t rval = QLA_SUCCESS; 29088c2ecf20Sopenharmony_ci struct qla83xx_minidump_entry_pollrdmwr *poll_hdr; 29098c2ecf20Sopenharmony_ci 29108c2ecf20Sopenharmony_ci poll_hdr = (struct qla83xx_minidump_entry_pollrdmwr *)entry_hdr; 29118c2ecf20Sopenharmony_ci addr_1 = le32_to_cpu(poll_hdr->addr_1); 29128c2ecf20Sopenharmony_ci addr_2 = le32_to_cpu(poll_hdr->addr_2); 29138c2ecf20Sopenharmony_ci value_1 = le32_to_cpu(poll_hdr->value_1); 29148c2ecf20Sopenharmony_ci value_2 = le32_to_cpu(poll_hdr->value_2); 29158c2ecf20Sopenharmony_ci poll_mask = le32_to_cpu(poll_hdr->poll_mask); 29168c2ecf20Sopenharmony_ci 29178c2ecf20Sopenharmony_ci ha->isp_ops->wr_reg_indirect(ha, addr_1, value_1); 29188c2ecf20Sopenharmony_ci 29198c2ecf20Sopenharmony_ci poll_wait = le32_to_cpu(poll_hdr->poll_wait); 29208c2ecf20Sopenharmony_ci while (1) { 29218c2ecf20Sopenharmony_ci ha->isp_ops->rd_reg_indirect(ha, addr_1, &r_value); 29228c2ecf20Sopenharmony_ci 29238c2ecf20Sopenharmony_ci if ((r_value & poll_mask) != 0) { 29248c2ecf20Sopenharmony_ci break; 29258c2ecf20Sopenharmony_ci } else { 29268c2ecf20Sopenharmony_ci msleep(1); 29278c2ecf20Sopenharmony_ci if (--poll_wait == 0) { 29288c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: TIMEOUT_1\n", 29298c2ecf20Sopenharmony_ci __func__); 29308c2ecf20Sopenharmony_ci rval = QLA_ERROR; 29318c2ecf20Sopenharmony_ci goto exit_process_pollrdmwr; 29328c2ecf20Sopenharmony_ci } 29338c2ecf20Sopenharmony_ci } 29348c2ecf20Sopenharmony_ci } 29358c2ecf20Sopenharmony_ci 29368c2ecf20Sopenharmony_ci ha->isp_ops->rd_reg_indirect(ha, addr_2, &data); 29378c2ecf20Sopenharmony_ci data &= le32_to_cpu(poll_hdr->modify_mask); 29388c2ecf20Sopenharmony_ci ha->isp_ops->wr_reg_indirect(ha, addr_2, data); 29398c2ecf20Sopenharmony_ci ha->isp_ops->wr_reg_indirect(ha, addr_1, value_2); 29408c2ecf20Sopenharmony_ci 29418c2ecf20Sopenharmony_ci poll_wait = le32_to_cpu(poll_hdr->poll_wait); 29428c2ecf20Sopenharmony_ci while (1) { 29438c2ecf20Sopenharmony_ci ha->isp_ops->rd_reg_indirect(ha, addr_1, &r_value); 29448c2ecf20Sopenharmony_ci 29458c2ecf20Sopenharmony_ci if ((r_value & poll_mask) != 0) { 29468c2ecf20Sopenharmony_ci break; 29478c2ecf20Sopenharmony_ci } else { 29488c2ecf20Sopenharmony_ci msleep(1); 29498c2ecf20Sopenharmony_ci if (--poll_wait == 0) { 29508c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: TIMEOUT_2\n", 29518c2ecf20Sopenharmony_ci __func__); 29528c2ecf20Sopenharmony_ci rval = QLA_ERROR; 29538c2ecf20Sopenharmony_ci goto exit_process_pollrdmwr; 29548c2ecf20Sopenharmony_ci } 29558c2ecf20Sopenharmony_ci } 29568c2ecf20Sopenharmony_ci } 29578c2ecf20Sopenharmony_ci 29588c2ecf20Sopenharmony_ci *data_ptr++ = cpu_to_le32(addr_2); 29598c2ecf20Sopenharmony_ci *data_ptr++ = cpu_to_le32(data); 29608c2ecf20Sopenharmony_ci *d_ptr = data_ptr; 29618c2ecf20Sopenharmony_ci 29628c2ecf20Sopenharmony_ciexit_process_pollrdmwr: 29638c2ecf20Sopenharmony_ci return rval; 29648c2ecf20Sopenharmony_ci} 29658c2ecf20Sopenharmony_ci 29668c2ecf20Sopenharmony_cistatic uint32_t qla4_83xx_minidump_process_rdrom(struct scsi_qla_host *ha, 29678c2ecf20Sopenharmony_ci struct qla8xxx_minidump_entry_hdr *entry_hdr, 29688c2ecf20Sopenharmony_ci uint32_t **d_ptr) 29698c2ecf20Sopenharmony_ci{ 29708c2ecf20Sopenharmony_ci uint32_t fl_addr, u32_count, rval; 29718c2ecf20Sopenharmony_ci struct qla8xxx_minidump_entry_rdrom *rom_hdr; 29728c2ecf20Sopenharmony_ci uint32_t *data_ptr = *d_ptr; 29738c2ecf20Sopenharmony_ci 29748c2ecf20Sopenharmony_ci rom_hdr = (struct qla8xxx_minidump_entry_rdrom *)entry_hdr; 29758c2ecf20Sopenharmony_ci fl_addr = le32_to_cpu(rom_hdr->read_addr); 29768c2ecf20Sopenharmony_ci u32_count = le32_to_cpu(rom_hdr->read_data_size)/sizeof(uint32_t); 29778c2ecf20Sopenharmony_ci 29788c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "[%s]: fl_addr: 0x%x, count: 0x%x\n", 29798c2ecf20Sopenharmony_ci __func__, fl_addr, u32_count)); 29808c2ecf20Sopenharmony_ci 29818c2ecf20Sopenharmony_ci rval = qla4_83xx_lockless_flash_read_u32(ha, fl_addr, 29828c2ecf20Sopenharmony_ci (u8 *)(data_ptr), u32_count); 29838c2ecf20Sopenharmony_ci 29848c2ecf20Sopenharmony_ci if (rval == QLA_ERROR) { 29858c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: Flash Read Error,Count=%d\n", 29868c2ecf20Sopenharmony_ci __func__, u32_count); 29878c2ecf20Sopenharmony_ci goto exit_process_rdrom; 29888c2ecf20Sopenharmony_ci } 29898c2ecf20Sopenharmony_ci 29908c2ecf20Sopenharmony_ci data_ptr += u32_count; 29918c2ecf20Sopenharmony_ci *d_ptr = data_ptr; 29928c2ecf20Sopenharmony_ci 29938c2ecf20Sopenharmony_ciexit_process_rdrom: 29948c2ecf20Sopenharmony_ci return rval; 29958c2ecf20Sopenharmony_ci} 29968c2ecf20Sopenharmony_ci 29978c2ecf20Sopenharmony_ci/** 29988c2ecf20Sopenharmony_ci * qla4_8xxx_collect_md_data - Retrieve firmware minidump data. 29998c2ecf20Sopenharmony_ci * @ha: pointer to adapter structure 30008c2ecf20Sopenharmony_ci **/ 30018c2ecf20Sopenharmony_cistatic int qla4_8xxx_collect_md_data(struct scsi_qla_host *ha) 30028c2ecf20Sopenharmony_ci{ 30038c2ecf20Sopenharmony_ci int num_entry_hdr = 0; 30048c2ecf20Sopenharmony_ci struct qla8xxx_minidump_entry_hdr *entry_hdr; 30058c2ecf20Sopenharmony_ci struct qla4_8xxx_minidump_template_hdr *tmplt_hdr; 30068c2ecf20Sopenharmony_ci uint32_t *data_ptr; 30078c2ecf20Sopenharmony_ci uint32_t data_collected = 0; 30088c2ecf20Sopenharmony_ci int i, rval = QLA_ERROR; 30098c2ecf20Sopenharmony_ci uint64_t now; 30108c2ecf20Sopenharmony_ci uint32_t timestamp; 30118c2ecf20Sopenharmony_ci 30128c2ecf20Sopenharmony_ci ha->fw_dump_skip_size = 0; 30138c2ecf20Sopenharmony_ci if (!ha->fw_dump) { 30148c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "%s(%ld) No buffer to dump\n", 30158c2ecf20Sopenharmony_ci __func__, ha->host_no); 30168c2ecf20Sopenharmony_ci return rval; 30178c2ecf20Sopenharmony_ci } 30188c2ecf20Sopenharmony_ci 30198c2ecf20Sopenharmony_ci tmplt_hdr = (struct qla4_8xxx_minidump_template_hdr *) 30208c2ecf20Sopenharmony_ci ha->fw_dump_tmplt_hdr; 30218c2ecf20Sopenharmony_ci data_ptr = (uint32_t *)((uint8_t *)ha->fw_dump + 30228c2ecf20Sopenharmony_ci ha->fw_dump_tmplt_size); 30238c2ecf20Sopenharmony_ci data_collected += ha->fw_dump_tmplt_size; 30248c2ecf20Sopenharmony_ci 30258c2ecf20Sopenharmony_ci num_entry_hdr = tmplt_hdr->num_of_entries; 30268c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "[%s]: starting data ptr: %p\n", 30278c2ecf20Sopenharmony_ci __func__, data_ptr); 30288c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, 30298c2ecf20Sopenharmony_ci "[%s]: no of entry headers in Template: 0x%x\n", 30308c2ecf20Sopenharmony_ci __func__, num_entry_hdr); 30318c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "[%s]: Capture Mask obtained: 0x%x\n", 30328c2ecf20Sopenharmony_ci __func__, ha->fw_dump_capture_mask); 30338c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "[%s]: Total_data_size 0x%x, %d obtained\n", 30348c2ecf20Sopenharmony_ci __func__, ha->fw_dump_size, ha->fw_dump_size); 30358c2ecf20Sopenharmony_ci 30368c2ecf20Sopenharmony_ci /* Update current timestamp before taking dump */ 30378c2ecf20Sopenharmony_ci now = get_jiffies_64(); 30388c2ecf20Sopenharmony_ci timestamp = (u32)(jiffies_to_msecs(now) / 1000); 30398c2ecf20Sopenharmony_ci tmplt_hdr->driver_timestamp = timestamp; 30408c2ecf20Sopenharmony_ci 30418c2ecf20Sopenharmony_ci entry_hdr = (struct qla8xxx_minidump_entry_hdr *) 30428c2ecf20Sopenharmony_ci (((uint8_t *)ha->fw_dump_tmplt_hdr) + 30438c2ecf20Sopenharmony_ci tmplt_hdr->first_entry_offset); 30448c2ecf20Sopenharmony_ci 30458c2ecf20Sopenharmony_ci if (is_qla8032(ha) || is_qla8042(ha)) 30468c2ecf20Sopenharmony_ci tmplt_hdr->saved_state_array[QLA83XX_SS_OCM_WNDREG_INDEX] = 30478c2ecf20Sopenharmony_ci tmplt_hdr->ocm_window_reg[ha->func_num]; 30488c2ecf20Sopenharmony_ci 30498c2ecf20Sopenharmony_ci /* Walk through the entry headers - validate/perform required action */ 30508c2ecf20Sopenharmony_ci for (i = 0; i < num_entry_hdr; i++) { 30518c2ecf20Sopenharmony_ci if (data_collected > ha->fw_dump_size) { 30528c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, 30538c2ecf20Sopenharmony_ci "Data collected: [0x%x], Total Dump size: [0x%x]\n", 30548c2ecf20Sopenharmony_ci data_collected, ha->fw_dump_size); 30558c2ecf20Sopenharmony_ci return rval; 30568c2ecf20Sopenharmony_ci } 30578c2ecf20Sopenharmony_ci 30588c2ecf20Sopenharmony_ci if (!(entry_hdr->d_ctrl.entry_capture_mask & 30598c2ecf20Sopenharmony_ci ha->fw_dump_capture_mask)) { 30608c2ecf20Sopenharmony_ci entry_hdr->d_ctrl.driver_flags |= 30618c2ecf20Sopenharmony_ci QLA8XXX_DBG_SKIPPED_FLAG; 30628c2ecf20Sopenharmony_ci goto skip_nxt_entry; 30638c2ecf20Sopenharmony_ci } 30648c2ecf20Sopenharmony_ci 30658c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 30668c2ecf20Sopenharmony_ci "Data collected: [0x%x], Dump size left:[0x%x]\n", 30678c2ecf20Sopenharmony_ci data_collected, 30688c2ecf20Sopenharmony_ci (ha->fw_dump_size - data_collected))); 30698c2ecf20Sopenharmony_ci 30708c2ecf20Sopenharmony_ci /* Decode the entry type and take required action to capture 30718c2ecf20Sopenharmony_ci * debug data 30728c2ecf20Sopenharmony_ci */ 30738c2ecf20Sopenharmony_ci switch (entry_hdr->entry_type) { 30748c2ecf20Sopenharmony_ci case QLA8XXX_RDEND: 30758c2ecf20Sopenharmony_ci qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i); 30768c2ecf20Sopenharmony_ci break; 30778c2ecf20Sopenharmony_ci case QLA8XXX_CNTRL: 30788c2ecf20Sopenharmony_ci rval = qla4_8xxx_minidump_process_control(ha, 30798c2ecf20Sopenharmony_ci entry_hdr); 30808c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) { 30818c2ecf20Sopenharmony_ci qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i); 30828c2ecf20Sopenharmony_ci goto md_failed; 30838c2ecf20Sopenharmony_ci } 30848c2ecf20Sopenharmony_ci break; 30858c2ecf20Sopenharmony_ci case QLA8XXX_RDCRB: 30868c2ecf20Sopenharmony_ci qla4_8xxx_minidump_process_rdcrb(ha, entry_hdr, 30878c2ecf20Sopenharmony_ci &data_ptr); 30888c2ecf20Sopenharmony_ci break; 30898c2ecf20Sopenharmony_ci case QLA8XXX_RDMEM: 30908c2ecf20Sopenharmony_ci rval = qla4_8xxx_minidump_process_rdmem(ha, entry_hdr, 30918c2ecf20Sopenharmony_ci &data_ptr); 30928c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) { 30938c2ecf20Sopenharmony_ci qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i); 30948c2ecf20Sopenharmony_ci goto md_failed; 30958c2ecf20Sopenharmony_ci } 30968c2ecf20Sopenharmony_ci break; 30978c2ecf20Sopenharmony_ci case QLA8XXX_BOARD: 30988c2ecf20Sopenharmony_ci case QLA8XXX_RDROM: 30998c2ecf20Sopenharmony_ci if (is_qla8022(ha)) { 31008c2ecf20Sopenharmony_ci qla4_82xx_minidump_process_rdrom(ha, entry_hdr, 31018c2ecf20Sopenharmony_ci &data_ptr); 31028c2ecf20Sopenharmony_ci } else if (is_qla8032(ha) || is_qla8042(ha)) { 31038c2ecf20Sopenharmony_ci rval = qla4_83xx_minidump_process_rdrom(ha, 31048c2ecf20Sopenharmony_ci entry_hdr, 31058c2ecf20Sopenharmony_ci &data_ptr); 31068c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) 31078c2ecf20Sopenharmony_ci qla4_8xxx_mark_entry_skipped(ha, 31088c2ecf20Sopenharmony_ci entry_hdr, 31098c2ecf20Sopenharmony_ci i); 31108c2ecf20Sopenharmony_ci } 31118c2ecf20Sopenharmony_ci break; 31128c2ecf20Sopenharmony_ci case QLA8XXX_L2DTG: 31138c2ecf20Sopenharmony_ci case QLA8XXX_L2ITG: 31148c2ecf20Sopenharmony_ci case QLA8XXX_L2DAT: 31158c2ecf20Sopenharmony_ci case QLA8XXX_L2INS: 31168c2ecf20Sopenharmony_ci rval = qla4_8xxx_minidump_process_l2tag(ha, entry_hdr, 31178c2ecf20Sopenharmony_ci &data_ptr); 31188c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) { 31198c2ecf20Sopenharmony_ci qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i); 31208c2ecf20Sopenharmony_ci goto md_failed; 31218c2ecf20Sopenharmony_ci } 31228c2ecf20Sopenharmony_ci break; 31238c2ecf20Sopenharmony_ci case QLA8XXX_L1DTG: 31248c2ecf20Sopenharmony_ci case QLA8XXX_L1ITG: 31258c2ecf20Sopenharmony_ci case QLA8XXX_L1DAT: 31268c2ecf20Sopenharmony_ci case QLA8XXX_L1INS: 31278c2ecf20Sopenharmony_ci qla4_8xxx_minidump_process_l1cache(ha, entry_hdr, 31288c2ecf20Sopenharmony_ci &data_ptr); 31298c2ecf20Sopenharmony_ci break; 31308c2ecf20Sopenharmony_ci case QLA8XXX_RDOCM: 31318c2ecf20Sopenharmony_ci qla4_8xxx_minidump_process_rdocm(ha, entry_hdr, 31328c2ecf20Sopenharmony_ci &data_ptr); 31338c2ecf20Sopenharmony_ci break; 31348c2ecf20Sopenharmony_ci case QLA8XXX_RDMUX: 31358c2ecf20Sopenharmony_ci qla4_8xxx_minidump_process_rdmux(ha, entry_hdr, 31368c2ecf20Sopenharmony_ci &data_ptr); 31378c2ecf20Sopenharmony_ci break; 31388c2ecf20Sopenharmony_ci case QLA8XXX_QUEUE: 31398c2ecf20Sopenharmony_ci qla4_8xxx_minidump_process_queue(ha, entry_hdr, 31408c2ecf20Sopenharmony_ci &data_ptr); 31418c2ecf20Sopenharmony_ci break; 31428c2ecf20Sopenharmony_ci case QLA83XX_POLLRD: 31438c2ecf20Sopenharmony_ci if (is_qla8022(ha)) { 31448c2ecf20Sopenharmony_ci qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i); 31458c2ecf20Sopenharmony_ci break; 31468c2ecf20Sopenharmony_ci } 31478c2ecf20Sopenharmony_ci rval = qla83xx_minidump_process_pollrd(ha, entry_hdr, 31488c2ecf20Sopenharmony_ci &data_ptr); 31498c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) 31508c2ecf20Sopenharmony_ci qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i); 31518c2ecf20Sopenharmony_ci break; 31528c2ecf20Sopenharmony_ci case QLA83XX_RDMUX2: 31538c2ecf20Sopenharmony_ci if (is_qla8022(ha)) { 31548c2ecf20Sopenharmony_ci qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i); 31558c2ecf20Sopenharmony_ci break; 31568c2ecf20Sopenharmony_ci } 31578c2ecf20Sopenharmony_ci qla83xx_minidump_process_rdmux2(ha, entry_hdr, 31588c2ecf20Sopenharmony_ci &data_ptr); 31598c2ecf20Sopenharmony_ci break; 31608c2ecf20Sopenharmony_ci case QLA83XX_POLLRDMWR: 31618c2ecf20Sopenharmony_ci if (is_qla8022(ha)) { 31628c2ecf20Sopenharmony_ci qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i); 31638c2ecf20Sopenharmony_ci break; 31648c2ecf20Sopenharmony_ci } 31658c2ecf20Sopenharmony_ci rval = qla83xx_minidump_process_pollrdmwr(ha, entry_hdr, 31668c2ecf20Sopenharmony_ci &data_ptr); 31678c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) 31688c2ecf20Sopenharmony_ci qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i); 31698c2ecf20Sopenharmony_ci break; 31708c2ecf20Sopenharmony_ci case QLA8044_RDDFE: 31718c2ecf20Sopenharmony_ci rval = qla4_84xx_minidump_process_rddfe(ha, entry_hdr, 31728c2ecf20Sopenharmony_ci &data_ptr); 31738c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) 31748c2ecf20Sopenharmony_ci qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i); 31758c2ecf20Sopenharmony_ci break; 31768c2ecf20Sopenharmony_ci case QLA8044_RDMDIO: 31778c2ecf20Sopenharmony_ci rval = qla4_84xx_minidump_process_rdmdio(ha, entry_hdr, 31788c2ecf20Sopenharmony_ci &data_ptr); 31798c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) 31808c2ecf20Sopenharmony_ci qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i); 31818c2ecf20Sopenharmony_ci break; 31828c2ecf20Sopenharmony_ci case QLA8044_POLLWR: 31838c2ecf20Sopenharmony_ci rval = qla4_84xx_minidump_process_pollwr(ha, entry_hdr, 31848c2ecf20Sopenharmony_ci &data_ptr); 31858c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) 31868c2ecf20Sopenharmony_ci qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i); 31878c2ecf20Sopenharmony_ci break; 31888c2ecf20Sopenharmony_ci case QLA8XXX_RDNOP: 31898c2ecf20Sopenharmony_ci default: 31908c2ecf20Sopenharmony_ci qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i); 31918c2ecf20Sopenharmony_ci break; 31928c2ecf20Sopenharmony_ci } 31938c2ecf20Sopenharmony_ci 31948c2ecf20Sopenharmony_ci data_collected = (uint8_t *)data_ptr - (uint8_t *)ha->fw_dump; 31958c2ecf20Sopenharmony_ciskip_nxt_entry: 31968c2ecf20Sopenharmony_ci /* next entry in the template */ 31978c2ecf20Sopenharmony_ci entry_hdr = (struct qla8xxx_minidump_entry_hdr *) 31988c2ecf20Sopenharmony_ci (((uint8_t *)entry_hdr) + 31998c2ecf20Sopenharmony_ci entry_hdr->entry_size); 32008c2ecf20Sopenharmony_ci } 32018c2ecf20Sopenharmony_ci 32028c2ecf20Sopenharmony_ci if ((data_collected + ha->fw_dump_skip_size) != ha->fw_dump_size) { 32038c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, 32048c2ecf20Sopenharmony_ci "Dump data mismatch: Data collected: [0x%x], total_data_size:[0x%x]\n", 32058c2ecf20Sopenharmony_ci data_collected, ha->fw_dump_size); 32068c2ecf20Sopenharmony_ci rval = QLA_ERROR; 32078c2ecf20Sopenharmony_ci goto md_failed; 32088c2ecf20Sopenharmony_ci } 32098c2ecf20Sopenharmony_ci 32108c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "Leaving fn: %s Last entry: 0x%x\n", 32118c2ecf20Sopenharmony_ci __func__, i)); 32128c2ecf20Sopenharmony_cimd_failed: 32138c2ecf20Sopenharmony_ci return rval; 32148c2ecf20Sopenharmony_ci} 32158c2ecf20Sopenharmony_ci 32168c2ecf20Sopenharmony_ci/** 32178c2ecf20Sopenharmony_ci * qla4_8xxx_uevent_emit - Send uevent when the firmware dump is ready. 32188c2ecf20Sopenharmony_ci * @ha: pointer to adapter structure 32198c2ecf20Sopenharmony_ci * @code: uevent code to act upon 32208c2ecf20Sopenharmony_ci **/ 32218c2ecf20Sopenharmony_cistatic void qla4_8xxx_uevent_emit(struct scsi_qla_host *ha, u32 code) 32228c2ecf20Sopenharmony_ci{ 32238c2ecf20Sopenharmony_ci char event_string[40]; 32248c2ecf20Sopenharmony_ci char *envp[] = { event_string, NULL }; 32258c2ecf20Sopenharmony_ci 32268c2ecf20Sopenharmony_ci switch (code) { 32278c2ecf20Sopenharmony_ci case QL4_UEVENT_CODE_FW_DUMP: 32288c2ecf20Sopenharmony_ci snprintf(event_string, sizeof(event_string), "FW_DUMP=%lu", 32298c2ecf20Sopenharmony_ci ha->host_no); 32308c2ecf20Sopenharmony_ci break; 32318c2ecf20Sopenharmony_ci default: 32328c2ecf20Sopenharmony_ci /*do nothing*/ 32338c2ecf20Sopenharmony_ci break; 32348c2ecf20Sopenharmony_ci } 32358c2ecf20Sopenharmony_ci 32368c2ecf20Sopenharmony_ci kobject_uevent_env(&(&ha->pdev->dev)->kobj, KOBJ_CHANGE, envp); 32378c2ecf20Sopenharmony_ci} 32388c2ecf20Sopenharmony_ci 32398c2ecf20Sopenharmony_civoid qla4_8xxx_get_minidump(struct scsi_qla_host *ha) 32408c2ecf20Sopenharmony_ci{ 32418c2ecf20Sopenharmony_ci if (ql4xenablemd && test_bit(AF_FW_RECOVERY, &ha->flags) && 32428c2ecf20Sopenharmony_ci !test_bit(AF_82XX_FW_DUMPED, &ha->flags)) { 32438c2ecf20Sopenharmony_ci if (!qla4_8xxx_collect_md_data(ha)) { 32448c2ecf20Sopenharmony_ci qla4_8xxx_uevent_emit(ha, QL4_UEVENT_CODE_FW_DUMP); 32458c2ecf20Sopenharmony_ci set_bit(AF_82XX_FW_DUMPED, &ha->flags); 32468c2ecf20Sopenharmony_ci } else { 32478c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "%s: Unable to collect minidump\n", 32488c2ecf20Sopenharmony_ci __func__); 32498c2ecf20Sopenharmony_ci } 32508c2ecf20Sopenharmony_ci } 32518c2ecf20Sopenharmony_ci} 32528c2ecf20Sopenharmony_ci 32538c2ecf20Sopenharmony_ci/** 32548c2ecf20Sopenharmony_ci * qla4_8xxx_device_bootstrap - Initialize device, set DEV_READY, start fw 32558c2ecf20Sopenharmony_ci * @ha: pointer to adapter structure 32568c2ecf20Sopenharmony_ci * 32578c2ecf20Sopenharmony_ci * Note: IDC lock must be held upon entry 32588c2ecf20Sopenharmony_ci **/ 32598c2ecf20Sopenharmony_ciint qla4_8xxx_device_bootstrap(struct scsi_qla_host *ha) 32608c2ecf20Sopenharmony_ci{ 32618c2ecf20Sopenharmony_ci int rval = QLA_ERROR; 32628c2ecf20Sopenharmony_ci int i; 32638c2ecf20Sopenharmony_ci uint32_t old_count, count; 32648c2ecf20Sopenharmony_ci int need_reset = 0; 32658c2ecf20Sopenharmony_ci 32668c2ecf20Sopenharmony_ci need_reset = ha->isp_ops->need_reset(ha); 32678c2ecf20Sopenharmony_ci 32688c2ecf20Sopenharmony_ci if (need_reset) { 32698c2ecf20Sopenharmony_ci /* We are trying to perform a recovery here. */ 32708c2ecf20Sopenharmony_ci if (test_bit(AF_FW_RECOVERY, &ha->flags)) 32718c2ecf20Sopenharmony_ci ha->isp_ops->rom_lock_recovery(ha); 32728c2ecf20Sopenharmony_ci } else { 32738c2ecf20Sopenharmony_ci old_count = qla4_8xxx_rd_direct(ha, QLA8XXX_PEG_ALIVE_COUNTER); 32748c2ecf20Sopenharmony_ci for (i = 0; i < 10; i++) { 32758c2ecf20Sopenharmony_ci msleep(200); 32768c2ecf20Sopenharmony_ci count = qla4_8xxx_rd_direct(ha, 32778c2ecf20Sopenharmony_ci QLA8XXX_PEG_ALIVE_COUNTER); 32788c2ecf20Sopenharmony_ci if (count != old_count) { 32798c2ecf20Sopenharmony_ci rval = QLA_SUCCESS; 32808c2ecf20Sopenharmony_ci goto dev_ready; 32818c2ecf20Sopenharmony_ci } 32828c2ecf20Sopenharmony_ci } 32838c2ecf20Sopenharmony_ci ha->isp_ops->rom_lock_recovery(ha); 32848c2ecf20Sopenharmony_ci } 32858c2ecf20Sopenharmony_ci 32868c2ecf20Sopenharmony_ci /* set to DEV_INITIALIZING */ 32878c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "HW State: INITIALIZING\n"); 32888c2ecf20Sopenharmony_ci qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DEV_STATE, 32898c2ecf20Sopenharmony_ci QLA8XXX_DEV_INITIALIZING); 32908c2ecf20Sopenharmony_ci 32918c2ecf20Sopenharmony_ci ha->isp_ops->idc_unlock(ha); 32928c2ecf20Sopenharmony_ci 32938c2ecf20Sopenharmony_ci if (is_qla8022(ha)) 32948c2ecf20Sopenharmony_ci qla4_8xxx_get_minidump(ha); 32958c2ecf20Sopenharmony_ci 32968c2ecf20Sopenharmony_ci rval = ha->isp_ops->restart_firmware(ha); 32978c2ecf20Sopenharmony_ci ha->isp_ops->idc_lock(ha); 32988c2ecf20Sopenharmony_ci 32998c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) { 33008c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "HW State: FAILED\n"); 33018c2ecf20Sopenharmony_ci qla4_8xxx_clear_drv_active(ha); 33028c2ecf20Sopenharmony_ci qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DEV_STATE, 33038c2ecf20Sopenharmony_ci QLA8XXX_DEV_FAILED); 33048c2ecf20Sopenharmony_ci return rval; 33058c2ecf20Sopenharmony_ci } 33068c2ecf20Sopenharmony_ci 33078c2ecf20Sopenharmony_cidev_ready: 33088c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "HW State: READY\n"); 33098c2ecf20Sopenharmony_ci qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DEV_STATE, QLA8XXX_DEV_READY); 33108c2ecf20Sopenharmony_ci 33118c2ecf20Sopenharmony_ci return rval; 33128c2ecf20Sopenharmony_ci} 33138c2ecf20Sopenharmony_ci 33148c2ecf20Sopenharmony_ci/** 33158c2ecf20Sopenharmony_ci * qla4_82xx_need_reset_handler - Code to start reset sequence 33168c2ecf20Sopenharmony_ci * @ha: pointer to adapter structure 33178c2ecf20Sopenharmony_ci * 33188c2ecf20Sopenharmony_ci * Note: IDC lock must be held upon entry 33198c2ecf20Sopenharmony_ci **/ 33208c2ecf20Sopenharmony_cistatic void 33218c2ecf20Sopenharmony_ciqla4_82xx_need_reset_handler(struct scsi_qla_host *ha) 33228c2ecf20Sopenharmony_ci{ 33238c2ecf20Sopenharmony_ci uint32_t dev_state, drv_state, drv_active; 33248c2ecf20Sopenharmony_ci uint32_t active_mask = 0xFFFFFFFF; 33258c2ecf20Sopenharmony_ci unsigned long reset_timeout; 33268c2ecf20Sopenharmony_ci 33278c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, 33288c2ecf20Sopenharmony_ci "Performing ISP error recovery\n"); 33298c2ecf20Sopenharmony_ci 33308c2ecf20Sopenharmony_ci if (test_and_clear_bit(AF_ONLINE, &ha->flags)) { 33318c2ecf20Sopenharmony_ci qla4_82xx_idc_unlock(ha); 33328c2ecf20Sopenharmony_ci ha->isp_ops->disable_intrs(ha); 33338c2ecf20Sopenharmony_ci qla4_82xx_idc_lock(ha); 33348c2ecf20Sopenharmony_ci } 33358c2ecf20Sopenharmony_ci 33368c2ecf20Sopenharmony_ci if (!test_bit(AF_8XXX_RST_OWNER, &ha->flags)) { 33378c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 33388c2ecf20Sopenharmony_ci "%s(%ld): reset acknowledged\n", 33398c2ecf20Sopenharmony_ci __func__, ha->host_no)); 33408c2ecf20Sopenharmony_ci qla4_8xxx_set_rst_ready(ha); 33418c2ecf20Sopenharmony_ci } else { 33428c2ecf20Sopenharmony_ci active_mask = (~(1 << (ha->func_num * 4))); 33438c2ecf20Sopenharmony_ci } 33448c2ecf20Sopenharmony_ci 33458c2ecf20Sopenharmony_ci /* wait for 10 seconds for reset ack from all functions */ 33468c2ecf20Sopenharmony_ci reset_timeout = jiffies + (ha->nx_reset_timeout * HZ); 33478c2ecf20Sopenharmony_ci 33488c2ecf20Sopenharmony_ci drv_state = qla4_82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE); 33498c2ecf20Sopenharmony_ci drv_active = qla4_82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); 33508c2ecf20Sopenharmony_ci 33518c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, 33528c2ecf20Sopenharmony_ci "%s(%ld): drv_state = 0x%x, drv_active = 0x%x\n", 33538c2ecf20Sopenharmony_ci __func__, ha->host_no, drv_state, drv_active); 33548c2ecf20Sopenharmony_ci 33558c2ecf20Sopenharmony_ci while (drv_state != (drv_active & active_mask)) { 33568c2ecf20Sopenharmony_ci if (time_after_eq(jiffies, reset_timeout)) { 33578c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, 33588c2ecf20Sopenharmony_ci "%s: RESET TIMEOUT! drv_state: 0x%08x, drv_active: 0x%08x\n", 33598c2ecf20Sopenharmony_ci DRIVER_NAME, drv_state, drv_active); 33608c2ecf20Sopenharmony_ci break; 33618c2ecf20Sopenharmony_ci } 33628c2ecf20Sopenharmony_ci 33638c2ecf20Sopenharmony_ci /* 33648c2ecf20Sopenharmony_ci * When reset_owner times out, check which functions 33658c2ecf20Sopenharmony_ci * acked/did not ack 33668c2ecf20Sopenharmony_ci */ 33678c2ecf20Sopenharmony_ci if (test_bit(AF_8XXX_RST_OWNER, &ha->flags)) { 33688c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, 33698c2ecf20Sopenharmony_ci "%s(%ld): drv_state = 0x%x, drv_active = 0x%x\n", 33708c2ecf20Sopenharmony_ci __func__, ha->host_no, drv_state, 33718c2ecf20Sopenharmony_ci drv_active); 33728c2ecf20Sopenharmony_ci } 33738c2ecf20Sopenharmony_ci qla4_82xx_idc_unlock(ha); 33748c2ecf20Sopenharmony_ci msleep(1000); 33758c2ecf20Sopenharmony_ci qla4_82xx_idc_lock(ha); 33768c2ecf20Sopenharmony_ci 33778c2ecf20Sopenharmony_ci drv_state = qla4_82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE); 33788c2ecf20Sopenharmony_ci drv_active = qla4_82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); 33798c2ecf20Sopenharmony_ci } 33808c2ecf20Sopenharmony_ci 33818c2ecf20Sopenharmony_ci /* Clear RESET OWNER as we are not going to use it any further */ 33828c2ecf20Sopenharmony_ci clear_bit(AF_8XXX_RST_OWNER, &ha->flags); 33838c2ecf20Sopenharmony_ci 33848c2ecf20Sopenharmony_ci dev_state = qla4_82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE); 33858c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "Device state is 0x%x = %s\n", dev_state, 33868c2ecf20Sopenharmony_ci dev_state < MAX_STATES ? qdev_state[dev_state] : "Unknown"); 33878c2ecf20Sopenharmony_ci 33888c2ecf20Sopenharmony_ci /* Force to DEV_COLD unless someone else is starting a reset */ 33898c2ecf20Sopenharmony_ci if (dev_state != QLA8XXX_DEV_INITIALIZING) { 33908c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "HW State: COLD/RE-INIT\n"); 33918c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA8XXX_DEV_COLD); 33928c2ecf20Sopenharmony_ci qla4_8xxx_set_rst_ready(ha); 33938c2ecf20Sopenharmony_ci } 33948c2ecf20Sopenharmony_ci} 33958c2ecf20Sopenharmony_ci 33968c2ecf20Sopenharmony_ci/** 33978c2ecf20Sopenharmony_ci * qla4_8xxx_need_qsnt_handler - Code to start qsnt 33988c2ecf20Sopenharmony_ci * @ha: pointer to adapter structure 33998c2ecf20Sopenharmony_ci **/ 34008c2ecf20Sopenharmony_civoid 34018c2ecf20Sopenharmony_ciqla4_8xxx_need_qsnt_handler(struct scsi_qla_host *ha) 34028c2ecf20Sopenharmony_ci{ 34038c2ecf20Sopenharmony_ci ha->isp_ops->idc_lock(ha); 34048c2ecf20Sopenharmony_ci qla4_8xxx_set_qsnt_ready(ha); 34058c2ecf20Sopenharmony_ci ha->isp_ops->idc_unlock(ha); 34068c2ecf20Sopenharmony_ci} 34078c2ecf20Sopenharmony_ci 34088c2ecf20Sopenharmony_cistatic void qla4_82xx_set_idc_ver(struct scsi_qla_host *ha) 34098c2ecf20Sopenharmony_ci{ 34108c2ecf20Sopenharmony_ci int idc_ver; 34118c2ecf20Sopenharmony_ci uint32_t drv_active; 34128c2ecf20Sopenharmony_ci 34138c2ecf20Sopenharmony_ci drv_active = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_ACTIVE); 34148c2ecf20Sopenharmony_ci if (drv_active == (1 << (ha->func_num * 4))) { 34158c2ecf20Sopenharmony_ci qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DRV_IDC_VERSION, 34168c2ecf20Sopenharmony_ci QLA82XX_IDC_VERSION); 34178c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, 34188c2ecf20Sopenharmony_ci "%s: IDC version updated to %d\n", __func__, 34198c2ecf20Sopenharmony_ci QLA82XX_IDC_VERSION); 34208c2ecf20Sopenharmony_ci } else { 34218c2ecf20Sopenharmony_ci idc_ver = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_IDC_VERSION); 34228c2ecf20Sopenharmony_ci if (QLA82XX_IDC_VERSION != idc_ver) { 34238c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, 34248c2ecf20Sopenharmony_ci "%s: qla4xxx driver IDC version %d is not compatible with IDC version %d of other drivers!\n", 34258c2ecf20Sopenharmony_ci __func__, QLA82XX_IDC_VERSION, idc_ver); 34268c2ecf20Sopenharmony_ci } 34278c2ecf20Sopenharmony_ci } 34288c2ecf20Sopenharmony_ci} 34298c2ecf20Sopenharmony_ci 34308c2ecf20Sopenharmony_cistatic int qla4_83xx_set_idc_ver(struct scsi_qla_host *ha) 34318c2ecf20Sopenharmony_ci{ 34328c2ecf20Sopenharmony_ci int idc_ver; 34338c2ecf20Sopenharmony_ci uint32_t drv_active; 34348c2ecf20Sopenharmony_ci int rval = QLA_SUCCESS; 34358c2ecf20Sopenharmony_ci 34368c2ecf20Sopenharmony_ci drv_active = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_ACTIVE); 34378c2ecf20Sopenharmony_ci if (drv_active == (1 << ha->func_num)) { 34388c2ecf20Sopenharmony_ci idc_ver = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_IDC_VERSION); 34398c2ecf20Sopenharmony_ci idc_ver &= (~0xFF); 34408c2ecf20Sopenharmony_ci idc_ver |= QLA83XX_IDC_VER_MAJ_VALUE; 34418c2ecf20Sopenharmony_ci qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DRV_IDC_VERSION, idc_ver); 34428c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, 34438c2ecf20Sopenharmony_ci "%s: IDC version updated to %d\n", __func__, 34448c2ecf20Sopenharmony_ci idc_ver); 34458c2ecf20Sopenharmony_ci } else { 34468c2ecf20Sopenharmony_ci idc_ver = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_IDC_VERSION); 34478c2ecf20Sopenharmony_ci idc_ver &= 0xFF; 34488c2ecf20Sopenharmony_ci if (QLA83XX_IDC_VER_MAJ_VALUE != idc_ver) { 34498c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, 34508c2ecf20Sopenharmony_ci "%s: qla4xxx driver IDC version %d is not compatible with IDC version %d of other drivers!\n", 34518c2ecf20Sopenharmony_ci __func__, QLA83XX_IDC_VER_MAJ_VALUE, 34528c2ecf20Sopenharmony_ci idc_ver); 34538c2ecf20Sopenharmony_ci rval = QLA_ERROR; 34548c2ecf20Sopenharmony_ci goto exit_set_idc_ver; 34558c2ecf20Sopenharmony_ci } 34568c2ecf20Sopenharmony_ci } 34578c2ecf20Sopenharmony_ci 34588c2ecf20Sopenharmony_ci /* Update IDC_MINOR_VERSION */ 34598c2ecf20Sopenharmony_ci idc_ver = qla4_83xx_rd_reg(ha, QLA83XX_CRB_IDC_VER_MINOR); 34608c2ecf20Sopenharmony_ci idc_ver &= ~(0x03 << (ha->func_num * 2)); 34618c2ecf20Sopenharmony_ci idc_ver |= (QLA83XX_IDC_VER_MIN_VALUE << (ha->func_num * 2)); 34628c2ecf20Sopenharmony_ci qla4_83xx_wr_reg(ha, QLA83XX_CRB_IDC_VER_MINOR, idc_ver); 34638c2ecf20Sopenharmony_ci 34648c2ecf20Sopenharmony_ciexit_set_idc_ver: 34658c2ecf20Sopenharmony_ci return rval; 34668c2ecf20Sopenharmony_ci} 34678c2ecf20Sopenharmony_ci 34688c2ecf20Sopenharmony_ciint qla4_8xxx_update_idc_reg(struct scsi_qla_host *ha) 34698c2ecf20Sopenharmony_ci{ 34708c2ecf20Sopenharmony_ci uint32_t drv_active; 34718c2ecf20Sopenharmony_ci int rval = QLA_SUCCESS; 34728c2ecf20Sopenharmony_ci 34738c2ecf20Sopenharmony_ci if (test_bit(AF_INIT_DONE, &ha->flags)) 34748c2ecf20Sopenharmony_ci goto exit_update_idc_reg; 34758c2ecf20Sopenharmony_ci 34768c2ecf20Sopenharmony_ci ha->isp_ops->idc_lock(ha); 34778c2ecf20Sopenharmony_ci qla4_8xxx_set_drv_active(ha); 34788c2ecf20Sopenharmony_ci 34798c2ecf20Sopenharmony_ci /* 34808c2ecf20Sopenharmony_ci * If we are the first driver to load and 34818c2ecf20Sopenharmony_ci * ql4xdontresethba is not set, clear IDC_CTRL BIT0. 34828c2ecf20Sopenharmony_ci */ 34838c2ecf20Sopenharmony_ci if (is_qla8032(ha) || is_qla8042(ha)) { 34848c2ecf20Sopenharmony_ci drv_active = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_ACTIVE); 34858c2ecf20Sopenharmony_ci if ((drv_active == (1 << ha->func_num)) && !ql4xdontresethba) 34868c2ecf20Sopenharmony_ci qla4_83xx_clear_idc_dontreset(ha); 34878c2ecf20Sopenharmony_ci } 34888c2ecf20Sopenharmony_ci 34898c2ecf20Sopenharmony_ci if (is_qla8022(ha)) { 34908c2ecf20Sopenharmony_ci qla4_82xx_set_idc_ver(ha); 34918c2ecf20Sopenharmony_ci } else if (is_qla8032(ha) || is_qla8042(ha)) { 34928c2ecf20Sopenharmony_ci rval = qla4_83xx_set_idc_ver(ha); 34938c2ecf20Sopenharmony_ci if (rval == QLA_ERROR) 34948c2ecf20Sopenharmony_ci qla4_8xxx_clear_drv_active(ha); 34958c2ecf20Sopenharmony_ci } 34968c2ecf20Sopenharmony_ci 34978c2ecf20Sopenharmony_ci ha->isp_ops->idc_unlock(ha); 34988c2ecf20Sopenharmony_ci 34998c2ecf20Sopenharmony_ciexit_update_idc_reg: 35008c2ecf20Sopenharmony_ci return rval; 35018c2ecf20Sopenharmony_ci} 35028c2ecf20Sopenharmony_ci 35038c2ecf20Sopenharmony_ci/** 35048c2ecf20Sopenharmony_ci * qla4_8xxx_device_state_handler - Adapter state machine 35058c2ecf20Sopenharmony_ci * @ha: pointer to host adapter structure. 35068c2ecf20Sopenharmony_ci * 35078c2ecf20Sopenharmony_ci * Note: IDC lock must be UNLOCKED upon entry 35088c2ecf20Sopenharmony_ci **/ 35098c2ecf20Sopenharmony_ciint qla4_8xxx_device_state_handler(struct scsi_qla_host *ha) 35108c2ecf20Sopenharmony_ci{ 35118c2ecf20Sopenharmony_ci uint32_t dev_state; 35128c2ecf20Sopenharmony_ci int rval = QLA_SUCCESS; 35138c2ecf20Sopenharmony_ci unsigned long dev_init_timeout; 35148c2ecf20Sopenharmony_ci 35158c2ecf20Sopenharmony_ci rval = qla4_8xxx_update_idc_reg(ha); 35168c2ecf20Sopenharmony_ci if (rval == QLA_ERROR) 35178c2ecf20Sopenharmony_ci goto exit_state_handler; 35188c2ecf20Sopenharmony_ci 35198c2ecf20Sopenharmony_ci dev_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DEV_STATE); 35208c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "Device state is 0x%x = %s\n", 35218c2ecf20Sopenharmony_ci dev_state, dev_state < MAX_STATES ? 35228c2ecf20Sopenharmony_ci qdev_state[dev_state] : "Unknown")); 35238c2ecf20Sopenharmony_ci 35248c2ecf20Sopenharmony_ci /* wait for 30 seconds for device to go ready */ 35258c2ecf20Sopenharmony_ci dev_init_timeout = jiffies + (ha->nx_dev_init_timeout * HZ); 35268c2ecf20Sopenharmony_ci 35278c2ecf20Sopenharmony_ci ha->isp_ops->idc_lock(ha); 35288c2ecf20Sopenharmony_ci while (1) { 35298c2ecf20Sopenharmony_ci 35308c2ecf20Sopenharmony_ci if (time_after_eq(jiffies, dev_init_timeout)) { 35318c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, 35328c2ecf20Sopenharmony_ci "%s: Device Init Failed 0x%x = %s\n", 35338c2ecf20Sopenharmony_ci DRIVER_NAME, 35348c2ecf20Sopenharmony_ci dev_state, dev_state < MAX_STATES ? 35358c2ecf20Sopenharmony_ci qdev_state[dev_state] : "Unknown"); 35368c2ecf20Sopenharmony_ci qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DEV_STATE, 35378c2ecf20Sopenharmony_ci QLA8XXX_DEV_FAILED); 35388c2ecf20Sopenharmony_ci } 35398c2ecf20Sopenharmony_ci 35408c2ecf20Sopenharmony_ci dev_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DEV_STATE); 35418c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "Device state is 0x%x = %s\n", 35428c2ecf20Sopenharmony_ci dev_state, dev_state < MAX_STATES ? 35438c2ecf20Sopenharmony_ci qdev_state[dev_state] : "Unknown"); 35448c2ecf20Sopenharmony_ci 35458c2ecf20Sopenharmony_ci /* NOTE: Make sure idc unlocked upon exit of switch statement */ 35468c2ecf20Sopenharmony_ci switch (dev_state) { 35478c2ecf20Sopenharmony_ci case QLA8XXX_DEV_READY: 35488c2ecf20Sopenharmony_ci goto exit; 35498c2ecf20Sopenharmony_ci case QLA8XXX_DEV_COLD: 35508c2ecf20Sopenharmony_ci rval = qla4_8xxx_device_bootstrap(ha); 35518c2ecf20Sopenharmony_ci goto exit; 35528c2ecf20Sopenharmony_ci case QLA8XXX_DEV_INITIALIZING: 35538c2ecf20Sopenharmony_ci ha->isp_ops->idc_unlock(ha); 35548c2ecf20Sopenharmony_ci msleep(1000); 35558c2ecf20Sopenharmony_ci ha->isp_ops->idc_lock(ha); 35568c2ecf20Sopenharmony_ci break; 35578c2ecf20Sopenharmony_ci case QLA8XXX_DEV_NEED_RESET: 35588c2ecf20Sopenharmony_ci /* 35598c2ecf20Sopenharmony_ci * For ISP8324 and ISP8042, if NEED_RESET is set by any 35608c2ecf20Sopenharmony_ci * driver, it should be honored, irrespective of 35618c2ecf20Sopenharmony_ci * IDC_CTRL DONTRESET_BIT0 35628c2ecf20Sopenharmony_ci */ 35638c2ecf20Sopenharmony_ci if (is_qla8032(ha) || is_qla8042(ha)) { 35648c2ecf20Sopenharmony_ci qla4_83xx_need_reset_handler(ha); 35658c2ecf20Sopenharmony_ci } else if (is_qla8022(ha)) { 35668c2ecf20Sopenharmony_ci if (!ql4xdontresethba) { 35678c2ecf20Sopenharmony_ci qla4_82xx_need_reset_handler(ha); 35688c2ecf20Sopenharmony_ci /* Update timeout value after need 35698c2ecf20Sopenharmony_ci * reset handler */ 35708c2ecf20Sopenharmony_ci dev_init_timeout = jiffies + 35718c2ecf20Sopenharmony_ci (ha->nx_dev_init_timeout * HZ); 35728c2ecf20Sopenharmony_ci } else { 35738c2ecf20Sopenharmony_ci ha->isp_ops->idc_unlock(ha); 35748c2ecf20Sopenharmony_ci msleep(1000); 35758c2ecf20Sopenharmony_ci ha->isp_ops->idc_lock(ha); 35768c2ecf20Sopenharmony_ci } 35778c2ecf20Sopenharmony_ci } 35788c2ecf20Sopenharmony_ci break; 35798c2ecf20Sopenharmony_ci case QLA8XXX_DEV_NEED_QUIESCENT: 35808c2ecf20Sopenharmony_ci /* idc locked/unlocked in handler */ 35818c2ecf20Sopenharmony_ci qla4_8xxx_need_qsnt_handler(ha); 35828c2ecf20Sopenharmony_ci break; 35838c2ecf20Sopenharmony_ci case QLA8XXX_DEV_QUIESCENT: 35848c2ecf20Sopenharmony_ci ha->isp_ops->idc_unlock(ha); 35858c2ecf20Sopenharmony_ci msleep(1000); 35868c2ecf20Sopenharmony_ci ha->isp_ops->idc_lock(ha); 35878c2ecf20Sopenharmony_ci break; 35888c2ecf20Sopenharmony_ci case QLA8XXX_DEV_FAILED: 35898c2ecf20Sopenharmony_ci ha->isp_ops->idc_unlock(ha); 35908c2ecf20Sopenharmony_ci qla4xxx_dead_adapter_cleanup(ha); 35918c2ecf20Sopenharmony_ci rval = QLA_ERROR; 35928c2ecf20Sopenharmony_ci ha->isp_ops->idc_lock(ha); 35938c2ecf20Sopenharmony_ci goto exit; 35948c2ecf20Sopenharmony_ci default: 35958c2ecf20Sopenharmony_ci ha->isp_ops->idc_unlock(ha); 35968c2ecf20Sopenharmony_ci qla4xxx_dead_adapter_cleanup(ha); 35978c2ecf20Sopenharmony_ci rval = QLA_ERROR; 35988c2ecf20Sopenharmony_ci ha->isp_ops->idc_lock(ha); 35998c2ecf20Sopenharmony_ci goto exit; 36008c2ecf20Sopenharmony_ci } 36018c2ecf20Sopenharmony_ci } 36028c2ecf20Sopenharmony_ciexit: 36038c2ecf20Sopenharmony_ci ha->isp_ops->idc_unlock(ha); 36048c2ecf20Sopenharmony_ciexit_state_handler: 36058c2ecf20Sopenharmony_ci return rval; 36068c2ecf20Sopenharmony_ci} 36078c2ecf20Sopenharmony_ci 36088c2ecf20Sopenharmony_ciint qla4_8xxx_load_risc(struct scsi_qla_host *ha) 36098c2ecf20Sopenharmony_ci{ 36108c2ecf20Sopenharmony_ci int retval; 36118c2ecf20Sopenharmony_ci 36128c2ecf20Sopenharmony_ci /* clear the interrupt */ 36138c2ecf20Sopenharmony_ci if (is_qla8032(ha) || is_qla8042(ha)) { 36148c2ecf20Sopenharmony_ci writel(0, &ha->qla4_83xx_reg->risc_intr); 36158c2ecf20Sopenharmony_ci readl(&ha->qla4_83xx_reg->risc_intr); 36168c2ecf20Sopenharmony_ci } else if (is_qla8022(ha)) { 36178c2ecf20Sopenharmony_ci writel(0, &ha->qla4_82xx_reg->host_int); 36188c2ecf20Sopenharmony_ci readl(&ha->qla4_82xx_reg->host_int); 36198c2ecf20Sopenharmony_ci } 36208c2ecf20Sopenharmony_ci 36218c2ecf20Sopenharmony_ci retval = qla4_8xxx_device_state_handler(ha); 36228c2ecf20Sopenharmony_ci 36238c2ecf20Sopenharmony_ci /* Initialize request and response queues. */ 36248c2ecf20Sopenharmony_ci if (retval == QLA_SUCCESS) 36258c2ecf20Sopenharmony_ci qla4xxx_init_rings(ha); 36268c2ecf20Sopenharmony_ci 36278c2ecf20Sopenharmony_ci if (retval == QLA_SUCCESS && !test_bit(AF_IRQ_ATTACHED, &ha->flags)) 36288c2ecf20Sopenharmony_ci retval = qla4xxx_request_irqs(ha); 36298c2ecf20Sopenharmony_ci 36308c2ecf20Sopenharmony_ci return retval; 36318c2ecf20Sopenharmony_ci} 36328c2ecf20Sopenharmony_ci 36338c2ecf20Sopenharmony_ci/*****************************************************************************/ 36348c2ecf20Sopenharmony_ci/* Flash Manipulation Routines */ 36358c2ecf20Sopenharmony_ci/*****************************************************************************/ 36368c2ecf20Sopenharmony_ci 36378c2ecf20Sopenharmony_ci#define OPTROM_BURST_SIZE 0x1000 36388c2ecf20Sopenharmony_ci#define OPTROM_BURST_DWORDS (OPTROM_BURST_SIZE / 4) 36398c2ecf20Sopenharmony_ci 36408c2ecf20Sopenharmony_ci#define FARX_DATA_FLAG BIT_31 36418c2ecf20Sopenharmony_ci#define FARX_ACCESS_FLASH_CONF 0x7FFD0000 36428c2ecf20Sopenharmony_ci#define FARX_ACCESS_FLASH_DATA 0x7FF00000 36438c2ecf20Sopenharmony_ci 36448c2ecf20Sopenharmony_cistatic inline uint32_t 36458c2ecf20Sopenharmony_ciflash_conf_addr(struct ql82xx_hw_data *hw, uint32_t faddr) 36468c2ecf20Sopenharmony_ci{ 36478c2ecf20Sopenharmony_ci return hw->flash_conf_off | faddr; 36488c2ecf20Sopenharmony_ci} 36498c2ecf20Sopenharmony_ci 36508c2ecf20Sopenharmony_cistatic inline uint32_t 36518c2ecf20Sopenharmony_ciflash_data_addr(struct ql82xx_hw_data *hw, uint32_t faddr) 36528c2ecf20Sopenharmony_ci{ 36538c2ecf20Sopenharmony_ci return hw->flash_data_off | faddr; 36548c2ecf20Sopenharmony_ci} 36558c2ecf20Sopenharmony_ci 36568c2ecf20Sopenharmony_cistatic uint32_t * 36578c2ecf20Sopenharmony_ciqla4_82xx_read_flash_data(struct scsi_qla_host *ha, uint32_t *dwptr, 36588c2ecf20Sopenharmony_ci uint32_t faddr, uint32_t length) 36598c2ecf20Sopenharmony_ci{ 36608c2ecf20Sopenharmony_ci uint32_t i; 36618c2ecf20Sopenharmony_ci uint32_t val; 36628c2ecf20Sopenharmony_ci int loops = 0; 36638c2ecf20Sopenharmony_ci while ((qla4_82xx_rom_lock(ha) != 0) && (loops < 50000)) { 36648c2ecf20Sopenharmony_ci udelay(100); 36658c2ecf20Sopenharmony_ci cond_resched(); 36668c2ecf20Sopenharmony_ci loops++; 36678c2ecf20Sopenharmony_ci } 36688c2ecf20Sopenharmony_ci if (loops >= 50000) { 36698c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, "ROM lock failed\n"); 36708c2ecf20Sopenharmony_ci return dwptr; 36718c2ecf20Sopenharmony_ci } 36728c2ecf20Sopenharmony_ci 36738c2ecf20Sopenharmony_ci /* Dword reads to flash. */ 36748c2ecf20Sopenharmony_ci for (i = 0; i < length/4; i++, faddr += 4) { 36758c2ecf20Sopenharmony_ci if (qla4_82xx_do_rom_fast_read(ha, faddr, &val)) { 36768c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, 36778c2ecf20Sopenharmony_ci "Do ROM fast read failed\n"); 36788c2ecf20Sopenharmony_ci goto done_read; 36798c2ecf20Sopenharmony_ci } 36808c2ecf20Sopenharmony_ci dwptr[i] = __constant_cpu_to_le32(val); 36818c2ecf20Sopenharmony_ci } 36828c2ecf20Sopenharmony_ci 36838c2ecf20Sopenharmony_cidone_read: 36848c2ecf20Sopenharmony_ci qla4_82xx_rom_unlock(ha); 36858c2ecf20Sopenharmony_ci return dwptr; 36868c2ecf20Sopenharmony_ci} 36878c2ecf20Sopenharmony_ci 36888c2ecf20Sopenharmony_ci/* 36898c2ecf20Sopenharmony_ci * Address and length are byte address 36908c2ecf20Sopenharmony_ci */ 36918c2ecf20Sopenharmony_cistatic uint8_t * 36928c2ecf20Sopenharmony_ciqla4_82xx_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf, 36938c2ecf20Sopenharmony_ci uint32_t offset, uint32_t length) 36948c2ecf20Sopenharmony_ci{ 36958c2ecf20Sopenharmony_ci qla4_82xx_read_flash_data(ha, (uint32_t *)buf, offset, length); 36968c2ecf20Sopenharmony_ci return buf; 36978c2ecf20Sopenharmony_ci} 36988c2ecf20Sopenharmony_ci 36998c2ecf20Sopenharmony_cistatic int 37008c2ecf20Sopenharmony_ciqla4_8xxx_find_flt_start(struct scsi_qla_host *ha, uint32_t *start) 37018c2ecf20Sopenharmony_ci{ 37028c2ecf20Sopenharmony_ci const char *loc, *locations[] = { "DEF", "PCI" }; 37038c2ecf20Sopenharmony_ci 37048c2ecf20Sopenharmony_ci /* 37058c2ecf20Sopenharmony_ci * FLT-location structure resides after the last PCI region. 37068c2ecf20Sopenharmony_ci */ 37078c2ecf20Sopenharmony_ci 37088c2ecf20Sopenharmony_ci /* Begin with sane defaults. */ 37098c2ecf20Sopenharmony_ci loc = locations[0]; 37108c2ecf20Sopenharmony_ci *start = FA_FLASH_LAYOUT_ADDR_82; 37118c2ecf20Sopenharmony_ci 37128c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "FLTL[%s] = 0x%x.\n", loc, *start)); 37138c2ecf20Sopenharmony_ci return QLA_SUCCESS; 37148c2ecf20Sopenharmony_ci} 37158c2ecf20Sopenharmony_ci 37168c2ecf20Sopenharmony_cistatic void 37178c2ecf20Sopenharmony_ciqla4_8xxx_get_flt_info(struct scsi_qla_host *ha, uint32_t flt_addr) 37188c2ecf20Sopenharmony_ci{ 37198c2ecf20Sopenharmony_ci const char *loc, *locations[] = { "DEF", "FLT" }; 37208c2ecf20Sopenharmony_ci uint16_t *wptr; 37218c2ecf20Sopenharmony_ci uint16_t cnt, chksum; 37228c2ecf20Sopenharmony_ci uint32_t start, status; 37238c2ecf20Sopenharmony_ci struct qla_flt_header *flt; 37248c2ecf20Sopenharmony_ci struct qla_flt_region *region; 37258c2ecf20Sopenharmony_ci struct ql82xx_hw_data *hw = &ha->hw; 37268c2ecf20Sopenharmony_ci 37278c2ecf20Sopenharmony_ci hw->flt_region_flt = flt_addr; 37288c2ecf20Sopenharmony_ci wptr = (uint16_t *)ha->request_ring; 37298c2ecf20Sopenharmony_ci flt = (struct qla_flt_header *)ha->request_ring; 37308c2ecf20Sopenharmony_ci region = (struct qla_flt_region *)&flt[1]; 37318c2ecf20Sopenharmony_ci 37328c2ecf20Sopenharmony_ci if (is_qla8022(ha)) { 37338c2ecf20Sopenharmony_ci qla4_82xx_read_optrom_data(ha, (uint8_t *)ha->request_ring, 37348c2ecf20Sopenharmony_ci flt_addr << 2, OPTROM_BURST_SIZE); 37358c2ecf20Sopenharmony_ci } else if (is_qla8032(ha) || is_qla8042(ha)) { 37368c2ecf20Sopenharmony_ci status = qla4_83xx_flash_read_u32(ha, flt_addr << 2, 37378c2ecf20Sopenharmony_ci (uint8_t *)ha->request_ring, 37388c2ecf20Sopenharmony_ci 0x400); 37398c2ecf20Sopenharmony_ci if (status != QLA_SUCCESS) 37408c2ecf20Sopenharmony_ci goto no_flash_data; 37418c2ecf20Sopenharmony_ci } 37428c2ecf20Sopenharmony_ci 37438c2ecf20Sopenharmony_ci if (*wptr == __constant_cpu_to_le16(0xffff)) 37448c2ecf20Sopenharmony_ci goto no_flash_data; 37458c2ecf20Sopenharmony_ci if (flt->version != __constant_cpu_to_le16(1)) { 37468c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "Unsupported FLT detected: " 37478c2ecf20Sopenharmony_ci "version=0x%x length=0x%x checksum=0x%x.\n", 37488c2ecf20Sopenharmony_ci le16_to_cpu(flt->version), le16_to_cpu(flt->length), 37498c2ecf20Sopenharmony_ci le16_to_cpu(flt->checksum))); 37508c2ecf20Sopenharmony_ci goto no_flash_data; 37518c2ecf20Sopenharmony_ci } 37528c2ecf20Sopenharmony_ci 37538c2ecf20Sopenharmony_ci cnt = (sizeof(struct qla_flt_header) + le16_to_cpu(flt->length)) >> 1; 37548c2ecf20Sopenharmony_ci for (chksum = 0; cnt; cnt--) 37558c2ecf20Sopenharmony_ci chksum += le16_to_cpu(*wptr++); 37568c2ecf20Sopenharmony_ci if (chksum) { 37578c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "Inconsistent FLT detected: " 37588c2ecf20Sopenharmony_ci "version=0x%x length=0x%x checksum=0x%x.\n", 37598c2ecf20Sopenharmony_ci le16_to_cpu(flt->version), le16_to_cpu(flt->length), 37608c2ecf20Sopenharmony_ci chksum)); 37618c2ecf20Sopenharmony_ci goto no_flash_data; 37628c2ecf20Sopenharmony_ci } 37638c2ecf20Sopenharmony_ci 37648c2ecf20Sopenharmony_ci loc = locations[1]; 37658c2ecf20Sopenharmony_ci cnt = le16_to_cpu(flt->length) / sizeof(struct qla_flt_region); 37668c2ecf20Sopenharmony_ci for ( ; cnt; cnt--, region++) { 37678c2ecf20Sopenharmony_ci /* Store addresses as DWORD offsets. */ 37688c2ecf20Sopenharmony_ci start = le32_to_cpu(region->start) >> 2; 37698c2ecf20Sopenharmony_ci 37708c2ecf20Sopenharmony_ci DEBUG3(ql4_printk(KERN_DEBUG, ha, "FLT[%02x]: start=0x%x " 37718c2ecf20Sopenharmony_ci "end=0x%x size=0x%x.\n", le32_to_cpu(region->code), start, 37728c2ecf20Sopenharmony_ci le32_to_cpu(region->end) >> 2, le32_to_cpu(region->size))); 37738c2ecf20Sopenharmony_ci 37748c2ecf20Sopenharmony_ci switch (le32_to_cpu(region->code) & 0xff) { 37758c2ecf20Sopenharmony_ci case FLT_REG_FDT: 37768c2ecf20Sopenharmony_ci hw->flt_region_fdt = start; 37778c2ecf20Sopenharmony_ci break; 37788c2ecf20Sopenharmony_ci case FLT_REG_BOOT_CODE_82: 37798c2ecf20Sopenharmony_ci hw->flt_region_boot = start; 37808c2ecf20Sopenharmony_ci break; 37818c2ecf20Sopenharmony_ci case FLT_REG_FW_82: 37828c2ecf20Sopenharmony_ci case FLT_REG_FW_82_1: 37838c2ecf20Sopenharmony_ci hw->flt_region_fw = start; 37848c2ecf20Sopenharmony_ci break; 37858c2ecf20Sopenharmony_ci case FLT_REG_BOOTLOAD_82: 37868c2ecf20Sopenharmony_ci hw->flt_region_bootload = start; 37878c2ecf20Sopenharmony_ci break; 37888c2ecf20Sopenharmony_ci case FLT_REG_ISCSI_PARAM: 37898c2ecf20Sopenharmony_ci hw->flt_iscsi_param = start; 37908c2ecf20Sopenharmony_ci break; 37918c2ecf20Sopenharmony_ci case FLT_REG_ISCSI_CHAP: 37928c2ecf20Sopenharmony_ci hw->flt_region_chap = start; 37938c2ecf20Sopenharmony_ci hw->flt_chap_size = le32_to_cpu(region->size); 37948c2ecf20Sopenharmony_ci break; 37958c2ecf20Sopenharmony_ci case FLT_REG_ISCSI_DDB: 37968c2ecf20Sopenharmony_ci hw->flt_region_ddb = start; 37978c2ecf20Sopenharmony_ci hw->flt_ddb_size = le32_to_cpu(region->size); 37988c2ecf20Sopenharmony_ci break; 37998c2ecf20Sopenharmony_ci } 38008c2ecf20Sopenharmony_ci } 38018c2ecf20Sopenharmony_ci goto done; 38028c2ecf20Sopenharmony_ci 38038c2ecf20Sopenharmony_cino_flash_data: 38048c2ecf20Sopenharmony_ci /* Use hardcoded defaults. */ 38058c2ecf20Sopenharmony_ci loc = locations[0]; 38068c2ecf20Sopenharmony_ci 38078c2ecf20Sopenharmony_ci hw->flt_region_fdt = FA_FLASH_DESCR_ADDR_82; 38088c2ecf20Sopenharmony_ci hw->flt_region_boot = FA_BOOT_CODE_ADDR_82; 38098c2ecf20Sopenharmony_ci hw->flt_region_bootload = FA_BOOT_LOAD_ADDR_82; 38108c2ecf20Sopenharmony_ci hw->flt_region_fw = FA_RISC_CODE_ADDR_82; 38118c2ecf20Sopenharmony_ci hw->flt_region_chap = FA_FLASH_ISCSI_CHAP >> 2; 38128c2ecf20Sopenharmony_ci hw->flt_chap_size = FA_FLASH_CHAP_SIZE; 38138c2ecf20Sopenharmony_ci hw->flt_region_ddb = FA_FLASH_ISCSI_DDB >> 2; 38148c2ecf20Sopenharmony_ci hw->flt_ddb_size = FA_FLASH_DDB_SIZE; 38158c2ecf20Sopenharmony_ci 38168c2ecf20Sopenharmony_cidone: 38178c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 38188c2ecf20Sopenharmony_ci "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", 38198c2ecf20Sopenharmony_ci loc, hw->flt_region_flt, hw->flt_region_fdt, 38208c2ecf20Sopenharmony_ci hw->flt_region_boot, hw->flt_region_bootload, 38218c2ecf20Sopenharmony_ci hw->flt_region_fw, hw->flt_region_chap, 38228c2ecf20Sopenharmony_ci hw->flt_chap_size, hw->flt_region_ddb, 38238c2ecf20Sopenharmony_ci hw->flt_ddb_size)); 38248c2ecf20Sopenharmony_ci} 38258c2ecf20Sopenharmony_ci 38268c2ecf20Sopenharmony_cistatic void 38278c2ecf20Sopenharmony_ciqla4_82xx_get_fdt_info(struct scsi_qla_host *ha) 38288c2ecf20Sopenharmony_ci{ 38298c2ecf20Sopenharmony_ci#define FLASH_BLK_SIZE_4K 0x1000 38308c2ecf20Sopenharmony_ci#define FLASH_BLK_SIZE_32K 0x8000 38318c2ecf20Sopenharmony_ci#define FLASH_BLK_SIZE_64K 0x10000 38328c2ecf20Sopenharmony_ci const char *loc, *locations[] = { "MID", "FDT" }; 38338c2ecf20Sopenharmony_ci uint16_t cnt, chksum; 38348c2ecf20Sopenharmony_ci uint16_t *wptr; 38358c2ecf20Sopenharmony_ci struct qla_fdt_layout *fdt; 38368c2ecf20Sopenharmony_ci uint16_t mid = 0; 38378c2ecf20Sopenharmony_ci uint16_t fid = 0; 38388c2ecf20Sopenharmony_ci struct ql82xx_hw_data *hw = &ha->hw; 38398c2ecf20Sopenharmony_ci 38408c2ecf20Sopenharmony_ci hw->flash_conf_off = FARX_ACCESS_FLASH_CONF; 38418c2ecf20Sopenharmony_ci hw->flash_data_off = FARX_ACCESS_FLASH_DATA; 38428c2ecf20Sopenharmony_ci 38438c2ecf20Sopenharmony_ci wptr = (uint16_t *)ha->request_ring; 38448c2ecf20Sopenharmony_ci fdt = (struct qla_fdt_layout *)ha->request_ring; 38458c2ecf20Sopenharmony_ci qla4_82xx_read_optrom_data(ha, (uint8_t *)ha->request_ring, 38468c2ecf20Sopenharmony_ci hw->flt_region_fdt << 2, OPTROM_BURST_SIZE); 38478c2ecf20Sopenharmony_ci 38488c2ecf20Sopenharmony_ci if (*wptr == __constant_cpu_to_le16(0xffff)) 38498c2ecf20Sopenharmony_ci goto no_flash_data; 38508c2ecf20Sopenharmony_ci 38518c2ecf20Sopenharmony_ci if (fdt->sig[0] != 'Q' || fdt->sig[1] != 'L' || fdt->sig[2] != 'I' || 38528c2ecf20Sopenharmony_ci fdt->sig[3] != 'D') 38538c2ecf20Sopenharmony_ci goto no_flash_data; 38548c2ecf20Sopenharmony_ci 38558c2ecf20Sopenharmony_ci for (cnt = 0, chksum = 0; cnt < sizeof(struct qla_fdt_layout) >> 1; 38568c2ecf20Sopenharmony_ci cnt++) 38578c2ecf20Sopenharmony_ci chksum += le16_to_cpu(*wptr++); 38588c2ecf20Sopenharmony_ci 38598c2ecf20Sopenharmony_ci if (chksum) { 38608c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "Inconsistent FDT detected: " 38618c2ecf20Sopenharmony_ci "checksum=0x%x id=%c version=0x%x.\n", chksum, fdt->sig[0], 38628c2ecf20Sopenharmony_ci le16_to_cpu(fdt->version))); 38638c2ecf20Sopenharmony_ci goto no_flash_data; 38648c2ecf20Sopenharmony_ci } 38658c2ecf20Sopenharmony_ci 38668c2ecf20Sopenharmony_ci loc = locations[1]; 38678c2ecf20Sopenharmony_ci mid = le16_to_cpu(fdt->man_id); 38688c2ecf20Sopenharmony_ci fid = le16_to_cpu(fdt->id); 38698c2ecf20Sopenharmony_ci hw->fdt_wrt_disable = fdt->wrt_disable_bits; 38708c2ecf20Sopenharmony_ci hw->fdt_erase_cmd = flash_conf_addr(hw, 0x0300 | fdt->erase_cmd); 38718c2ecf20Sopenharmony_ci hw->fdt_block_size = le32_to_cpu(fdt->block_size); 38728c2ecf20Sopenharmony_ci 38738c2ecf20Sopenharmony_ci if (fdt->unprotect_sec_cmd) { 38748c2ecf20Sopenharmony_ci hw->fdt_unprotect_sec_cmd = flash_conf_addr(hw, 0x0300 | 38758c2ecf20Sopenharmony_ci fdt->unprotect_sec_cmd); 38768c2ecf20Sopenharmony_ci hw->fdt_protect_sec_cmd = fdt->protect_sec_cmd ? 38778c2ecf20Sopenharmony_ci flash_conf_addr(hw, 0x0300 | fdt->protect_sec_cmd) : 38788c2ecf20Sopenharmony_ci flash_conf_addr(hw, 0x0336); 38798c2ecf20Sopenharmony_ci } 38808c2ecf20Sopenharmony_ci goto done; 38818c2ecf20Sopenharmony_ci 38828c2ecf20Sopenharmony_cino_flash_data: 38838c2ecf20Sopenharmony_ci loc = locations[0]; 38848c2ecf20Sopenharmony_ci hw->fdt_block_size = FLASH_BLK_SIZE_64K; 38858c2ecf20Sopenharmony_cidone: 38868c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "FDT[%s]: (0x%x/0x%x) erase=0x%x " 38878c2ecf20Sopenharmony_ci "pro=%x upro=%x wrtd=0x%x blk=0x%x.\n", loc, mid, fid, 38888c2ecf20Sopenharmony_ci hw->fdt_erase_cmd, hw->fdt_protect_sec_cmd, 38898c2ecf20Sopenharmony_ci hw->fdt_unprotect_sec_cmd, hw->fdt_wrt_disable, 38908c2ecf20Sopenharmony_ci hw->fdt_block_size)); 38918c2ecf20Sopenharmony_ci} 38928c2ecf20Sopenharmony_ci 38938c2ecf20Sopenharmony_cistatic void 38948c2ecf20Sopenharmony_ciqla4_82xx_get_idc_param(struct scsi_qla_host *ha) 38958c2ecf20Sopenharmony_ci{ 38968c2ecf20Sopenharmony_ci#define QLA82XX_IDC_PARAM_ADDR 0x003e885c 38978c2ecf20Sopenharmony_ci uint32_t *wptr; 38988c2ecf20Sopenharmony_ci 38998c2ecf20Sopenharmony_ci if (!is_qla8022(ha)) 39008c2ecf20Sopenharmony_ci return; 39018c2ecf20Sopenharmony_ci wptr = (uint32_t *)ha->request_ring; 39028c2ecf20Sopenharmony_ci qla4_82xx_read_optrom_data(ha, (uint8_t *)ha->request_ring, 39038c2ecf20Sopenharmony_ci QLA82XX_IDC_PARAM_ADDR , 8); 39048c2ecf20Sopenharmony_ci 39058c2ecf20Sopenharmony_ci if (*wptr == __constant_cpu_to_le32(0xffffffff)) { 39068c2ecf20Sopenharmony_ci ha->nx_dev_init_timeout = ROM_DEV_INIT_TIMEOUT; 39078c2ecf20Sopenharmony_ci ha->nx_reset_timeout = ROM_DRV_RESET_ACK_TIMEOUT; 39088c2ecf20Sopenharmony_ci } else { 39098c2ecf20Sopenharmony_ci ha->nx_dev_init_timeout = le32_to_cpu(*wptr++); 39108c2ecf20Sopenharmony_ci ha->nx_reset_timeout = le32_to_cpu(*wptr); 39118c2ecf20Sopenharmony_ci } 39128c2ecf20Sopenharmony_ci 39138c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_DEBUG, ha, 39148c2ecf20Sopenharmony_ci "ha->nx_dev_init_timeout = %d\n", ha->nx_dev_init_timeout)); 39158c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_DEBUG, ha, 39168c2ecf20Sopenharmony_ci "ha->nx_reset_timeout = %d\n", ha->nx_reset_timeout)); 39178c2ecf20Sopenharmony_ci return; 39188c2ecf20Sopenharmony_ci} 39198c2ecf20Sopenharmony_ci 39208c2ecf20Sopenharmony_civoid qla4_82xx_queue_mbox_cmd(struct scsi_qla_host *ha, uint32_t *mbx_cmd, 39218c2ecf20Sopenharmony_ci int in_count) 39228c2ecf20Sopenharmony_ci{ 39238c2ecf20Sopenharmony_ci int i; 39248c2ecf20Sopenharmony_ci 39258c2ecf20Sopenharmony_ci /* Load all mailbox registers, except mailbox 0. */ 39268c2ecf20Sopenharmony_ci for (i = 1; i < in_count; i++) 39278c2ecf20Sopenharmony_ci writel(mbx_cmd[i], &ha->qla4_82xx_reg->mailbox_in[i]); 39288c2ecf20Sopenharmony_ci 39298c2ecf20Sopenharmony_ci /* Wakeup firmware */ 39308c2ecf20Sopenharmony_ci writel(mbx_cmd[0], &ha->qla4_82xx_reg->mailbox_in[0]); 39318c2ecf20Sopenharmony_ci readl(&ha->qla4_82xx_reg->mailbox_in[0]); 39328c2ecf20Sopenharmony_ci writel(HINT_MBX_INT_PENDING, &ha->qla4_82xx_reg->hint); 39338c2ecf20Sopenharmony_ci readl(&ha->qla4_82xx_reg->hint); 39348c2ecf20Sopenharmony_ci} 39358c2ecf20Sopenharmony_ci 39368c2ecf20Sopenharmony_civoid qla4_82xx_process_mbox_intr(struct scsi_qla_host *ha, int out_count) 39378c2ecf20Sopenharmony_ci{ 39388c2ecf20Sopenharmony_ci int intr_status; 39398c2ecf20Sopenharmony_ci 39408c2ecf20Sopenharmony_ci intr_status = readl(&ha->qla4_82xx_reg->host_int); 39418c2ecf20Sopenharmony_ci if (intr_status & ISRX_82XX_RISC_INT) { 39428c2ecf20Sopenharmony_ci ha->mbox_status_count = out_count; 39438c2ecf20Sopenharmony_ci intr_status = readl(&ha->qla4_82xx_reg->host_status); 39448c2ecf20Sopenharmony_ci ha->isp_ops->interrupt_service_routine(ha, intr_status); 39458c2ecf20Sopenharmony_ci 39468c2ecf20Sopenharmony_ci if (test_bit(AF_INTERRUPTS_ON, &ha->flags) && 39478c2ecf20Sopenharmony_ci (!ha->pdev->msi_enabled && !ha->pdev->msix_enabled)) 39488c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 39498c2ecf20Sopenharmony_ci 0xfbff); 39508c2ecf20Sopenharmony_ci } 39518c2ecf20Sopenharmony_ci} 39528c2ecf20Sopenharmony_ci 39538c2ecf20Sopenharmony_ciint 39548c2ecf20Sopenharmony_ciqla4_8xxx_get_flash_info(struct scsi_qla_host *ha) 39558c2ecf20Sopenharmony_ci{ 39568c2ecf20Sopenharmony_ci int ret; 39578c2ecf20Sopenharmony_ci uint32_t flt_addr; 39588c2ecf20Sopenharmony_ci 39598c2ecf20Sopenharmony_ci ret = qla4_8xxx_find_flt_start(ha, &flt_addr); 39608c2ecf20Sopenharmony_ci if (ret != QLA_SUCCESS) 39618c2ecf20Sopenharmony_ci return ret; 39628c2ecf20Sopenharmony_ci 39638c2ecf20Sopenharmony_ci qla4_8xxx_get_flt_info(ha, flt_addr); 39648c2ecf20Sopenharmony_ci if (is_qla8022(ha)) { 39658c2ecf20Sopenharmony_ci qla4_82xx_get_fdt_info(ha); 39668c2ecf20Sopenharmony_ci qla4_82xx_get_idc_param(ha); 39678c2ecf20Sopenharmony_ci } else if (is_qla8032(ha) || is_qla8042(ha)) { 39688c2ecf20Sopenharmony_ci qla4_83xx_get_idc_param(ha); 39698c2ecf20Sopenharmony_ci } 39708c2ecf20Sopenharmony_ci 39718c2ecf20Sopenharmony_ci return QLA_SUCCESS; 39728c2ecf20Sopenharmony_ci} 39738c2ecf20Sopenharmony_ci 39748c2ecf20Sopenharmony_ci/** 39758c2ecf20Sopenharmony_ci * qla4_8xxx_stop_firmware - stops firmware on specified adapter instance 39768c2ecf20Sopenharmony_ci * @ha: pointer to host adapter structure. 39778c2ecf20Sopenharmony_ci * 39788c2ecf20Sopenharmony_ci * Remarks: 39798c2ecf20Sopenharmony_ci * For iSCSI, throws away all I/O and AENs into bit bucket, so they will 39808c2ecf20Sopenharmony_ci * not be available after successful return. Driver must cleanup potential 39818c2ecf20Sopenharmony_ci * outstanding I/O's after calling this funcion. 39828c2ecf20Sopenharmony_ci **/ 39838c2ecf20Sopenharmony_ciint 39848c2ecf20Sopenharmony_ciqla4_8xxx_stop_firmware(struct scsi_qla_host *ha) 39858c2ecf20Sopenharmony_ci{ 39868c2ecf20Sopenharmony_ci int status; 39878c2ecf20Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 39888c2ecf20Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 39898c2ecf20Sopenharmony_ci 39908c2ecf20Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 39918c2ecf20Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 39928c2ecf20Sopenharmony_ci 39938c2ecf20Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_STOP_FW; 39948c2ecf20Sopenharmony_ci status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, 39958c2ecf20Sopenharmony_ci &mbox_cmd[0], &mbox_sts[0]); 39968c2ecf20Sopenharmony_ci 39978c2ecf20Sopenharmony_ci DEBUG2(printk("scsi%ld: %s: status = %d\n", ha->host_no, 39988c2ecf20Sopenharmony_ci __func__, status)); 39998c2ecf20Sopenharmony_ci return status; 40008c2ecf20Sopenharmony_ci} 40018c2ecf20Sopenharmony_ci 40028c2ecf20Sopenharmony_ci/** 40038c2ecf20Sopenharmony_ci * qla4_82xx_isp_reset - Resets ISP and aborts all outstanding commands. 40048c2ecf20Sopenharmony_ci * @ha: pointer to host adapter structure. 40058c2ecf20Sopenharmony_ci **/ 40068c2ecf20Sopenharmony_ciint 40078c2ecf20Sopenharmony_ciqla4_82xx_isp_reset(struct scsi_qla_host *ha) 40088c2ecf20Sopenharmony_ci{ 40098c2ecf20Sopenharmony_ci int rval; 40108c2ecf20Sopenharmony_ci uint32_t dev_state; 40118c2ecf20Sopenharmony_ci 40128c2ecf20Sopenharmony_ci qla4_82xx_idc_lock(ha); 40138c2ecf20Sopenharmony_ci dev_state = qla4_82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE); 40148c2ecf20Sopenharmony_ci 40158c2ecf20Sopenharmony_ci if (dev_state == QLA8XXX_DEV_READY) { 40168c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "HW State: NEED RESET\n"); 40178c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, 40188c2ecf20Sopenharmony_ci QLA8XXX_DEV_NEED_RESET); 40198c2ecf20Sopenharmony_ci set_bit(AF_8XXX_RST_OWNER, &ha->flags); 40208c2ecf20Sopenharmony_ci } else 40218c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "HW State: DEVICE INITIALIZING\n"); 40228c2ecf20Sopenharmony_ci 40238c2ecf20Sopenharmony_ci qla4_82xx_idc_unlock(ha); 40248c2ecf20Sopenharmony_ci 40258c2ecf20Sopenharmony_ci rval = qla4_8xxx_device_state_handler(ha); 40268c2ecf20Sopenharmony_ci 40278c2ecf20Sopenharmony_ci qla4_82xx_idc_lock(ha); 40288c2ecf20Sopenharmony_ci qla4_8xxx_clear_rst_ready(ha); 40298c2ecf20Sopenharmony_ci qla4_82xx_idc_unlock(ha); 40308c2ecf20Sopenharmony_ci 40318c2ecf20Sopenharmony_ci if (rval == QLA_SUCCESS) { 40328c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "Clearing AF_RECOVERY in qla4_82xx_isp_reset\n"); 40338c2ecf20Sopenharmony_ci clear_bit(AF_FW_RECOVERY, &ha->flags); 40348c2ecf20Sopenharmony_ci } 40358c2ecf20Sopenharmony_ci 40368c2ecf20Sopenharmony_ci return rval; 40378c2ecf20Sopenharmony_ci} 40388c2ecf20Sopenharmony_ci 40398c2ecf20Sopenharmony_ci/** 40408c2ecf20Sopenharmony_ci * qla4_8xxx_get_sys_info - get adapter MAC address(es) and serial number 40418c2ecf20Sopenharmony_ci * @ha: pointer to host adapter structure. 40428c2ecf20Sopenharmony_ci * 40438c2ecf20Sopenharmony_ci **/ 40448c2ecf20Sopenharmony_ciint qla4_8xxx_get_sys_info(struct scsi_qla_host *ha) 40458c2ecf20Sopenharmony_ci{ 40468c2ecf20Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 40478c2ecf20Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 40488c2ecf20Sopenharmony_ci struct mbx_sys_info *sys_info; 40498c2ecf20Sopenharmony_ci dma_addr_t sys_info_dma; 40508c2ecf20Sopenharmony_ci int status = QLA_ERROR; 40518c2ecf20Sopenharmony_ci 40528c2ecf20Sopenharmony_ci sys_info = dma_alloc_coherent(&ha->pdev->dev, sizeof(*sys_info), 40538c2ecf20Sopenharmony_ci &sys_info_dma, GFP_KERNEL); 40548c2ecf20Sopenharmony_ci if (sys_info == NULL) { 40558c2ecf20Sopenharmony_ci DEBUG2(printk("scsi%ld: %s: Unable to allocate dma buffer.\n", 40568c2ecf20Sopenharmony_ci ha->host_no, __func__)); 40578c2ecf20Sopenharmony_ci return status; 40588c2ecf20Sopenharmony_ci } 40598c2ecf20Sopenharmony_ci 40608c2ecf20Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 40618c2ecf20Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 40628c2ecf20Sopenharmony_ci 40638c2ecf20Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_GET_SYS_INFO; 40648c2ecf20Sopenharmony_ci mbox_cmd[1] = LSDW(sys_info_dma); 40658c2ecf20Sopenharmony_ci mbox_cmd[2] = MSDW(sys_info_dma); 40668c2ecf20Sopenharmony_ci mbox_cmd[4] = sizeof(*sys_info); 40678c2ecf20Sopenharmony_ci 40688c2ecf20Sopenharmony_ci if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 6, &mbox_cmd[0], 40698c2ecf20Sopenharmony_ci &mbox_sts[0]) != QLA_SUCCESS) { 40708c2ecf20Sopenharmony_ci DEBUG2(printk("scsi%ld: %s: GET_SYS_INFO failed\n", 40718c2ecf20Sopenharmony_ci ha->host_no, __func__)); 40728c2ecf20Sopenharmony_ci goto exit_validate_mac82; 40738c2ecf20Sopenharmony_ci } 40748c2ecf20Sopenharmony_ci 40758c2ecf20Sopenharmony_ci /* Make sure we receive the minimum required data to cache internally */ 40768c2ecf20Sopenharmony_ci if (((is_qla8032(ha) || is_qla8042(ha)) ? mbox_sts[3] : mbox_sts[4]) < 40778c2ecf20Sopenharmony_ci offsetof(struct mbx_sys_info, reserved)) { 40788c2ecf20Sopenharmony_ci DEBUG2(printk("scsi%ld: %s: GET_SYS_INFO data receive" 40798c2ecf20Sopenharmony_ci " error (%x)\n", ha->host_no, __func__, mbox_sts[4])); 40808c2ecf20Sopenharmony_ci goto exit_validate_mac82; 40818c2ecf20Sopenharmony_ci } 40828c2ecf20Sopenharmony_ci 40838c2ecf20Sopenharmony_ci /* Save M.A.C. address & serial_number */ 40848c2ecf20Sopenharmony_ci ha->port_num = sys_info->port_num; 40858c2ecf20Sopenharmony_ci memcpy(ha->my_mac, &sys_info->mac_addr[0], 40868c2ecf20Sopenharmony_ci min(sizeof(ha->my_mac), sizeof(sys_info->mac_addr))); 40878c2ecf20Sopenharmony_ci memcpy(ha->serial_number, &sys_info->serial_number, 40888c2ecf20Sopenharmony_ci min(sizeof(ha->serial_number), sizeof(sys_info->serial_number))); 40898c2ecf20Sopenharmony_ci memcpy(ha->model_name, &sys_info->board_id_str, 40908c2ecf20Sopenharmony_ci min(sizeof(ha->model_name), sizeof(sys_info->board_id_str))); 40918c2ecf20Sopenharmony_ci ha->phy_port_cnt = sys_info->phys_port_cnt; 40928c2ecf20Sopenharmony_ci ha->phy_port_num = sys_info->port_num; 40938c2ecf20Sopenharmony_ci ha->iscsi_pci_func_cnt = sys_info->iscsi_pci_func_cnt; 40948c2ecf20Sopenharmony_ci 40958c2ecf20Sopenharmony_ci DEBUG2(printk("scsi%ld: %s: mac %pM serial %s\n", 40968c2ecf20Sopenharmony_ci ha->host_no, __func__, ha->my_mac, ha->serial_number)); 40978c2ecf20Sopenharmony_ci 40988c2ecf20Sopenharmony_ci status = QLA_SUCCESS; 40998c2ecf20Sopenharmony_ci 41008c2ecf20Sopenharmony_ciexit_validate_mac82: 41018c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, sizeof(*sys_info), sys_info, 41028c2ecf20Sopenharmony_ci sys_info_dma); 41038c2ecf20Sopenharmony_ci return status; 41048c2ecf20Sopenharmony_ci} 41058c2ecf20Sopenharmony_ci 41068c2ecf20Sopenharmony_ci/* Interrupt handling helpers. */ 41078c2ecf20Sopenharmony_ci 41088c2ecf20Sopenharmony_ciint qla4_8xxx_intr_enable(struct scsi_qla_host *ha) 41098c2ecf20Sopenharmony_ci{ 41108c2ecf20Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 41118c2ecf20Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 41128c2ecf20Sopenharmony_ci 41138c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "%s\n", __func__)); 41148c2ecf20Sopenharmony_ci 41158c2ecf20Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 41168c2ecf20Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 41178c2ecf20Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_ENABLE_INTRS; 41188c2ecf20Sopenharmony_ci mbox_cmd[1] = INTR_ENABLE; 41198c2ecf20Sopenharmony_ci if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], 41208c2ecf20Sopenharmony_ci &mbox_sts[0]) != QLA_SUCCESS) { 41218c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 41228c2ecf20Sopenharmony_ci "%s: MBOX_CMD_ENABLE_INTRS failed (0x%04x)\n", 41238c2ecf20Sopenharmony_ci __func__, mbox_sts[0])); 41248c2ecf20Sopenharmony_ci return QLA_ERROR; 41258c2ecf20Sopenharmony_ci } 41268c2ecf20Sopenharmony_ci return QLA_SUCCESS; 41278c2ecf20Sopenharmony_ci} 41288c2ecf20Sopenharmony_ci 41298c2ecf20Sopenharmony_ciint qla4_8xxx_intr_disable(struct scsi_qla_host *ha) 41308c2ecf20Sopenharmony_ci{ 41318c2ecf20Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 41328c2ecf20Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 41338c2ecf20Sopenharmony_ci 41348c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "%s\n", __func__)); 41358c2ecf20Sopenharmony_ci 41368c2ecf20Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 41378c2ecf20Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 41388c2ecf20Sopenharmony_ci mbox_cmd[0] = MBOX_CMD_ENABLE_INTRS; 41398c2ecf20Sopenharmony_ci mbox_cmd[1] = INTR_DISABLE; 41408c2ecf20Sopenharmony_ci if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], 41418c2ecf20Sopenharmony_ci &mbox_sts[0]) != QLA_SUCCESS) { 41428c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 41438c2ecf20Sopenharmony_ci "%s: MBOX_CMD_ENABLE_INTRS failed (0x%04x)\n", 41448c2ecf20Sopenharmony_ci __func__, mbox_sts[0])); 41458c2ecf20Sopenharmony_ci return QLA_ERROR; 41468c2ecf20Sopenharmony_ci } 41478c2ecf20Sopenharmony_ci 41488c2ecf20Sopenharmony_ci return QLA_SUCCESS; 41498c2ecf20Sopenharmony_ci} 41508c2ecf20Sopenharmony_ci 41518c2ecf20Sopenharmony_civoid 41528c2ecf20Sopenharmony_ciqla4_82xx_enable_intrs(struct scsi_qla_host *ha) 41538c2ecf20Sopenharmony_ci{ 41548c2ecf20Sopenharmony_ci qla4_8xxx_intr_enable(ha); 41558c2ecf20Sopenharmony_ci 41568c2ecf20Sopenharmony_ci spin_lock_irq(&ha->hardware_lock); 41578c2ecf20Sopenharmony_ci /* BIT 10 - reset */ 41588c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 0xfbff); 41598c2ecf20Sopenharmony_ci spin_unlock_irq(&ha->hardware_lock); 41608c2ecf20Sopenharmony_ci set_bit(AF_INTERRUPTS_ON, &ha->flags); 41618c2ecf20Sopenharmony_ci} 41628c2ecf20Sopenharmony_ci 41638c2ecf20Sopenharmony_civoid 41648c2ecf20Sopenharmony_ciqla4_82xx_disable_intrs(struct scsi_qla_host *ha) 41658c2ecf20Sopenharmony_ci{ 41668c2ecf20Sopenharmony_ci if (test_and_clear_bit(AF_INTERRUPTS_ON, &ha->flags)) 41678c2ecf20Sopenharmony_ci qla4_8xxx_intr_disable(ha); 41688c2ecf20Sopenharmony_ci 41698c2ecf20Sopenharmony_ci spin_lock_irq(&ha->hardware_lock); 41708c2ecf20Sopenharmony_ci /* BIT 10 - set */ 41718c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 0x0400); 41728c2ecf20Sopenharmony_ci spin_unlock_irq(&ha->hardware_lock); 41738c2ecf20Sopenharmony_ci} 41748c2ecf20Sopenharmony_ci 41758c2ecf20Sopenharmony_ciint 41768c2ecf20Sopenharmony_ciqla4_8xxx_enable_msix(struct scsi_qla_host *ha) 41778c2ecf20Sopenharmony_ci{ 41788c2ecf20Sopenharmony_ci int ret; 41798c2ecf20Sopenharmony_ci 41808c2ecf20Sopenharmony_ci ret = pci_alloc_irq_vectors(ha->pdev, QLA_MSIX_ENTRIES, 41818c2ecf20Sopenharmony_ci QLA_MSIX_ENTRIES, PCI_IRQ_MSIX); 41828c2ecf20Sopenharmony_ci if (ret < 0) { 41838c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, 41848c2ecf20Sopenharmony_ci "MSI-X: Failed to enable support -- %d/%d\n", 41858c2ecf20Sopenharmony_ci QLA_MSIX_ENTRIES, ret); 41868c2ecf20Sopenharmony_ci return ret; 41878c2ecf20Sopenharmony_ci } 41888c2ecf20Sopenharmony_ci 41898c2ecf20Sopenharmony_ci ret = request_irq(pci_irq_vector(ha->pdev, 0), 41908c2ecf20Sopenharmony_ci qla4_8xxx_default_intr_handler, 0, "qla4xxx (default)", 41918c2ecf20Sopenharmony_ci ha); 41928c2ecf20Sopenharmony_ci if (ret) 41938c2ecf20Sopenharmony_ci goto out_free_vectors; 41948c2ecf20Sopenharmony_ci 41958c2ecf20Sopenharmony_ci ret = request_irq(pci_irq_vector(ha->pdev, 1), 41968c2ecf20Sopenharmony_ci qla4_8xxx_msix_rsp_q, 0, "qla4xxx (rsp_q)", ha); 41978c2ecf20Sopenharmony_ci if (ret) 41988c2ecf20Sopenharmony_ci goto out_free_default_irq; 41998c2ecf20Sopenharmony_ci 42008c2ecf20Sopenharmony_ci return 0; 42018c2ecf20Sopenharmony_ci 42028c2ecf20Sopenharmony_ciout_free_default_irq: 42038c2ecf20Sopenharmony_ci free_irq(pci_irq_vector(ha->pdev, 0), ha); 42048c2ecf20Sopenharmony_ciout_free_vectors: 42058c2ecf20Sopenharmony_ci pci_free_irq_vectors(ha->pdev); 42068c2ecf20Sopenharmony_ci return ret; 42078c2ecf20Sopenharmony_ci} 42088c2ecf20Sopenharmony_ci 42098c2ecf20Sopenharmony_ciint qla4_8xxx_check_init_adapter_retry(struct scsi_qla_host *ha) 42108c2ecf20Sopenharmony_ci{ 42118c2ecf20Sopenharmony_ci int status = QLA_SUCCESS; 42128c2ecf20Sopenharmony_ci 42138c2ecf20Sopenharmony_ci /* Dont retry adapter initialization if IRQ allocation failed */ 42148c2ecf20Sopenharmony_ci if (!test_bit(AF_IRQ_ATTACHED, &ha->flags)) { 42158c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, "%s: Skipping retry of adapter initialization as IRQs are not attached\n", 42168c2ecf20Sopenharmony_ci __func__); 42178c2ecf20Sopenharmony_ci status = QLA_ERROR; 42188c2ecf20Sopenharmony_ci goto exit_init_adapter_failure; 42198c2ecf20Sopenharmony_ci } 42208c2ecf20Sopenharmony_ci 42218c2ecf20Sopenharmony_ci /* Since interrupts are registered in start_firmware for 42228c2ecf20Sopenharmony_ci * 8xxx, release them here if initialize_adapter fails 42238c2ecf20Sopenharmony_ci * and retry adapter initialization */ 42248c2ecf20Sopenharmony_ci qla4xxx_free_irqs(ha); 42258c2ecf20Sopenharmony_ci 42268c2ecf20Sopenharmony_ciexit_init_adapter_failure: 42278c2ecf20Sopenharmony_ci return status; 42288c2ecf20Sopenharmony_ci} 4229