11da177e4SLinus Torvalds /* 2fa90c54fSAndrew Vasquez * QLogic Fibre Channel HBA Driver 301e58d8eSAndrew Vasquez * Copyright (c) 2003-2008 QLogic Corporation 41da177e4SLinus Torvalds * 5fa90c54fSAndrew Vasquez * See LICENSE.qla2xxx for copyright and licensing details. 61da177e4SLinus Torvalds */ 71da177e4SLinus Torvalds #include "qla_def.h" 81da177e4SLinus Torvalds 91da177e4SLinus Torvalds #include <linux/delay.h> 101da177e4SLinus Torvalds 11a7a167bfSAndrew Vasquez static inline void 12*7b867cf7SAnirban Chakraborty qla2xxx_prep_dump(struct qla_hw_data *ha, struct qla2xxx_fw_dump *fw_dump) 13a7a167bfSAndrew Vasquez { 14a7a167bfSAndrew Vasquez fw_dump->fw_major_version = htonl(ha->fw_major_version); 15a7a167bfSAndrew Vasquez fw_dump->fw_minor_version = htonl(ha->fw_minor_version); 16a7a167bfSAndrew Vasquez fw_dump->fw_subminor_version = htonl(ha->fw_subminor_version); 17a7a167bfSAndrew Vasquez fw_dump->fw_attributes = htonl(ha->fw_attributes); 18a7a167bfSAndrew Vasquez 19a7a167bfSAndrew Vasquez fw_dump->vendor = htonl(ha->pdev->vendor); 20a7a167bfSAndrew Vasquez fw_dump->device = htonl(ha->pdev->device); 21a7a167bfSAndrew Vasquez fw_dump->subsystem_vendor = htonl(ha->pdev->subsystem_vendor); 22a7a167bfSAndrew Vasquez fw_dump->subsystem_device = htonl(ha->pdev->subsystem_device); 23a7a167bfSAndrew Vasquez } 24a7a167bfSAndrew Vasquez 25a7a167bfSAndrew Vasquez static inline void * 26*7b867cf7SAnirban Chakraborty qla2xxx_copy_queues(scsi_qla_host_t *vha, void *ptr) 27a7a167bfSAndrew Vasquez { 28*7b867cf7SAnirban Chakraborty struct req_que *req = vha->hw->req; 29*7b867cf7SAnirban Chakraborty struct rsp_que *rsp = vha->hw->rsp; 30*7b867cf7SAnirban Chakraborty 31a7a167bfSAndrew Vasquez /* Request queue. */ 32*7b867cf7SAnirban Chakraborty memcpy(ptr, req->ring, req->length * 33a7a167bfSAndrew Vasquez sizeof(request_t)); 34a7a167bfSAndrew Vasquez 35a7a167bfSAndrew Vasquez /* Response queue. */ 36*7b867cf7SAnirban Chakraborty ptr += req->length * sizeof(request_t); 37*7b867cf7SAnirban Chakraborty memcpy(ptr, rsp->ring, rsp->length * 38a7a167bfSAndrew Vasquez sizeof(response_t)); 39a7a167bfSAndrew Vasquez 40*7b867cf7SAnirban Chakraborty return ptr + (rsp->length * sizeof(response_t)); 41a7a167bfSAndrew Vasquez } 421da177e4SLinus Torvalds 43c3a2f0dfSAndrew Vasquez static int 44*7b867cf7SAnirban Chakraborty qla24xx_dump_ram(struct qla_hw_data *ha, uint32_t addr, uint32_t *ram, 45c5722708SAndrew Vasquez uint32_t ram_dwords, void **nxt) 46c3a2f0dfSAndrew Vasquez { 47c3a2f0dfSAndrew Vasquez int rval; 48c5722708SAndrew Vasquez uint32_t cnt, stat, timer, dwords, idx; 49c5722708SAndrew Vasquez uint16_t mb0; 50c3a2f0dfSAndrew Vasquez struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; 51c5722708SAndrew Vasquez dma_addr_t dump_dma = ha->gid_list_dma; 52c5722708SAndrew Vasquez uint32_t *dump = (uint32_t *)ha->gid_list; 53c3a2f0dfSAndrew Vasquez 54c3a2f0dfSAndrew Vasquez rval = QLA_SUCCESS; 55c5722708SAndrew Vasquez mb0 = 0; 56c5722708SAndrew Vasquez 57c5722708SAndrew Vasquez WRT_REG_WORD(®->mailbox0, MBC_DUMP_RISC_RAM_EXTENDED); 58c5722708SAndrew Vasquez clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); 59c5722708SAndrew Vasquez 60c5722708SAndrew Vasquez dwords = GID_LIST_SIZE / 4; 61c5722708SAndrew Vasquez for (cnt = 0; cnt < ram_dwords && rval == QLA_SUCCESS; 62c5722708SAndrew Vasquez cnt += dwords, addr += dwords) { 63c5722708SAndrew Vasquez if (cnt + dwords > ram_dwords) 64c5722708SAndrew Vasquez dwords = ram_dwords - cnt; 65c5722708SAndrew Vasquez 66c5722708SAndrew Vasquez WRT_REG_WORD(®->mailbox1, LSW(addr)); 67c5722708SAndrew Vasquez WRT_REG_WORD(®->mailbox8, MSW(addr)); 68c5722708SAndrew Vasquez 69c5722708SAndrew Vasquez WRT_REG_WORD(®->mailbox2, MSW(dump_dma)); 70c5722708SAndrew Vasquez WRT_REG_WORD(®->mailbox3, LSW(dump_dma)); 71c5722708SAndrew Vasquez WRT_REG_WORD(®->mailbox6, MSW(MSD(dump_dma))); 72c5722708SAndrew Vasquez WRT_REG_WORD(®->mailbox7, LSW(MSD(dump_dma))); 73c5722708SAndrew Vasquez 74c5722708SAndrew Vasquez WRT_REG_WORD(®->mailbox4, MSW(dwords)); 75c5722708SAndrew Vasquez WRT_REG_WORD(®->mailbox5, LSW(dwords)); 76c5722708SAndrew Vasquez WRT_REG_DWORD(®->hccr, HCCRX_SET_HOST_INT); 77c5722708SAndrew Vasquez 78c5722708SAndrew Vasquez for (timer = 6000000; timer; timer--) { 79c5722708SAndrew Vasquez /* Check for pending interrupts. */ 80c5722708SAndrew Vasquez stat = RD_REG_DWORD(®->host_status); 81c5722708SAndrew Vasquez if (stat & HSRX_RISC_INT) { 82c5722708SAndrew Vasquez stat &= 0xff; 83c5722708SAndrew Vasquez 84c5722708SAndrew Vasquez if (stat == 0x1 || stat == 0x2 || 85c5722708SAndrew Vasquez stat == 0x10 || stat == 0x11) { 86c5722708SAndrew Vasquez set_bit(MBX_INTERRUPT, 87c5722708SAndrew Vasquez &ha->mbx_cmd_flags); 88c5722708SAndrew Vasquez 89c5722708SAndrew Vasquez mb0 = RD_REG_WORD(®->mailbox0); 90c5722708SAndrew Vasquez 91c5722708SAndrew Vasquez WRT_REG_DWORD(®->hccr, 92c5722708SAndrew Vasquez HCCRX_CLR_RISC_INT); 93c5722708SAndrew Vasquez RD_REG_DWORD(®->hccr); 94c5722708SAndrew Vasquez break; 95c5722708SAndrew Vasquez } 96c5722708SAndrew Vasquez 97c5722708SAndrew Vasquez /* Clear this intr; it wasn't a mailbox intr */ 98c5722708SAndrew Vasquez WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); 99c5722708SAndrew Vasquez RD_REG_DWORD(®->hccr); 100c5722708SAndrew Vasquez } 101c5722708SAndrew Vasquez udelay(5); 102c5722708SAndrew Vasquez } 103c5722708SAndrew Vasquez 104c5722708SAndrew Vasquez if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) { 105c5722708SAndrew Vasquez rval = mb0 & MBS_MASK; 106c5722708SAndrew Vasquez for (idx = 0; idx < dwords; idx++) 107c5722708SAndrew Vasquez ram[cnt + idx] = swab32(dump[idx]); 108c5722708SAndrew Vasquez } else { 109c5722708SAndrew Vasquez rval = QLA_FUNCTION_FAILED; 110c5722708SAndrew Vasquez } 111c5722708SAndrew Vasquez } 112c5722708SAndrew Vasquez 113c5722708SAndrew Vasquez *nxt = rval == QLA_SUCCESS ? &ram[cnt]: NULL; 114c5722708SAndrew Vasquez return rval; 115c5722708SAndrew Vasquez } 116c5722708SAndrew Vasquez 117c5722708SAndrew Vasquez static int 118*7b867cf7SAnirban Chakraborty qla24xx_dump_memory(struct qla_hw_data *ha, uint32_t *code_ram, 119c5722708SAndrew Vasquez uint32_t cram_size, void **nxt) 120c5722708SAndrew Vasquez { 121c5722708SAndrew Vasquez int rval; 122c3a2f0dfSAndrew Vasquez 123c3a2f0dfSAndrew Vasquez /* Code RAM. */ 124c5722708SAndrew Vasquez rval = qla24xx_dump_ram(ha, 0x20000, code_ram, cram_size / 4, nxt); 125c5722708SAndrew Vasquez if (rval != QLA_SUCCESS) 126c3a2f0dfSAndrew Vasquez return rval; 127c5722708SAndrew Vasquez 128c5722708SAndrew Vasquez /* External Memory. */ 129c5722708SAndrew Vasquez return qla24xx_dump_ram(ha, 0x100000, *nxt, 130c5722708SAndrew Vasquez ha->fw_memory_size - 0x100000 + 1, nxt); 131c3a2f0dfSAndrew Vasquez } 132c3a2f0dfSAndrew Vasquez 133c81d04c9SAndrew Vasquez static uint32_t * 134c81d04c9SAndrew Vasquez qla24xx_read_window(struct device_reg_24xx __iomem *reg, uint32_t iobase, 135c81d04c9SAndrew Vasquez uint32_t count, uint32_t *buf) 136c81d04c9SAndrew Vasquez { 137c81d04c9SAndrew Vasquez uint32_t __iomem *dmp_reg; 138c81d04c9SAndrew Vasquez 139c81d04c9SAndrew Vasquez WRT_REG_DWORD(®->iobase_addr, iobase); 140c81d04c9SAndrew Vasquez dmp_reg = ®->iobase_window; 141c81d04c9SAndrew Vasquez while (count--) 142c81d04c9SAndrew Vasquez *buf++ = htonl(RD_REG_DWORD(dmp_reg++)); 143c81d04c9SAndrew Vasquez 144c81d04c9SAndrew Vasquez return buf; 145c81d04c9SAndrew Vasquez } 146c81d04c9SAndrew Vasquez 147c81d04c9SAndrew Vasquez static inline int 148c81d04c9SAndrew Vasquez qla24xx_pause_risc(struct device_reg_24xx __iomem *reg) 149c81d04c9SAndrew Vasquez { 150c81d04c9SAndrew Vasquez int rval = QLA_SUCCESS; 151c81d04c9SAndrew Vasquez uint32_t cnt; 152c81d04c9SAndrew Vasquez 153c3b058afSAndrew Vasquez if (RD_REG_DWORD(®->hccr) & HCCRX_RISC_PAUSE) 154c3b058afSAndrew Vasquez return rval; 155c3b058afSAndrew Vasquez 156c81d04c9SAndrew Vasquez WRT_REG_DWORD(®->hccr, HCCRX_SET_RISC_PAUSE); 157c3b058afSAndrew Vasquez for (cnt = 30000; (RD_REG_DWORD(®->hccr) & HCCRX_RISC_PAUSE) == 0 && 158c81d04c9SAndrew Vasquez rval == QLA_SUCCESS; cnt--) { 159c81d04c9SAndrew Vasquez if (cnt) 160c81d04c9SAndrew Vasquez udelay(100); 161c81d04c9SAndrew Vasquez else 162c81d04c9SAndrew Vasquez rval = QLA_FUNCTION_TIMEOUT; 163c81d04c9SAndrew Vasquez } 164c81d04c9SAndrew Vasquez 165c81d04c9SAndrew Vasquez return rval; 166c81d04c9SAndrew Vasquez } 167c81d04c9SAndrew Vasquez 168c81d04c9SAndrew Vasquez static int 169*7b867cf7SAnirban Chakraborty qla24xx_soft_reset(struct qla_hw_data *ha) 170c81d04c9SAndrew Vasquez { 171c81d04c9SAndrew Vasquez int rval = QLA_SUCCESS; 172c81d04c9SAndrew Vasquez uint32_t cnt; 173c81d04c9SAndrew Vasquez uint16_t mb0, wd; 174c81d04c9SAndrew Vasquez struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; 175c81d04c9SAndrew Vasquez 176c81d04c9SAndrew Vasquez /* Reset RISC. */ 177c81d04c9SAndrew Vasquez WRT_REG_DWORD(®->ctrl_status, CSRX_DMA_SHUTDOWN|MWB_4096_BYTES); 178c81d04c9SAndrew Vasquez for (cnt = 0; cnt < 30000; cnt++) { 179c81d04c9SAndrew Vasquez if ((RD_REG_DWORD(®->ctrl_status) & CSRX_DMA_ACTIVE) == 0) 180c81d04c9SAndrew Vasquez break; 181c81d04c9SAndrew Vasquez 182c81d04c9SAndrew Vasquez udelay(10); 183c81d04c9SAndrew Vasquez } 184c81d04c9SAndrew Vasquez 185c81d04c9SAndrew Vasquez WRT_REG_DWORD(®->ctrl_status, 186c81d04c9SAndrew Vasquez CSRX_ISP_SOFT_RESET|CSRX_DMA_SHUTDOWN|MWB_4096_BYTES); 187c81d04c9SAndrew Vasquez pci_read_config_word(ha->pdev, PCI_COMMAND, &wd); 188c81d04c9SAndrew Vasquez 189c81d04c9SAndrew Vasquez udelay(100); 190c81d04c9SAndrew Vasquez /* Wait for firmware to complete NVRAM accesses. */ 191c81d04c9SAndrew Vasquez mb0 = (uint32_t) RD_REG_WORD(®->mailbox0); 192c81d04c9SAndrew Vasquez for (cnt = 10000 ; cnt && mb0; cnt--) { 193c81d04c9SAndrew Vasquez udelay(5); 194c81d04c9SAndrew Vasquez mb0 = (uint32_t) RD_REG_WORD(®->mailbox0); 195c81d04c9SAndrew Vasquez barrier(); 196c81d04c9SAndrew Vasquez } 197c81d04c9SAndrew Vasquez 198c81d04c9SAndrew Vasquez /* Wait for soft-reset to complete. */ 199c81d04c9SAndrew Vasquez for (cnt = 0; cnt < 30000; cnt++) { 200c81d04c9SAndrew Vasquez if ((RD_REG_DWORD(®->ctrl_status) & 201c81d04c9SAndrew Vasquez CSRX_ISP_SOFT_RESET) == 0) 202c81d04c9SAndrew Vasquez break; 203c81d04c9SAndrew Vasquez 204c81d04c9SAndrew Vasquez udelay(10); 205c81d04c9SAndrew Vasquez } 206c81d04c9SAndrew Vasquez WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_RESET); 207c81d04c9SAndrew Vasquez RD_REG_DWORD(®->hccr); /* PCI Posting. */ 208c81d04c9SAndrew Vasquez 209c81d04c9SAndrew Vasquez for (cnt = 30000; RD_REG_WORD(®->mailbox0) != 0 && 210c81d04c9SAndrew Vasquez rval == QLA_SUCCESS; cnt--) { 211c81d04c9SAndrew Vasquez if (cnt) 212c81d04c9SAndrew Vasquez udelay(100); 213c81d04c9SAndrew Vasquez else 214c81d04c9SAndrew Vasquez rval = QLA_FUNCTION_TIMEOUT; 215c81d04c9SAndrew Vasquez } 216c81d04c9SAndrew Vasquez 217c81d04c9SAndrew Vasquez return rval; 218c81d04c9SAndrew Vasquez } 219c81d04c9SAndrew Vasquez 220c5722708SAndrew Vasquez static int 221*7b867cf7SAnirban Chakraborty qla2xxx_dump_ram(struct qla_hw_data *ha, uint32_t addr, uint16_t *ram, 222*7b867cf7SAnirban Chakraborty uint16_t ram_words, void **nxt) 223c5722708SAndrew Vasquez { 224c5722708SAndrew Vasquez int rval; 225c5722708SAndrew Vasquez uint32_t cnt, stat, timer, words, idx; 226c5722708SAndrew Vasquez uint16_t mb0; 227c5722708SAndrew Vasquez struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; 228c5722708SAndrew Vasquez dma_addr_t dump_dma = ha->gid_list_dma; 229c5722708SAndrew Vasquez uint16_t *dump = (uint16_t *)ha->gid_list; 230c5722708SAndrew Vasquez 231c5722708SAndrew Vasquez rval = QLA_SUCCESS; 232c5722708SAndrew Vasquez mb0 = 0; 233c5722708SAndrew Vasquez 234c5722708SAndrew Vasquez WRT_MAILBOX_REG(ha, reg, 0, MBC_DUMP_RISC_RAM_EXTENDED); 235c5722708SAndrew Vasquez clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); 236c5722708SAndrew Vasquez 237c5722708SAndrew Vasquez words = GID_LIST_SIZE / 2; 238c5722708SAndrew Vasquez for (cnt = 0; cnt < ram_words && rval == QLA_SUCCESS; 239c5722708SAndrew Vasquez cnt += words, addr += words) { 240c5722708SAndrew Vasquez if (cnt + words > ram_words) 241c5722708SAndrew Vasquez words = ram_words - cnt; 242c5722708SAndrew Vasquez 243c5722708SAndrew Vasquez WRT_MAILBOX_REG(ha, reg, 1, LSW(addr)); 244c5722708SAndrew Vasquez WRT_MAILBOX_REG(ha, reg, 8, MSW(addr)); 245c5722708SAndrew Vasquez 246c5722708SAndrew Vasquez WRT_MAILBOX_REG(ha, reg, 2, MSW(dump_dma)); 247c5722708SAndrew Vasquez WRT_MAILBOX_REG(ha, reg, 3, LSW(dump_dma)); 248c5722708SAndrew Vasquez WRT_MAILBOX_REG(ha, reg, 6, MSW(MSD(dump_dma))); 249c5722708SAndrew Vasquez WRT_MAILBOX_REG(ha, reg, 7, LSW(MSD(dump_dma))); 250c5722708SAndrew Vasquez 251c5722708SAndrew Vasquez WRT_MAILBOX_REG(ha, reg, 4, words); 252c5722708SAndrew Vasquez WRT_REG_WORD(®->hccr, HCCR_SET_HOST_INT); 253c5722708SAndrew Vasquez 254c5722708SAndrew Vasquez for (timer = 6000000; timer; timer--) { 255c5722708SAndrew Vasquez /* Check for pending interrupts. */ 256c5722708SAndrew Vasquez stat = RD_REG_DWORD(®->u.isp2300.host_status); 257c5722708SAndrew Vasquez if (stat & HSR_RISC_INT) { 258c5722708SAndrew Vasquez stat &= 0xff; 259c5722708SAndrew Vasquez 260c5722708SAndrew Vasquez if (stat == 0x1 || stat == 0x2) { 261c5722708SAndrew Vasquez set_bit(MBX_INTERRUPT, 262c5722708SAndrew Vasquez &ha->mbx_cmd_flags); 263c5722708SAndrew Vasquez 264c5722708SAndrew Vasquez mb0 = RD_MAILBOX_REG(ha, reg, 0); 265c5722708SAndrew Vasquez 266c5722708SAndrew Vasquez /* Release mailbox registers. */ 267c5722708SAndrew Vasquez WRT_REG_WORD(®->semaphore, 0); 268c5722708SAndrew Vasquez WRT_REG_WORD(®->hccr, 269c5722708SAndrew Vasquez HCCR_CLR_RISC_INT); 270c5722708SAndrew Vasquez RD_REG_WORD(®->hccr); 271c5722708SAndrew Vasquez break; 272c5722708SAndrew Vasquez } else if (stat == 0x10 || stat == 0x11) { 273c5722708SAndrew Vasquez set_bit(MBX_INTERRUPT, 274c5722708SAndrew Vasquez &ha->mbx_cmd_flags); 275c5722708SAndrew Vasquez 276c5722708SAndrew Vasquez mb0 = RD_MAILBOX_REG(ha, reg, 0); 277c5722708SAndrew Vasquez 278c5722708SAndrew Vasquez WRT_REG_WORD(®->hccr, 279c5722708SAndrew Vasquez HCCR_CLR_RISC_INT); 280c5722708SAndrew Vasquez RD_REG_WORD(®->hccr); 281c5722708SAndrew Vasquez break; 282c5722708SAndrew Vasquez } 283c5722708SAndrew Vasquez 284c5722708SAndrew Vasquez /* clear this intr; it wasn't a mailbox intr */ 285c5722708SAndrew Vasquez WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT); 286c5722708SAndrew Vasquez RD_REG_WORD(®->hccr); 287c5722708SAndrew Vasquez } 288c5722708SAndrew Vasquez udelay(5); 289c5722708SAndrew Vasquez } 290c5722708SAndrew Vasquez 291c5722708SAndrew Vasquez if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) { 292c5722708SAndrew Vasquez rval = mb0 & MBS_MASK; 293c5722708SAndrew Vasquez for (idx = 0; idx < words; idx++) 294c5722708SAndrew Vasquez ram[cnt + idx] = swab16(dump[idx]); 295c5722708SAndrew Vasquez } else { 296c5722708SAndrew Vasquez rval = QLA_FUNCTION_FAILED; 297c5722708SAndrew Vasquez } 298c5722708SAndrew Vasquez } 299c5722708SAndrew Vasquez 300c5722708SAndrew Vasquez *nxt = rval == QLA_SUCCESS ? &ram[cnt]: NULL; 301c5722708SAndrew Vasquez return rval; 302c5722708SAndrew Vasquez } 303c5722708SAndrew Vasquez 304c81d04c9SAndrew Vasquez static inline void 305c81d04c9SAndrew Vasquez qla2xxx_read_window(struct device_reg_2xxx __iomem *reg, uint32_t count, 306c81d04c9SAndrew Vasquez uint16_t *buf) 307c81d04c9SAndrew Vasquez { 308c81d04c9SAndrew Vasquez uint16_t __iomem *dmp_reg = ®->u.isp2300.fb_cmd; 309c81d04c9SAndrew Vasquez 310c81d04c9SAndrew Vasquez while (count--) 311c81d04c9SAndrew Vasquez *buf++ = htons(RD_REG_WORD(dmp_reg++)); 312c81d04c9SAndrew Vasquez } 313c81d04c9SAndrew Vasquez 3141da177e4SLinus Torvalds /** 3151da177e4SLinus Torvalds * qla2300_fw_dump() - Dumps binary data from the 2300 firmware. 3161da177e4SLinus Torvalds * @ha: HA context 3171da177e4SLinus Torvalds * @hardware_locked: Called with the hardware_lock 3181da177e4SLinus Torvalds */ 3191da177e4SLinus Torvalds void 320*7b867cf7SAnirban Chakraborty qla2300_fw_dump(scsi_qla_host_t *vha, int hardware_locked) 3211da177e4SLinus Torvalds { 3221da177e4SLinus Torvalds int rval; 323c5722708SAndrew Vasquez uint32_t cnt; 324*7b867cf7SAnirban Chakraborty struct qla_hw_data *ha = vha->hw; 3253d71644cSAndrew Vasquez struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; 3261da177e4SLinus Torvalds uint16_t __iomem *dmp_reg; 3271da177e4SLinus Torvalds unsigned long flags; 3281da177e4SLinus Torvalds struct qla2300_fw_dump *fw; 329c5722708SAndrew Vasquez void *nxt; 3301da177e4SLinus Torvalds 3311da177e4SLinus Torvalds flags = 0; 3321da177e4SLinus Torvalds 3331da177e4SLinus Torvalds if (!hardware_locked) 3341da177e4SLinus Torvalds spin_lock_irqsave(&ha->hardware_lock, flags); 3351da177e4SLinus Torvalds 336d4e3e04dSAndrew Vasquez if (!ha->fw_dump) { 3371da177e4SLinus Torvalds qla_printk(KERN_WARNING, ha, 338d4e3e04dSAndrew Vasquez "No buffer available for dump!!!\n"); 3391da177e4SLinus Torvalds goto qla2300_fw_dump_failed; 3401da177e4SLinus Torvalds } 3411da177e4SLinus Torvalds 342d4e3e04dSAndrew Vasquez if (ha->fw_dumped) { 3431da177e4SLinus Torvalds qla_printk(KERN_WARNING, ha, 344d4e3e04dSAndrew Vasquez "Firmware has been previously dumped (%p) -- ignoring " 345d4e3e04dSAndrew Vasquez "request...\n", ha->fw_dump); 3461da177e4SLinus Torvalds goto qla2300_fw_dump_failed; 3471da177e4SLinus Torvalds } 348a7a167bfSAndrew Vasquez fw = &ha->fw_dump->isp.isp23; 349a7a167bfSAndrew Vasquez qla2xxx_prep_dump(ha, ha->fw_dump); 3501da177e4SLinus Torvalds 3511da177e4SLinus Torvalds rval = QLA_SUCCESS; 352a7a167bfSAndrew Vasquez fw->hccr = htons(RD_REG_WORD(®->hccr)); 3531da177e4SLinus Torvalds 3541da177e4SLinus Torvalds /* Pause RISC. */ 3551da177e4SLinus Torvalds WRT_REG_WORD(®->hccr, HCCR_PAUSE_RISC); 3561da177e4SLinus Torvalds if (IS_QLA2300(ha)) { 3571da177e4SLinus Torvalds for (cnt = 30000; 3581da177e4SLinus Torvalds (RD_REG_WORD(®->hccr) & HCCR_RISC_PAUSE) == 0 && 3591da177e4SLinus Torvalds rval == QLA_SUCCESS; cnt--) { 3601da177e4SLinus Torvalds if (cnt) 3611da177e4SLinus Torvalds udelay(100); 3621da177e4SLinus Torvalds else 3631da177e4SLinus Torvalds rval = QLA_FUNCTION_TIMEOUT; 3641da177e4SLinus Torvalds } 3651da177e4SLinus Torvalds } else { 3661da177e4SLinus Torvalds RD_REG_WORD(®->hccr); /* PCI Posting. */ 3671da177e4SLinus Torvalds udelay(10); 3681da177e4SLinus Torvalds } 3691da177e4SLinus Torvalds 3701da177e4SLinus Torvalds if (rval == QLA_SUCCESS) { 371c81d04c9SAndrew Vasquez dmp_reg = ®->flash_address; 3721da177e4SLinus Torvalds for (cnt = 0; cnt < sizeof(fw->pbiu_reg) / 2; cnt++) 373a7a167bfSAndrew Vasquez fw->pbiu_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); 3741da177e4SLinus Torvalds 375c81d04c9SAndrew Vasquez dmp_reg = ®->u.isp2300.req_q_in; 3761da177e4SLinus Torvalds for (cnt = 0; cnt < sizeof(fw->risc_host_reg) / 2; cnt++) 377a7a167bfSAndrew Vasquez fw->risc_host_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); 3781da177e4SLinus Torvalds 379c81d04c9SAndrew Vasquez dmp_reg = ®->u.isp2300.mailbox0; 3801da177e4SLinus Torvalds for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++) 381a7a167bfSAndrew Vasquez fw->mailbox_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); 3821da177e4SLinus Torvalds 3831da177e4SLinus Torvalds WRT_REG_WORD(®->ctrl_status, 0x40); 384c81d04c9SAndrew Vasquez qla2xxx_read_window(reg, 32, fw->resp_dma_reg); 3851da177e4SLinus Torvalds 3861da177e4SLinus Torvalds WRT_REG_WORD(®->ctrl_status, 0x50); 387c81d04c9SAndrew Vasquez qla2xxx_read_window(reg, 48, fw->dma_reg); 3881da177e4SLinus Torvalds 3891da177e4SLinus Torvalds WRT_REG_WORD(®->ctrl_status, 0x00); 390c81d04c9SAndrew Vasquez dmp_reg = ®->risc_hw; 3911da177e4SLinus Torvalds for (cnt = 0; cnt < sizeof(fw->risc_hdw_reg) / 2; cnt++) 392a7a167bfSAndrew Vasquez fw->risc_hdw_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); 3931da177e4SLinus Torvalds 3941da177e4SLinus Torvalds WRT_REG_WORD(®->pcr, 0x2000); 395c81d04c9SAndrew Vasquez qla2xxx_read_window(reg, 16, fw->risc_gp0_reg); 3961da177e4SLinus Torvalds 3971da177e4SLinus Torvalds WRT_REG_WORD(®->pcr, 0x2200); 398c81d04c9SAndrew Vasquez qla2xxx_read_window(reg, 16, fw->risc_gp1_reg); 3991da177e4SLinus Torvalds 4001da177e4SLinus Torvalds WRT_REG_WORD(®->pcr, 0x2400); 401c81d04c9SAndrew Vasquez qla2xxx_read_window(reg, 16, fw->risc_gp2_reg); 4021da177e4SLinus Torvalds 4031da177e4SLinus Torvalds WRT_REG_WORD(®->pcr, 0x2600); 404c81d04c9SAndrew Vasquez qla2xxx_read_window(reg, 16, fw->risc_gp3_reg); 4051da177e4SLinus Torvalds 4061da177e4SLinus Torvalds WRT_REG_WORD(®->pcr, 0x2800); 407c81d04c9SAndrew Vasquez qla2xxx_read_window(reg, 16, fw->risc_gp4_reg); 4081da177e4SLinus Torvalds 4091da177e4SLinus Torvalds WRT_REG_WORD(®->pcr, 0x2A00); 410c81d04c9SAndrew Vasquez qla2xxx_read_window(reg, 16, fw->risc_gp5_reg); 4111da177e4SLinus Torvalds 4121da177e4SLinus Torvalds WRT_REG_WORD(®->pcr, 0x2C00); 413c81d04c9SAndrew Vasquez qla2xxx_read_window(reg, 16, fw->risc_gp6_reg); 4141da177e4SLinus Torvalds 4151da177e4SLinus Torvalds WRT_REG_WORD(®->pcr, 0x2E00); 416c81d04c9SAndrew Vasquez qla2xxx_read_window(reg, 16, fw->risc_gp7_reg); 4171da177e4SLinus Torvalds 4181da177e4SLinus Torvalds WRT_REG_WORD(®->ctrl_status, 0x10); 419c81d04c9SAndrew Vasquez qla2xxx_read_window(reg, 64, fw->frame_buf_hdw_reg); 4201da177e4SLinus Torvalds 4211da177e4SLinus Torvalds WRT_REG_WORD(®->ctrl_status, 0x20); 422c81d04c9SAndrew Vasquez qla2xxx_read_window(reg, 64, fw->fpm_b0_reg); 4231da177e4SLinus Torvalds 4241da177e4SLinus Torvalds WRT_REG_WORD(®->ctrl_status, 0x30); 425c81d04c9SAndrew Vasquez qla2xxx_read_window(reg, 64, fw->fpm_b1_reg); 4261da177e4SLinus Torvalds 4271da177e4SLinus Torvalds /* Reset RISC. */ 4281da177e4SLinus Torvalds WRT_REG_WORD(®->ctrl_status, CSR_ISP_SOFT_RESET); 4291da177e4SLinus Torvalds for (cnt = 0; cnt < 30000; cnt++) { 4301da177e4SLinus Torvalds if ((RD_REG_WORD(®->ctrl_status) & 4311da177e4SLinus Torvalds CSR_ISP_SOFT_RESET) == 0) 4321da177e4SLinus Torvalds break; 4331da177e4SLinus Torvalds 4341da177e4SLinus Torvalds udelay(10); 4351da177e4SLinus Torvalds } 4361da177e4SLinus Torvalds } 4371da177e4SLinus Torvalds 4381da177e4SLinus Torvalds if (!IS_QLA2300(ha)) { 4391da177e4SLinus Torvalds for (cnt = 30000; RD_MAILBOX_REG(ha, reg, 0) != 0 && 4401da177e4SLinus Torvalds rval == QLA_SUCCESS; cnt--) { 4411da177e4SLinus Torvalds if (cnt) 4421da177e4SLinus Torvalds udelay(100); 4431da177e4SLinus Torvalds else 4441da177e4SLinus Torvalds rval = QLA_FUNCTION_TIMEOUT; 4451da177e4SLinus Torvalds } 4461da177e4SLinus Torvalds } 4471da177e4SLinus Torvalds 4481da177e4SLinus Torvalds /* Get RISC SRAM. */ 449c5722708SAndrew Vasquez if (rval == QLA_SUCCESS) 450c5722708SAndrew Vasquez rval = qla2xxx_dump_ram(ha, 0x800, fw->risc_ram, 451c5722708SAndrew Vasquez sizeof(fw->risc_ram) / 2, &nxt); 4521da177e4SLinus Torvalds 4531da177e4SLinus Torvalds /* Get stack SRAM. */ 454c5722708SAndrew Vasquez if (rval == QLA_SUCCESS) 455c5722708SAndrew Vasquez rval = qla2xxx_dump_ram(ha, 0x10000, fw->stack_ram, 456c5722708SAndrew Vasquez sizeof(fw->stack_ram) / 2, &nxt); 4571da177e4SLinus Torvalds 4581da177e4SLinus Torvalds /* Get data SRAM. */ 459c5722708SAndrew Vasquez if (rval == QLA_SUCCESS) 460c5722708SAndrew Vasquez rval = qla2xxx_dump_ram(ha, 0x11000, fw->data_ram, 461c5722708SAndrew Vasquez ha->fw_memory_size - 0x11000 + 1, &nxt); 4621da177e4SLinus Torvalds 463a7a167bfSAndrew Vasquez if (rval == QLA_SUCCESS) 464*7b867cf7SAnirban Chakraborty qla2xxx_copy_queues(vha, nxt); 465a7a167bfSAndrew Vasquez 4661da177e4SLinus Torvalds if (rval != QLA_SUCCESS) { 4671da177e4SLinus Torvalds qla_printk(KERN_WARNING, ha, 4681da177e4SLinus Torvalds "Failed to dump firmware (%x)!!!\n", rval); 469d4e3e04dSAndrew Vasquez ha->fw_dumped = 0; 4701da177e4SLinus Torvalds 4711da177e4SLinus Torvalds } else { 4721da177e4SLinus Torvalds qla_printk(KERN_INFO, ha, 4731da177e4SLinus Torvalds "Firmware dump saved to temp buffer (%ld/%p).\n", 474*7b867cf7SAnirban Chakraborty vha->host_no, ha->fw_dump); 475d4e3e04dSAndrew Vasquez ha->fw_dumped = 1; 4761da177e4SLinus Torvalds } 4771da177e4SLinus Torvalds 4781da177e4SLinus Torvalds qla2300_fw_dump_failed: 4791da177e4SLinus Torvalds if (!hardware_locked) 4801da177e4SLinus Torvalds spin_unlock_irqrestore(&ha->hardware_lock, flags); 4811da177e4SLinus Torvalds } 4821da177e4SLinus Torvalds 4831da177e4SLinus Torvalds /** 4841da177e4SLinus Torvalds * qla2100_fw_dump() - Dumps binary data from the 2100/2200 firmware. 4851da177e4SLinus Torvalds * @ha: HA context 4861da177e4SLinus Torvalds * @hardware_locked: Called with the hardware_lock 4871da177e4SLinus Torvalds */ 4881da177e4SLinus Torvalds void 489*7b867cf7SAnirban Chakraborty qla2100_fw_dump(scsi_qla_host_t *vha, int hardware_locked) 4901da177e4SLinus Torvalds { 4911da177e4SLinus Torvalds int rval; 4921da177e4SLinus Torvalds uint32_t cnt, timer; 4931da177e4SLinus Torvalds uint16_t risc_address; 4941da177e4SLinus Torvalds uint16_t mb0, mb2; 495*7b867cf7SAnirban Chakraborty struct qla_hw_data *ha = vha->hw; 4963d71644cSAndrew Vasquez struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; 4971da177e4SLinus Torvalds uint16_t __iomem *dmp_reg; 4981da177e4SLinus Torvalds unsigned long flags; 4991da177e4SLinus Torvalds struct qla2100_fw_dump *fw; 5001da177e4SLinus Torvalds 5011da177e4SLinus Torvalds risc_address = 0; 5021da177e4SLinus Torvalds mb0 = mb2 = 0; 5031da177e4SLinus Torvalds flags = 0; 5041da177e4SLinus Torvalds 5051da177e4SLinus Torvalds if (!hardware_locked) 5061da177e4SLinus Torvalds spin_lock_irqsave(&ha->hardware_lock, flags); 5071da177e4SLinus Torvalds 508d4e3e04dSAndrew Vasquez if (!ha->fw_dump) { 5091da177e4SLinus Torvalds qla_printk(KERN_WARNING, ha, 510d4e3e04dSAndrew Vasquez "No buffer available for dump!!!\n"); 5111da177e4SLinus Torvalds goto qla2100_fw_dump_failed; 5121da177e4SLinus Torvalds } 5131da177e4SLinus Torvalds 514d4e3e04dSAndrew Vasquez if (ha->fw_dumped) { 5151da177e4SLinus Torvalds qla_printk(KERN_WARNING, ha, 516d4e3e04dSAndrew Vasquez "Firmware has been previously dumped (%p) -- ignoring " 517d4e3e04dSAndrew Vasquez "request...\n", ha->fw_dump); 5181da177e4SLinus Torvalds goto qla2100_fw_dump_failed; 5191da177e4SLinus Torvalds } 520a7a167bfSAndrew Vasquez fw = &ha->fw_dump->isp.isp21; 521a7a167bfSAndrew Vasquez qla2xxx_prep_dump(ha, ha->fw_dump); 5221da177e4SLinus Torvalds 5231da177e4SLinus Torvalds rval = QLA_SUCCESS; 524a7a167bfSAndrew Vasquez fw->hccr = htons(RD_REG_WORD(®->hccr)); 5251da177e4SLinus Torvalds 5261da177e4SLinus Torvalds /* Pause RISC. */ 5271da177e4SLinus Torvalds WRT_REG_WORD(®->hccr, HCCR_PAUSE_RISC); 5281da177e4SLinus Torvalds for (cnt = 30000; (RD_REG_WORD(®->hccr) & HCCR_RISC_PAUSE) == 0 && 5291da177e4SLinus Torvalds rval == QLA_SUCCESS; cnt--) { 5301da177e4SLinus Torvalds if (cnt) 5311da177e4SLinus Torvalds udelay(100); 5321da177e4SLinus Torvalds else 5331da177e4SLinus Torvalds rval = QLA_FUNCTION_TIMEOUT; 5341da177e4SLinus Torvalds } 5351da177e4SLinus Torvalds if (rval == QLA_SUCCESS) { 536c81d04c9SAndrew Vasquez dmp_reg = ®->flash_address; 5371da177e4SLinus Torvalds for (cnt = 0; cnt < sizeof(fw->pbiu_reg) / 2; cnt++) 538a7a167bfSAndrew Vasquez fw->pbiu_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); 5391da177e4SLinus Torvalds 540c81d04c9SAndrew Vasquez dmp_reg = ®->u.isp2100.mailbox0; 5411da177e4SLinus Torvalds for (cnt = 0; cnt < ha->mbx_count; cnt++) { 542c81d04c9SAndrew Vasquez if (cnt == 8) 543c81d04c9SAndrew Vasquez dmp_reg = ®->u_end.isp2200.mailbox8; 544c81d04c9SAndrew Vasquez 545a7a167bfSAndrew Vasquez fw->mailbox_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); 5461da177e4SLinus Torvalds } 5471da177e4SLinus Torvalds 548c81d04c9SAndrew Vasquez dmp_reg = ®->u.isp2100.unused_2[0]; 5491da177e4SLinus Torvalds for (cnt = 0; cnt < sizeof(fw->dma_reg) / 2; cnt++) 550a7a167bfSAndrew Vasquez fw->dma_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); 5511da177e4SLinus Torvalds 5521da177e4SLinus Torvalds WRT_REG_WORD(®->ctrl_status, 0x00); 553c81d04c9SAndrew Vasquez dmp_reg = ®->risc_hw; 5541da177e4SLinus Torvalds for (cnt = 0; cnt < sizeof(fw->risc_hdw_reg) / 2; cnt++) 555a7a167bfSAndrew Vasquez fw->risc_hdw_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); 5561da177e4SLinus Torvalds 5571da177e4SLinus Torvalds WRT_REG_WORD(®->pcr, 0x2000); 558c81d04c9SAndrew Vasquez qla2xxx_read_window(reg, 16, fw->risc_gp0_reg); 5591da177e4SLinus Torvalds 5601da177e4SLinus Torvalds WRT_REG_WORD(®->pcr, 0x2100); 561c81d04c9SAndrew Vasquez qla2xxx_read_window(reg, 16, fw->risc_gp1_reg); 5621da177e4SLinus Torvalds 5631da177e4SLinus Torvalds WRT_REG_WORD(®->pcr, 0x2200); 564c81d04c9SAndrew Vasquez qla2xxx_read_window(reg, 16, fw->risc_gp2_reg); 5651da177e4SLinus Torvalds 5661da177e4SLinus Torvalds WRT_REG_WORD(®->pcr, 0x2300); 567c81d04c9SAndrew Vasquez qla2xxx_read_window(reg, 16, fw->risc_gp3_reg); 5681da177e4SLinus Torvalds 5691da177e4SLinus Torvalds WRT_REG_WORD(®->pcr, 0x2400); 570c81d04c9SAndrew Vasquez qla2xxx_read_window(reg, 16, fw->risc_gp4_reg); 5711da177e4SLinus Torvalds 5721da177e4SLinus Torvalds WRT_REG_WORD(®->pcr, 0x2500); 573c81d04c9SAndrew Vasquez qla2xxx_read_window(reg, 16, fw->risc_gp5_reg); 5741da177e4SLinus Torvalds 5751da177e4SLinus Torvalds WRT_REG_WORD(®->pcr, 0x2600); 576c81d04c9SAndrew Vasquez qla2xxx_read_window(reg, 16, fw->risc_gp6_reg); 5771da177e4SLinus Torvalds 5781da177e4SLinus Torvalds WRT_REG_WORD(®->pcr, 0x2700); 579c81d04c9SAndrew Vasquez qla2xxx_read_window(reg, 16, fw->risc_gp7_reg); 5801da177e4SLinus Torvalds 5811da177e4SLinus Torvalds WRT_REG_WORD(®->ctrl_status, 0x10); 582c81d04c9SAndrew Vasquez qla2xxx_read_window(reg, 16, fw->frame_buf_hdw_reg); 5831da177e4SLinus Torvalds 5841da177e4SLinus Torvalds WRT_REG_WORD(®->ctrl_status, 0x20); 585c81d04c9SAndrew Vasquez qla2xxx_read_window(reg, 64, fw->fpm_b0_reg); 5861da177e4SLinus Torvalds 5871da177e4SLinus Torvalds WRT_REG_WORD(®->ctrl_status, 0x30); 588c81d04c9SAndrew Vasquez qla2xxx_read_window(reg, 64, fw->fpm_b1_reg); 5891da177e4SLinus Torvalds 5901da177e4SLinus Torvalds /* Reset the ISP. */ 5911da177e4SLinus Torvalds WRT_REG_WORD(®->ctrl_status, CSR_ISP_SOFT_RESET); 5921da177e4SLinus Torvalds } 5931da177e4SLinus Torvalds 5941da177e4SLinus Torvalds for (cnt = 30000; RD_MAILBOX_REG(ha, reg, 0) != 0 && 5951da177e4SLinus Torvalds rval == QLA_SUCCESS; cnt--) { 5961da177e4SLinus Torvalds if (cnt) 5971da177e4SLinus Torvalds udelay(100); 5981da177e4SLinus Torvalds else 5991da177e4SLinus Torvalds rval = QLA_FUNCTION_TIMEOUT; 6001da177e4SLinus Torvalds } 6011da177e4SLinus Torvalds 6021da177e4SLinus Torvalds /* Pause RISC. */ 6031da177e4SLinus Torvalds if (rval == QLA_SUCCESS && (IS_QLA2200(ha) || (IS_QLA2100(ha) && 6041da177e4SLinus Torvalds (RD_REG_WORD(®->mctr) & (BIT_1 | BIT_0)) != 0))) { 6051da177e4SLinus Torvalds 6061da177e4SLinus Torvalds WRT_REG_WORD(®->hccr, HCCR_PAUSE_RISC); 6071da177e4SLinus Torvalds for (cnt = 30000; 6081da177e4SLinus Torvalds (RD_REG_WORD(®->hccr) & HCCR_RISC_PAUSE) == 0 && 6091da177e4SLinus Torvalds rval == QLA_SUCCESS; cnt--) { 6101da177e4SLinus Torvalds if (cnt) 6111da177e4SLinus Torvalds udelay(100); 6121da177e4SLinus Torvalds else 6131da177e4SLinus Torvalds rval = QLA_FUNCTION_TIMEOUT; 6141da177e4SLinus Torvalds } 6151da177e4SLinus Torvalds if (rval == QLA_SUCCESS) { 6161da177e4SLinus Torvalds /* Set memory configuration and timing. */ 6171da177e4SLinus Torvalds if (IS_QLA2100(ha)) 6181da177e4SLinus Torvalds WRT_REG_WORD(®->mctr, 0xf1); 6191da177e4SLinus Torvalds else 6201da177e4SLinus Torvalds WRT_REG_WORD(®->mctr, 0xf2); 6211da177e4SLinus Torvalds RD_REG_WORD(®->mctr); /* PCI Posting. */ 6221da177e4SLinus Torvalds 6231da177e4SLinus Torvalds /* Release RISC. */ 6241da177e4SLinus Torvalds WRT_REG_WORD(®->hccr, HCCR_RELEASE_RISC); 6251da177e4SLinus Torvalds } 6261da177e4SLinus Torvalds } 6271da177e4SLinus Torvalds 6281da177e4SLinus Torvalds if (rval == QLA_SUCCESS) { 6291da177e4SLinus Torvalds /* Get RISC SRAM. */ 6301da177e4SLinus Torvalds risc_address = 0x1000; 6311da177e4SLinus Torvalds WRT_MAILBOX_REG(ha, reg, 0, MBC_READ_RAM_WORD); 6321da177e4SLinus Torvalds clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); 6331da177e4SLinus Torvalds } 6341da177e4SLinus Torvalds for (cnt = 0; cnt < sizeof(fw->risc_ram) / 2 && rval == QLA_SUCCESS; 6351da177e4SLinus Torvalds cnt++, risc_address++) { 6361da177e4SLinus Torvalds WRT_MAILBOX_REG(ha, reg, 1, risc_address); 6371da177e4SLinus Torvalds WRT_REG_WORD(®->hccr, HCCR_SET_HOST_INT); 6381da177e4SLinus Torvalds 6391da177e4SLinus Torvalds for (timer = 6000000; timer != 0; timer--) { 6401da177e4SLinus Torvalds /* Check for pending interrupts. */ 6411da177e4SLinus Torvalds if (RD_REG_WORD(®->istatus) & ISR_RISC_INT) { 6421da177e4SLinus Torvalds if (RD_REG_WORD(®->semaphore) & BIT_0) { 6431da177e4SLinus Torvalds set_bit(MBX_INTERRUPT, 6441da177e4SLinus Torvalds &ha->mbx_cmd_flags); 6451da177e4SLinus Torvalds 6461da177e4SLinus Torvalds mb0 = RD_MAILBOX_REG(ha, reg, 0); 6471da177e4SLinus Torvalds mb2 = RD_MAILBOX_REG(ha, reg, 2); 6481da177e4SLinus Torvalds 6491da177e4SLinus Torvalds WRT_REG_WORD(®->semaphore, 0); 6501da177e4SLinus Torvalds WRT_REG_WORD(®->hccr, 6511da177e4SLinus Torvalds HCCR_CLR_RISC_INT); 6521da177e4SLinus Torvalds RD_REG_WORD(®->hccr); 6531da177e4SLinus Torvalds break; 6541da177e4SLinus Torvalds } 6551da177e4SLinus Torvalds WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT); 6561da177e4SLinus Torvalds RD_REG_WORD(®->hccr); 6571da177e4SLinus Torvalds } 6581da177e4SLinus Torvalds udelay(5); 6591da177e4SLinus Torvalds } 6601da177e4SLinus Torvalds 6611da177e4SLinus Torvalds if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) { 6621da177e4SLinus Torvalds rval = mb0 & MBS_MASK; 663a7a167bfSAndrew Vasquez fw->risc_ram[cnt] = htons(mb2); 6641da177e4SLinus Torvalds } else { 6651da177e4SLinus Torvalds rval = QLA_FUNCTION_FAILED; 6661da177e4SLinus Torvalds } 6671da177e4SLinus Torvalds } 6681da177e4SLinus Torvalds 669a7a167bfSAndrew Vasquez if (rval == QLA_SUCCESS) 670*7b867cf7SAnirban Chakraborty qla2xxx_copy_queues(vha, &fw->risc_ram[cnt]); 671a7a167bfSAndrew Vasquez 6721da177e4SLinus Torvalds if (rval != QLA_SUCCESS) { 6731da177e4SLinus Torvalds qla_printk(KERN_WARNING, ha, 6741da177e4SLinus Torvalds "Failed to dump firmware (%x)!!!\n", rval); 675d4e3e04dSAndrew Vasquez ha->fw_dumped = 0; 6761da177e4SLinus Torvalds 6771da177e4SLinus Torvalds } else { 6781da177e4SLinus Torvalds qla_printk(KERN_INFO, ha, 6791da177e4SLinus Torvalds "Firmware dump saved to temp buffer (%ld/%p).\n", 680*7b867cf7SAnirban Chakraborty vha->host_no, ha->fw_dump); 681d4e3e04dSAndrew Vasquez ha->fw_dumped = 1; 6821da177e4SLinus Torvalds } 6831da177e4SLinus Torvalds 6841da177e4SLinus Torvalds qla2100_fw_dump_failed: 6851da177e4SLinus Torvalds if (!hardware_locked) 6861da177e4SLinus Torvalds spin_unlock_irqrestore(&ha->hardware_lock, flags); 6871da177e4SLinus Torvalds } 6881da177e4SLinus Torvalds 6896d9b61edSAndrew Vasquez void 690*7b867cf7SAnirban Chakraborty qla24xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) 6916d9b61edSAndrew Vasquez { 6926d9b61edSAndrew Vasquez int rval; 693c3a2f0dfSAndrew Vasquez uint32_t cnt; 6946d9b61edSAndrew Vasquez uint32_t risc_address; 695*7b867cf7SAnirban Chakraborty struct qla_hw_data *ha = vha->hw; 6966d9b61edSAndrew Vasquez struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; 6976d9b61edSAndrew Vasquez uint32_t __iomem *dmp_reg; 6986d9b61edSAndrew Vasquez uint32_t *iter_reg; 6996d9b61edSAndrew Vasquez uint16_t __iomem *mbx_reg; 7006d9b61edSAndrew Vasquez unsigned long flags; 7016d9b61edSAndrew Vasquez struct qla24xx_fw_dump *fw; 7026d9b61edSAndrew Vasquez uint32_t ext_mem_cnt; 703c3a2f0dfSAndrew Vasquez void *nxt; 7046d9b61edSAndrew Vasquez 7056d9b61edSAndrew Vasquez risc_address = ext_mem_cnt = 0; 7066d9b61edSAndrew Vasquez flags = 0; 7076d9b61edSAndrew Vasquez 7086d9b61edSAndrew Vasquez if (!hardware_locked) 7096d9b61edSAndrew Vasquez spin_lock_irqsave(&ha->hardware_lock, flags); 7106d9b61edSAndrew Vasquez 711d4e3e04dSAndrew Vasquez if (!ha->fw_dump) { 7126d9b61edSAndrew Vasquez qla_printk(KERN_WARNING, ha, 7136d9b61edSAndrew Vasquez "No buffer available for dump!!!\n"); 7146d9b61edSAndrew Vasquez goto qla24xx_fw_dump_failed; 7156d9b61edSAndrew Vasquez } 7166d9b61edSAndrew Vasquez 7176d9b61edSAndrew Vasquez if (ha->fw_dumped) { 7186d9b61edSAndrew Vasquez qla_printk(KERN_WARNING, ha, 7196d9b61edSAndrew Vasquez "Firmware has been previously dumped (%p) -- ignoring " 720d4e3e04dSAndrew Vasquez "request...\n", ha->fw_dump); 7216d9b61edSAndrew Vasquez goto qla24xx_fw_dump_failed; 7226d9b61edSAndrew Vasquez } 723a7a167bfSAndrew Vasquez fw = &ha->fw_dump->isp.isp24; 724a7a167bfSAndrew Vasquez qla2xxx_prep_dump(ha, ha->fw_dump); 7256d9b61edSAndrew Vasquez 726a7a167bfSAndrew Vasquez fw->host_status = htonl(RD_REG_DWORD(®->host_status)); 7276d9b61edSAndrew Vasquez 7286d9b61edSAndrew Vasquez /* Pause RISC. */ 729c81d04c9SAndrew Vasquez rval = qla24xx_pause_risc(reg); 730c81d04c9SAndrew Vasquez if (rval != QLA_SUCCESS) 731c81d04c9SAndrew Vasquez goto qla24xx_fw_dump_failed_0; 7326d9b61edSAndrew Vasquez 7336d9b61edSAndrew Vasquez /* Host interface registers. */ 734c81d04c9SAndrew Vasquez dmp_reg = ®->flash_addr; 7356d9b61edSAndrew Vasquez for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++) 736a7a167bfSAndrew Vasquez fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); 7376d9b61edSAndrew Vasquez 738210d5350Sandrew.vasquez@qlogic.com /* Disable interrupts. */ 739210d5350Sandrew.vasquez@qlogic.com WRT_REG_DWORD(®->ictrl, 0); 740210d5350Sandrew.vasquez@qlogic.com RD_REG_DWORD(®->ictrl); 741210d5350Sandrew.vasquez@qlogic.com 742210d5350Sandrew.vasquez@qlogic.com /* Shadow registers. */ 743210d5350Sandrew.vasquez@qlogic.com WRT_REG_DWORD(®->iobase_addr, 0x0F70); 744210d5350Sandrew.vasquez@qlogic.com RD_REG_DWORD(®->iobase_addr); 745c3a2f0dfSAndrew Vasquez WRT_REG_DWORD(®->iobase_select, 0xB0000000); 746c3a2f0dfSAndrew Vasquez fw->shadow_reg[0] = htonl(RD_REG_DWORD(®->iobase_sdata)); 747210d5350Sandrew.vasquez@qlogic.com 748c3a2f0dfSAndrew Vasquez WRT_REG_DWORD(®->iobase_select, 0xB0100000); 749c3a2f0dfSAndrew Vasquez fw->shadow_reg[1] = htonl(RD_REG_DWORD(®->iobase_sdata)); 750210d5350Sandrew.vasquez@qlogic.com 751c3a2f0dfSAndrew Vasquez WRT_REG_DWORD(®->iobase_select, 0xB0200000); 752c3a2f0dfSAndrew Vasquez fw->shadow_reg[2] = htonl(RD_REG_DWORD(®->iobase_sdata)); 753210d5350Sandrew.vasquez@qlogic.com 754c3a2f0dfSAndrew Vasquez WRT_REG_DWORD(®->iobase_select, 0xB0300000); 755c3a2f0dfSAndrew Vasquez fw->shadow_reg[3] = htonl(RD_REG_DWORD(®->iobase_sdata)); 756210d5350Sandrew.vasquez@qlogic.com 757c3a2f0dfSAndrew Vasquez WRT_REG_DWORD(®->iobase_select, 0xB0400000); 758c3a2f0dfSAndrew Vasquez fw->shadow_reg[4] = htonl(RD_REG_DWORD(®->iobase_sdata)); 759210d5350Sandrew.vasquez@qlogic.com 760c3a2f0dfSAndrew Vasquez WRT_REG_DWORD(®->iobase_select, 0xB0500000); 761c3a2f0dfSAndrew Vasquez fw->shadow_reg[5] = htonl(RD_REG_DWORD(®->iobase_sdata)); 762210d5350Sandrew.vasquez@qlogic.com 763c3a2f0dfSAndrew Vasquez WRT_REG_DWORD(®->iobase_select, 0xB0600000); 764c3a2f0dfSAndrew Vasquez fw->shadow_reg[6] = htonl(RD_REG_DWORD(®->iobase_sdata)); 765210d5350Sandrew.vasquez@qlogic.com 7666d9b61edSAndrew Vasquez /* Mailbox registers. */ 767c3a2f0dfSAndrew Vasquez mbx_reg = ®->mailbox0; 7686d9b61edSAndrew Vasquez for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++) 769a7a167bfSAndrew Vasquez fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg++)); 7706d9b61edSAndrew Vasquez 7716d9b61edSAndrew Vasquez /* Transfer sequence registers. */ 7726d9b61edSAndrew Vasquez iter_reg = fw->xseq_gp_reg; 773c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0xBF00, 16, iter_reg); 774c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0xBF10, 16, iter_reg); 775c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0xBF20, 16, iter_reg); 776c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0xBF30, 16, iter_reg); 777c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0xBF40, 16, iter_reg); 778c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0xBF50, 16, iter_reg); 779c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0xBF60, 16, iter_reg); 780c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0xBF70, 16, iter_reg); 7816d9b61edSAndrew Vasquez 782c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0xBFE0, 16, fw->xseq_0_reg); 783c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0xBFF0, 16, fw->xseq_1_reg); 7846d9b61edSAndrew Vasquez 7856d9b61edSAndrew Vasquez /* Receive sequence registers. */ 7866d9b61edSAndrew Vasquez iter_reg = fw->rseq_gp_reg; 787c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0xFF00, 16, iter_reg); 788c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0xFF10, 16, iter_reg); 789c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0xFF20, 16, iter_reg); 790c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0xFF30, 16, iter_reg); 791c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0xFF40, 16, iter_reg); 792c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0xFF50, 16, iter_reg); 793c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0xFF60, 16, iter_reg); 794c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0xFF70, 16, iter_reg); 7956d9b61edSAndrew Vasquez 796c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0xFFD0, 16, fw->rseq_0_reg); 797c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0xFFE0, 16, fw->rseq_1_reg); 798c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0xFFF0, 16, fw->rseq_2_reg); 7996d9b61edSAndrew Vasquez 8006d9b61edSAndrew Vasquez /* Command DMA registers. */ 801c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0x7100, 16, fw->cmd_dma_reg); 8026d9b61edSAndrew Vasquez 8036d9b61edSAndrew Vasquez /* Queues. */ 8046d9b61edSAndrew Vasquez iter_reg = fw->req0_dma_reg; 805c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x7200, 8, iter_reg); 806c3a2f0dfSAndrew Vasquez dmp_reg = ®->iobase_q; 8076d9b61edSAndrew Vasquez for (cnt = 0; cnt < 7; cnt++) 808a7a167bfSAndrew Vasquez *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); 8096d9b61edSAndrew Vasquez 8106d9b61edSAndrew Vasquez iter_reg = fw->resp0_dma_reg; 811c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x7300, 8, iter_reg); 812c3a2f0dfSAndrew Vasquez dmp_reg = ®->iobase_q; 8136d9b61edSAndrew Vasquez for (cnt = 0; cnt < 7; cnt++) 814a7a167bfSAndrew Vasquez *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); 8156d9b61edSAndrew Vasquez 8166d9b61edSAndrew Vasquez iter_reg = fw->req1_dma_reg; 817c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x7400, 8, iter_reg); 818c3a2f0dfSAndrew Vasquez dmp_reg = ®->iobase_q; 8196d9b61edSAndrew Vasquez for (cnt = 0; cnt < 7; cnt++) 820a7a167bfSAndrew Vasquez *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); 8216d9b61edSAndrew Vasquez 8226d9b61edSAndrew Vasquez /* Transmit DMA registers. */ 8236d9b61edSAndrew Vasquez iter_reg = fw->xmt0_dma_reg; 824c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x7600, 16, iter_reg); 825c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0x7610, 16, iter_reg); 8266d9b61edSAndrew Vasquez 8276d9b61edSAndrew Vasquez iter_reg = fw->xmt1_dma_reg; 828c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x7620, 16, iter_reg); 829c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0x7630, 16, iter_reg); 8306d9b61edSAndrew Vasquez 8316d9b61edSAndrew Vasquez iter_reg = fw->xmt2_dma_reg; 832c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x7640, 16, iter_reg); 833c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0x7650, 16, iter_reg); 8346d9b61edSAndrew Vasquez 8356d9b61edSAndrew Vasquez iter_reg = fw->xmt3_dma_reg; 836c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x7660, 16, iter_reg); 837c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0x7670, 16, iter_reg); 8386d9b61edSAndrew Vasquez 8396d9b61edSAndrew Vasquez iter_reg = fw->xmt4_dma_reg; 840c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x7680, 16, iter_reg); 841c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0x7690, 16, iter_reg); 8426d9b61edSAndrew Vasquez 843c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0x76A0, 16, fw->xmt_data_dma_reg); 8446d9b61edSAndrew Vasquez 8456d9b61edSAndrew Vasquez /* Receive DMA registers. */ 8466d9b61edSAndrew Vasquez iter_reg = fw->rcvt0_data_dma_reg; 847c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x7700, 16, iter_reg); 848c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0x7710, 16, iter_reg); 8496d9b61edSAndrew Vasquez 8506d9b61edSAndrew Vasquez iter_reg = fw->rcvt1_data_dma_reg; 851c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x7720, 16, iter_reg); 852c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0x7730, 16, iter_reg); 8536d9b61edSAndrew Vasquez 8546d9b61edSAndrew Vasquez /* RISC registers. */ 8556d9b61edSAndrew Vasquez iter_reg = fw->risc_gp_reg; 856c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x0F00, 16, iter_reg); 857c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x0F10, 16, iter_reg); 858c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x0F20, 16, iter_reg); 859c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x0F30, 16, iter_reg); 860c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x0F40, 16, iter_reg); 861c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x0F50, 16, iter_reg); 862c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x0F60, 16, iter_reg); 863c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0x0F70, 16, iter_reg); 8646d9b61edSAndrew Vasquez 8656d9b61edSAndrew Vasquez /* Local memory controller registers. */ 8666d9b61edSAndrew Vasquez iter_reg = fw->lmc_reg; 867c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x3000, 16, iter_reg); 868c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x3010, 16, iter_reg); 869c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x3020, 16, iter_reg); 870c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x3030, 16, iter_reg); 871c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x3040, 16, iter_reg); 872c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x3050, 16, iter_reg); 873c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0x3060, 16, iter_reg); 8746d9b61edSAndrew Vasquez 8756d9b61edSAndrew Vasquez /* Fibre Protocol Module registers. */ 8766d9b61edSAndrew Vasquez iter_reg = fw->fpm_hdw_reg; 877c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x4000, 16, iter_reg); 878c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x4010, 16, iter_reg); 879c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x4020, 16, iter_reg); 880c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x4030, 16, iter_reg); 881c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x4040, 16, iter_reg); 882c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x4050, 16, iter_reg); 883c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x4060, 16, iter_reg); 884c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x4070, 16, iter_reg); 885c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x4080, 16, iter_reg); 886c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x4090, 16, iter_reg); 887c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x40A0, 16, iter_reg); 888c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0x40B0, 16, iter_reg); 8896d9b61edSAndrew Vasquez 8906d9b61edSAndrew Vasquez /* Frame Buffer registers. */ 8916d9b61edSAndrew Vasquez iter_reg = fw->fb_hdw_reg; 892c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x6000, 16, iter_reg); 893c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x6010, 16, iter_reg); 894c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x6020, 16, iter_reg); 895c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x6030, 16, iter_reg); 896c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x6040, 16, iter_reg); 897c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x6100, 16, iter_reg); 898c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x6130, 16, iter_reg); 899c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x6150, 16, iter_reg); 900c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x6170, 16, iter_reg); 901c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x6190, 16, iter_reg); 902c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0x61B0, 16, iter_reg); 9036d9b61edSAndrew Vasquez 904c81d04c9SAndrew Vasquez rval = qla24xx_soft_reset(ha); 905c81d04c9SAndrew Vasquez if (rval != QLA_SUCCESS) 906c81d04c9SAndrew Vasquez goto qla24xx_fw_dump_failed_0; 9076d9b61edSAndrew Vasquez 908c81d04c9SAndrew Vasquez rval = qla24xx_dump_memory(ha, fw->code_ram, sizeof(fw->code_ram), 909c5722708SAndrew Vasquez &nxt); 910c81d04c9SAndrew Vasquez if (rval != QLA_SUCCESS) 911c81d04c9SAndrew Vasquez goto qla24xx_fw_dump_failed_0; 9126d9b61edSAndrew Vasquez 913*7b867cf7SAnirban Chakraborty nxt = qla2xxx_copy_queues(vha, nxt); 914a7a167bfSAndrew Vasquez if (ha->eft) 915c3a2f0dfSAndrew Vasquez memcpy(nxt, ha->eft, ntohl(ha->fw_dump->eft_size)); 916a7a167bfSAndrew Vasquez 917c81d04c9SAndrew Vasquez qla24xx_fw_dump_failed_0: 9186d9b61edSAndrew Vasquez if (rval != QLA_SUCCESS) { 9196d9b61edSAndrew Vasquez qla_printk(KERN_WARNING, ha, 9206d9b61edSAndrew Vasquez "Failed to dump firmware (%x)!!!\n", rval); 9216d9b61edSAndrew Vasquez ha->fw_dumped = 0; 9226d9b61edSAndrew Vasquez 9236d9b61edSAndrew Vasquez } else { 9246d9b61edSAndrew Vasquez qla_printk(KERN_INFO, ha, 9256d9b61edSAndrew Vasquez "Firmware dump saved to temp buffer (%ld/%p).\n", 926*7b867cf7SAnirban Chakraborty vha->host_no, ha->fw_dump); 9276d9b61edSAndrew Vasquez ha->fw_dumped = 1; 9286d9b61edSAndrew Vasquez } 9296d9b61edSAndrew Vasquez 9306d9b61edSAndrew Vasquez qla24xx_fw_dump_failed: 9316d9b61edSAndrew Vasquez if (!hardware_locked) 9326d9b61edSAndrew Vasquez spin_unlock_irqrestore(&ha->hardware_lock, flags); 9336d9b61edSAndrew Vasquez } 9346d9b61edSAndrew Vasquez 935c3a2f0dfSAndrew Vasquez void 936*7b867cf7SAnirban Chakraborty qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) 937c3a2f0dfSAndrew Vasquez { 938c3a2f0dfSAndrew Vasquez int rval; 939c3a2f0dfSAndrew Vasquez uint32_t cnt; 940c3a2f0dfSAndrew Vasquez uint32_t risc_address; 941*7b867cf7SAnirban Chakraborty struct qla_hw_data *ha = vha->hw; 942c3a2f0dfSAndrew Vasquez struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; 943c3a2f0dfSAndrew Vasquez uint32_t __iomem *dmp_reg; 944c3a2f0dfSAndrew Vasquez uint32_t *iter_reg; 945c3a2f0dfSAndrew Vasquez uint16_t __iomem *mbx_reg; 946c3a2f0dfSAndrew Vasquez unsigned long flags; 947c3a2f0dfSAndrew Vasquez struct qla25xx_fw_dump *fw; 948c3a2f0dfSAndrew Vasquez uint32_t ext_mem_cnt; 949c3a2f0dfSAndrew Vasquez void *nxt; 950df613b96SAndrew Vasquez struct qla2xxx_fce_chain *fcec; 951c3a2f0dfSAndrew Vasquez 952c3a2f0dfSAndrew Vasquez risc_address = ext_mem_cnt = 0; 953c3a2f0dfSAndrew Vasquez flags = 0; 954c3a2f0dfSAndrew Vasquez 955c3a2f0dfSAndrew Vasquez if (!hardware_locked) 956c3a2f0dfSAndrew Vasquez spin_lock_irqsave(&ha->hardware_lock, flags); 957c3a2f0dfSAndrew Vasquez 958c3a2f0dfSAndrew Vasquez if (!ha->fw_dump) { 959c3a2f0dfSAndrew Vasquez qla_printk(KERN_WARNING, ha, 960c3a2f0dfSAndrew Vasquez "No buffer available for dump!!!\n"); 961c3a2f0dfSAndrew Vasquez goto qla25xx_fw_dump_failed; 962c3a2f0dfSAndrew Vasquez } 963c3a2f0dfSAndrew Vasquez 964c3a2f0dfSAndrew Vasquez if (ha->fw_dumped) { 965c3a2f0dfSAndrew Vasquez qla_printk(KERN_WARNING, ha, 966c3a2f0dfSAndrew Vasquez "Firmware has been previously dumped (%p) -- ignoring " 967c3a2f0dfSAndrew Vasquez "request...\n", ha->fw_dump); 968c3a2f0dfSAndrew Vasquez goto qla25xx_fw_dump_failed; 969c3a2f0dfSAndrew Vasquez } 970c3a2f0dfSAndrew Vasquez fw = &ha->fw_dump->isp.isp25; 971c3a2f0dfSAndrew Vasquez qla2xxx_prep_dump(ha, ha->fw_dump); 972b5836927SAndrew Vasquez ha->fw_dump->version = __constant_htonl(2); 973c3a2f0dfSAndrew Vasquez 974c3a2f0dfSAndrew Vasquez fw->host_status = htonl(RD_REG_DWORD(®->host_status)); 975c3a2f0dfSAndrew Vasquez 976c3a2f0dfSAndrew Vasquez /* Pause RISC. */ 977c81d04c9SAndrew Vasquez rval = qla24xx_pause_risc(reg); 978c81d04c9SAndrew Vasquez if (rval != QLA_SUCCESS) 979c81d04c9SAndrew Vasquez goto qla25xx_fw_dump_failed_0; 980c3a2f0dfSAndrew Vasquez 981b5836927SAndrew Vasquez /* Host/Risc registers. */ 982b5836927SAndrew Vasquez iter_reg = fw->host_risc_reg; 983b5836927SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x7000, 16, iter_reg); 984b5836927SAndrew Vasquez qla24xx_read_window(reg, 0x7010, 16, iter_reg); 985b5836927SAndrew Vasquez 986b5836927SAndrew Vasquez /* PCIe registers. */ 987b5836927SAndrew Vasquez WRT_REG_DWORD(®->iobase_addr, 0x7C00); 988b5836927SAndrew Vasquez RD_REG_DWORD(®->iobase_addr); 989b5836927SAndrew Vasquez WRT_REG_DWORD(®->iobase_window, 0x01); 990b5836927SAndrew Vasquez dmp_reg = ®->iobase_c4; 991b5836927SAndrew Vasquez fw->pcie_regs[0] = htonl(RD_REG_DWORD(dmp_reg++)); 992b5836927SAndrew Vasquez fw->pcie_regs[1] = htonl(RD_REG_DWORD(dmp_reg++)); 993b5836927SAndrew Vasquez fw->pcie_regs[2] = htonl(RD_REG_DWORD(dmp_reg)); 994b5836927SAndrew Vasquez fw->pcie_regs[3] = htonl(RD_REG_DWORD(®->iobase_window)); 995b5836927SAndrew Vasquez WRT_REG_DWORD(®->iobase_window, 0x00); 996b5836927SAndrew Vasquez RD_REG_DWORD(®->iobase_window); 997b5836927SAndrew Vasquez 998c3a2f0dfSAndrew Vasquez /* Host interface registers. */ 999c81d04c9SAndrew Vasquez dmp_reg = ®->flash_addr; 1000c3a2f0dfSAndrew Vasquez for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++) 1001c3a2f0dfSAndrew Vasquez fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); 1002c3a2f0dfSAndrew Vasquez 1003c3a2f0dfSAndrew Vasquez /* Disable interrupts. */ 1004c3a2f0dfSAndrew Vasquez WRT_REG_DWORD(®->ictrl, 0); 1005c3a2f0dfSAndrew Vasquez RD_REG_DWORD(®->ictrl); 1006c3a2f0dfSAndrew Vasquez 1007c3a2f0dfSAndrew Vasquez /* Shadow registers. */ 1008c3a2f0dfSAndrew Vasquez WRT_REG_DWORD(®->iobase_addr, 0x0F70); 1009c3a2f0dfSAndrew Vasquez RD_REG_DWORD(®->iobase_addr); 1010c3a2f0dfSAndrew Vasquez WRT_REG_DWORD(®->iobase_select, 0xB0000000); 1011c3a2f0dfSAndrew Vasquez fw->shadow_reg[0] = htonl(RD_REG_DWORD(®->iobase_sdata)); 1012c3a2f0dfSAndrew Vasquez 1013c3a2f0dfSAndrew Vasquez WRT_REG_DWORD(®->iobase_select, 0xB0100000); 1014c3a2f0dfSAndrew Vasquez fw->shadow_reg[1] = htonl(RD_REG_DWORD(®->iobase_sdata)); 1015c3a2f0dfSAndrew Vasquez 1016c3a2f0dfSAndrew Vasquez WRT_REG_DWORD(®->iobase_select, 0xB0200000); 1017c3a2f0dfSAndrew Vasquez fw->shadow_reg[2] = htonl(RD_REG_DWORD(®->iobase_sdata)); 1018c3a2f0dfSAndrew Vasquez 1019c3a2f0dfSAndrew Vasquez WRT_REG_DWORD(®->iobase_select, 0xB0300000); 1020c3a2f0dfSAndrew Vasquez fw->shadow_reg[3] = htonl(RD_REG_DWORD(®->iobase_sdata)); 1021c3a2f0dfSAndrew Vasquez 1022c3a2f0dfSAndrew Vasquez WRT_REG_DWORD(®->iobase_select, 0xB0400000); 1023c3a2f0dfSAndrew Vasquez fw->shadow_reg[4] = htonl(RD_REG_DWORD(®->iobase_sdata)); 1024c3a2f0dfSAndrew Vasquez 1025c3a2f0dfSAndrew Vasquez WRT_REG_DWORD(®->iobase_select, 0xB0500000); 1026c3a2f0dfSAndrew Vasquez fw->shadow_reg[5] = htonl(RD_REG_DWORD(®->iobase_sdata)); 1027c3a2f0dfSAndrew Vasquez 1028c3a2f0dfSAndrew Vasquez WRT_REG_DWORD(®->iobase_select, 0xB0600000); 1029c3a2f0dfSAndrew Vasquez fw->shadow_reg[6] = htonl(RD_REG_DWORD(®->iobase_sdata)); 1030c3a2f0dfSAndrew Vasquez 1031c3a2f0dfSAndrew Vasquez WRT_REG_DWORD(®->iobase_select, 0xB0700000); 1032c3a2f0dfSAndrew Vasquez fw->shadow_reg[7] = htonl(RD_REG_DWORD(®->iobase_sdata)); 1033c3a2f0dfSAndrew Vasquez 1034c3a2f0dfSAndrew Vasquez WRT_REG_DWORD(®->iobase_select, 0xB0800000); 1035c3a2f0dfSAndrew Vasquez fw->shadow_reg[8] = htonl(RD_REG_DWORD(®->iobase_sdata)); 1036c3a2f0dfSAndrew Vasquez 1037c3a2f0dfSAndrew Vasquez WRT_REG_DWORD(®->iobase_select, 0xB0900000); 1038c3a2f0dfSAndrew Vasquez fw->shadow_reg[9] = htonl(RD_REG_DWORD(®->iobase_sdata)); 1039c3a2f0dfSAndrew Vasquez 1040c3a2f0dfSAndrew Vasquez WRT_REG_DWORD(®->iobase_select, 0xB0A00000); 1041c3a2f0dfSAndrew Vasquez fw->shadow_reg[10] = htonl(RD_REG_DWORD(®->iobase_sdata)); 1042c3a2f0dfSAndrew Vasquez 1043c3a2f0dfSAndrew Vasquez /* RISC I/O register. */ 1044c3a2f0dfSAndrew Vasquez WRT_REG_DWORD(®->iobase_addr, 0x0010); 1045c3a2f0dfSAndrew Vasquez fw->risc_io_reg = htonl(RD_REG_DWORD(®->iobase_window)); 1046c3a2f0dfSAndrew Vasquez 1047c3a2f0dfSAndrew Vasquez /* Mailbox registers. */ 1048c3a2f0dfSAndrew Vasquez mbx_reg = ®->mailbox0; 1049c3a2f0dfSAndrew Vasquez for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++) 1050c3a2f0dfSAndrew Vasquez fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg++)); 1051c3a2f0dfSAndrew Vasquez 1052c3a2f0dfSAndrew Vasquez /* Transfer sequence registers. */ 1053c3a2f0dfSAndrew Vasquez iter_reg = fw->xseq_gp_reg; 1054c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0xBF00, 16, iter_reg); 1055c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0xBF10, 16, iter_reg); 1056c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0xBF20, 16, iter_reg); 1057c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0xBF30, 16, iter_reg); 1058c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0xBF40, 16, iter_reg); 1059c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0xBF50, 16, iter_reg); 1060c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0xBF60, 16, iter_reg); 1061c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0xBF70, 16, iter_reg); 1062c3a2f0dfSAndrew Vasquez 1063c3a2f0dfSAndrew Vasquez iter_reg = fw->xseq_0_reg; 1064c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0xBFC0, 16, iter_reg); 1065c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0xBFD0, 16, iter_reg); 1066c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0xBFE0, 16, iter_reg); 1067c3a2f0dfSAndrew Vasquez 1068c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0xBFF0, 16, fw->xseq_1_reg); 1069c3a2f0dfSAndrew Vasquez 1070c3a2f0dfSAndrew Vasquez /* Receive sequence registers. */ 1071c3a2f0dfSAndrew Vasquez iter_reg = fw->rseq_gp_reg; 1072c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0xFF00, 16, iter_reg); 1073c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0xFF10, 16, iter_reg); 1074c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0xFF20, 16, iter_reg); 1075c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0xFF30, 16, iter_reg); 1076c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0xFF40, 16, iter_reg); 1077c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0xFF50, 16, iter_reg); 1078c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0xFF60, 16, iter_reg); 1079c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0xFF70, 16, iter_reg); 1080c3a2f0dfSAndrew Vasquez 1081c3a2f0dfSAndrew Vasquez iter_reg = fw->rseq_0_reg; 1082c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0xFFC0, 16, iter_reg); 1083c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0xFFD0, 16, iter_reg); 1084c3a2f0dfSAndrew Vasquez 1085c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0xFFE0, 16, fw->rseq_1_reg); 1086c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0xFFF0, 16, fw->rseq_2_reg); 1087c3a2f0dfSAndrew Vasquez 1088c3a2f0dfSAndrew Vasquez /* Auxiliary sequence registers. */ 1089c3a2f0dfSAndrew Vasquez iter_reg = fw->aseq_gp_reg; 1090c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0xB000, 16, iter_reg); 1091c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0xB010, 16, iter_reg); 1092c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0xB020, 16, iter_reg); 1093c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0xB030, 16, iter_reg); 1094c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0xB040, 16, iter_reg); 1095c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0xB050, 16, iter_reg); 1096c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0xB060, 16, iter_reg); 1097c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0xB070, 16, iter_reg); 1098c3a2f0dfSAndrew Vasquez 1099c3a2f0dfSAndrew Vasquez iter_reg = fw->aseq_0_reg; 1100c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0xB0C0, 16, iter_reg); 1101c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0xB0D0, 16, iter_reg); 1102c3a2f0dfSAndrew Vasquez 1103c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0xB0E0, 16, fw->aseq_1_reg); 1104c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0xB0F0, 16, fw->aseq_2_reg); 1105c3a2f0dfSAndrew Vasquez 1106c3a2f0dfSAndrew Vasquez /* Command DMA registers. */ 1107c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0x7100, 16, fw->cmd_dma_reg); 1108c3a2f0dfSAndrew Vasquez 1109c3a2f0dfSAndrew Vasquez /* Queues. */ 1110c3a2f0dfSAndrew Vasquez iter_reg = fw->req0_dma_reg; 1111c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x7200, 8, iter_reg); 1112c3a2f0dfSAndrew Vasquez dmp_reg = ®->iobase_q; 1113c3a2f0dfSAndrew Vasquez for (cnt = 0; cnt < 7; cnt++) 1114c3a2f0dfSAndrew Vasquez *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); 1115c3a2f0dfSAndrew Vasquez 1116c3a2f0dfSAndrew Vasquez iter_reg = fw->resp0_dma_reg; 1117c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x7300, 8, iter_reg); 1118c3a2f0dfSAndrew Vasquez dmp_reg = ®->iobase_q; 1119c3a2f0dfSAndrew Vasquez for (cnt = 0; cnt < 7; cnt++) 1120c3a2f0dfSAndrew Vasquez *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); 1121c3a2f0dfSAndrew Vasquez 1122c3a2f0dfSAndrew Vasquez iter_reg = fw->req1_dma_reg; 1123c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x7400, 8, iter_reg); 1124c3a2f0dfSAndrew Vasquez dmp_reg = ®->iobase_q; 1125c3a2f0dfSAndrew Vasquez for (cnt = 0; cnt < 7; cnt++) 1126c3a2f0dfSAndrew Vasquez *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); 1127c3a2f0dfSAndrew Vasquez 1128c3a2f0dfSAndrew Vasquez /* Transmit DMA registers. */ 1129c3a2f0dfSAndrew Vasquez iter_reg = fw->xmt0_dma_reg; 1130c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x7600, 16, iter_reg); 1131c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0x7610, 16, iter_reg); 1132c3a2f0dfSAndrew Vasquez 1133c3a2f0dfSAndrew Vasquez iter_reg = fw->xmt1_dma_reg; 1134c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x7620, 16, iter_reg); 1135c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0x7630, 16, iter_reg); 1136c3a2f0dfSAndrew Vasquez 1137c3a2f0dfSAndrew Vasquez iter_reg = fw->xmt2_dma_reg; 1138c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x7640, 16, iter_reg); 1139c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0x7650, 16, iter_reg); 1140c3a2f0dfSAndrew Vasquez 1141c3a2f0dfSAndrew Vasquez iter_reg = fw->xmt3_dma_reg; 1142c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x7660, 16, iter_reg); 1143c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0x7670, 16, iter_reg); 1144c3a2f0dfSAndrew Vasquez 1145c3a2f0dfSAndrew Vasquez iter_reg = fw->xmt4_dma_reg; 1146c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x7680, 16, iter_reg); 1147c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0x7690, 16, iter_reg); 1148c3a2f0dfSAndrew Vasquez 1149c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0x76A0, 16, fw->xmt_data_dma_reg); 1150c3a2f0dfSAndrew Vasquez 1151c3a2f0dfSAndrew Vasquez /* Receive DMA registers. */ 1152c3a2f0dfSAndrew Vasquez iter_reg = fw->rcvt0_data_dma_reg; 1153c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x7700, 16, iter_reg); 1154c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0x7710, 16, iter_reg); 1155c3a2f0dfSAndrew Vasquez 1156c3a2f0dfSAndrew Vasquez iter_reg = fw->rcvt1_data_dma_reg; 1157c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x7720, 16, iter_reg); 1158c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0x7730, 16, iter_reg); 1159c3a2f0dfSAndrew Vasquez 1160c3a2f0dfSAndrew Vasquez /* RISC registers. */ 1161c3a2f0dfSAndrew Vasquez iter_reg = fw->risc_gp_reg; 1162c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x0F00, 16, iter_reg); 1163c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x0F10, 16, iter_reg); 1164c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x0F20, 16, iter_reg); 1165c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x0F30, 16, iter_reg); 1166c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x0F40, 16, iter_reg); 1167c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x0F50, 16, iter_reg); 1168c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x0F60, 16, iter_reg); 1169c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0x0F70, 16, iter_reg); 1170c3a2f0dfSAndrew Vasquez 1171c3a2f0dfSAndrew Vasquez /* Local memory controller registers. */ 1172c3a2f0dfSAndrew Vasquez iter_reg = fw->lmc_reg; 1173c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x3000, 16, iter_reg); 1174c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x3010, 16, iter_reg); 1175c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x3020, 16, iter_reg); 1176c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x3030, 16, iter_reg); 1177c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x3040, 16, iter_reg); 1178c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x3050, 16, iter_reg); 1179c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x3060, 16, iter_reg); 1180c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0x3070, 16, iter_reg); 1181c3a2f0dfSAndrew Vasquez 1182c3a2f0dfSAndrew Vasquez /* Fibre Protocol Module registers. */ 1183c3a2f0dfSAndrew Vasquez iter_reg = fw->fpm_hdw_reg; 1184c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x4000, 16, iter_reg); 1185c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x4010, 16, iter_reg); 1186c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x4020, 16, iter_reg); 1187c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x4030, 16, iter_reg); 1188c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x4040, 16, iter_reg); 1189c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x4050, 16, iter_reg); 1190c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x4060, 16, iter_reg); 1191c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x4070, 16, iter_reg); 1192c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x4080, 16, iter_reg); 1193c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x4090, 16, iter_reg); 1194c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x40A0, 16, iter_reg); 1195c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0x40B0, 16, iter_reg); 1196c3a2f0dfSAndrew Vasquez 1197c3a2f0dfSAndrew Vasquez /* Frame Buffer registers. */ 1198c3a2f0dfSAndrew Vasquez iter_reg = fw->fb_hdw_reg; 1199c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x6000, 16, iter_reg); 1200c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x6010, 16, iter_reg); 1201c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x6020, 16, iter_reg); 1202c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x6030, 16, iter_reg); 1203c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x6040, 16, iter_reg); 1204c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x6100, 16, iter_reg); 1205c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x6130, 16, iter_reg); 1206c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x6150, 16, iter_reg); 1207c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x6170, 16, iter_reg); 1208c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x6190, 16, iter_reg); 1209c81d04c9SAndrew Vasquez iter_reg = qla24xx_read_window(reg, 0x61B0, 16, iter_reg); 1210c81d04c9SAndrew Vasquez qla24xx_read_window(reg, 0x6F00, 16, iter_reg); 1211c3a2f0dfSAndrew Vasquez 1212c81d04c9SAndrew Vasquez rval = qla24xx_soft_reset(ha); 1213c81d04c9SAndrew Vasquez if (rval != QLA_SUCCESS) 1214c81d04c9SAndrew Vasquez goto qla25xx_fw_dump_failed_0; 1215c3a2f0dfSAndrew Vasquez 1216c81d04c9SAndrew Vasquez rval = qla24xx_dump_memory(ha, fw->code_ram, sizeof(fw->code_ram), 1217c5722708SAndrew Vasquez &nxt); 1218c81d04c9SAndrew Vasquez if (rval != QLA_SUCCESS) 1219c81d04c9SAndrew Vasquez goto qla25xx_fw_dump_failed_0; 1220c3a2f0dfSAndrew Vasquez 1221df613b96SAndrew Vasquez /* Fibre Channel Trace Buffer. */ 1222*7b867cf7SAnirban Chakraborty nxt = qla2xxx_copy_queues(vha, nxt); 1223c3a2f0dfSAndrew Vasquez if (ha->eft) 1224c3a2f0dfSAndrew Vasquez memcpy(nxt, ha->eft, ntohl(ha->fw_dump->eft_size)); 1225c3a2f0dfSAndrew Vasquez 1226df613b96SAndrew Vasquez /* Fibre Channel Event Buffer. */ 1227df613b96SAndrew Vasquez if (!ha->fce) 1228df613b96SAndrew Vasquez goto qla25xx_fw_dump_failed_0; 1229df613b96SAndrew Vasquez 1230df613b96SAndrew Vasquez ha->fw_dump->version |= __constant_htonl(DUMP_CHAIN_VARIANT); 1231df613b96SAndrew Vasquez 1232df613b96SAndrew Vasquez fcec = nxt + ntohl(ha->fw_dump->eft_size); 1233df613b96SAndrew Vasquez fcec->type = __constant_htonl(DUMP_CHAIN_FCE | DUMP_CHAIN_LAST); 1234df613b96SAndrew Vasquez fcec->chain_size = htonl(sizeof(struct qla2xxx_fce_chain) + 1235df613b96SAndrew Vasquez fce_calc_size(ha->fce_bufs)); 1236df613b96SAndrew Vasquez fcec->size = htonl(fce_calc_size(ha->fce_bufs)); 1237df613b96SAndrew Vasquez fcec->addr_l = htonl(LSD(ha->fce_dma)); 1238df613b96SAndrew Vasquez fcec->addr_h = htonl(MSD(ha->fce_dma)); 1239df613b96SAndrew Vasquez 1240df613b96SAndrew Vasquez iter_reg = fcec->eregs; 1241df613b96SAndrew Vasquez for (cnt = 0; cnt < 8; cnt++) 1242df613b96SAndrew Vasquez *iter_reg++ = htonl(ha->fce_mb[cnt]); 1243df613b96SAndrew Vasquez 1244df613b96SAndrew Vasquez memcpy(iter_reg, ha->fce, ntohl(fcec->size)); 1245df613b96SAndrew Vasquez 1246c81d04c9SAndrew Vasquez qla25xx_fw_dump_failed_0: 1247c3a2f0dfSAndrew Vasquez if (rval != QLA_SUCCESS) { 1248c3a2f0dfSAndrew Vasquez qla_printk(KERN_WARNING, ha, 1249c3a2f0dfSAndrew Vasquez "Failed to dump firmware (%x)!!!\n", rval); 1250c3a2f0dfSAndrew Vasquez ha->fw_dumped = 0; 1251c3a2f0dfSAndrew Vasquez 1252c3a2f0dfSAndrew Vasquez } else { 1253c3a2f0dfSAndrew Vasquez qla_printk(KERN_INFO, ha, 1254c3a2f0dfSAndrew Vasquez "Firmware dump saved to temp buffer (%ld/%p).\n", 1255*7b867cf7SAnirban Chakraborty vha->host_no, ha->fw_dump); 1256c3a2f0dfSAndrew Vasquez ha->fw_dumped = 1; 1257c3a2f0dfSAndrew Vasquez } 1258c3a2f0dfSAndrew Vasquez 1259c3a2f0dfSAndrew Vasquez qla25xx_fw_dump_failed: 1260c3a2f0dfSAndrew Vasquez if (!hardware_locked) 1261c3a2f0dfSAndrew Vasquez spin_unlock_irqrestore(&ha->hardware_lock, flags); 1262c3a2f0dfSAndrew Vasquez } 1263c3a2f0dfSAndrew Vasquez 12641da177e4SLinus Torvalds /****************************************************************************/ 12651da177e4SLinus Torvalds /* Driver Debug Functions. */ 12661da177e4SLinus Torvalds /****************************************************************************/ 12671da177e4SLinus Torvalds 12681da177e4SLinus Torvalds void 1269*7b867cf7SAnirban Chakraborty qla2x00_dump_regs(scsi_qla_host_t *vha) 12701da177e4SLinus Torvalds { 12716afd9763SAndrew Vasquez int i; 1272*7b867cf7SAnirban Chakraborty struct qla_hw_data *ha = vha->hw; 12733d71644cSAndrew Vasquez struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; 12746afd9763SAndrew Vasquez struct device_reg_24xx __iomem *reg24 = &ha->iobase->isp24; 12756afd9763SAndrew Vasquez uint16_t __iomem *mbx_reg; 12766afd9763SAndrew Vasquez 12776afd9763SAndrew Vasquez mbx_reg = IS_FWI2_CAPABLE(ha) ? ®24->mailbox0: 12786afd9763SAndrew Vasquez MAILBOX_REG(ha, reg, 0); 12791da177e4SLinus Torvalds 12801da177e4SLinus Torvalds printk("Mailbox registers:\n"); 12816afd9763SAndrew Vasquez for (i = 0; i < 6; i++) 1282*7b867cf7SAnirban Chakraborty printk("scsi(%ld): mbox %d 0x%04x \n", vha->host_no, i, 12836afd9763SAndrew Vasquez RD_REG_WORD(mbx_reg++)); 12841da177e4SLinus Torvalds } 12851da177e4SLinus Torvalds 12861da177e4SLinus Torvalds 12871da177e4SLinus Torvalds void 12881da177e4SLinus Torvalds qla2x00_dump_buffer(uint8_t * b, uint32_t size) 12891da177e4SLinus Torvalds { 12901da177e4SLinus Torvalds uint32_t cnt; 12911da177e4SLinus Torvalds uint8_t c; 12921da177e4SLinus Torvalds 12931da177e4SLinus Torvalds printk(" 0 1 2 3 4 5 6 7 8 9 " 12941da177e4SLinus Torvalds "Ah Bh Ch Dh Eh Fh\n"); 12951da177e4SLinus Torvalds printk("----------------------------------------" 12961da177e4SLinus Torvalds "----------------------\n"); 12971da177e4SLinus Torvalds 12981da177e4SLinus Torvalds for (cnt = 0; cnt < size;) { 12991da177e4SLinus Torvalds c = *b++; 13001da177e4SLinus Torvalds printk("%02x",(uint32_t) c); 13011da177e4SLinus Torvalds cnt++; 13021da177e4SLinus Torvalds if (!(cnt % 16)) 13031da177e4SLinus Torvalds printk("\n"); 13041da177e4SLinus Torvalds else 13051da177e4SLinus Torvalds printk(" "); 13061da177e4SLinus Torvalds } 13071da177e4SLinus Torvalds if (cnt % 16) 13081da177e4SLinus Torvalds printk("\n"); 13091da177e4SLinus Torvalds } 1310