diff options
Diffstat (limited to 'drivers/scsi/qla2xxx')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_attr.c | 22 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_bsg.c | 201 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_bsg.h | 34 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_dbg.c | 146 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_def.h | 56 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_fw.h | 14 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_gbl.h | 2 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 119 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_inline.h | 4 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_isr.c | 4 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_mbx.c | 27 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 10 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_sup.c | 70 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_version.h | 2 |
14 files changed, 594 insertions, 117 deletions
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 6992ebc..4dc06a13 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -272,8 +272,8 @@ qla2x00_sysfs_write_nvram(struct file *filp, struct kobject *kobj, iter = (uint32_t *)buf; chksum = 0; - for (cnt = 0; cnt < ((count >> 2) - 1); cnt++) - chksum += le32_to_cpu(*iter++); + for (cnt = 0; cnt < ((count >> 2) - 1); cnt++, iter++) + chksum += le32_to_cpu(*iter); chksum = ~chksum + 1; *iter = cpu_to_le32(chksum); } else { @@ -562,6 +562,7 @@ qla2x00_sysfs_read_vpd(struct file *filp, struct kobject *kobj, struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj, struct device, kobj))); struct qla_hw_data *ha = vha->hw; + uint32_t faddr; if (unlikely(pci_channel_offline(ha->pdev))) return -EAGAIN; @@ -569,9 +570,16 @@ qla2x00_sysfs_read_vpd(struct file *filp, struct kobject *kobj, if (!capable(CAP_SYS_ADMIN)) return -EINVAL; - if (IS_NOCACHE_VPD_TYPE(ha)) - ha->isp_ops->read_optrom(vha, ha->vpd, ha->flt_region_vpd << 2, + if (IS_NOCACHE_VPD_TYPE(ha)) { + faddr = ha->flt_region_vpd << 2; + + if (IS_QLA27XX(ha) && + qla27xx_find_valid_image(vha) == QLA27XX_SECONDARY_IMAGE) + faddr = ha->flt_region_vpd_sec << 2; + + ha->isp_ops->read_optrom(vha, ha->vpd, faddr, ha->vpd_size); + } return memory_read_from_buffer(buf, count, &off, ha->vpd, ha->vpd_size); } @@ -1909,7 +1917,8 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost) if (qla2x00_reset_active(vha)) goto done; - stats = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &stats_dma); + stats = dma_alloc_coherent(&ha->pdev->dev, + sizeof(struct link_statistics), &stats_dma, GFP_KERNEL); if (stats == NULL) { ql_log(ql_log_warn, vha, 0x707d, "Failed to allocate memory for stats.\n"); @@ -1957,7 +1966,8 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost) do_div(pfc_host_stat->seconds_since_last_reset, HZ); done_free: - dma_pool_free(ha->s_dma_pool, stats, stats_dma); + dma_free_coherent(&ha->pdev->dev, sizeof(struct link_statistics), + stats, stats_dma); done: return pfc_host_stat; } diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index c26acde..392c147 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -2107,6 +2107,195 @@ qla8044_serdes_op(struct fc_bsg_job *bsg_job) } static int +qla27xx_get_flash_upd_cap(struct fc_bsg_job *bsg_job) +{ + struct Scsi_Host *host = bsg_job->shost; + scsi_qla_host_t *vha = shost_priv(host); + struct qla_hw_data *ha = vha->hw; + struct qla_flash_update_caps cap; + + if (!(IS_QLA27XX(ha))) + return -EPERM; + + memset(&cap, 0, sizeof(cap)); + cap.capabilities = (uint64_t)ha->fw_attributes_ext[1] << 48 | + (uint64_t)ha->fw_attributes_ext[0] << 32 | + (uint64_t)ha->fw_attributes_h << 16 | + (uint64_t)ha->fw_attributes; + + sg_copy_from_buffer(bsg_job->reply_payload.sg_list, + bsg_job->reply_payload.sg_cnt, &cap, sizeof(cap)); + bsg_job->reply->reply_payload_rcv_len = sizeof(cap); + + bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = + EXT_STATUS_OK; + + bsg_job->reply_len = sizeof(struct fc_bsg_reply); + bsg_job->reply->result = DID_OK << 16; + bsg_job->job_done(bsg_job); + return 0; +} + +static int +qla27xx_set_flash_upd_cap(struct fc_bsg_job *bsg_job) +{ + struct Scsi_Host *host = bsg_job->shost; + scsi_qla_host_t *vha = shost_priv(host); + struct qla_hw_data *ha = vha->hw; + uint64_t online_fw_attr = 0; + struct qla_flash_update_caps cap; + + if (!(IS_QLA27XX(ha))) + return -EPERM; + + memset(&cap, 0, sizeof(cap)); + sg_copy_to_buffer(bsg_job->request_payload.sg_list, + bsg_job->request_payload.sg_cnt, &cap, sizeof(cap)); + + online_fw_attr = (uint64_t)ha->fw_attributes_ext[1] << 48 | + (uint64_t)ha->fw_attributes_ext[0] << 32 | + (uint64_t)ha->fw_attributes_h << 16 | + (uint64_t)ha->fw_attributes; + + if (online_fw_attr != cap.capabilities) { + bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = + EXT_STATUS_INVALID_PARAM; + return -EINVAL; + } + + if (cap.outage_duration < MAX_LOOP_TIMEOUT) { + bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = + EXT_STATUS_INVALID_PARAM; + return -EINVAL; + } + + bsg_job->reply->reply_payload_rcv_len = 0; + + bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = + EXT_STATUS_OK; + + bsg_job->reply_len = sizeof(struct fc_bsg_reply); + bsg_job->reply->result = DID_OK << 16; + bsg_job->job_done(bsg_job); + return 0; +} + +static int +qla27xx_get_bbcr_data(struct fc_bsg_job *bsg_job) +{ + struct Scsi_Host *host = bsg_job->shost; + scsi_qla_host_t *vha = shost_priv(host); + struct qla_hw_data *ha = vha->hw; + struct qla_bbcr_data bbcr; + uint16_t loop_id, topo, sw_cap; + uint8_t domain, area, al_pa, state; + int rval; + + if (!(IS_QLA27XX(ha))) + return -EPERM; + + memset(&bbcr, 0, sizeof(bbcr)); + + if (vha->flags.bbcr_enable) + bbcr.status = QLA_BBCR_STATUS_ENABLED; + else + bbcr.status = QLA_BBCR_STATUS_DISABLED; + + if (bbcr.status == QLA_BBCR_STATUS_ENABLED) { + rval = qla2x00_get_adapter_id(vha, &loop_id, &al_pa, + &area, &domain, &topo, &sw_cap); + if (rval != QLA_SUCCESS) { + bbcr.status = QLA_BBCR_STATUS_UNKNOWN; + bbcr.state = QLA_BBCR_STATE_OFFLINE; + bbcr.mbx1 = loop_id; + goto done; + } + + state = (vha->bbcr >> 12) & 0x1; + + if (state) { + bbcr.state = QLA_BBCR_STATE_OFFLINE; + bbcr.offline_reason_code = QLA_BBCR_REASON_LOGIN_REJECT; + } else { + bbcr.state = QLA_BBCR_STATE_ONLINE; + bbcr.negotiated_bbscn = (vha->bbcr >> 8) & 0xf; + } + + bbcr.configured_bbscn = vha->bbcr & 0xf; + } + +done: + sg_copy_from_buffer(bsg_job->reply_payload.sg_list, + bsg_job->reply_payload.sg_cnt, &bbcr, sizeof(bbcr)); + bsg_job->reply->reply_payload_rcv_len = sizeof(bbcr); + + bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK; + + bsg_job->reply_len = sizeof(struct fc_bsg_reply); + bsg_job->reply->result = DID_OK << 16; + bsg_job->job_done(bsg_job); + return 0; +} + +static int +qla2x00_get_priv_stats(struct fc_bsg_job *bsg_job) +{ + struct Scsi_Host *host = bsg_job->shost; + scsi_qla_host_t *vha = shost_priv(host); + struct qla_hw_data *ha = vha->hw; + struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); + struct link_statistics *stats = NULL; + dma_addr_t stats_dma; + int rval = QLA_FUNCTION_FAILED; + + if (test_bit(UNLOADING, &vha->dpc_flags)) + goto done; + + if (unlikely(pci_channel_offline(ha->pdev))) + goto done; + + if (qla2x00_reset_active(vha)) + goto done; + + if (!IS_FWI2_CAPABLE(ha)) + goto done; + + stats = dma_alloc_coherent(&ha->pdev->dev, + sizeof(struct link_statistics), &stats_dma, GFP_KERNEL); + if (!stats) { + ql_log(ql_log_warn, vha, 0x70e2, + "Failed to allocate memory for stats.\n"); + goto done; + } + + memset(stats, 0, sizeof(struct link_statistics)); + + rval = qla24xx_get_isp_stats(base_vha, stats, stats_dma); + + if (rval != QLA_SUCCESS) + goto done_free; + + ql_dump_buffer(ql_dbg_user + ql_dbg_verbose, vha, 0x70e3, + (uint8_t *)stats, sizeof(struct link_statistics)); + + sg_copy_from_buffer(bsg_job->reply_payload.sg_list, + bsg_job->reply_payload.sg_cnt, stats, sizeof(struct link_statistics)); + bsg_job->reply->reply_payload_rcv_len = sizeof(struct link_statistics); + + bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK; + + bsg_job->reply_len = sizeof(struct fc_bsg_reply); + bsg_job->reply->result = DID_OK << 16; + bsg_job->job_done(bsg_job); + +done_free: + dma_free_coherent(&ha->pdev->dev, sizeof(struct link_statistics), + stats, stats_dma); +done: + return rval; +} + +static int qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job) { switch (bsg_job->request->rqst_data.h_vendor.vendor_cmd[0]) { @@ -2161,6 +2350,18 @@ qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job) case QL_VND_SERDES_OP_EX: return qla8044_serdes_op(bsg_job); + case QL_VND_GET_FLASH_UPDATE_CAPS: + return qla27xx_get_flash_upd_cap(bsg_job); + + case QL_VND_SET_FLASH_UPDATE_CAPS: + return qla27xx_set_flash_upd_cap(bsg_job); + + case QL_VND_GET_BBCR_DATA: + return qla27xx_get_bbcr_data(bsg_job); + + case QL_VND_GET_PRIV_STATS: + return qla2x00_get_priv_stats(bsg_job); + default: return -ENOSYS; } diff --git a/drivers/scsi/qla2xxx/qla_bsg.h b/drivers/scsi/qla2xxx/qla_bsg.h index d38f9ef..c80192d 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.h +++ b/drivers/scsi/qla2xxx/qla_bsg.h @@ -25,6 +25,10 @@ #define QL_VND_FX00_MGMT_CMD 0x12 #define QL_VND_SERDES_OP 0x13 #define QL_VND_SERDES_OP_EX 0x14 +#define QL_VND_GET_FLASH_UPDATE_CAPS 0x15 +#define QL_VND_SET_FLASH_UPDATE_CAPS 0x16 +#define QL_VND_GET_BBCR_DATA 0x17 +#define QL_VND_GET_PRIV_STATS 0x18 /* BSG Vendor specific subcode returns */ #define EXT_STATUS_OK 0 @@ -232,4 +236,34 @@ struct qla_serdes_reg_ex { uint32_t val; } __packed; +struct qla_flash_update_caps { + uint64_t capabilities; + uint32_t outage_duration; + uint8_t reserved[20]; +} __packed; + +/* BB_CR Status */ +#define QLA_BBCR_STATUS_DISABLED 0 +#define QLA_BBCR_STATUS_ENABLED 1 +#define QLA_BBCR_STATUS_UNKNOWN 2 + +/* BB_CR State */ +#define QLA_BBCR_STATE_OFFLINE 0 +#define QLA_BBCR_STATE_ONLINE 1 + +/* BB_CR Offline Reason Code */ +#define QLA_BBCR_REASON_PORT_SPEED 1 +#define QLA_BBCR_REASON_PEER_PORT 2 +#define QLA_BBCR_REASON_SWITCH 3 +#define QLA_BBCR_REASON_LOGIN_REJECT 4 + +struct qla_bbcr_data { + uint8_t status; /* 1 - enabled, 0 - Disabled */ + uint8_t state; /* 1 - online, 0 - offline */ + uint8_t configured_bbscn; /* 0-15 */ + uint8_t negotiated_bbscn; /* 0-15 */ + uint8_t offline_reason_code; + uint16_t mbx1; /* Port state */ + uint8_t reserved[9]; +} __packed; #endif diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index cd0d94e..b64c504 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -11,7 +11,7 @@ * ---------------------------------------------------------------------- * | Level | Last Value Used | Holes | * ---------------------------------------------------------------------- - * | Module Init and Probe | 0x017f | 0x0146 | + * | Module Init and Probe | 0x018f | 0x0146 | * | | | 0x015b-0x0160 | * | | | 0x016e-0x0170 | * | Mailbox commands | 0x1192 | | @@ -27,11 +27,12 @@ * | | | 0x303a | * | DPC Thread | 0x4023 | 0x4002,0x4013 | * | Async Events | 0x5089 | 0x502b-0x502f | + * | | | 0x505e | * | | | 0x5084,0x5075 | * | | | 0x503d,0x5044 | * | | | 0x507b,0x505f | * | Timer Routines | 0x6012 | | - * | User Space Interactions | 0x70e65 | 0x7018,0x702e | + * | User Space Interactions | 0x70e3 | 0x7018,0x702e | * | | | 0x7020,0x7024 | * | | | 0x7039,0x7045 | * | | | 0x7073-0x7075 | @@ -293,8 +294,8 @@ qla24xx_read_window(struct device_reg_24xx __iomem *reg, uint32_t iobase, WRT_REG_DWORD(®->iobase_addr, iobase); dmp_reg = ®->iobase_window; - while (count--) - *buf++ = htonl(RD_REG_DWORD(dmp_reg++)); + for ( ; count--; dmp_reg++) + *buf++ = htonl(RD_REG_DWORD(dmp_reg)); return buf; } @@ -456,8 +457,8 @@ qla2xxx_read_window(struct device_reg_2xxx __iomem *reg, uint32_t count, { uint16_t __iomem *dmp_reg = ®->u.isp2300.fb_cmd; - while (count--) - *buf++ = htons(RD_REG_WORD(dmp_reg++)); + for ( ; count--; dmp_reg++) + *buf++ = htons(RD_REG_WORD(dmp_reg)); } static inline void * @@ -732,16 +733,18 @@ qla2300_fw_dump(scsi_qla_host_t *vha, int hardware_locked) if (rval == QLA_SUCCESS) { dmp_reg = ®->flash_address; - for (cnt = 0; cnt < sizeof(fw->pbiu_reg) / 2; cnt++) - fw->pbiu_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + for (cnt = 0; cnt < sizeof(fw->pbiu_reg) / 2; cnt++, dmp_reg++) + fw->pbiu_reg[cnt] = htons(RD_REG_WORD(dmp_reg)); dmp_reg = ®->u.isp2300.req_q_in; - for (cnt = 0; cnt < sizeof(fw->risc_host_reg) / 2; cnt++) - fw->risc_host_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + for (cnt = 0; cnt < sizeof(fw->risc_host_reg) / 2; + cnt++, dmp_reg++) + fw->risc_host_reg[cnt] = htons(RD_REG_WORD(dmp_reg)); dmp_reg = ®->u.isp2300.mailbox0; - for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++) - fw->mailbox_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; + cnt++, dmp_reg++) + fw->mailbox_reg[cnt] = htons(RD_REG_WORD(dmp_reg)); WRT_REG_WORD(®->ctrl_status, 0x40); qla2xxx_read_window(reg, 32, fw->resp_dma_reg); @@ -751,8 +754,9 @@ qla2300_fw_dump(scsi_qla_host_t *vha, int hardware_locked) WRT_REG_WORD(®->ctrl_status, 0x00); dmp_reg = ®->risc_hw; - for (cnt = 0; cnt < sizeof(fw->risc_hdw_reg) / 2; cnt++) - fw->risc_hdw_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + for (cnt = 0; cnt < sizeof(fw->risc_hdw_reg) / 2; + cnt++, dmp_reg++) + fw->risc_hdw_reg[cnt] = htons(RD_REG_WORD(dmp_reg)); WRT_REG_WORD(®->pcr, 0x2000); qla2xxx_read_window(reg, 16, fw->risc_gp0_reg); @@ -895,25 +899,25 @@ qla2100_fw_dump(scsi_qla_host_t *vha, int hardware_locked) } if (rval == QLA_SUCCESS) { dmp_reg = ®->flash_address; - for (cnt = 0; cnt < sizeof(fw->pbiu_reg) / 2; cnt++) - fw->pbiu_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + for (cnt = 0; cnt < sizeof(fw->pbiu_reg) / 2; cnt++, dmp_reg++) + fw->pbiu_reg[cnt] = htons(RD_REG_WORD(dmp_reg)); dmp_reg = ®->u.isp2100.mailbox0; - for (cnt = 0; cnt < ha->mbx_count; cnt++) { + for (cnt = 0; cnt < ha->mbx_count; cnt++, dmp_reg++) { if (cnt == 8) dmp_reg = ®->u_end.isp2200.mailbox8; - fw->mailbox_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + fw->mailbox_reg[cnt] = htons(RD_REG_WORD(dmp_reg)); } dmp_reg = ®->u.isp2100.unused_2[0]; - for (cnt = 0; cnt < sizeof(fw->dma_reg) / 2; cnt++) - fw->dma_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + for (cnt = 0; cnt < sizeof(fw->dma_reg) / 2; cnt++, dmp_reg++) + fw->dma_reg[cnt] = htons(RD_REG_WORD(dmp_reg)); WRT_REG_WORD(®->ctrl_status, 0x00); dmp_reg = ®->risc_hw; - for (cnt = 0; cnt < sizeof(fw->risc_hdw_reg) / 2; cnt++) - fw->risc_hdw_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + for (cnt = 0; cnt < sizeof(fw->risc_hdw_reg) / 2; cnt++, dmp_reg++) + fw->risc_hdw_reg[cnt] = htons(RD_REG_WORD(dmp_reg)); WRT_REG_WORD(®->pcr, 0x2000); qla2xxx_read_window(reg, 16, fw->risc_gp0_reg); @@ -1095,8 +1099,8 @@ qla24xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) /* 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++)); + for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++, dmp_reg++) + fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg)); /* Disable interrupts. */ WRT_REG_DWORD(®->ictrl, 0); @@ -1128,8 +1132,8 @@ qla24xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) /* 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++)); + for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++, dmp_reg++) + fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg)); /* Transfer sequence registers. */ iter_reg = fw->xseq_gp_reg; @@ -1167,20 +1171,20 @@ qla24xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) 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++)); + for (cnt = 0; cnt < 7; cnt++, dmp_reg++) + *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++)); + for (cnt = 0; cnt < 7; cnt++, dmp_reg++) + *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++)); + for (cnt = 0; cnt < 7; cnt++, dmp_reg++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg)); /* Transmit DMA registers. */ iter_reg = fw->xmt0_dma_reg; @@ -1358,8 +1362,10 @@ qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) 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[0] = htonl(RD_REG_DWORD(dmp_reg)); + dmp_reg++; + fw->pcie_regs[1] = htonl(RD_REG_DWORD(dmp_reg)); + dmp_reg++; fw->pcie_regs[2] = htonl(RD_REG_DWORD(dmp_reg)); fw->pcie_regs[3] = htonl(RD_REG_DWORD(®->iobase_window)); @@ -1368,8 +1374,8 @@ qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) /* 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++)); + for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++, dmp_reg++) + fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg)); /* Disable interrupts. */ WRT_REG_DWORD(®->ictrl, 0); @@ -1417,8 +1423,8 @@ qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) /* 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++)); + for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++, mbx_reg++) + fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg)); /* Transfer sequence registers. */ iter_reg = fw->xseq_gp_reg; @@ -1481,20 +1487,20 @@ qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) 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++)); + for (cnt = 0; cnt < 7; cnt++, dmp_reg++) + *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++)); + for (cnt = 0; cnt < 7; cnt++, dmp_reg++) + *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++)); + for (cnt = 0; cnt < 7; cnt++, dmp_reg++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg)); /* Transmit DMA registers. */ iter_reg = fw->xmt0_dma_reg; @@ -1679,8 +1685,10 @@ qla81xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) 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[0] = htonl(RD_REG_DWORD(dmp_reg)); + dmp_reg++; + fw->pcie_regs[1] = htonl(RD_REG_DWORD(dmp_reg)); + dmp_reg++; fw->pcie_regs[2] = htonl(RD_REG_DWORD(dmp_reg)); fw->pcie_regs[3] = htonl(RD_REG_DWORD(®->iobase_window)); @@ -1689,8 +1697,8 @@ qla81xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) /* 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++)); + for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++, dmp_reg++) + fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg)); /* Disable interrupts. */ WRT_REG_DWORD(®->ictrl, 0); @@ -1738,8 +1746,8 @@ qla81xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) /* 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++)); + for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++, mbx_reg++) + fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg)); /* Transfer sequence registers. */ iter_reg = fw->xseq_gp_reg; @@ -1802,20 +1810,20 @@ qla81xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) 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++)); + for (cnt = 0; cnt < 7; cnt++, dmp_reg++) + *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++)); + for (cnt = 0; cnt < 7; cnt++, dmp_reg++) + *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++)); + for (cnt = 0; cnt < 7; cnt++, dmp_reg++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg)); /* Transmit DMA registers. */ iter_reg = fw->xmt0_dma_reg; @@ -2022,8 +2030,10 @@ qla83xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) 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[0] = htonl(RD_REG_DWORD(dmp_reg)); + dmp_reg++; + fw->pcie_regs[1] = htonl(RD_REG_DWORD(dmp_reg)); + dmp_reg++; fw->pcie_regs[2] = htonl(RD_REG_DWORD(dmp_reg)); fw->pcie_regs[3] = htonl(RD_REG_DWORD(®->iobase_window)); @@ -2032,8 +2042,8 @@ qla83xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) /* 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++)); + for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++, dmp_reg++) + fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg)); /* Disable interrupts. */ WRT_REG_DWORD(®->ictrl, 0); @@ -2081,8 +2091,8 @@ qla83xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) /* 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++)); + for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++, dmp_reg++) + fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg)); /* Transfer sequence registers. */ iter_reg = fw->xseq_gp_reg; @@ -2177,20 +2187,20 @@ qla83xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) 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++)); + for (cnt = 0; cnt < 7; cnt++, dmp_reg++) + *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++)); + for (cnt = 0; cnt < 7; cnt++, dmp_reg++) + *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++)); + for (cnt = 0; cnt < 7; cnt++, dmp_reg++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg)); /* Transmit DMA registers. */ iter_reg = fw->xmt0_dma_reg; diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 9872f34..ceb452d 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -1060,6 +1060,12 @@ struct mbx_cmd_32 { #define FSTATE_FATAL_ERROR 4 #define FSTATE_LOOP_BACK_CONN 5 +#define QLA27XX_IMG_STATUS_VER_MAJOR 0x01 +#define QLA27XX_IMG_STATUS_VER_MINOR 0x00 +#define QLA27XX_IMG_STATUS_SIGN 0xFACEFADE +#define QLA27XX_PRIMARY_IMAGE 1 +#define QLA27XX_SECONDARY_IMAGE 2 + /* * Port Database structure definition * Little endian except where noted. @@ -1248,13 +1254,41 @@ struct link_statistics { uint32_t inval_xmit_word_cnt; uint32_t inval_crc_cnt; uint32_t lip_cnt; - uint32_t unused1[0x1a]; + uint32_t link_up_cnt; + uint32_t link_down_loop_init_tmo; + uint32_t link_down_los; + uint32_t link_down_loss_rcv_clk; + uint32_t reserved0[5]; + uint32_t port_cfg_chg; + uint32_t reserved1[11]; + uint32_t rsp_q_full; + uint32_t atio_q_full; + uint32_t drop_ae; + uint32_t els_proto_err; + uint32_t reserved2; uint32_t tx_frames; uint32_t rx_frames; uint32_t discarded_frames; uint32_t dropped_frames; - uint32_t unused2[1]; + uint32_t reserved3; uint32_t nos_rcvd; + uint32_t reserved4[4]; + uint32_t tx_prjt; + uint32_t rcv_exfail; + uint32_t rcv_abts; + uint32_t seq_frm_miss; + uint32_t corr_err; + uint32_t mb_rqst; + uint32_t nport_full; + uint32_t eofa; + uint32_t reserved5; + uint32_t fpm_recv_word_cnt_lo; + uint32_t fpm_recv_word_cnt_hi; + uint32_t fpm_disc_word_cnt_lo; + uint32_t fpm_disc_word_cnt_hi; + uint32_t fpm_xmit_word_cnt_lo; + uint32_t fpm_xmit_word_cnt_hi; + uint32_t reserved6[70]; }; /* @@ -3433,14 +3467,20 @@ struct qla_hw_data { uint32_t flt_region_flt; uint32_t flt_region_fdt; uint32_t flt_region_boot; + uint32_t flt_region_boot_sec; uint32_t flt_region_fw; + uint32_t flt_region_fw_sec; uint32_t flt_region_vpd_nvram; uint32_t flt_region_vpd; + uint32_t flt_region_vpd_sec; uint32_t flt_region_nvram; uint32_t flt_region_npiv_conf; uint32_t flt_region_gold_fw; uint32_t flt_region_fcp_prio; uint32_t flt_region_bootload; + uint32_t flt_region_img_status_pri; + uint32_t flt_region_img_status_sec; + uint8_t active_image; /* Needed for BEACON */ uint16_t beacon_blink_led; @@ -3571,6 +3611,7 @@ typedef struct scsi_qla_host { uint32_t delete_progress:1; uint32_t fw_tgt_reported:1; + uint32_t bbcr_enable:1; } flags; atomic_t loop_state; @@ -3703,8 +3744,19 @@ typedef struct scsi_qla_host { atomic_t vref_count; struct qla8044_reset_template reset_tmplt; struct qla_tgt_counters tgt_counters; + uint16_t bbcr; } scsi_qla_host_t; +struct qla27xx_image_status { + uint8_t image_status_mask; + uint16_t generation_number; + uint8_t reserved[3]; + uint8_t ver_minor; + uint8_t ver_major; + uint32_t checksum; + uint32_t signature; +} __packed; + #define SET_VP_IDX 1 #define SET_AL_PA 2 #define RESET_VP_IDX 3 diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h index 42bb357..4c0f3a7 100644 --- a/drivers/scsi/qla2xxx/qla_fw.h +++ b/drivers/scsi/qla2xxx/qla_fw.h @@ -1288,7 +1288,9 @@ struct vp_rpt_id_entry_24xx { uint8_t vp_idx_map[16]; - uint8_t reserved_4[32]; + uint8_t reserved_4[28]; + uint16_t bbcr; + uint8_t reserved_5[6]; }; #define VF_EVFP_IOCB_TYPE 0x26 /* Exchange Virtual Fabric Parameters entry. */ @@ -1393,6 +1395,16 @@ struct qla_flt_header { #define FLT_REG_FCOE_NVRAM_0 0xAA #define FLT_REG_FCOE_NVRAM_1 0xAC +/* 27xx */ +#define FLT_REG_IMG_PRI_27XX 0x95 +#define FLT_REG_IMG_SEC_27XX 0x96 +#define FLT_REG_FW_SEC_27XX 0x02 +#define FLT_REG_BOOTLOAD_SEC_27XX 0x9 +#define FLT_REG_VPD_SEC_27XX_0 0x50 +#define FLT_REG_VPD_SEC_27XX_1 0x52 +#define FLT_REG_VPD_SEC_27XX_2 0xD8 +#define FLT_REG_VPD_SEC_27XX_3 0xDA + struct qla_flt_region { uint32_t code; uint32_t size; diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 0103e46..fe94377 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -90,6 +90,7 @@ extern int qla2xxx_mctp_dump(scsi_qla_host_t *); extern int qla2x00_alloc_outstanding_cmds(struct qla_hw_data *, struct req_que *); extern int qla2x00_init_rings(scsi_qla_host_t *); +extern uint8_t qla27xx_find_valid_image(struct scsi_qla_host *); /* * Global Data in qla_os.c source file. @@ -121,6 +122,7 @@ extern int ql2xmdcapmask; extern int ql2xmdenable; extern int ql2xexlogins; extern int ql2xexchoffld; +extern int ql2xfwholdabts; extern int qla2x00_loop_reset(scsi_qla_host_t *); extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int); diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 692a757..c56cdb3 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -157,8 +157,12 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport, if (data[1] & QLA_LOGIO_LOGIN_RETRIED) lio->u.logio.flags |= SRB_LOGIN_RETRIED; rval = qla2x00_start_sp(sp); - if (rval != QLA_SUCCESS) + if (rval != QLA_SUCCESS) { + fcport->flags &= ~FCF_ASYNC_SENT; + fcport->flags |= FCF_LOGIN_NEEDED; + set_bit(RELOGIN_NEEDED, &vha->dpc_flags); goto done_free_sp; + } ql_dbg(ql_dbg_disc, vha, 0x2072, "Async-login - hdl=%x, loopid=%x portid=%02x%02x%02x " @@ -2062,6 +2066,10 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha) if (IS_P3P_TYPE(ha)) return; + /* Hold status IOCBs until ABTS response received. */ + if (ql2xfwholdabts) + ha->fw_options[3] |= BIT_12; + /* Update Serial Link options. */ if ((le16_to_cpu(ha->fw_seriallink_options24[0]) & BIT_0) == 0) return; @@ -2844,7 +2852,6 @@ qla2x00_nvram_config(scsi_qla_host_t *vha) if (nv->login_timeout < 4) nv->login_timeout = 4; ha->login_timeout = nv->login_timeout; - icb->login_timeout = nv->login_timeout; /* Set minimum RATOV to 100 tenths of a second. */ ha->r_a_tov = 100; @@ -5122,8 +5129,8 @@ qla24xx_nvram_config(scsi_qla_host_t *vha) dptr = (uint32_t *)nv; ha->isp_ops->read_nvram(vha, (uint8_t *)dptr, ha->nvram_base, ha->nvram_size); - for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++) - chksum += le32_to_cpu(*dptr++); + for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++, dptr++) + chksum += le32_to_cpu(*dptr); ql_dbg(ql_dbg_init + ql_dbg_buffer, vha, 0x006a, "Contents of NVRAM\n"); @@ -5274,7 +5281,6 @@ qla24xx_nvram_config(scsi_qla_host_t *vha) if (le16_to_cpu(nv->login_timeout) < 4) nv->login_timeout = cpu_to_le16(4); ha->login_timeout = le16_to_cpu(nv->login_timeout); - icb->login_timeout = nv->login_timeout; /* Set minimum RATOV to 100 tenths of a second. */ ha->r_a_tov = 100; @@ -5346,6 +5352,93 @@ qla24xx_nvram_config(scsi_qla_host_t *vha) return (rval); } +uint8_t qla27xx_find_valid_image(struct scsi_qla_host *vha) +{ + struct qla27xx_image_status pri_image_status, sec_image_status; + uint8_t valid_pri_image, valid_sec_image; + uint32_t *wptr; + uint32_t cnt, chksum, size; + struct qla_hw_data *ha = vha->hw; + + valid_pri_image = valid_sec_image = 1; + ha->active_image = 0; + size = sizeof(struct qla27xx_image_status) / sizeof(uint32_t); + + if (!ha->flt_region_img_status_pri) { + valid_pri_image = 0; + goto check_sec_image; + } + + qla24xx_read_flash_data(vha, (uint32_t *)(&pri_image_status), + ha->flt_region_img_status_pri, size); + + if (pri_image_status.signature != QLA27XX_IMG_STATUS_SIGN) { + ql_dbg(ql_dbg_init, vha, 0x018b, + "Primary image signature (0x%x) not valid\n", + pri_image_status.signature); + valid_pri_image = 0; + goto check_sec_image; + } + + wptr = (uint32_t *)(&pri_image_status); + cnt = size; + + for (chksum = 0; cnt--; wptr++) + chksum += le32_to_cpu(*wptr); + if (chksum) { + ql_dbg(ql_dbg_init, vha, 0x018c, + "Checksum validation failed for primary image (0x%x)\n", + chksum); + valid_pri_image = 0; + } + +check_sec_image: + if (!ha->flt_region_img_status_sec) { + valid_sec_image = 0; + goto check_valid_image; + } + + qla24xx_read_flash_data(vha, (uint32_t *)(&sec_image_status), + ha->flt_region_img_status_sec, size); + + if (sec_image_status.signature != QLA27XX_IMG_STATUS_SIGN) { + ql_dbg(ql_dbg_init, vha, 0x018d, + "Secondary image signature(0x%x) not valid\n", + sec_image_status.signature); + valid_sec_image = 0; + goto check_valid_image; + } + + wptr = (uint32_t *)(&sec_image_status); + cnt = size; + for (chksum = 0; cnt--; wptr++) + chksum += le32_to_cpu(*wptr); + if (chksum) { + ql_dbg(ql_dbg_init, vha, 0x018e, + "Checksum validation failed for secondary image (0x%x)\n", + chksum); + valid_sec_image = 0; + } + +check_valid_image: + if (valid_pri_image && (pri_image_status.image_status_mask & 0x1)) + ha->active_image = QLA27XX_PRIMARY_IMAGE; + if (valid_sec_image && (sec_image_status.image_status_mask & 0x1)) { + if (!ha->active_image || + pri_image_status.generation_number < + sec_image_status.generation_number) + ha->active_image = QLA27XX_SECONDARY_IMAGE; + } + + ql_dbg(ql_dbg_init, vha, 0x018f, "%s image\n", + ha->active_image == 0 ? "default bootld and fw" : + ha->active_image == 1 ? "primary" : + ha->active_image == 2 ? "secondary" : + "Invalid"); + + return ha->active_image; +} + static int qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr, uint32_t faddr) @@ -5368,6 +5461,10 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr, dcode = (uint32_t *)req->ring; *srisc_addr = 0; + if (IS_QLA27XX(ha) && + qla27xx_find_valid_image(vha) == QLA27XX_SECONDARY_IMAGE) + faddr = ha->flt_region_fw_sec; + /* Validate firmware image by checking version. */ qla24xx_read_flash_data(vha, dcode, faddr + 4, 4); for (i = 0; i < 4; i++) @@ -6068,8 +6165,8 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) ha->isp_ops->read_optrom(vha, ha->nvram, ha->flt_region_nvram << 2, ha->nvram_size); dptr = (uint32_t *)nv; - for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++) - chksum += le32_to_cpu(*dptr++); + for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++, dptr++) + chksum += le32_to_cpu(*dptr); ql_dbg(ql_dbg_init + ql_dbg_buffer, vha, 0x0111, "Contents of NVRAM:\n"); @@ -6231,7 +6328,6 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) if (le16_to_cpu(nv->login_timeout) < 4) nv->login_timeout = cpu_to_le16(4); ha->login_timeout = le16_to_cpu(nv->login_timeout); - icb->login_timeout = nv->login_timeout; /* Set minimum RATOV to 100 tenths of a second. */ ha->r_a_tov = 100; @@ -6413,12 +6509,17 @@ qla81xx_update_fw_options(scsi_qla_host_t *vha) { struct qla_hw_data *ha = vha->hw; + /* Hold status IOCBs until ABTS response received. */ + if (ql2xfwholdabts) + ha->fw_options[3] |= BIT_12; + if (!ql2xetsenable) - return; + goto out; /* Enable ETS Burst. */ memset(ha->fw_options, 0, sizeof(ha->fw_options)); ha->fw_options[2] |= BIT_9; +out: qla2x00_set_fw_options(vha, ha->fw_options); } diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h index a6b7f15..edc48f3 100644 --- a/drivers/scsi/qla2xxx/qla_inline.h +++ b/drivers/scsi/qla2xxx/qla_inline.h @@ -87,8 +87,8 @@ host_to_adap(uint8_t *src, uint8_t *dst, uint32_t bsize) __le32 *odest = (__le32 *) dst; uint32_t iter = bsize >> 2; - for (; iter ; iter--) - *odest++ = cpu_to_le32(*isrc++); + for ( ; iter--; isrc++) + *odest++ = cpu_to_le32(*isrc); } static inline void diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 4af9547..5649c20 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -934,10 +934,6 @@ skip_rio: break; global_port_update: - /* Port unavailable. */ - ql_log(ql_log_warn, vha, 0x505e, - "Link is offline.\n"); - if (atomic_read(&vha->loop_state) != LOOP_DOWN) { atomic_set(&vha->loop_state, LOOP_DOWN); atomic_set(&vha->loop_down_timer, diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 87e6758..968b846 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -1349,6 +1349,8 @@ qla2x00_get_adapter_id(scsi_qla_host_t *vha, uint16_t *id, uint8_t *al_pa, mcp->in_mb |= MBX_13|MBX_12|MBX_11|MBX_10; if (IS_FWI2_CAPABLE(vha->hw)) mcp->in_mb |= MBX_19|MBX_18|MBX_17|MBX_16; + if (IS_QLA27XX(vha->hw)) + mcp->in_mb |= MBX_15; mcp->tov = MBX_TOV_SECONDS; mcp->flags = 0; rval = qla2x00_mailbox_command(vha, mcp); @@ -1400,6 +1402,9 @@ qla2x00_get_adapter_id(scsi_qla_host_t *vha, uint16_t *id, uint8_t *al_pa, wwn_to_u64(vha->port_name)); } } + + if (IS_QLA27XX(vha->hw)) + vha->bbcr = mcp->mb[15]; } return rval; @@ -2754,7 +2759,7 @@ qla2x00_get_link_status(scsi_qla_host_t *vha, uint16_t loop_id, int rval; mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - uint32_t *siter, *diter, dwords; + uint32_t *iter, dwords; struct qla_hw_data *ha = vha->hw; ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1084, @@ -2794,10 +2799,11 @@ qla2x00_get_link_status(scsi_qla_host_t *vha, uint16_t loop_id, /* Copy over data -- firmware data is LE. */ ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1086, "Done %s.\n", __func__); - dwords = offsetof(struct link_statistics, unused1) / 4; - siter = diter = &stats->link_fail_cnt; - while (dwords--) - *diter++ = le32_to_cpu(*siter++); + dwords = offsetof(struct link_statistics, + link_up_cnt) / 4; + iter = &stats->link_fail_cnt; + for ( ; dwords--; iter++) + le32_to_cpus(iter); } } else { /* Failed. */ @@ -2814,7 +2820,7 @@ qla24xx_get_isp_stats(scsi_qla_host_t *vha, struct link_statistics *stats, int rval; mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - uint32_t *siter, *diter, dwords; + uint32_t *iter, dwords; ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1088, "Entered %s.\n", __func__); @@ -2843,9 +2849,9 @@ qla24xx_get_isp_stats(scsi_qla_host_t *vha, struct link_statistics *stats, "Done %s.\n", __func__); /* Copy over data -- firmware data is LE. */ dwords = sizeof(struct link_statistics) / 4; - siter = diter = &stats->link_fail_cnt; - while (dwords--) - *diter++ = le32_to_cpu(*siter++); + iter = &stats->link_fail_cnt; + for ( ; dwords--; iter++) + le32_to_cpus(iter); } } else { /* Failed. */ @@ -3612,6 +3618,9 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha, rptid_entry->port_id[2], rptid_entry->port_id[1], rptid_entry->port_id[0]); + /* buffer to buffer credit flag */ + vha->flags.bbcr_enable = (rptid_entry->bbcr & 0xf) != 0; + /* FA-WWN is only for physical port */ if (!vp_idx) { void *wwpn = ha->init_cb->port_name; diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index f6c7ce3..7c0b60c 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -233,6 +233,13 @@ MODULE_PARM_DESC(ql2xexchoffld, "Number of exchanges to offload. " "0 (Default)- Disabled."); +int ql2xfwholdabts = 0; +module_param(ql2xfwholdabts, int, S_IRUGO); +MODULE_PARM_DESC(ql2xfwholdabts, + "Allow FW to hold status IOCB until ABTS rsp received. " + "0 (Default) Do not set fw option. " + "1 - Set fw option to hold ABTS."); + /* * SCSI host template entry points */ @@ -2216,6 +2223,7 @@ qla2x00_set_isp_flags(struct qla_hw_data *ha) ha->device_type |= DT_ZIO_SUPPORTED; ha->device_type |= DT_FWI2; ha->device_type |= DT_IIDMA; + ha->device_type |= DT_T10_PI; ha->fw_srisc_address = RISC_START_ADDRESS_2400; break; case PCI_DEVICE_ID_QLOGIC_ISP2271: @@ -2223,6 +2231,7 @@ qla2x00_set_isp_flags(struct qla_hw_data *ha) ha->device_type |= DT_ZIO_SUPPORTED; ha->device_type |= DT_FWI2; ha->device_type |= DT_IIDMA; + ha->device_type |= DT_T10_PI; ha->fw_srisc_address = RISC_START_ADDRESS_2400; break; case PCI_DEVICE_ID_QLOGIC_ISP2261: @@ -2230,6 +2239,7 @@ qla2x00_set_isp_flags(struct qla_hw_data *ha) ha->device_type |= DT_ZIO_SUPPORTED; ha->device_type |= DT_FWI2; ha->device_type |= DT_IIDMA; + ha->device_type |= DT_T10_PI; ha->fw_srisc_address = RISC_START_ADDRESS_2400; break; } diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index 3272ed5b..5e93923 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c @@ -610,8 +610,8 @@ qla2xxx_find_flt_start(scsi_qla_host_t *vha, uint32_t *start) wptr = (uint16_t *)req->ring; cnt = sizeof(struct qla_flt_location) >> 1; - for (chksum = 0; cnt; cnt--) - chksum += le16_to_cpu(*wptr++); + for (chksum = 0; cnt--; wptr++) + chksum += le16_to_cpu(*wptr); if (chksum) { ql_log(ql_log_fatal, vha, 0x0045, "Inconsistent FLTL detected: checksum=0x%x.\n", chksum); @@ -702,8 +702,8 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr) } cnt = (sizeof(struct qla_flt_header) + le16_to_cpu(flt->length)) >> 1; - for (chksum = 0; cnt; cnt--) - chksum += le16_to_cpu(*wptr++); + for (chksum = 0; cnt--; wptr++) + chksum += le16_to_cpu(*wptr); if (chksum) { ql_log(ql_log_fatal, vha, 0x0048, "Inconsistent FLT detected: version=0x%x length=0x%x checksum=0x%x.\n", @@ -846,6 +846,38 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr) if (ha->port_no == 1) ha->flt_region_nvram = start; break; + case FLT_REG_IMG_PRI_27XX: + if (IS_QLA27XX(ha)) + ha->flt_region_img_status_pri = start; + break; + case FLT_REG_IMG_SEC_27XX: + if (IS_QLA27XX(ha)) + ha->flt_region_img_status_sec = start; + break; + case FLT_REG_FW_SEC_27XX: + if (IS_QLA27XX(ha)) + ha->flt_region_fw_sec = start; + break; + case FLT_REG_BOOTLOAD_SEC_27XX: + if (IS_QLA27XX(ha)) + ha->flt_region_boot_sec = start; + break; + case FLT_REG_VPD_SEC_27XX_0: + if (IS_QLA27XX(ha)) + ha->flt_region_vpd_sec = start; + break; + case FLT_REG_VPD_SEC_27XX_1: + if (IS_QLA27XX(ha)) + ha->flt_region_vpd_sec = start; + break; + case FLT_REG_VPD_SEC_27XX_2: + if (IS_QLA27XX(ha)) + ha->flt_region_vpd_sec = start; + break; + case FLT_REG_VPD_SEC_27XX_3: + if (IS_QLA27XX(ha)) + ha->flt_region_vpd_sec = start; + break; } } goto done; @@ -898,9 +930,8 @@ qla2xxx_get_fdt_info(scsi_qla_host_t *vha) fdt->sig[3] != 'D') goto no_flash_data; - for (cnt = 0, chksum = 0; cnt < sizeof(struct qla_fdt_layout) >> 1; - cnt++) - chksum += le16_to_cpu(*wptr++); + for (cnt = 0, chksum = 0; cnt < sizeof(*fdt) >> 1; cnt++, wptr++) + chksum += le16_to_cpu(*wptr); if (chksum) { ql_dbg(ql_dbg_init, vha, 0x004c, "Inconsistent FDT detected:" @@ -995,7 +1026,8 @@ qla2xxx_get_idc_param(scsi_qla_host_t *vha) ha->fcoe_dev_init_timeout = QLA82XX_ROM_DEV_INIT_TIMEOUT; ha->fcoe_reset_timeout = QLA82XX_ROM_DRV_RESET_ACK_TIMEOUT; } else { - ha->fcoe_dev_init_timeout = le32_to_cpu(*wptr++); + ha->fcoe_dev_init_timeout = le32_to_cpu(*wptr); + wptr++; ha->fcoe_reset_timeout = le32_to_cpu(*wptr); } ql_dbg(ql_dbg_init, vha, 0x004e, @@ -1072,10 +1104,9 @@ qla2xxx_flash_npiv_conf(scsi_qla_host_t *vha) ha->isp_ops->read_optrom(vha, (uint8_t *)data, ha->flt_region_npiv_conf << 2, NPIV_CONFIG_SIZE); - cnt = (sizeof(struct qla_npiv_header) + le16_to_cpu(hdr.entries) * - sizeof(struct qla_npiv_entry)) >> 1; - for (wptr = data, chksum = 0; cnt; cnt--) - chksum += le16_to_cpu(*wptr++); + cnt = (sizeof(hdr) + le16_to_cpu(hdr.entries) * sizeof(*entry)) >> 1; + for (wptr = data, chksum = 0; cnt--; wptr++) + chksum += le16_to_cpu(*wptr); if (chksum) { ql_dbg(ql_dbg_user, vha, 0x7092, "Inconsistent NPIV-Config " @@ -2989,6 +3020,9 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf) uint8_t code_type, last_image; int i; struct qla_hw_data *ha = vha->hw; + uint32_t faddr = 0; + + pcihdr = pcids = 0; if (IS_P3P_TYPE(ha)) return ret; @@ -3002,9 +3036,11 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf) memset(ha->fw_revision, 0, sizeof(ha->fw_revision)); dcode = mbuf; - - /* Begin with first PCI expansion ROM header. */ pcihdr = ha->flt_region_boot << 2; + if (IS_QLA27XX(ha) && + qla27xx_find_valid_image(vha) == QLA27XX_SECONDARY_IMAGE) + pcihdr = ha->flt_region_boot_sec << 2; + last_image = 1; do { /* Verify PCI expansion ROM header. */ @@ -3077,8 +3113,12 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf) /* Read firmware image information. */ memset(ha->fw_revision, 0, sizeof(ha->fw_revision)); dcode = mbuf; + faddr = ha->flt_region_fw; + if (IS_QLA27XX(ha) && + qla27xx_find_valid_image(vha) == QLA27XX_SECONDARY_IMAGE) + faddr = ha->flt_region_fw_sec; - qla24xx_read_flash_data(vha, dcode, ha->flt_region_fw + 4, 4); + qla24xx_read_flash_data(vha, dcode, faddr + 4, 4); for (i = 0; i < 4; i++) dcode[i] = be32_to_cpu(dcode[i]); diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index 6d31faa..0bc93fa 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -7,7 +7,7 @@ /* * Driver version */ -#define QLA2XXX_VERSION "8.07.00.26-k" +#define QLA2XXX_VERSION "8.07.00.33-k" #define QLA_DRIVER_MAJOR_VER 8 #define QLA_DRIVER_MINOR_VER 7 |