diff options
Diffstat (limited to 'drivers/scsi/qla2xxx')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_attr.c | 26 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_dbg.c | 462 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_dbg.h | 40 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_def.h | 33 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_dfs.c | 3 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_fw.h | 294 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_gbl.h | 10 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_gs.c | 9 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 295 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_iocb.c | 12 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_isr.c | 82 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_mbx.c | 41 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_mid.c | 4 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 139 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_sup.c | 263 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_version.h | 6 |
16 files changed, 1345 insertions, 374 deletions
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index cd53627cc76..c7acef50d5d 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -303,7 +303,7 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, else if (start == (ha->flt_region_boot * 4) || start == (ha->flt_region_fw * 4)) valid = 1; - else if (IS_QLA25XX(ha) && + else if ((IS_QLA25XX(ha) || IS_QLA81XX(ha)) && start == (ha->flt_region_vpd_nvram * 4)) valid = 1; if (!valid) { @@ -815,6 +815,21 @@ qla2x00_total_isp_aborts_show(struct device *dev, ha->qla_stats.total_isp_aborts); } +static ssize_t +qla2x00_mpi_version_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); + struct qla_hw_data *ha = vha->hw; + + if (!IS_QLA81XX(ha)) + return snprintf(buf, PAGE_SIZE, "\n"); + + return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x (%x)\n", + ha->mpi_version[0], ha->mpi_version[1], ha->mpi_version[2], + ha->mpi_version[3], ha->mpi_capabilities); +} + static DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show, NULL); static DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL); static DEVICE_ATTR(serial_num, S_IRUGO, qla2x00_serial_num_show, NULL); @@ -839,6 +854,7 @@ static DEVICE_ATTR(optrom_fw_version, S_IRUGO, qla2x00_optrom_fw_version_show, NULL); static DEVICE_ATTR(total_isp_aborts, S_IRUGO, qla2x00_total_isp_aborts_show, NULL); +static DEVICE_ATTR(mpi_version, S_IRUGO, qla2x00_mpi_version_show, NULL); struct device_attribute *qla2x00_host_attrs[] = { &dev_attr_driver_version, @@ -858,6 +874,7 @@ struct device_attribute *qla2x00_host_attrs[] = { &dev_attr_optrom_fcode_version, &dev_attr_optrom_fw_version, &dev_attr_total_isp_aborts, + &dev_attr_mpi_version, NULL, }; @@ -892,6 +909,9 @@ qla2x00_get_host_speed(struct Scsi_Host *shost) case PORT_SPEED_8GB: speed = FC_PORTSPEED_8GBIT; break; + case PORT_SPEED_10GB: + speed = FC_PORTSPEED_10GBIT; + break; } fc_host_speed(shost) = speed; } @@ -1382,7 +1402,9 @@ qla2x00_init_host_attr(scsi_qla_host_t *vha) fc_host_max_npiv_vports(vha->host) = ha->max_npiv_vports; fc_host_npiv_vports_inuse(vha->host) = ha->cur_vport_count; - if (IS_QLA25XX(ha)) + if (IS_QLA81XX(ha)) + speed = FC_PORTSPEED_10GBIT; + else if (IS_QLA25XX(ha)) speed = FC_PORTSPEED_8GBIT | FC_PORTSPEED_4GBIT | FC_PORTSPEED_2GBIT | FC_PORTSPEED_1GBIT; else if (IS_QLA24XX_TYPE(ha)) diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 1cf77772623..34760f8d4f1 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -310,6 +310,76 @@ qla2xxx_read_window(struct device_reg_2xxx __iomem *reg, uint32_t count, *buf++ = htons(RD_REG_WORD(dmp_reg++)); } +static inline void * +qla24xx_copy_eft(struct qla_hw_data *ha, void *ptr) +{ + if (!ha->eft) + return ptr; + + memcpy(ptr, ha->eft, ntohl(ha->fw_dump->eft_size)); + return ptr + ntohl(ha->fw_dump->eft_size); +} + +static inline void * +qla25xx_copy_fce(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain) +{ + uint32_t cnt; + uint32_t *iter_reg; + struct qla2xxx_fce_chain *fcec = ptr; + + if (!ha->fce) + return ptr; + + *last_chain = &fcec->type; + fcec->type = __constant_htonl(DUMP_CHAIN_FCE); + fcec->chain_size = htonl(sizeof(struct qla2xxx_fce_chain) + + fce_calc_size(ha->fce_bufs)); + fcec->size = htonl(fce_calc_size(ha->fce_bufs)); + fcec->addr_l = htonl(LSD(ha->fce_dma)); + fcec->addr_h = htonl(MSD(ha->fce_dma)); + + iter_reg = fcec->eregs; + for (cnt = 0; cnt < 8; cnt++) + *iter_reg++ = htonl(ha->fce_mb[cnt]); + + memcpy(iter_reg, ha->fce, ntohl(fcec->size)); + + return iter_reg; +} + +static inline void * +qla25xx_copy_mq(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain) +{ + uint32_t cnt, que_idx; + uint8_t req_cnt, rsp_cnt, que_cnt; + struct qla2xxx_mq_chain *mq = ptr; + struct device_reg_25xxmq __iomem *reg; + + if (!ha->mqenable) + return ptr; + + mq = ptr; + *last_chain = &mq->type; + mq->type = __constant_htonl(DUMP_CHAIN_MQ); + mq->chain_size = __constant_htonl(sizeof(struct qla2xxx_mq_chain)); + + req_cnt = find_first_zero_bit(ha->req_qid_map, ha->max_queues); + rsp_cnt = find_first_zero_bit(ha->rsp_qid_map, ha->max_queues); + que_cnt = req_cnt > rsp_cnt ? req_cnt : rsp_cnt; + mq->count = htonl(que_cnt); + for (cnt = 0; cnt < que_cnt; cnt++) { + reg = (struct device_reg_25xxmq *) ((void *) + ha->mqiobase + cnt * QLA_QUE_PAGE); + que_idx = cnt * 4; + mq->qregs[que_idx] = htonl(RD_REG_DWORD(®->req_q_in)); + mq->qregs[que_idx+1] = htonl(RD_REG_DWORD(®->req_q_out)); + mq->qregs[que_idx+2] = htonl(RD_REG_DWORD(®->rsp_q_in)); + mq->qregs[que_idx+3] = htonl(RD_REG_DWORD(®->rsp_q_out)); + } + + return ptr + sizeof(struct qla2xxx_mq_chain); +} + /** * qla2300_fw_dump() - Dumps binary data from the 2300 firmware. * @ha: HA context @@ -913,8 +983,8 @@ qla24xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) goto qla24xx_fw_dump_failed_0; nxt = qla2xxx_copy_queues(ha, nxt); - if (ha->eft) - memcpy(nxt, ha->eft, ntohl(ha->fw_dump->eft_size)); + + qla24xx_copy_eft(ha, nxt); qla24xx_fw_dump_failed_0: if (rval != QLA_SUCCESS) { @@ -942,19 +1012,14 @@ qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) uint32_t risc_address; struct qla_hw_data *ha = vha->hw; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; - struct device_reg_25xxmq __iomem *reg25; uint32_t __iomem *dmp_reg; uint32_t *iter_reg; uint16_t __iomem *mbx_reg; unsigned long flags; struct qla25xx_fw_dump *fw; uint32_t ext_mem_cnt; - void *nxt; - struct qla2xxx_fce_chain *fcec; - struct qla2xxx_mq_chain *mq = NULL; - uint32_t qreg_size; - uint8_t req_cnt, rsp_cnt, que_cnt; - uint32_t que_idx; + void *nxt, *nxt_chain; + uint32_t *last_chain = NULL; struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); risc_address = ext_mem_cnt = 0; @@ -1001,28 +1066,6 @@ qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) fw->pcie_regs[2] = htonl(RD_REG_DWORD(dmp_reg)); fw->pcie_regs[3] = htonl(RD_REG_DWORD(®->iobase_window)); - /* Multi queue registers */ - if (ha->mqenable) { - qreg_size = sizeof(struct qla2xxx_mq_chain); - mq = kzalloc(qreg_size, GFP_KERNEL); - if (!mq) - goto qla25xx_fw_dump_failed_0; - req_cnt = find_first_zero_bit(ha->req_qid_map, ha->max_queues); - rsp_cnt = find_first_zero_bit(ha->rsp_qid_map, ha->max_queues); - que_cnt = req_cnt > rsp_cnt ? req_cnt : rsp_cnt; - mq->count = htonl(que_cnt); - mq->chain_size = htonl(qreg_size); - mq->type = __constant_htonl(DUMP_CHAIN_MQ); - for (cnt = 0; cnt < que_cnt; cnt++) { - reg25 = (struct device_reg_25xxmq *) ((void *) - ha->mqiobase + cnt * QLA_QUE_PAGE); - que_idx = cnt * 4; - mq->qregs[que_idx] = htonl(reg25->req_q_in); - mq->qregs[que_idx+1] = htonl(reg25->req_q_out); - mq->qregs[que_idx+2] = htonl(reg25->rsp_q_in); - mq->qregs[que_idx+3] = htonl(reg25->rsp_q_out); - } - } WRT_REG_DWORD(®->iobase_window, 0x00); RD_REG_DWORD(®->iobase_window); @@ -1240,6 +1283,10 @@ qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) iter_reg = qla24xx_read_window(reg, 0x61B0, 16, iter_reg); qla24xx_read_window(reg, 0x6F00, 16, iter_reg); + /* Multi queue registers */ + nxt_chain = qla25xx_copy_mq(ha, (void *)ha->fw_dump + ha->chain_offset, + &last_chain); + rval = qla24xx_soft_reset(ha); if (rval != QLA_SUCCESS) goto qla25xx_fw_dump_failed_0; @@ -1249,39 +1296,341 @@ qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) if (rval != QLA_SUCCESS) goto qla25xx_fw_dump_failed_0; - /* Fibre Channel Trace Buffer. */ nxt = qla2xxx_copy_queues(ha, nxt); - if (ha->eft) - memcpy(nxt, ha->eft, ntohl(ha->fw_dump->eft_size)); - /* Fibre Channel Event Buffer. */ - if (!ha->fce) - goto qla25xx_fw_dump_failed_0; + nxt = qla24xx_copy_eft(ha, nxt); + + /* Chain entries -- started with MQ. */ + qla25xx_copy_fce(ha, nxt_chain, &last_chain); + if (last_chain) { + ha->fw_dump->version |= __constant_htonl(DUMP_CHAIN_VARIANT); + *last_chain |= __constant_htonl(DUMP_CHAIN_LAST); + } - ha->fw_dump->version |= __constant_htonl(DUMP_CHAIN_VARIANT); +qla25xx_fw_dump_failed_0: + if (rval != QLA_SUCCESS) { + qla_printk(KERN_WARNING, ha, + "Failed to dump firmware (%x)!!!\n", rval); + ha->fw_dumped = 0; - if (ha->mqenable) { - nxt = nxt + ntohl(ha->fw_dump->eft_size); - memcpy(nxt, mq, qreg_size); - kfree(mq); - fcec = nxt + qreg_size; } else { - fcec = nxt + ntohl(ha->fw_dump->eft_size); + qla_printk(KERN_INFO, ha, + "Firmware dump saved to temp buffer (%ld/%p).\n", + base_vha->host_no, ha->fw_dump); + ha->fw_dumped = 1; } - fcec->type = __constant_htonl(DUMP_CHAIN_FCE | DUMP_CHAIN_LAST); - fcec->chain_size = htonl(sizeof(struct qla2xxx_fce_chain) + - fce_calc_size(ha->fce_bufs)); - fcec->size = htonl(fce_calc_size(ha->fce_bufs)); - fcec->addr_l = htonl(LSD(ha->fce_dma)); - fcec->addr_h = htonl(MSD(ha->fce_dma)); - iter_reg = fcec->eregs; - for (cnt = 0; cnt < 8; cnt++) - *iter_reg++ = htonl(ha->fce_mb[cnt]); +qla25xx_fw_dump_failed: + if (!hardware_locked) + spin_unlock_irqrestore(&ha->hardware_lock, flags); +} - memcpy(iter_reg, ha->fce, ntohl(fcec->size)); +void +qla81xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) +{ + int rval; + uint32_t cnt; + uint32_t risc_address; + struct qla_hw_data *ha = vha->hw; + struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; + uint32_t __iomem *dmp_reg; + uint32_t *iter_reg; + uint16_t __iomem *mbx_reg; + unsigned long flags; + struct qla81xx_fw_dump *fw; + uint32_t ext_mem_cnt; + void *nxt, *nxt_chain; + uint32_t *last_chain = NULL; + struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); -qla25xx_fw_dump_failed_0: + risc_address = ext_mem_cnt = 0; + flags = 0; + + if (!hardware_locked) + spin_lock_irqsave(&ha->hardware_lock, flags); + + if (!ha->fw_dump) { + qla_printk(KERN_WARNING, ha, + "No buffer available for dump!!!\n"); + goto qla81xx_fw_dump_failed; + } + + if (ha->fw_dumped) { + qla_printk(KERN_WARNING, ha, + "Firmware has been previously dumped (%p) -- ignoring " + "request...\n", ha->fw_dump); + goto qla81xx_fw_dump_failed; + } + fw = &ha->fw_dump->isp.isp81; + qla2xxx_prep_dump(ha, ha->fw_dump); + + fw->host_status = htonl(RD_REG_DWORD(®->host_status)); + + /* Pause RISC. */ + rval = qla24xx_pause_risc(reg); + if (rval != QLA_SUCCESS) + goto qla81xx_fw_dump_failed_0; + + /* Host/Risc registers. */ + iter_reg = fw->host_risc_reg; + iter_reg = qla24xx_read_window(reg, 0x7000, 16, iter_reg); + qla24xx_read_window(reg, 0x7010, 16, iter_reg); + + /* PCIe registers. */ + WRT_REG_DWORD(®->iobase_addr, 0x7C00); + RD_REG_DWORD(®->iobase_addr); + WRT_REG_DWORD(®->iobase_window, 0x01); + dmp_reg = ®->iobase_c4; + fw->pcie_regs[0] = htonl(RD_REG_DWORD(dmp_reg++)); + fw->pcie_regs[1] = htonl(RD_REG_DWORD(dmp_reg++)); + fw->pcie_regs[2] = htonl(RD_REG_DWORD(dmp_reg)); + fw->pcie_regs[3] = htonl(RD_REG_DWORD(®->iobase_window)); + + WRT_REG_DWORD(®->iobase_window, 0x00); + RD_REG_DWORD(®->iobase_window); + + /* Host interface registers. */ + dmp_reg = ®->flash_addr; + for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++) + fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); + + /* Disable interrupts. */ + WRT_REG_DWORD(®->ictrl, 0); + RD_REG_DWORD(®->ictrl); + + /* Shadow registers. */ + WRT_REG_DWORD(®->iobase_addr, 0x0F70); + RD_REG_DWORD(®->iobase_addr); + WRT_REG_DWORD(®->iobase_select, 0xB0000000); + fw->shadow_reg[0] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0100000); + fw->shadow_reg[1] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0200000); + fw->shadow_reg[2] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0300000); + fw->shadow_reg[3] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0400000); + fw->shadow_reg[4] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0500000); + fw->shadow_reg[5] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0600000); + fw->shadow_reg[6] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0700000); + fw->shadow_reg[7] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0800000); + fw->shadow_reg[8] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0900000); + fw->shadow_reg[9] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0A00000); + fw->shadow_reg[10] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + /* RISC I/O register. */ + WRT_REG_DWORD(®->iobase_addr, 0x0010); + fw->risc_io_reg = htonl(RD_REG_DWORD(®->iobase_window)); + + /* Mailbox registers. */ + mbx_reg = ®->mailbox0; + for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++) + fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg++)); + + /* Transfer sequence registers. */ + iter_reg = fw->xseq_gp_reg; + iter_reg = qla24xx_read_window(reg, 0xBF00, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xBF10, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xBF20, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xBF30, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xBF40, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xBF50, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xBF60, 16, iter_reg); + qla24xx_read_window(reg, 0xBF70, 16, iter_reg); + + iter_reg = fw->xseq_0_reg; + iter_reg = qla24xx_read_window(reg, 0xBFC0, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xBFD0, 16, iter_reg); + qla24xx_read_window(reg, 0xBFE0, 16, iter_reg); + + qla24xx_read_window(reg, 0xBFF0, 16, fw->xseq_1_reg); + + /* Receive sequence registers. */ + iter_reg = fw->rseq_gp_reg; + iter_reg = qla24xx_read_window(reg, 0xFF00, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xFF10, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xFF20, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xFF30, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xFF40, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xFF50, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xFF60, 16, iter_reg); + qla24xx_read_window(reg, 0xFF70, 16, iter_reg); + + iter_reg = fw->rseq_0_reg; + iter_reg = qla24xx_read_window(reg, 0xFFC0, 16, iter_reg); + qla24xx_read_window(reg, 0xFFD0, 16, iter_reg); + + qla24xx_read_window(reg, 0xFFE0, 16, fw->rseq_1_reg); + qla24xx_read_window(reg, 0xFFF0, 16, fw->rseq_2_reg); + + /* Auxiliary sequence registers. */ + iter_reg = fw->aseq_gp_reg; + iter_reg = qla24xx_read_window(reg, 0xB000, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xB010, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xB020, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xB030, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xB040, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xB050, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xB060, 16, iter_reg); + qla24xx_read_window(reg, 0xB070, 16, iter_reg); + + iter_reg = fw->aseq_0_reg; + iter_reg = qla24xx_read_window(reg, 0xB0C0, 16, iter_reg); + qla24xx_read_window(reg, 0xB0D0, 16, iter_reg); + + qla24xx_read_window(reg, 0xB0E0, 16, fw->aseq_1_reg); + qla24xx_read_window(reg, 0xB0F0, 16, fw->aseq_2_reg); + + /* Command DMA registers. */ + qla24xx_read_window(reg, 0x7100, 16, fw->cmd_dma_reg); + + /* Queues. */ + iter_reg = fw->req0_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7200, 8, iter_reg); + dmp_reg = ®->iobase_q; + for (cnt = 0; cnt < 7; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + iter_reg = fw->resp0_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7300, 8, iter_reg); + dmp_reg = ®->iobase_q; + for (cnt = 0; cnt < 7; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + iter_reg = fw->req1_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7400, 8, iter_reg); + dmp_reg = ®->iobase_q; + for (cnt = 0; cnt < 7; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + /* Transmit DMA registers. */ + iter_reg = fw->xmt0_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7600, 16, iter_reg); + qla24xx_read_window(reg, 0x7610, 16, iter_reg); + + iter_reg = fw->xmt1_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7620, 16, iter_reg); + qla24xx_read_window(reg, 0x7630, 16, iter_reg); + + iter_reg = fw->xmt2_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7640, 16, iter_reg); + qla24xx_read_window(reg, 0x7650, 16, iter_reg); + + iter_reg = fw->xmt3_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7660, 16, iter_reg); + qla24xx_read_window(reg, 0x7670, 16, iter_reg); + + iter_reg = fw->xmt4_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7680, 16, iter_reg); + qla24xx_read_window(reg, 0x7690, 16, iter_reg); + + qla24xx_read_window(reg, 0x76A0, 16, fw->xmt_data_dma_reg); + + /* Receive DMA registers. */ + iter_reg = fw->rcvt0_data_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7700, 16, iter_reg); + qla24xx_read_window(reg, 0x7710, 16, iter_reg); + + iter_reg = fw->rcvt1_data_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7720, 16, iter_reg); + qla24xx_read_window(reg, 0x7730, 16, iter_reg); + + /* RISC registers. */ + iter_reg = fw->risc_gp_reg; + iter_reg = qla24xx_read_window(reg, 0x0F00, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x0F10, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x0F20, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x0F30, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x0F40, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x0F50, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x0F60, 16, iter_reg); + qla24xx_read_window(reg, 0x0F70, 16, iter_reg); + + /* Local memory controller registers. */ + iter_reg = fw->lmc_reg; + iter_reg = qla24xx_read_window(reg, 0x3000, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x3010, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x3020, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x3030, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x3040, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x3050, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x3060, 16, iter_reg); + qla24xx_read_window(reg, 0x3070, 16, iter_reg); + + /* Fibre Protocol Module registers. */ + iter_reg = fw->fpm_hdw_reg; + iter_reg = qla24xx_read_window(reg, 0x4000, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4010, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4020, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4030, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4040, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4050, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4060, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4070, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4080, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4090, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x40A0, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x40B0, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x40C0, 16, iter_reg); + qla24xx_read_window(reg, 0x40D0, 16, iter_reg); + + /* Frame Buffer registers. */ + iter_reg = fw->fb_hdw_reg; + iter_reg = qla24xx_read_window(reg, 0x6000, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6010, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6020, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6030, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6040, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6100, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6130, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6150, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6170, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6190, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x61B0, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x61C0, 16, iter_reg); + qla24xx_read_window(reg, 0x6F00, 16, iter_reg); + + /* Multi queue registers */ + nxt_chain = qla25xx_copy_mq(ha, (void *)ha->fw_dump + ha->chain_offset, + &last_chain); + + rval = qla24xx_soft_reset(ha); + if (rval != QLA_SUCCESS) + goto qla81xx_fw_dump_failed_0; + + rval = qla24xx_dump_memory(ha, fw->code_ram, sizeof(fw->code_ram), + &nxt); + if (rval != QLA_SUCCESS) + goto qla81xx_fw_dump_failed_0; + + nxt = qla2xxx_copy_queues(ha, nxt); + + nxt = qla24xx_copy_eft(ha, nxt); + + /* Chain entries -- started with MQ. */ + qla25xx_copy_fce(ha, nxt_chain, &last_chain); + if (last_chain) { + ha->fw_dump->version |= __constant_htonl(DUMP_CHAIN_VARIANT); + *last_chain |= __constant_htonl(DUMP_CHAIN_LAST); + } + +qla81xx_fw_dump_failed_0: if (rval != QLA_SUCCESS) { qla_printk(KERN_WARNING, ha, "Failed to dump firmware (%x)!!!\n", rval); @@ -1294,10 +1643,11 @@ qla25xx_fw_dump_failed_0: ha->fw_dumped = 1; } -qla25xx_fw_dump_failed: +qla81xx_fw_dump_failed: if (!hardware_locked) spin_unlock_irqrestore(&ha->hardware_lock, flags); } + /****************************************************************************/ /* Driver Debug Functions. */ /****************************************************************************/ diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h index c1794a70a45..f660dd70b72 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.h +++ b/drivers/scsi/qla2xxx/qla_dbg.h @@ -251,6 +251,45 @@ struct qla25xx_fw_dump { uint32_t ext_mem[1]; }; +struct qla81xx_fw_dump { + uint32_t host_status; + uint32_t host_risc_reg[32]; + uint32_t pcie_regs[4]; + uint32_t host_reg[32]; + uint32_t shadow_reg[11]; + uint32_t risc_io_reg; + uint16_t mailbox_reg[32]; + uint32_t xseq_gp_reg[128]; + uint32_t xseq_0_reg[48]; + uint32_t xseq_1_reg[16]; + uint32_t rseq_gp_reg[128]; + uint32_t rseq_0_reg[32]; + uint32_t rseq_1_reg[16]; + uint32_t rseq_2_reg[16]; + uint32_t aseq_gp_reg[128]; + uint32_t aseq_0_reg[32]; + uint32_t aseq_1_reg[16]; + uint32_t aseq_2_reg[16]; + uint32_t cmd_dma_reg[16]; + uint32_t req0_dma_reg[15]; + uint32_t resp0_dma_reg[15]; + uint32_t req1_dma_reg[15]; + uint32_t xmt0_dma_reg[32]; + uint32_t xmt1_dma_reg[32]; + uint32_t xmt2_dma_reg[32]; + uint32_t xmt3_dma_reg[32]; + uint32_t xmt4_dma_reg[32]; + uint32_t xmt_data_dma_reg[16]; + uint32_t rcvt0_data_dma_reg[32]; + uint32_t rcvt1_data_dma_reg[32]; + uint32_t risc_gp_reg[128]; + uint32_t lmc_reg[128]; + uint32_t fpm_hdw_reg[224]; + uint32_t fb_hdw_reg[208]; + uint32_t code_ram[0x2000]; + uint32_t ext_mem[1]; +}; + #define EFT_NUM_BUFFERS 4 #define EFT_BYTES_PER_BUFFER 0x4000 #define EFT_SIZE ((EFT_BYTES_PER_BUFFER) * (EFT_NUM_BUFFERS)) @@ -313,5 +352,6 @@ struct qla2xxx_fw_dump { struct qla2300_fw_dump isp23; struct qla24xx_fw_dump isp24; struct qla25xx_fw_dump isp25; + struct qla81xx_fw_dump isp81; } isp; }; diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index a29c9520497..023ee77fb02 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -187,7 +187,6 @@ struct req_que; * SCSI Request Block */ typedef struct srb { - struct scsi_qla_host *vha; /* HA the SP is queued on */ struct req_que *que; struct fc_port *fcport; @@ -2136,7 +2135,6 @@ struct qla_msix_entry { /* Work events. */ enum qla_work_type { QLA_EVT_AEN, - QLA_EVT_HWE_LOG, }; @@ -2151,10 +2149,6 @@ struct qla_work_evt { enum fc_host_event_code code; u32 data; } aen; - struct { - uint16_t code; - uint16_t d1, d2, d3; - } hwe; } u; }; @@ -2309,6 +2303,7 @@ struct qla_hw_data { #define PORT_SPEED_2GB 0x01 #define PORT_SPEED_4GB 0x03 #define PORT_SPEED_8GB 0x04 +#define PORT_SPEED_10GB 0x13 uint16_t link_data_rate; /* F/W operating speed */ uint8_t current_topology; @@ -2328,6 +2323,7 @@ struct qla_hw_data { #define PCI_DEVICE_ID_QLOGIC_ISP2532 0x2532 #define PCI_DEVICE_ID_QLOGIC_ISP8432 0x8432 +#define PCI_DEVICE_ID_QLOGIC_ISP8001 0x8001 uint32_t device_type; #define DT_ISP2100 BIT_0 #define DT_ISP2200 BIT_1 @@ -2342,7 +2338,8 @@ struct qla_hw_data { #define DT_ISP5432 BIT_10 #define DT_ISP2532 BIT_11 #define DT_ISP8432 BIT_12 -#define DT_ISP_LAST (DT_ISP8432 << 1) +#define DT_ISP8001 BIT_13 +#define DT_ISP_LAST (DT_ISP8001 << 1) #define DT_IIDMA BIT_26 #define DT_FWI2 BIT_27 @@ -2364,6 +2361,7 @@ struct qla_hw_data { #define IS_QLA5432(ha) (DT_MASK(ha) & DT_ISP5432) #define IS_QLA2532(ha) (DT_MASK(ha) & DT_ISP2532) #define IS_QLA8432(ha) (DT_MASK(ha) & DT_ISP8432) +#define IS_QLA8001(ha) (DT_MASK(ha) & DT_ISP8001) #define IS_QLA23XX(ha) (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA2322(ha) || \ IS_QLA6312(ha) || IS_QLA6322(ha)) @@ -2373,8 +2371,11 @@ struct qla_hw_data { #define IS_QLA84XX(ha) (IS_QLA8432(ha)) #define IS_QLA24XX_TYPE(ha) (IS_QLA24XX(ha) || IS_QLA54XX(ha) || \ IS_QLA84XX(ha)) +#define IS_QLA81XX(ha) (IS_QLA8001(ha)) #define IS_QLA2XXX_MIDTYPE(ha) (IS_QLA24XX(ha) || IS_QLA84XX(ha) || \ - IS_QLA25XX(ha)) + IS_QLA25XX(ha) || IS_QLA81XX(ha)) +#define IS_NOPOLLING_TYPE(ha) ((IS_QLA25XX(ha) || IS_QLA81XX(ha)) && \ + (ha)->flags.msix_enabled) #define IS_IIDMA_CAPABLE(ha) ((ha)->device_type & DT_IIDMA) #define IS_FWI2_CAPABLE(ha) ((ha)->device_type & DT_FWI2) @@ -2472,6 +2473,9 @@ struct qla_hw_data { uint8_t fw_seriallink_options[4]; uint16_t fw_seriallink_options24[4]; + uint8_t mpi_version[4]; + uint32_t mpi_capabilities; + /* Firmware dump information. */ struct qla2xxx_fw_dump *fw_dump; uint32_t fw_dump_len; @@ -2480,6 +2484,7 @@ struct qla_hw_data { dma_addr_t eft_dma; void *eft; + uint32_t chain_offset; struct dentry *dfs_dir; struct dentry *dfs_fce; dma_addr_t fce_dma; @@ -2489,10 +2494,6 @@ struct qla_hw_data { uint64_t fce_wr, fce_rd; struct mutex fce_mutex; - uint32_t hw_event_start; - uint32_t hw_event_ptr; - uint32_t hw_event_pause_errors; - uint32_t pci_attr; uint16_t chip_revision; @@ -2522,6 +2523,12 @@ struct qla_hw_data { uint8_t fcode_revision[16]; uint32_t fw_revision[4]; + /* Offsets for flash/nvram access (set to ~0 if not used). */ + uint32_t flash_conf_off; + uint32_t flash_data_off; + uint32_t nvram_conf_off; + uint32_t nvram_data_off; + uint32_t fdt_wrt_disable; uint32_t fdt_erase_cmd; uint32_t fdt_block_size; @@ -2533,7 +2540,6 @@ struct qla_hw_data { uint32_t flt_region_boot; uint32_t flt_region_fw; uint32_t flt_region_vpd_nvram; - uint32_t flt_region_hw_event; uint32_t flt_region_npiv_conf; /* Needed for BEACON */ @@ -2737,6 +2743,7 @@ typedef struct scsi_qla_host { #define OPTROM_SIZE_2322 0x100000 #define OPTROM_SIZE_24XX 0x100000 #define OPTROM_SIZE_25XX 0x200000 +#define OPTROM_SIZE_81XX 0x400000 #include "qla_gbl.h" #include "qla_dbg.h" diff --git a/drivers/scsi/qla2xxx/qla_dfs.c b/drivers/scsi/qla2xxx/qla_dfs.c index 0e366a1b44b..c66036da7d2 100644 --- a/drivers/scsi/qla2xxx/qla_dfs.c +++ b/drivers/scsi/qla2xxx/qla_dfs.c @@ -113,7 +113,8 @@ int qla2x00_dfs_setup(scsi_qla_host_t *vha) { struct qla_hw_data *ha = vha->hw; - if (!IS_QLA25XX(ha)) + + if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha)) goto out; if (!ha->fce) goto out; diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h index ee1f1e794c2..7abb045a041 100644 --- a/drivers/scsi/qla2xxx/qla_fw.h +++ b/drivers/scsi/qla2xxx/qla_fw.h @@ -1215,9 +1215,10 @@ struct qla_fdt_layout { struct qla_flt_location { uint8_t sig[4]; - uint32_t start_lo; - uint32_t start_hi; - uint16_t unused; + uint16_t start_lo; + uint16_t start_hi; + uint8_t version; + uint8_t unused[5]; uint16_t checksum; }; @@ -1390,4 +1391,291 @@ struct access_chip_rsp_84xx { uint32_t reserved[12]; }; + +/* 81XX Support **************************************************************/ + +#define MBA_DCBX_START 0x8016 +#define MBA_DCBX_COMPLETE 0x8030 +#define MBA_FCF_CONF_ERR 0x8031 +#define MBA_DCBX_PARAM_UPDATE 0x8032 +#define MBA_IDC_COMPLETE 0x8100 +#define MBA_IDC_NOTIFY 0x8101 +#define MBA_IDC_TIME_EXT 0x8102 + +struct nvram_81xx { + /* NVRAM header. */ + uint8_t id[4]; + uint16_t nvram_version; + uint16_t reserved_0; + + /* Firmware Initialization Control Block. */ + uint16_t version; + uint16_t reserved_1; + uint16_t frame_payload_size; + uint16_t execution_throttle; + uint16_t exchange_count; + uint16_t reserved_2; + + uint8_t port_name[WWN_SIZE]; + uint8_t node_name[WWN_SIZE]; + + uint16_t login_retry_count; + uint16_t reserved_3; + uint16_t interrupt_delay_timer; + uint16_t login_timeout; + + uint32_t firmware_options_1; + uint32_t firmware_options_2; + uint32_t firmware_options_3; + + uint16_t reserved_4[4]; + + /* Offset 64. */ + uint8_t enode_mac[6]; + uint16_t reserved_5[5]; + + /* Offset 80. */ + uint16_t reserved_6[24]; + + /* Offset 128. */ + uint16_t reserved_7[64]; + + /* + * BIT 0 = Enable spinup delay + * BIT 1 = Disable BIOS + * BIT 2 = Enable Memory Map BIOS + * BIT 3 = Enable Selectable Boot + * BIT 4 = Disable RISC code load + * BIT 5 = Disable Serdes + * BIT 6 = Opt boot mode + * BIT 7 = Interrupt enable + * + * BIT 8 = EV Control enable + * BIT 9 = Enable lip reset + * BIT 10 = Enable lip full login + * BIT 11 = Enable target reset + * BIT 12 = Stop firmware + * BIT 13 = Enable nodename option + * BIT 14 = Default WWPN valid + * BIT 15 = Enable alternate WWN + * + * BIT 16 = CLP LUN string + * BIT 17 = CLP Target string + * BIT 18 = CLP BIOS enable string + * BIT 19 = CLP Serdes string + * BIT 20 = CLP WWPN string + * BIT 21 = CLP WWNN string + * BIT 22 = + * BIT 23 = + * BIT 24 = Keep WWPN + * BIT 25 = Temp WWPN + * BIT 26-31 = + */ + uint32_t host_p; + + uint8_t alternate_port_name[WWN_SIZE]; + uint8_t alternate_node_name[WWN_SIZE]; + + uint8_t boot_port_name[WWN_SIZE]; + uint16_t boot_lun_number; + uint16_t reserved_8; + + uint8_t alt1_boot_port_name[WWN_SIZE]; + uint16_t alt1_boot_lun_number; + uint16_t reserved_9; + + uint8_t alt2_boot_port_name[WWN_SIZE]; + uint16_t alt2_boot_lun_number; + uint16_t reserved_10; + + uint8_t alt3_boot_port_name[WWN_SIZE]; + uint16_t alt3_boot_lun_number; + uint16_t reserved_11; + + /* + * BIT 0 = Selective Login + * BIT 1 = Alt-Boot Enable + * BIT 2 = Reserved + * BIT 3 = Boot Order List + * BIT 4 = Reserved + * BIT 5 = Selective LUN + * BIT 6 = Reserved + |