diff options
Diffstat (limited to 'drivers/scsi/qla2xxx')
32 files changed, 3603 insertions, 2784 deletions
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index f928c4d3a1ef..8d560c562e9c 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -29,24 +29,27 @@ qla2x00_sysfs_read_fw_dump(struct file *filp, struct kobject *kobj, if (!(ha->fw_dump_reading || ha->mctp_dump_reading)) return 0; + mutex_lock(&ha->optrom_mutex); if (IS_P3P_TYPE(ha)) { if (off < ha->md_template_size) { rval = memory_read_from_buffer(buf, count, &off, ha->md_tmplt_hdr, ha->md_template_size); - return rval; + } else { + off -= ha->md_template_size; + rval = memory_read_from_buffer(buf, count, + &off, ha->md_dump, ha->md_dump_size); } - off -= ha->md_template_size; - rval = memory_read_from_buffer(buf, count, - &off, ha->md_dump, ha->md_dump_size); - return rval; - } else if (ha->mctp_dumped && ha->mctp_dump_reading) - return memory_read_from_buffer(buf, count, &off, ha->mctp_dump, + } else if (ha->mctp_dumped && ha->mctp_dump_reading) { + rval = memory_read_from_buffer(buf, count, &off, ha->mctp_dump, MCTP_DUMP_SIZE); - else if (ha->fw_dump_reading) - return memory_read_from_buffer(buf, count, &off, ha->fw_dump, + } else if (ha->fw_dump_reading) { + rval = memory_read_from_buffer(buf, count, &off, ha->fw_dump, ha->fw_dump_len); - else - return 0; + } else { + rval = 0; + } + mutex_unlock(&ha->optrom_mutex); + return rval; } static ssize_t @@ -154,6 +157,8 @@ qla2x00_sysfs_read_nvram(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; + struct active_regions active_regions = { }; if (!capable(CAP_SYS_ADMIN)) return 0; @@ -164,11 +169,21 @@ qla2x00_sysfs_read_nvram(struct file *filp, struct kobject *kobj, return -EAGAIN; } - if (IS_NOCACHE_VPD_TYPE(ha)) - ha->isp_ops->read_optrom(vha, ha->nvram, ha->flt_region_nvram << 2, - ha->nvram_size); + if (!IS_NOCACHE_VPD_TYPE(ha)) { + mutex_unlock(&ha->optrom_mutex); + goto skip; + } + + faddr = ha->flt_region_nvram; + if (IS_QLA28XX(ha)) { + if (active_regions.aux.vpd_nvram == QLA27XX_SECONDARY_IMAGE) + faddr = ha->flt_region_nvram_sec; + } + ha->isp_ops->read_optrom(vha, ha->nvram, faddr << 2, ha->nvram_size); + mutex_unlock(&ha->optrom_mutex); +skip: return memory_read_from_buffer(buf, count, &off, ha->nvram, ha->nvram_size); } @@ -223,9 +238,9 @@ qla2x00_sysfs_write_nvram(struct file *filp, struct kobject *kobj, } /* Write NVRAM. */ - ha->isp_ops->write_nvram(vha, (uint8_t *)buf, ha->nvram_base, count); - ha->isp_ops->read_nvram(vha, (uint8_t *)ha->nvram, ha->nvram_base, - count); + ha->isp_ops->write_nvram(vha, buf, ha->nvram_base, count); + ha->isp_ops->read_nvram(vha, ha->nvram, ha->nvram_base, + count); mutex_unlock(&ha->optrom_mutex); ql_dbg(ql_dbg_user, vha, 0x7060, @@ -364,7 +379,7 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj, } ha->optrom_region_start = start; - ha->optrom_region_size = start + size; + ha->optrom_region_size = size; ha->optrom_state = QLA_SREADING; ha->optrom_buffer = vmalloc(ha->optrom_region_size); @@ -418,6 +433,10 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj, * 0x000000 -> 0x07ffff -- Boot code. * 0x080000 -> 0x0fffff -- Firmware. * 0x120000 -> 0x12ffff -- VPD and HBA parameters. + * + * > ISP25xx type boards: + * + * None -- should go through BSG. */ valid = 0; if (ha->optrom_size == OPTROM_SIZE_2300 && start == 0) @@ -425,9 +444,7 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj, else if (start == (ha->flt_region_boot * 4) || start == (ha->flt_region_fw * 4)) valid = 1; - else if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) - || IS_CNA_CAPABLE(ha) || IS_QLA2031(ha) - || IS_QLA27XX(ha)) + else if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha)) valid = 1; if (!valid) { ql_log(ql_log_warn, vha, 0x7065, @@ -437,7 +454,7 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj, } ha->optrom_region_start = start; - ha->optrom_region_size = start + size; + ha->optrom_region_size = size; ha->optrom_state = QLA_SWRITING; ha->optrom_buffer = vmalloc(ha->optrom_region_size); @@ -504,6 +521,7 @@ qla2x00_sysfs_read_vpd(struct file *filp, struct kobject *kobj, struct device, kobj))); struct qla_hw_data *ha = vha->hw; uint32_t faddr; + struct active_regions active_regions = { }; if (unlikely(pci_channel_offline(ha->pdev))) return -EAGAIN; @@ -511,22 +529,33 @@ qla2x00_sysfs_read_vpd(struct file *filp, struct kobject *kobj, if (!capable(CAP_SYS_ADMIN)) return -EINVAL; - if (IS_NOCACHE_VPD_TYPE(ha)) { - faddr = ha->flt_region_vpd << 2; + if (IS_NOCACHE_VPD_TYPE(ha)) + goto skip; + + faddr = ha->flt_region_vpd << 2; - if (IS_QLA27XX(ha) && - qla27xx_find_valid_image(vha) == QLA27XX_SECONDARY_IMAGE) + if (IS_QLA28XX(ha)) { + qla28xx_get_aux_images(vha, &active_regions); + if (active_regions.aux.vpd_nvram == QLA27XX_SECONDARY_IMAGE) faddr = ha->flt_region_vpd_sec << 2; - mutex_lock(&ha->optrom_mutex); - if (qla2x00_chip_is_down(vha)) { - mutex_unlock(&ha->optrom_mutex); - return -EAGAIN; - } - ha->isp_ops->read_optrom(vha, ha->vpd, faddr, - ha->vpd_size); + ql_dbg(ql_dbg_init, vha, 0x7070, + "Loading %s nvram image.\n", + active_regions.aux.vpd_nvram == QLA27XX_PRIMARY_IMAGE ? + "primary" : "secondary"); + } + + mutex_lock(&ha->optrom_mutex); + if (qla2x00_chip_is_down(vha)) { mutex_unlock(&ha->optrom_mutex); + return -EAGAIN; } + + ha->isp_ops->read_optrom(vha, ha->vpd, faddr, ha->vpd_size); + mutex_unlock(&ha->optrom_mutex); + + ha->isp_ops->read_optrom(vha, ha->vpd, faddr, ha->vpd_size); +skip: return memory_read_from_buffer(buf, count, &off, ha->vpd, ha->vpd_size); } @@ -563,8 +592,8 @@ qla2x00_sysfs_write_vpd(struct file *filp, struct kobject *kobj, } /* Write NVRAM. */ - ha->isp_ops->write_nvram(vha, (uint8_t *)buf, ha->vpd_base, count); - ha->isp_ops->read_nvram(vha, (uint8_t *)ha->vpd, ha->vpd_base, count); + ha->isp_ops->write_nvram(vha, buf, ha->vpd_base, count); + ha->isp_ops->read_nvram(vha, ha->vpd, ha->vpd_base, count); /* Update flash version information for 4Gb & above. */ if (!IS_FWI2_CAPABLE(ha)) { @@ -645,6 +674,7 @@ qla2x00_sysfs_write_reset(struct file *filp, struct kobject *kobj, int type; uint32_t idc_control; uint8_t *tmp_data = NULL; + if (off != 0) return -EINVAL; @@ -682,7 +712,7 @@ qla2x00_sysfs_write_reset(struct file *filp, struct kobject *kobj, ql_log(ql_log_info, vha, 0x706f, "Issuing MPI reset.\n"); - if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) { + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { uint32_t idc_control; qla83xx_idc_lock(vha, 0); @@ -858,7 +888,7 @@ do_read: count = 0; } - count = actual_size > count ? count: actual_size; + count = actual_size > count ? count : actual_size; memcpy(buf, ha->xgmac_data, count); return count; @@ -934,7 +964,7 @@ static struct bin_attribute sysfs_dcbx_tlv_attr = { static struct sysfs_entry { char *name; struct bin_attribute *attr; - int is4GBp_only; + int type; } bin_file_entries[] = { { "fw_dump", &sysfs_fw_dump_attr, }, { "nvram", &sysfs_nvram_attr, }, @@ -957,11 +987,11 @@ qla2x00_alloc_sysfs_attr(scsi_qla_host_t *vha) int ret; for (iter = bin_file_entries; iter->name; iter++) { - if (iter->is4GBp_only && !IS_FWI2_CAPABLE(vha->hw)) + if (iter->type && !IS_FWI2_CAPABLE(vha->hw)) continue; - if (iter->is4GBp_only == 2 && !IS_QLA25XX(vha->hw)) + if (iter->type == 2 && !IS_QLA25XX(vha->hw)) continue; - if (iter->is4GBp_only == 3 && !(IS_CNA_CAPABLE(vha->hw))) + if (iter->type == 3 && !(IS_CNA_CAPABLE(vha->hw))) continue; ret = sysfs_create_bin_file(&host->shost_gendev.kobj, @@ -985,13 +1015,14 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *vha, bool stop_beacon) struct qla_hw_data *ha = vha->hw; for (iter = bin_file_entries; iter->name; iter++) { - if (iter->is4GBp_only && !IS_FWI2_CAPABLE(ha)) + if (iter->type && !IS_FWI2_CAPABLE(ha)) continue; - if (iter->is4GBp_only == 2 && !IS_QLA25XX(ha)) + if (iter->type == 2 && !IS_QLA25XX(ha)) continue; - if (iter->is4GBp_only == 3 && !(IS_CNA_CAPABLE(vha->hw))) + if (iter->type == 3 && !(IS_CNA_CAPABLE(ha))) continue; - if (iter->is4GBp_only == 0x27 && !IS_QLA27XX(vha->hw)) + if (iter->type == 0x27 && + (!IS_QLA27XX(ha) || !IS_QLA28XX(ha))) continue; sysfs_remove_bin_file(&host->shost_gendev.kobj, @@ -1049,6 +1080,7 @@ qla2x00_isp_name_show(struct device *dev, struct device_attribute *attr, char *buf) { scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); + return scnprintf(buf, PAGE_SIZE, "ISP%04X\n", vha->hw->pdev->device); } @@ -1082,6 +1114,7 @@ qla2x00_model_desc_show(struct device *dev, struct device_attribute *attr, char *buf) { scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); + return scnprintf(buf, PAGE_SIZE, "%s\n", vha->hw->model_desc); } @@ -1294,6 +1327,7 @@ qla2x00_optrom_bios_version_show(struct device *dev, { scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); struct qla_hw_data *ha = vha->hw; + return scnprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->bios_revision[1], ha->bios_revision[0]); } @@ -1304,6 +1338,7 @@ qla2x00_optrom_efi_version_show(struct device *dev, { scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); struct qla_hw_data *ha = vha->hw; + return scnprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->efi_revision[1], ha->efi_revision[0]); } @@ -1314,6 +1349,7 @@ qla2x00_optrom_fcode_version_show(struct device *dev, { scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); struct qla_hw_data *ha = vha->hw; + return scnprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->fcode_revision[1], ha->fcode_revision[0]); } @@ -1324,6 +1360,7 @@ qla2x00_optrom_fw_version_show(struct device *dev, { scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); struct qla_hw_data *ha = vha->hw; + return scnprintf(buf, PAGE_SIZE, "%d.%02d.%02d %d\n", ha->fw_revision[0], ha->fw_revision[1], ha->fw_revision[2], ha->fw_revision[3]); @@ -1336,7 +1373,8 @@ qla2x00_optrom_gold_fw_version_show(struct device *dev, scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); struct qla_hw_data *ha = vha->hw; - if (!IS_QLA81XX(ha) && !IS_QLA83XX(ha) && !IS_QLA27XX(ha)) + if (!IS_QLA81XX(ha) && !IS_QLA83XX(ha) && + !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) return scnprintf(buf, PAGE_SIZE, "\n"); return scnprintf(buf, PAGE_SIZE, "%d.%02d.%02d (%d)\n", @@ -1349,6 +1387,7 @@ qla2x00_total_isp_aborts_show(struct device *dev, struct device_attribute *attr, char *buf) { scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); + return scnprintf(buf, PAGE_SIZE, "%d\n", vha->qla_stats.total_isp_aborts); } @@ -1358,24 +1397,40 @@ qla24xx_84xx_fw_version_show(struct device *dev, struct device_attribute *attr, char *buf) { int rval = QLA_SUCCESS; - uint16_t status[2] = {0, 0}; + uint16_t status[2] = { 0 }; scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); struct qla_hw_data *ha = vha->hw; if (!IS_QLA84XX(ha)) return scnprintf(buf, PAGE_SIZE, "\n"); - if (ha->cs84xx->op_fw_version == 0) + if (!ha->cs84xx->op_fw_version) { rval = qla84xx_verify_chip(vha, status); - if ((rval == QLA_SUCCESS) && (status[0] == 0)) - return scnprintf(buf, PAGE_SIZE, "%u\n", - (uint32_t)ha->cs84xx->op_fw_version); + if (!rval && !status[0]) + return scnprintf(buf, PAGE_SIZE, "%u\n", + (uint32_t)ha->cs84xx->op_fw_version); + } return scnprintf(buf, PAGE_SIZE, "\n"); } static ssize_t +qla2x00_serdes_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_QLA27XX(ha) && !IS_QLA28XX(ha)) + return scnprintf(buf, PAGE_SIZE, "\n"); + + return scnprintf(buf, PAGE_SIZE, "%d.%02d.%02d\n", + ha->serdes_version[0], ha->serdes_version[1], + ha->serdes_version[2]); +} + +static ssize_t qla2x00_mpi_version_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -1383,7 +1438,7 @@ qla2x00_mpi_version_show(struct device *dev, struct device_attribute *attr, struct qla_hw_data *ha = vha->hw; if (!IS_QLA81XX(ha) && !IS_QLA8031(ha) && !IS_QLA8044(ha) && - !IS_QLA27XX(ha)) + !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) return scnprintf(buf, PAGE_SIZE, "\n"); return scnprintf(buf, PAGE_SIZE, "%d.%02d.%02d (%x)\n", @@ -1596,7 +1651,7 @@ qla2x00_pep_version_show(struct device *dev, struct device_attribute *attr, scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); struct qla_hw_data *ha = vha->hw; - if (!IS_QLA27XX(ha)) + if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) return scnprintf(buf, PAGE_SIZE, "\n"); return scnprintf(buf, PAGE_SIZE, "%d.%02d.%02d\n", @@ -1604,35 +1659,38 @@ qla2x00_pep_version_show(struct device *dev, struct device_attribute *attr, } static ssize_t -qla2x00_min_link_speed_show(struct device *dev, struct device_attribute *attr, - char *buf) +qla2x00_min_supported_speed_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_QLA27XX(ha)) + if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) return scnprintf(buf, PAGE_SIZE, "\n"); return scnprintf(buf, PAGE_SIZE, "%s\n", - ha->min_link_speed == 5 ? "32Gps" : - ha->min_link_speed == 4 ? "16Gps" : - ha->min_link_speed == 3 ? "8Gps" : - ha->min_link_speed == 2 ? "4Gps" : - ha->min_link_speed != 0 ? "unknown" : ""); + ha->min_supported_speed == 6 ? "64Gps" : + ha->min_supported_speed == 5 ? "32Gps" : + ha->min_supported_speed == 4 ? "16Gps" : + ha->min_supported_speed == 3 ? "8Gps" : + ha->min_supported_speed == 2 ? "4Gps" : + ha->min_supported_speed != 0 ? "unknown" : ""); } static ssize_t -qla2x00_max_speed_sup_show(struct device *dev, struct device_attribute *attr, - char *buf) +qla2x00_max_supported_speed_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_QLA27XX(ha)) + if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) return scnprintf(buf, PAGE_SIZE, "\n"); return scnprintf(buf, PAGE_SIZE, "%s\n", - ha->max_speed_sup ? "32Gps" : "16Gps"); + ha->max_supported_speed == 2 ? "64Gps" : + ha->max_supported_speed == 1 ? "32Gps" : + ha->max_supported_speed == 0 ? "16Gps" : "unknown"); } static ssize_t @@ -1645,7 +1703,7 @@ qla2x00_port_speed_store(struct device *dev, struct device_attribute *attr, int mode = QLA_SET_DATA_RATE_LR; struct qla_hw_data *ha = vha->hw; - if (!IS_QLA27XX(vha->hw)) { + if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) { ql_log(ql_log_warn, vha, 0x70d8, "Speed setting not supported \n"); return -EINVAL; @@ -2164,6 +2222,32 @@ qla2x00_dif_bundle_statistics_show(struct device *dev, ha->dif_bundle_dma_allocs, ha->pool.unusable.count); } +static ssize_t +qla2x00_fw_attr_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_QLA27XX(ha) && !IS_QLA28XX(ha)) + return scnprintf(buf, PAGE_SIZE, "\n"); + + return scnprintf(buf, PAGE_SIZE, "%llx\n", + (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); +} + +static ssize_t +qla2x00_port_no_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); + + return scnprintf(buf, PAGE_SIZE, "%u\n", vha->hw->port_no); +} + static DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_driver_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); @@ -2192,6 +2276,7 @@ static DEVICE_ATTR(84xx_fw_version, S_IRUGO, qla24xx_84xx_fw_version_show, NULL); static DEVICE_ATTR(total_isp_aborts, S_IRUGO, qla2x00_total_isp_aborts_show, NULL); +static DEVICE_ATTR(serdes_version, 0444, qla2x00_serdes_version_show, NULL); static DEVICE_ATTR(mpi_version, S_IRUGO, qla2x00_mpi_version_show, NULL); static DEVICE_ATTR(phy_version, S_IRUGO, qla2x00_phy_version_show, NULL); static DEVICE_ATTR(flash_block_size, S_IRUGO, qla2x00_flash_block_size_show, @@ -2209,8 +2294,10 @@ static DEVICE_ATTR(allow_cna_fw_dump, S_IRUGO | S_IWUSR, qla2x00_allow_cna_fw_dump_show, qla2x00_allow_cna_fw_dump_store); static DEVICE_ATTR(pep_version, S_IRUGO, qla2x00_pep_version_show, NULL); -static DEVICE_ATTR(min_link_speed, S_IRUGO, qla2x00_min_link_speed_show, NULL); -static DEVICE_ATTR(max_speed_sup, S_IRUGO, qla2x00_max_speed_sup_show, NULL); +static DEVICE_ATTR(min_supported_speed, 0444, + qla2x00_min_supported_speed_show, NULL); +static DEVICE_ATTR(max_supported_speed, 0444, + qla2x00_max_supported_speed_show, NULL); static DEVICE_ATTR(zio_threshold, 0644, qla_zio_threshold_show, qla_zio_threshold_store); @@ -2221,6 +2308,8 @@ static DEVICE_ATTR(dif_bundle_statistics, 0444, qla2x00_dif_bundle_statistics_show, NULL); static DEVICE_ATTR(port_speed, 0644, qla2x00_port_speed_show, qla2x00_port_speed_store); +static DEVICE_ATTR(port_no, 0444, qla2x00_port_no_show, NULL); +static DEVICE_ATTR(fw_attr, 0444, qla2x00_fw_attr_show, NULL); struct device_attribute *qla2x00_host_attrs[] = { @@ -2242,6 +2331,7 @@ struct device_attribute *qla2x00_host_attrs[] = { &dev_attr_optrom_fw_version, &dev_attr_84xx_fw_version, &dev_attr_total_isp_aborts, + &dev_attr_serdes_version, &dev_attr_mpi_version, &dev_attr_phy_version, &dev_attr_flash_block_size, @@ -2256,11 +2346,13 @@ struct device_attribute *qla2x00_host_attrs[] = { &dev_attr_fw_dump_size, &dev_attr_allow_cna_fw_dump, &dev_attr_pep_version, - &dev_attr_min_link_speed, - &dev_attr_max_speed_sup, + &dev_attr_min_supported_speed, + &dev_attr_max_supported_speed, &dev_attr_zio_threshold, &dev_attr_dif_bundle_statistics, &dev_attr_port_speed, + &dev_attr_port_no, + &dev_attr_fw_attr, NULL, /* reserve for qlini_mode */ NULL, /* reserve for ql2xiniexchg */ NULL, /* reserve for ql2xexchoffld */ @@ -2296,16 +2388,15 @@ qla2x00_get_host_port_id(struct Scsi_Host *shost) static void qla2x00_get_host_speed(struct Scsi_Host *shost) { - struct qla_hw_data *ha = ((struct scsi_qla_host *) - (shost_priv(shost)))->hw; - u32 speed = FC_PORTSPEED_UNKNOWN; + scsi_qla_host_t *vha = shost_priv(shost); + u32 speed; - if (IS_QLAFX00(ha)) { + if (IS_QLAFX00(vha->hw)) { qlafx00_get_host_speed(shost); return; } - switch (ha->link_data_rate) { + switch (vha->hw->link_data_rate) { case PORT_SPEED_1GB: speed = FC_PORTSPEED_1GBIT; break; @@ -2327,7 +2418,14 @@ qla2x00_get_host_speed(struct Scsi_Host *shost) case PORT_SPEED_32GB: speed = FC_PORTSPEED_32GBIT; break; + case PORT_SPEED_64GB: + speed = FC_PORTSPEED_64GBIT; + break; + default: + speed = FC_PORTSPEED_UNKNOWN; + break; } + fc_host_speed(shost) = speed; } @@ -2335,7 +2433,7 @@ static void qla2x00_get_host_port_type(struct Scsi_Host *shost) { scsi_qla_host_t *vha = shost_priv(shost); - uint32_t port_type = FC_PORTTYPE_UNKNOWN; + uint32_t port_type; if (vha->vp_idx) { fc_host_port_type(shost) = FC_PORTTYPE_NPIV; @@ -2354,7 +2452,11 @@ qla2x00_get_host_port_type(struct Scsi_Host *shost) case ISP_CFG_F: port_type = FC_PORTTYPE_NPORT; break; + default: + port_type = FC_PORTTYPE_UNKNOWN; + break; } + fc_host_port_type(shost) = port_type; } @@ -2416,13 +2518,10 @@ qla2x00_get_starget_port_id(struct scsi_target *starget) fc_starget_port_id(starget) = port_id; } -static void +static inline void qla2x00_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout) { - if (timeout) - rport->dev_loss_tmo = timeout; - else - rport->dev_loss_tmo = 1; + rport->dev_loss_tmo = timeout ? timeout : 1; } static void @@ -2632,8 +2731,9 @@ static void qla2x00_get_host_fabric_name(struct Scsi_Host *shost) { scsi_qla_host_t *vha = shost_priv(shost); - uint8_t node_name[WWN_SIZE] = { 0xFF, 0xFF, 0xFF, 0xFF, \ - 0xFF, 0xFF, 0xFF, 0xFF}; + static const uint8_t node_name[WWN_SIZE] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF + }; u64 fabric_name = wwn_to_u64(node_name); if (vha->device_flags & SWITCH_FOUND) @@ -2711,8 +2811,8 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable) /* initialized vport states */ atomic_set(&vha->loop_state, LOOP_DOWN); - vha->vp_err_state= VP_ERR_PORTDWN; - vha->vp_prev_err_state= VP_ERR_UNKWN; + vha->vp_err_state = VP_ERR_PORTDWN; + vha->vp_prev_err_state = VP_ERR_UNKWN; /* Check if physical ha port is Up */ if (atomic_read(&base_vha->loop_state) == LOOP_DOWN || atomic_read(&base_vha->loop_state) == LOOP_DEAD) { @@ -2727,6 +2827,7 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable) if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif) { if (ha->fw_attributes & BIT_4) { int prot = 0, guard; + vha->flags.difdix_supported = 1; ql_dbg(ql_dbg_user, vha, 0x7082, "Registered for DIF/DIX type 1 and 3 protection.\n"); @@ -2977,7 +3078,7 @@ void qla2x00_init_host_attr(scsi_qla_host_t *vha) { struct qla_hw_data *ha = vha->hw; - u32 speed = FC_PORTSPEED_UNKNOWN; + u32 speeds = FC_PORTSPEED_UNKNOWN; fc_host_dev_loss_tmo(vha->host) = ha->port_down_retry_count; fc_host_node_name(vha->host) = wwn_to_u64(vha->node_name); @@ -2988,25 +3089,45 @@ qla2x00_init_host_attr(scsi_qla_host_t *vha) fc_host_npiv_vports_inuse(vha->host) = ha->cur_vport_count; if (IS_CNA_CAPABLE(ha)) - speed = FC_PORTSPEED_10GBIT; - else if (IS_QLA2031(ha)) - speed = FC_PORTSPEED_16GBIT | FC_PORTSPEED_8GBIT | - FC_PORTSPEED_4GBIT; - else if (IS_QLA25XX(ha)) - speed = FC_PORTSPEED_8GBIT | FC_PORTSPEED_4GBIT | - FC_PORTSPEED_2GBIT | FC_PORTSPEED_1GBIT; + speeds = FC_PORTSPEED_10GBIT; + else if (IS_QLA28XX(ha) || IS_QLA27XX(ha)) { + if (ha->max_supported_speed == 2) { + if (ha->min_supported_speed <= 6) + speeds |= FC_PORTSPEED_64GBIT; + } + if (ha->max_supported_speed == 2 || + ha->max_supported_speed == 1) { + if (ha->min_supported_speed <= 5) + speeds |= FC_PORTSPEED_32GBIT; + } + if (ha->max_supported_speed == 2 || + ha->max_supported_speed == 1 || + ha->max_supported_speed == 0) { + if (ha->min_supported_speed <= 4) + speeds |= FC_PORTSPEED_16GBIT; + } + if (ha->max_supported_speed == 1 || + ha->max_supported_speed == 0) { + if (ha->min_supported_speed <= 3) + speeds |= FC_PORTSPEED_8GBIT; + } + if (ha->max_supported_speed == 0) { + if (ha->min_supported_speed <= 2) + speeds |= FC_PORTSPEED_4GBIT; + } + } else if (IS_QLA2031(ha)) + speeds = FC_PORTSPEED_16GBIT|FC_PORTSPEED_8GBIT| + FC_PORTSPEED_4GBIT; + else if (IS_QLA25XX(ha) || IS_QLAFX00(ha)) + speeds = FC_PORTSPEED_8GBIT|FC_PORTSPEED_4GBIT| + FC_PORTSPEED_2GBIT|FC_PORTSPEED_1GBIT; else if (IS_QLA24XX_TYPE(ha)) - speed = FC_PORTSPEED_4GBIT | FC_PORTSPEED_2GBIT | - FC_PORTSPEED_1GBIT; + speeds = FC_PORTSPEED_4GBIT|FC_PORTSPEED_2GBIT| + FC_PORTSPEED_1GBIT; else if (IS_QLA23XX(ha)) - speed = FC_PORTSPEED_2GBIT | FC_PORTSPEED_1GBIT; - else if (IS_QLAFX00(ha)) - speed = FC_PORTSPEED_8GBIT | FC_PORTSPEED_4GBIT | - FC_PORTSPEED_2GBIT | FC_PORTSPEED_1GBIT; - else if (IS_QLA27XX(ha)) - speed = FC_PORTSPEED_32GBIT | FC_PORTSPEED_16GBIT | - FC_PORTSPEED_8GBIT; + speeds = FC_PORTSPEED_2GBIT|FC_PORTSPEED_1GBIT; else - speed = FC_PORTSPEED_1GBIT; - fc_host_supported_speeds(vha->host) = speed; + speeds = FC_PORTSPEED_1GBIT; + + fc_host_supported_speeds(vha->host) = speeds; } diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index 17d42658ad9a..5441557b424b 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -1,4 +1,4 @@ - /* +/* * QLogic Fibre Channel HBA Driver * Copyright (c) 2003-2014 QLogic Corporation * @@ -84,8 +84,7 @@ qla24xx_fcp_prio_cfg_valid(scsi_qla_host_t *vha, return 0; } - if (bcode[0] != 'H' || bcode[1] != 'Q' || bcode[2] != 'O' || - bcode[3] != 'S') { + if (memcmp(bcode, "HQOS", 4)) { /* Invalid FCP priority data header*/ ql_dbg(ql_dbg_user, vha, 0x7052, "Invalid FCP Priority data header. bcode=0x%x.\n", @@ -1044,7 +1043,7 @@ qla84xx_updatefw(struct bsg_job *bsg_job) } flag = bsg_request->rqst_data.h_vendor.vendor_cmd[1]; - fw_ver = le32_to_cpu(*((uint32_t *)((uint32_t *)fw_buf + 2))); + fw_ver = get_unaligned_le32((uint32_t *)fw_buf + 2); mn->entry_type = VERIFY_CHIP_IOCB_TYPE; mn->entry_count = 1; @@ -1057,9 +1056,8 @@ qla84xx_updatefw(struct bsg_job *bsg_job) mn->fw_ver = cpu_to_le32(fw_ver); mn->fw_size = cpu_to_le32(data_len); mn->fw_seq_size = cpu_to_le32(data_len); - mn->dseg_address[0] = cpu_to_le32(LSD(fw_dma)); - mn->dseg_address[1] = cpu_to_le32(MSD(fw_dma)); - mn->dseg_length = cpu_to_le32(data_len); + put_unaligned_le64(fw_dma, &mn->dsd.address); + mn->dsd.length = cpu_to_le32(data_len); mn->data_seg_cnt = cpu_to_le16(1); rval = qla2x00_issue_iocb_timeout(vha, mn, mn_dma, 0, 120); @@ -1238,9 +1236,8 @@ qla84xx_mgmt_cmd(struct bsg_job *bsg_job) if (ql84_mgmt->mgmt.cmd != QLA84_MGMT_CHNG_CONFIG) { mn->total_byte_cnt = cpu_to_le32(ql84_mgmt->mgmt.len); mn->dseg_count = cpu_to_le16(1); - mn->dseg_address[0] = cpu_to_le32(LSD(mgmt_dma)); - mn->dseg_address[1] = cpu_to_le32(MSD(mgmt_dma)); - mn->dseg_length = cpu_to_le32(ql84_mgmt->mgmt.len); + put_unaligned_le64(mgmt_dma, &mn->dsd.address); + mn->dsd.length = cpu_to_le32(ql84_mgmt->mgmt.len); } rval = qla2x00_issue_iocb(vha, mn, mn_dma, 0); @@ -1354,7 +1351,7 @@ qla24xx_iidma(struct bsg_job *bsg_job) if (rval) { ql_log(ql_log_warn, vha, 0x704c, - "iIDMA cmd failed for %8phN -- " + "iiDMA cmd failed for %8phN -- " "%04x %x %04x %04x.\n", fcport->port_name, rval, fcport->fp_speed, mb[0], mb[1]); rval = (DID_ERROR << 16); @@ -1412,7 +1409,8 @@ qla2x00_optrom_setup(struct bsg_job *bsg_job, scsi_qla_host_t *vha, start == (ha->flt_region_fw * 4)) valid = 1; else if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) || - IS_CNA_CAPABLE(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha)) + IS_CNA_CAPABLE(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha) || + IS_QLA28XX(ha)) valid = 1; if (!valid) { ql_log(ql_log_warn, vha, 0x7058, @@ -1534,6 +1532,7 @@ qla2x00_update_fru_versions(struct bsg_job *bsg_job) uint32_t count; dma_addr_t sfp_dma; void *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma); + if (!sfp) { bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_NO_MEMORY; @@ -1584,6 +1583,7 @@ qla2x00_read_fru_status(struct bsg_job *bsg_job) struct qla_status_reg *sr = (void *)bsg; dma_addr_t sfp_dma; uint8_t *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma); + if (!sfp) { bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_NO_MEMORY; @@ -1634,6 +1634,7 @@ qla2x00_write_fru_status(struct bsg_job *bsg_job) struct qla_status_reg *sr = (void *)bsg; dma_addr_t sfp_dma; uint8_t *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma); + if (!sfp) { bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_NO_MEMORY; @@ -1680,6 +1681,7 @@ qla2x00_write_i2c(struct bsg_job *bsg_job) struct qla_i2c_access *i2c = (void *)bsg; dma_addr_t sfp_dma; uint8_t *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma); + if (!sfp) { bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_NO_MEMORY; @@ -1725,6 +1727,7 @@ qla2x00_read_i2c(struct bsg_job *bsg_job) struct qla_i2c_access *i2c = (void *)bsg; dma_addr_t sfp_dma; uint8_t *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma); + if (!sfp) { bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_NO_MEMORY; @@ -1961,7 +1964,7 @@ qlafx00_mgmt_cmd(struct bsg_job *bsg_job) /* Dump the vendor information */ ql_dump_buffer(ql_dbg_user + ql_dbg_verbose , vha, 0x70cf, - (uint8_t *)piocb_rqst, sizeof(struct qla_mt_iocb_rqst_fx00)); + piocb_rqst, sizeof(*piocb_rqst)); if (!vha->flags.online) { ql_log(ql_log_warn, vha, 0x70d0, @@ -2157,7 +2160,7 @@ qla27xx_get_flash_upd_cap(struct bsg_job *bsg_job) struct qla_hw_data *ha = vha->hw; struct qla_flash_update_caps cap; - if (!(IS_QLA27XX(ha))) + if (!(IS_QLA27XX(ha)) && !IS_QLA28XX(ha)) return -EPERM; memset(&cap, 0, sizeof(cap)); @@ -2190,7 +2193,7 @@ qla27xx_set_flash_upd_cap(struct bsg_job *bsg_job) uint64_t online_fw_attr = 0; struct qla_flash_update_caps cap; - if (!(IS_QLA27XX(ha))) + if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) return -EPERM; memset(&cap, 0, sizeof(cap)); @@ -2238,7 +2241,7 @@ qla27xx_get_bbcr_data(struct bsg_job *bsg_job) uint8_t domain, area, al_pa, state; int rval; - if (!(IS_QLA27XX(ha))) + if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) return -EPERM; memset(&bbcr, 0, sizeof(bbcr)); @@ -2323,8 +2326,8 @@ qla2x00_get_priv_stats(struct bsg_job *bsg_job) rval = qla24xx_get_isp_stats(base_vha, stats, stats_dma, options); if (rval == QLA_SUCCESS) { - ql_dump_buffer(ql_dbg_user + ql_dbg_verbose, vha, 0x70e3, - (uint8_t *)stats, sizeof(*stats)); + ql_dump_buffer(ql_dbg_user + ql_dbg_verbose, vha, 0x70e5, + stats, sizeof(*stats)); sg_copy_from_buffer(bsg_job->reply_payload.sg_list, bsg_job->reply_payload.sg_cnt, stats, sizeof(*stats)); } @@ -2353,7 +2356,8 @@ qla2x00_do_dport_diagnostics(struct bsg_job *bsg_job) int rval; struct qla_dport_diag *dd; - if (!IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw)) + if (!IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw) && + !IS_QLA28XX(vha->hw)) return -EPERM; dd = kmalloc(sizeof(*dd), GFP_KERNEL); @@ -2388,6 +2392,45 @@ qla2x00_do_dport_diagnostics(struct bsg_job *bsg_job) } static int +qla2x00_get_flash_image_status(struct bsg_job *bsg_job) +{ + scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job)); + struct fc_bsg_reply *bsg_reply = bsg_job->reply; + struct qla_hw_data *ha = vha->hw; + struct qla_active_regions regions = { }; + struct active_regions active_regions = { }; + + qla28xx_get_aux_images(vha, &active_regions); + regions.global_image = active_regions.global; + + if (IS_QLA28XX(ha)) { + qla27xx_get_active_image(vha, &active_regions); + regions.board_config = active_regions.aux.board_config; + regions.vpd_nvram = active_regions.aux.vpd_nvram; + regions.npiv_config_0_1 = active_regions.aux.npiv_config_0_1; + regions.npiv_config_2_3 = active_regions.aux.npiv_config_2_3; + } + + ql_dbg(ql_dbg_user, vha, 0x70e1, + "%s(%lu): FW=%u BCFG=%u VPDNVR=%u NPIV01=%u NPIV02=%u\n", + __func__, vha->host_no, regions.global_image, + regions.board_config, regions.vpd_nvram, + regions.npiv_config_0_1, regions.npiv_config_2_3); + + sg_copy_from_buffer(bsg_job->reply_payload.sg_list, + bsg_job->reply_payload.sg_cnt, ®ions, sizeof(regions)); + + bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK; + bsg_reply->reply_payload_rcv_len = sizeof(regions); + bsg_reply->result = DID_OK << 16; + bsg_job->reply_len = sizeof(struct fc_bsg_reply); + bsg_job_done(bsg_job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); + + return 0; +} + +static int qla2x00_process_vendor_specific(struct bsg_job *bsg_job) { struct fc_bsg_request *bsg_request = bsg_job->request; @@ -2460,6 +2503,9 @@ qla2x00_process_vendor_specific(struct bsg_job *bsg_job) case QL_VND_DPORT_DIAGNOSTICS: return qla2x00_do_dport_diagnostics(bsg_job); + case QL_VND_SS_GET_FLASH_IMAGE_STATUS: + return qla2x00_get_flash_image_status(bsg_job); + default: return -ENOSYS; } diff --git a/drivers/scsi/qla2xxx/qla_bsg.h b/drivers/scsi/qla2xxx/qla_bsg.h index d97dfd521356..7594fad7b5b5 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.h +++ b/drivers/scsi/qla2xxx/qla_bsg.h @@ -31,6 +31,7 @@ #define QL_VND_GET_PRIV_STATS 0x18 #define QL_VND_DPORT_DIAGNOSTICS 0x19 #define QL_VND_GET_PRIV_STATS_EX 0x1A +#define QL_VND_SS_GET_FLASH_IMAGE_STATUS 0x1E /* BSG Vendor specific subcode returns */ #define EXT_STATUS_OK 0 @@ -279,4 +280,14 @@ struct qla_dport_diag { #define QLA_DPORT_RESULT 0x0 #define QLA_DPORT_START 0x2 +/* active images in flash */ +struct qla_active_regions { + uint8_t global_image; + uint8_t board_config; + uint8_t vpd_nvram; + uint8_t npiv_config_0_1; + uint8_t npiv_config_2_3; + uint8_t reserved[32]; +} __packed; + #endif diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index c7533fa7f46e..9e80646722e2 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -111,30 +111,25 @@ int qla27xx_dump_mpi_ram(struct qla_hw_data *ha, uint32_t addr, uint32_t *ram, uint32_t ram_dwords, void **nxt) { - int rval; - uint32_t cnt, stat, timer, dwords, idx; - uint16_t mb0; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; dma_addr_t dump_dma = ha->gid_list_dma; - uint32_t *dump = (uint32_t *)ha->gid_list; - - rval = QLA_SUCCESS; - mb0 = 0; + uint32_t *chunk = (void *)ha->gid_list; + uint32_t dwords = qla2x00_gid_list_size(ha) / 4; + uint32_t stat; + ulong i, j, timer = 6000000; + int rval = QLA_FUNCTION_FAILED; - WRT_REG_WORD(®->mailbox0, MBC_LOAD_DUMP_MPI_RAM); clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); + for (i = 0; i < ram_dwords; i += dwords, addr += dwords) { + if (i + dwords > ram_dwords) + dwords = ram_dwords - i; - dwords = qla2x00_gid_list_size(ha) / 4; - for (cnt = 0; cnt < ram_dwords && rval == QLA_SUCCESS; - cnt += dwords, addr += dwords) { - if (cnt + dwords > ram_dwords) - dwords = ram_dwords - cnt; - + WRT_REG_WORD(®->mailbox0, MBC_LOAD_DUMP_MPI_RAM); WRT_REG_WORD(®->mailbox1, LSW(addr)); WRT_REG_WORD(®->mailbox8, MSW(addr)); - WRT_REG_WORD(®->mailbox2, MSW(dump_dma)); - WRT_REG_WORD(®->mailbox3, LSW(dump_dma)); + WRT_REG_WORD(®->mailbox2, MSW(LSD(dump_dma))); + WRT_REG_WORD(®->mailbox3, LSW(LSD(dump_dma))); WRT_REG_WORD(®->mailbox6, MSW(MSD(dump_dma))); WRT_REG_WORD(®->mailbox7, LSW(MSD(dump_dma))); @@ -145,76 +140,76 @@ qla27xx_dump_mpi_ram(struct qla_hw_data *ha, uint32_t addr, uint32_t *ram, WRT_REG_DWORD(®->hccr, HCCRX_SET_HOST_INT); ha->flags.mbox_int = 0; - for (timer = 6000000; timer; timer--) { - /* Check for pending interrupts. */ - stat = RD_REG_DWORD(®->host_status); - if (stat & HSRX_RISC_INT) { - stat &= 0xff; - - if (stat == 0x1 || stat == 0x2 || - stat == 0x10 || stat == 0x11) { - set_bit(MBX_INTERRUPT, - &ha->mbx_cmd_flags); + while (timer--) { + udelay(5); - mb0 = RD_REG_WORD(®->mailbox0); - RD_REG_WORD(®->mailbox1); + stat = RD_REG_DWORD(®->host_status); + /* Check for pending interrupts. */ + if (!(stat & HSRX_RISC_INT)) + continue; - WRT_REG_DWORD(®->hccr, - HCCRX_CLR_RISC_INT); - RD_REG_DWORD(®->hccr); - break; - } + stat &= 0xff; + if (stat != 0x1 && stat != 0x2 && + stat != 0x10 && stat != 0x11) { /* Clear this intr; it wasn't a mailbox intr */ WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); RD_REG_DWORD(®->hccr); + continue; } - udelay(5); + + set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); + rval = RD_REG_WORD(®->mailbox0) & MBS_MASK; + WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); + RD_REG_DWORD(®->hccr); + break; } ha->flags.mbox_int = 1; + *nxt = ram + i; - if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) { - rval = mb0 & MBS_MASK; - for (idx = 0; idx < dwords; idx++) - ram[cnt + idx] = IS_QLA27XX(ha) ? - le32_to_cpu(dump[idx]) : swab32(dump[idx]); - } else { - rval = QLA_FUNCTION_FAILED; + if (!test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) { + /* no interrupt, timed out*/ + return rval; + } + if (rval) { + /* error completion status */ + return rval; + } + for (j = 0; j < dwords; j++) { + ram[i + j] = + (IS_QLA27XX(ha) || IS_QLA28XX(ha)) ? + chunk[j] : swab32(chunk[j]); } } - *nxt = rval == QLA_SUCCESS ? &ram[cnt] : NULL; - return rval; + *nxt = ram + i; + return QLA_SUCCESS; } int qla24xx_dump_ram(struct qla_hw_data *ha, uint32_t addr, uint32_t *ram, uint32_t ram_dwords, void **nxt) { - int rval; - uint32_t cnt, stat, timer, dwords, idx; - uint16_t mb0; + int rval = QLA_FUNCTION_FAILED; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; dma_addr_t dump_dma = ha->gid_list_dma; - uint32_t *dump = (uint32_t *)ha->gid_list; + uint32_t *chunk = (void *)ha->gid_list; + uint32_t dwords = qla2x00_gid_list_size(ha) / 4; + uint32_t stat; + ulong i, j, timer = 6000000; - rval = QLA_SUCCESS; - mb0 = 0; - - WRT_REG_WORD(®->mailbox0, MBC_DUMP_RISC_RAM_EXTENDED); clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); - dwords = qla2x00_gid_list_size(ha) / 4; - for (cnt = 0; cnt < ram_dwords && rval == QLA_SUCCESS; - cnt += dwords, addr += dwords) { - if (cnt + dwords > ram_dwords) - dwords = ram_dwords - cnt; + for (i = 0; i < ram_dwords; i += dwords, addr += dwords) { + if (i + dwords > ram_dwords) + dwords = ram_dwords - i; + WRT_REG_WORD(®->mailbox0, MBC_DUMP_RISC_RAM_EXTENDED); WRT_REG_WORD(®->mailbox1, LSW(addr)); WRT_REG_WORD(®->mailbox8, MSW(addr)); - WRT_REG_WORD(®->mailbox2, MSW(dump_dma)); - WRT_REG_WORD(®->mailbox3, LSW(dump_dma)); + WRT_REG_WORD(®->mailbox2, MSW(LSD(dump_dma))); + WRT_REG_WORD(®->mailbox3, LSW(LSD(dump_dma))); WRT_REG_WORD(®->mailbox6, MSW(MSD(dump_dma))); WRT_REG_WORD(®->mailbox7, LSW(MSD(dump_dma))); @@ -223,45 +218,48 @@ qla24xx_dump_ram(struct qla_hw_data *ha, uint32_t addr, uint32_t *ram, WRT_REG_DWORD(®->hccr, HCCRX_SET_HOST_INT); ha->flags.mbox_int = 0; - for (timer = 6000000; timer; timer--) { - /* Check for pending interrupts. */ + while (timer--) { + udelay(5); stat = RD_REG_DWORD(®->host_status); - if (stat & HSRX_RISC_INT) { - stat &= 0xff; - if (stat == 0x1 || stat == 0x2 || - stat == 0x10 || stat == 0x11) { - set_bit(MBX_INTERRUPT, - &ha->mbx_cmd_flags); - - mb0 = RD_REG_WORD(®->mailbox0); - - WRT_REG_DWORD(®->hccr, - HCCRX_CLR_RISC_INT); - RD_REG_DWORD(®->hccr); - break; - } + /* Check for pending interrupts. */ + if (!(stat & HSRX_RISC_INT)) + continue; - /* Clear this intr; it wasn't a mailbox intr */ + stat &= 0xff; + if (stat != 0x1 && stat != 0x2 && + stat != 0x10 && stat != 0x11) { WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); RD_REG_DWORD(®->hccr); + continue; } - udelay(5); + + set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); + rval = RD_REG_WORD(®->mailbox0) & MBS_MASK; + WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); + RD_REG_DWORD(®->hccr); + break; } ha->flags.mbox_int = 1; + *nxt = ram + i; - if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) { - rval = mb0 & MBS_MASK; - for (idx = 0; idx < dwords; idx++) - ram[cnt + idx] = IS_QLA27XX(ha) ? - le32_to_cpu(dump[idx]) : swab32(dump[idx]); - } else { - rval = QLA_FUNCTION_FAILED; + if (!test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) { + /* no interrupt, timed out*/ + return rval; + } + if (rval) { + /* error completion status */ + return rval; + } + for (j = 0; j < dwords; j++) { + ram[i + j] = + (IS_QLA27XX(ha) || IS_QLA28XX(ha)) ? + chunk[j] : swab32(chunk[j]); } } - *nxt = rval == QLA_SUCCESS ? &ram[cnt]: NULL; - return rval; + *nxt = ram + i; + return QLA_SUCCESS; } static int @@ -447,7 +445,7 @@ qla2xxx_dump_ram(struct qla_hw_data *ha, uint32_t addr, uint16_t *ram, } } - *nxt = rval == QLA_SUCCESS ? &ram[cnt]: NULL; + *nxt = rval == QLA_SUCCESS ? &ram[cnt] : NULL; return rval; } @@ -669,7 +667,8 @@ qla25xx_copy_mq(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain) struct qla2xxx_mq_chain *mq = ptr; device_reg_t *reg; - if (!ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha)) + if (!ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha) || + IS_QLA28XX(ha)) return ptr; mq = ptr; @@ -2521,7 +2520,7 @@ qla83xx_fw_dump_failed: /****************************************************************************/ static inline int -ql_mask_match(uint32_t level) +ql_mask_match(uint level) { return (level & ql2xextended_error_logging) == level; } @@ -2540,7 +2539,7 @@ ql_mask_match(uint32_t level) * msg: The message to be displayed. */ void -ql_dbg(uint32_t level, scsi_qla_host_t *vha, int32_t id, const char *fmt, ...) +ql_dbg(uint level, scsi_qla_host_t *vha, uint id, const char *fmt, ...) { va_list va; struct va_format vaf; @@ -2583,8 +2582,7 @@ ql_dbg(uint32_t level, scsi_qla_host_t *vha, int32_t id, const char *fmt, ...) * msg: The message to be displayed. */ void -ql_dbg_pci(uint32_t level, struct pci_dev *pdev, int32_t id, - const char *fmt, ...) +ql_dbg_pci(uint level, struct pci_dev *pdev, uint id, const char *fmt, ...) { va_list va; struct va_format vaf; @@ -2620,7 +2618,7 @@ ql_dbg_pci(uint32_t level, struct pci_dev *pdev, int32_t id, * msg: The message to be displayed. */ void -ql_log(uint32_t level, scsi_qla_host_t *vha, int32_t id, const char *fmt, ...) +ql_log(uint level, scsi_qla_host_t *vha, uint id, const char *fmt, ...) { va_list va; struct va_format vaf; @@ -2678,8 +2676,7 @@ ql_log(uint32_t level, scsi_qla_host_t *vha, int32_t id, const char *fmt, ...) * msg: The message to be displayed. */ void -ql_log_pci(uint32_t level, struct pci_dev *pdev, int32_t id, - const char *fmt, ...) +ql_log_pci(uint level, struct pci_dev *pdev, uint id, const char *fmt, ...) { va_list va; struct va_format vaf; @@ -2719,7 +2716,7 @@ ql_log_pci(uint32_t level, struct pci_dev *pdev, int32_t id, } void -ql_dump_regs(uint32_t level, scsi_qla_host_t *vha, int32_t id) +ql_dump_regs(uint level, scsi_qla_host_t *vha, uint id) { int i; struct qla_hw_data *ha = vha->hw; @@ -2741,13 +2738,12 @@ ql_dump_regs(uint32_t level, scsi_qla_host_t *vha, int32_t id) ql_dbg(level, vha, id, "Mailbox registers:\n"); for (i = 0; i < 6; i++, mbx_reg++) ql_dbg(level, vha, id, - "mbox[%d] 0x%04x\n", i, RD_REG_WORD(mbx_reg)); + "mbox[%d] %#04x\n", i, RD_REG_WORD(mbx_reg)); } void -ql_dump_buffer(uint32_t level, scsi_qla_host_t *vha, int32_t id, - uint8_t *buf, uint size) +ql_dump_buffer(uint level, scsi_qla_host_t *vha, uint id, void *buf, uint size) { uint cnt; diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h index 8877aa97d829..bb01b680ce9f 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.h +++ b/drivers/scsi/qla2xxx/qla_dbg.h @@ -318,20 +318,20 @@ struct qla2xxx_fw_dump { * as compared to other log levels. */ -extern int ql_errlev; +extern uint ql_errlev; void __attribute__((format (printf, 4, 5))) -ql_dbg(uint32_t, scsi_qla_host_t *vha, int32_t, const char *fmt, ...); +ql_dbg(uint, scsi_qla_host_t *vha, uint, const char *fmt, ...); void __attribute__((format (printf, 4, 5))) -ql_dbg_pci(uint32_t, struct pci_dev *pdev, int32_t, const char *fmt, ...); +ql_dbg_pci(uint, struct pci_dev *pdev, uint, const char *fmt, ...); void __attribute__((format (printf, 4, 5))) ql_dbg_qp(uint32_t, struct qla_qpair *, int32_t, const char *fmt, ...); void __attribute__((format (printf, 4, 5))) -ql_log(uint32_t, scsi_qla_host_t *vha, int32_t, const char *fmt, ...); +ql_log(uint, scsi_qla_host_t *vha, uint, const char *fmt, ...); void __attribute__((format (printf, 4, 5))) -ql_log_pci(uint32_t, struct pci_dev *pdev, int32_t, const char *fmt, ...); +ql_log_pci(uint, struct pci_dev *pdev, uint, const char *fmt, ...); void __attribute__((format (printf, 4, 5))) ql_log_qp(uint32_t, struct qla_qpair *, int32_t, const char *fmt, ...); diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 3d46975a5e5c..1a4095c56eee 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -35,6 +35,7 @@ #include <scsi/scsi_bsg_fc.h> #include "qla_bsg.h" +#include "qla_dsd.h" #include "qla_nx.h" #include "qla_nx2.h" #include "qla_nvme.h" @@ -545,7 +546,7 @@ typedef struct srb { u32 gen2; /* scratch */ int rc; int retry_count; - struct completion comp; + struct completion *comp; union { struct srb_iocb iocb_cmd; struct bsg_job *bsg_job; @@ -1033,6 +1034,7 @@ struct mbx_cmd_32 { #define MBC_GET_FIRMWARE_VERSION 8 /* Get firmware revision. */ #define MBC_LOAD_RISC_RAM 9 /* Load RAM command. */ #define MBC_DUMP_RISC_RAM 0xa /* Dump RAM command. */ +#define MBC_SECURE_FLASH_UPDATE 0xa /* Secure Flash Update(28xx) */ #define MBC_LOAD_RISC_RAM_EXTENDED 0xb /* Load RAM extended. */ #define MBC_DUMP_RISC_RAM_EXTENDED 0xc /* Dump RAM extended. */ #define MBC_WRITE_RAM_WORD_EXTENDED 0xd /* Write RAM word extended */ @@ -1203,6 +1205,10 @@ struct mbx_cmd_32 { #define QLA27XX_IMG_STATUS_VER_MAJOR 0x01 #define QLA27XX_IMG_STATUS_VER_MINOR 0x00 #define QLA27XX_IMG_STATUS_SIGN 0xFACEFADE +#define QLA28XX_IMG_STATUS_SIGN 0xFACEFADF +#define QLA28XX_IMG_STATUS_SIGN 0xFACEFADF +#define QLA28XX_AUX_IMG_STATUS_SIGN 0xFACEFAED +#define QLA27XX_DEFAULT_IMAGE 0 #define QLA27XX_PRIMARY_IMAGE 1 #define QLA27XX_SECONDARY_IMAGE 2 @@ -1323,8 +1329,8 @@ typedef struct { uint16_t response_q_inpointer; uint16_t request_q_length; uint16_t response_q_length; - uint32_t request_q_address[2]; - uint32_t response_q_address[2]; + __le64 request_q_address __packed; + __le64 response_q_address __packed; uint16_t lun_enables; uint8_t command_resource_count; @@ -1749,12 +1755,10 @@ typedef struct { uint16_t dseg_count; /* Data segment count. */ uint8_t scsi_cdb[MAX_CMDSZ]; /* SCSI command words. */ uint32_t byte_count; /* Total byte count. */ - uint32_t dseg_0_address; /* Data segment 0 address. */ - uint32_t dseg_0_length; /* Data segment 0 length. */ - uint32_t dseg_1_address; /* Data segment 1 address. */ - uint32_t dseg_1_length; /* Data segment 1 length. */ - uint32_t dseg_2_address; /* Data segment 2 address. */ - uint32_t dseg_2_length; /* Data segment 2 length. */ + union { + struct dsd32 dsd32[3]; + struct dsd64 dsd64[2]; + }; } cmd_entry_t; /* @@ -1775,10 +1779,7 @@ typedef struct { uint16_t dseg_count; /* Data segment count. */ uint8_t scsi_cdb[MAX_CMDSZ]; /* SCSI command words. */ uint32_t byte_count; /* Total byte count. */ - uint32_t dseg_0_address[2]; /* Data segment 0 address. */ - uint32_t dseg_0_length; /* Data segment 0 length. */ - uint32_t dseg_1_address[2]; /* Data segment 1 address. */ - uint32_t dseg_1_length; /* Data segment 1 length. */ + struct dsd64 dsd[2]; } cmd_a64_entry_t, request_t; /* @@ -1791,20 +1792,7 @@ typedef struct { uint8_t sys_define; /* System defined. */ uint8_t entry_status; /* Entry Status. */ uint32_t reserved; - uint32_t dseg_0_address; /* Data segment 0 address. */ - uint32_t dseg_0_length; /* Data segment 0 length. */ - uint32_t dseg_1_address; /* Data segment 1 address. */ - uint32_t dseg_1_length; /* Data segment 1 length. */ - uint32_t dseg_2_address; /* Data segment 2 address. */ - uint32_t dseg_2_length; /* Data segment 2 length. */ - uint32_t dseg_3_address; /* Data segment 3 address. */ - uint32_t dseg_3_length; /* Data segment 3 length. */ - uint32_t dseg_4_address; /* Data segment 4 address. */ - uint32_t dseg_4_length; /* Data segment 4 length. */ - uint32_t dseg_5_address; /* Data segment 5 address. */ - uint32_t dseg_5_length; /* Data segment 5 length. */ - uint32_t dseg_6_address; /* Data segment 6 address. */ - uint32_t dseg_6_length; /* Data segment 6 length. */ + struct dsd32 dsd[7]; } cont_entry_t; /* @@ -1816,16 +1804,7 @@ typedef struct { uint8_t entry_count; /* Entry count. */ uint8_t sys_define; /* System defined. */ uint8_t entry_status; /* Entry Status. */ - uint32_t dseg_0_address[2]; /* Data segment 0 address. */ - uint32_t dseg_0_length; /* Data segment 0 length. */ - uint32_t dseg_1_address[2]; /* Data segment 1 address. */ - uint32_t dseg_1_length; /* Data segment 1 length. */ - uint32_t dseg_2_address [2]; /* Data segment 2 address. */ - uint32_t dseg_2_length; /* Data segment 2 length. */ - uint32_t dseg_3_address[2]; /* Data segment 3 address. */ - uint32_t dseg_3_length; /* Data segment 3 length. */ - uint32_t dseg_4_address[2]; /* Data segment 4 address. */ - uint32_t dseg_4_length; /* Data segment 4 length. */ + struct dsd64 dsd[5]; } cont_a64_entry_t; #define PO_MODE_DIF_INSERT 0 @@ -1869,8 +1848,7 @@ struct crc_context { uint16_t reserved_2; uint16_t reserved_3; uint32_t reserved_4; - uint32_t data_address[2]; - uint32_t data_length; + struct dsd64 data_dsd; uint32_t reserved_5[2]; uint32_t reserved_6; } nobundling; @@ -1880,11 +1858,8 @@ struct crc_context { uint16_t reserved_1; __le16 dseg_count; /* Data segment count */ uint32_t reserved_2; - uint32_t data_address[2]; - uint32_t data_length; - uint32_t dif_address[2]; - uint32_t dif_length; /* Data segment 0 - * length */ + struct dsd64 data_dsd; + struct dsd64 dif_dsd; } bundling; } u; @@ -2083,10 +2058,8 @@ typedef struct { uint32_t handle2; uint32_t rsp_bytecount; uint32_t req_bytecount; - uint32_t dseg_req_address[2]; /* Data segment 0 address. */ - uint32_t dseg_req_length; /* Data segment 0 length. */ - uint32_t dseg_rsp_address[2]; /* Data segment 1 address. */ - uint32_t dseg_rsp_length; /* Data segment 1 length. */ + struct dsd64 req_dsd; + struct dsd64 rsp_dsd; } ms_iocb_entry_t; @@ -2258,7 +2231,10 @@ typedef enum { FCT_BROADCAST, FCT_INITIATOR, FCT_TARGET, - FCT_NVME + FCT_NVME_INITIATOR = 0x10, + FCT_NVME_TARGET = 0x20, + FCT_NVME_DISCOVERY = 0x40, + FCT_NVME = 0xf0, } fc_port_type_t; enum qla_sess_deletion { @@ -2463,13 +2439,7 @@ struct event_arg { #define FCS_DEVICE_LOST 3 #define FCS_ONLINE 4 -static const char * const port_state_str[] = { - "Unknown", - "UNCONFIGURED", - "DEAD", - "LOST", - "ONLINE" -}; +extern const char *const port_state_str[5]; /* * FC port flags. @@ -2672,6 +2642,7 @@ struct ct_fdmiv2_hba_attributes { #define FDMI_PORT_SPEED_8GB 0x10 #define FDMI_PORT_SPEED_16GB 0x20 #define FDMI_PORT_SPEED_32GB 0x40 +#define FDMI_PORT_SPEED_64GB 0x80 #define FDMI_PORT_SPEED_UNKNOWN 0x8000 #define FC_CLASS_2 0x04 @@ -3060,7 +3031,7 @@ struct sns_cmd_pkt { struct { uint16_t buffer_length; uint16_t reserved_1; - uint32_t buffer_address[2]; + __le64 buffer_address __packed; uint16_t subcommand_length; uint16_t reserved_2; uint16_t subcommand; @@ -3130,10 +3101,10 @@ struct rsp_que; struct isp_operations { int (*pci_config) (struct scsi_qla_host *); - void (*reset_chip) (struct scsi_qla_host *); + int (*reset_chip)(struct scsi_qla_host *); int (*chip_diag) (struct scsi_qla_host *); void (*config_rings) (struct scsi_qla_host *); - void (*reset_adapter) (struct scsi_qla_host *); + int (*reset_adapter)(struct scsi_qla_host *); int (*nvram_config) (struct scsi_qla_host *); void (*update_fw_options) (struct scsi_qla_host *); int (*load_risc) (struct scsi_qla_host *, uint32_t *); @@ -3159,9 +3130,9 @@ struct isp_operations { void *(*prep_ms_fdmi_iocb) (struct scsi_qla_host *, uint32_t, uint32_t); - uint8_t *(*read_nvram) (struct scsi_qla_host *, uint8_t *, + uint8_t *(*read_nvram)(struct scsi_qla_host *, void *, uint32_t, uint32_t); - int (*write_nvram) (struct scsi_qla_host *, uint8_t *, uint32_t, + int (*write_nvram)(struct scsi_qla_host *, void *, uint32_t, uint32_t); void (*fw_dump) (struct scsi_qla_host *, int); @@ -3170,16 +3141,16 @@ struct isp_operations { int (*beacon_off) (struct scsi_qla_host *); void (*beacon_blink) (struct scsi_qla_host *); - uint8_t * (*read_optrom) (struct scsi_qla_host *, uint8_t *, + void *(*read_optrom)(struct scsi_qla_host *, void *, uint32_t, uint32_t); - int (*write_optrom) (struct scsi_qla_host *, uint8_t *, uint32_t, + int (*write_optrom)(struct scsi_qla_host *, void *, uint32_t, uint32_t); int (*get_flash_version) (struct scsi_qla_host *, void *); int (*start_scsi) (srb_t *); int (*start_scsi_mq) (srb_t *); int (*abort_isp) (struct scsi_qla_host *); - int (*iospace_config)(struct qla_hw_data*); + int (*iospace_config)(struct qla_hw_data *); int (*initialize_adapter)(struct scsi_qla_host *); }; @@ -3368,7 +3339,8 @@ struct qla_tc_param { #define QLA_MQ_SIZE 32 #define QLA_MAX_QUEUES 256 #define ISP_QUE_REG(ha, id) \ - ((ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha)) ? \ + ((ha->mqenable || IS_QLA83XX(ha) || \ + IS_QLA27XX(ha) || IS_QLA28XX(ha)) ? \ ((void __iomem *)ha->mqiobase + (QLA_QUE_PAGE * id)) :\ ((void __iomem *)ha->iobase)) #define QLA_REQ_QUE_ID(tag) \ @@ -3621,6 +3593,8 @@ struct qla_hw_data { uint32_t rida_fmt2:1; uint32_t purge_mbox:1; uint32_t n2n_bigger:1; + uint32_t secure_adapter:1; + uint32_t secure_fw:1; } flags; uint16_t max_exchg; @@ -3703,6 +3677,7 @@ struct qla_hw_data { #define PORT_SPEED_8GB 0x04 #define PORT_SPEED_16GB 0x05 #define PORT_SPEED_32GB 0x06 +#define PORT_SPEED_64GB 0x07 #define PORT_SPEED_10GB 0x13 uint16_t link_data_rate; /* F/W operating speed */ uint16_t set_data_rate; /* Set by user */ @@ -3729,6 +3704,11 @@ struct qla_hw_data { #define PCI_DEVICE_ID_QLOGIC_ISP2071 0x2071 #define PCI_DEVICE_ID_QLOGIC_ISP2271 0x2271 #define PCI_DEVICE_ID_QLOGIC_ISP2261 0x2261 +#define PCI_DEVICE_ID_QLOGIC_ISP2061 0x2061 +#define PCI_DEVICE_ID_QLOGIC_ISP2081 0x2081 +#define PCI_DEVICE_ID_QLOGIC_ISP2089 0x2089 +#define PCI_DEVICE_ID_QLOGIC_ISP2281 0x2281 +#define PCI_DEVICE_ID_QLOGIC_ISP2289 0x2289 uint32_t isp_type; #define DT_ISP2100 BIT_0 @@ -3753,7 +3733,12 @@ struct qla_hw_data { #define DT_ISP2071 BIT_19 #define DT_ISP2271 BIT_20 #define DT_ISP2261 BIT_21 -#define DT_ISP_LAST (DT_ISP2261 << 1) +#define DT_ISP2061 BIT_22 +#define DT_ISP2081 BIT_23 +#define DT_ISP2089 BIT_24 +#define DT_ISP2281 BIT_25 +#define DT_ISP2289 BIT_26 +#define DT_ISP_LAST (DT_ISP2289 << 1) uint32_t device_type; #define DT_T10_PI BIT_25 @@ -3788,6 +3773,8 @@ struct qla_hw_data { #define IS_QLA2071(ha) (DT_MASK(ha) & DT_ISP2071) #define IS_QLA2271(ha) (DT_MASK(ha) & DT_ISP2271) #define IS_QLA2261(ha) (DT_MASK(ha) & DT_ISP2261) +#define IS_QLA2081(ha) (DT_MASK(ha) & DT_ISP2081) +#define IS_QLA2281(ha) (DT_MASK(ha) & DT_ISP2281) #define IS_QLA23XX(ha) (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA2322(ha) || \ IS_QLA6312(ha) || IS_QLA6322(ha)) @@ -3797,6 +3784,7 @@ struct qla_hw_data { #define IS_QLA83XX(ha) (IS_QLA2031(ha) || IS_QLA8031(ha)) #define IS_QLA84XX(ha) (IS_QLA8432(ha)) #define IS_QLA27XX(ha) (IS_QLA2071(ha) || IS_QLA2271(ha) || IS_QLA2261(ha)) +#define IS_QLA28XX(ha) (IS_QLA2081(ha) || IS_QLA2281(ha)) #define IS_QLA24XX_TYPE(ha) (IS_QLA24XX(ha) || IS_QLA54XX(ha) || \ IS_QLA84XX(ha)) #define IS_CNA_CAPABLE(ha) (IS_QLA81XX(ha) || IS_QLA82XX(ha) || \ @@ -3805,14 +3793,15 @@ struct qla_hw_data { #define IS_QLA2XXX_MIDTYPE(ha) (IS_QLA24XX(ha) || IS_QLA84XX(ha) || \ IS_QLA25XX(ha) || IS_QLA81XX(ha) || \ IS_QLA82XX(ha) || IS_QLA83XX(ha) || \ - IS_QLA8044(ha) || IS_QLA27XX(ha)) + IS_QLA8044(ha) || IS_QLA27XX(ha) || \ + IS_QLA28XX(ha)) #define IS_MSIX_NACK_CAPABLE(ha) (IS_QLA81XX(ha) || IS_QLA83XX(ha) || \ - IS_QLA27XX(ha)) + IS_QLA27XX(ha) || IS_QLA28XX(ha)) #define IS_NOPOLLING_TYPE(ha) (IS_QLA81XX(ha) && (ha)->flags.msix_enabled) #define IS_FAC_REQUIRED(ha) (IS_QLA81XX(ha) || IS_QLA83XX(ha) || \ - IS_QLA27XX(ha)) + IS_QLA27XX(ha) || IS_QLA28XX(ha)) #define IS_NOCACHE_VPD_TYPE(ha) (IS_QLA81XX(ha) || IS_QLA83XX(ha) || \ - IS_QLA27XX(ha)) + IS_QLA27XX(ha) || IS_QLA28XX(ha)) #define IS_ALOGIO_CAPABLE(ha) (IS_QLA23XX(ha) || IS_FWI2_CAPABLE(ha)) #define IS_T10_PI_CAPABLE(ha) ((ha)->device_type & DT_T10_PI) @@ -3823,28 +3812,34 @@ struct qla_hw_data { #define HAS_EXTENDED_IDS(ha) ((ha)->device_type & DT_EXTENDED_IDS) #define IS_CT6_SUPPORTED(ha) ((ha)->device_type & DT_CT6_SUPPORTED) #define IS_MQUE_CAPABLE(ha) ((ha)->mqenable || IS_QLA83XX(ha) || \ - IS_QLA27XX(ha)) -#define IS_BIDI_CAPABLE(ha) ((IS_QLA25XX(ha) || IS_QLA2031(ha))) + IS_QLA27XX(ha) || IS_QLA28XX(ha)) +#define IS_BIDI_CAPABLE(ha) \ + (IS_QLA25XX(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) /* Bit 21 of fw_attributes decides the MCTP capabilities */ #define IS_MCTP_CAPABLE(ha) (IS_QLA2031(ha) && \ ((ha)->fw_attributes_ext[0] & BIT_0)) #define IS_PI_UNINIT_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha)) #define IS_PI_IPGUARD_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha)) #define IS_PI_DIFB_DIX0_CAPABLE(ha) (0) -#define IS_PI_SPLIT_DET_CAPABLE_HBA(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha)) +#define IS_PI_SPLIT_DET_CAPABLE_HBA(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha) || \ + IS_QLA28XX(ha)) #define IS_PI_SPLIT_DET_CAPABLE(ha) (IS_PI_SPLIT_DET_CAPABLE_HBA(ha) && \ (((ha)->fw_attributes_h << 16 | (ha)->fw_attributes) & BIT_22)) -#define IS_ATIO_MSIX_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha)) +#define IS_ATIO_MSIX_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha) || \ + IS_QLA28XX(ha)) #define IS_TGT_MODE_CAPABLE(ha) (ha->tgt.atio_q_length) -#define IS_SHADOW_REG_CAPABLE(ha) (IS_QLA27XX(ha)) -#define IS_DPORT_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha)) -#define IS_FAWWN_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha)) +#define IS_SHADOW_REG_CAPABLE(ha) (IS_QLA27XX(ha) || IS_QLA28XX(ha)) +#define IS_DPORT_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha) || \ + IS_QLA28XX(ha)) +#define IS_FAWWN_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha) || \ + IS_QLA28XX(ha)) #define IS_EXCHG_OFFLD_CAPABLE(ha) \ - (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha)) + (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) #define IS_EXLOGIN_OFFLD_CAPABLE(ha) \ - (IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha)) + (IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) || \ + IS_QLA27XX(ha) || IS_QLA28XX(ha)) #define USE_ASYNC_SCAN(ha) (IS_QLA25XX(ha) || IS_QLA81XX(ha) ||\ - IS_QLA83XX(ha) || IS_QLA27XX(ha)) + IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) /* HBA serial number */ uint8_t serial0; @@ -3888,6 +3883,9 @@ struct qla_hw_data { void *sfp_data; dma_addr_t sfp_data_dma; + void *flt; + dma_addr_t flt_dma; + #define XGMAC_DATA_SIZE 4096 void *xgmac_data; dma_addr_t xgmac_data_dma; @@ -3999,18 +3997,23 @@ struct qla_hw_data { uint8_t fw_seriallink_options[4]; uint16_t fw_seriallink_options24[4]; + uint8_t serdes_version[3]; uint8_t mpi_version[3]; uint32_t mpi_capabilities; uint8_t phy_version[3]; uint8_t pep_version[3]; /* Firmware dump template */ - void *fw_dump_template; - uint32_t fw_dump_template_len; - /* Firmware dump information. */ + struct fwdt { + void *template; + ulong length; + ulong dump_size; + } fwdt[2]; struct qla2xxx_fw_dump *fw_dump; uint32_t fw_dump_len; - int fw_dumped; + u32 fw_dump_alloc_len; + bool fw_dumped; + bool fw_dump_mpi; unsigned long fw_dump_cap_flags; #define RISC_PAUSE_CMPL 0 #define DMA_SHUTDOWN_CMPL 1 @@ -4049,7 +4052,6 @@ struct qla_hw_data { uint16_t product_id[4]; uint8_t model_number[16+1]; -#define BINZERO "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" char model_desc[80]; uint8_t adapter_id[16+1]; @@ -4089,22 +4091,28 @@ struct qla_hw_data { uint32_t fdt_protect_sec_cmd; uint32_t fdt_wrt_sts_reg_cmd; - 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; + struct { + 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_nvram_sec; + uint32_t flt_region_vpd; + uint32_t flt_region_vpd_sec; + uint32_t flt_region_nvram; + uint32_t flt_region_nvram_sec; + 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; + uint32_t flt_region_aux_img_status_pri; + uint32_t flt_region_aux_img_status_sec; + }; uint8_t active_image; /* Needed for BEACON */ @@ -4197,8 +4205,8 @@ struct qla_hw_data { struct qlt_hw_data tgt; int allow_cna_fw_dump; uint32_t fw_ability_mask; - uint16_t min_link_speed; - uint16_t max_speed_sup; + uint16_t min_supported_speed; + uint16_t max_supported_speed; /* DMA pool for the DIF bundling buffers */ struct dma_pool *dif_bundl_pool; @@ -4225,9 +4233,20 @@ struct qla_hw_data { atomic_t zio_threshold; uint16_t last_zio_threshold; + #define DEFAULT_ZIO_THRESHOLD 5 }; +struct active_regions { + uint8_t global; + struct { + uint8_t board_config; + uint8_t vpd_nvram; + uint8_t npiv_config_0_1; + uint8_t npiv_config_2_3; + } aux; +}; + #define FW_ABILITY_MAX_SPEED_MASK 0xFUL #define FW_ABILITY_MAX_SPEED_16G 0x0 #define FW_ABILITY_MAX_SPEED_32G 0x1 @@ -4315,6 +4334,7 @@ typedef struct scsi_qla_host { #define N2N_LOGIN_NEEDED 30 #define IOCB_WORK_ACTIVE 31 #define SET_ZIO_THRESHOLD_NEEDED 32 +#define ISP_ABORT_TO_ROM 33 unsigned long pci_flags; #define PFLG_DISCONNECTED 0 /* PCI device removed */ @@ -4429,7 +4449,7 @@ typedef struct scsi_qla_host { int fcport_count; wait_queue_head_t fcport_waitQ; wait_queue_head_t vref_waitq; - uint8_t min_link_speed_feat; + uint8_t min_supported_speed; uint8_t n2n_node_name[WWN_SIZE]; uint8_t n2n_port_name[WWN_SIZE]; uint16_t n2n_id; @@ -4441,14 +4461,21 @@ typedef struct scsi_qla_host { struct qla27xx_image_status { uint8_t image_status_mask; - uint16_t generation_number; - uint8_t reserved[3]; - uint8_t ver_minor; + uint16_t generation; uint8_t ver_major; + uint8_t ver_minor; + uint8_t bitmap; /* 28xx only */ + uint8_t reserved[2]; uint32_t checksum; uint32_t signature; } __packed; +/* 28xx aux image status bimap values */ +#define QLA28XX_AUX_IMG_BOARD_CONFIG BIT_0 +#define QLA28XX_AUX_IMG_VPD_NVRAM BIT_1 +#define QLA28XX_AUX_IMG_NPIV_CONFIG_0_1 BIT_2 +#define QLA28XX_AUX_IMG_NPIV_CONFIG_2_3 BIT_3 + #define SET_VP_IDX 1 #define SET_AL_PA 2 #define RESET_VP_IDX 3 @@ -4495,6 +4522,24 @@ struct qla2_sgx { } \ } + +#define SFUB_CHECKSUM_SIZE 4 + +struct secure_flash_update_block { + uint32_t block_info; + uint32_t signature_lo; + uint32_t signature_hi; + uint32_t signature_upper[0x3e]; +}; + +struct secure_flash_update_block_pk { + uint32_t block_info; + uint32_t signature_lo; + uint32_t signature_hi; + uint32_t signature_upper[0x3e]; + uint32_t public_key[0x41]; +}; + /* * Macros to help code, maintain, etc. */ @@ -4595,6 +4640,7 @@ struct qla2_sgx { #define OPTROM_SIZE_81XX 0x400000 #define OPTROM_SIZE_82XX 0x800000 #define OPTROM_SIZE_83XX 0x1000000 +#define OPTROM_SIZE_28XX 0x2000000 #define OPTROM_BURST_SIZE 0x1000 #define OPTROM_BURST_DWORDS (OPTROM_BURST_SIZE / 4) @@ -4691,10 +4737,13 @@ struct sff_8247_a0 { #define AUTO_DETECT_SFP_SUPPORT(_vha)\ (ql2xautodetectsfp && !_vha->vp_idx && \ (IS_QLA25XX(_vha->hw) || IS_QLA81XX(_vha->hw) ||\ - IS_QLA83XX(_vha->hw) || IS_QLA27XX(_vha->hw))) + IS_QLA83XX(_vha->hw) || IS_QLA27XX(_vha->hw) || \ + IS_QLA28XX(_vha->hw))) + +#define FLASH_SEMAPHORE_REGISTER_ADDR 0x00101016 #define USER_CTRL_IRQ(_ha) (ql2xuctrlirq && QLA_TGT_MODE_ENABLED() && \ - (IS_QLA27XX(_ha) || IS_QLA83XX(_ha))) + (IS_QLA27XX(_ha) || IS_QLA28XX(_ha) || IS_QLA83XX(_ha))) #define SAVE_TOPO(_ha) { \ if (_ha->current_topology) \ diff --git a/drivers/scsi/qla2xxx/qla_dfs.c b/drivers/scsi/qla2xxx/qla_dfs.c index 5819a45ac5ef..a432caebefec 100644 --- a/drivers/scsi/qla2xxx/qla_dfs.c +++ b/drivers/scsi/qla2xxx/qla_dfs.c @@ -41,6 +41,7 @@ static int qla2x00_dfs_tgt_sess_open(struct inode *inode, struct file *file) { scsi_qla_host_t *vha = inode->i_private; + return single_open(file, qla2x00_dfs_tgt_sess_show, vha); } @@ -161,6 +162,7 @@ static int qla_dfs_fw_resource_cnt_open(struct inode *inode, struct file *file) { struct scsi_qla_host *vha = inode->i_private; + return single_open(file, qla_dfs_fw_resource_cnt_show, vha); } @@ -250,6 +252,7 @@ static int qla_dfs_tgt_counters_open(struct inode *inode, struct file *file) { struct scsi_qla_host *vha = inode->i_private; + return single_open(file, qla_dfs_tgt_counters_show, vha); } @@ -386,7 +389,7 @@ qla_dfs_naqp_write(struct file *file, const char __user *buffer, int rc = 0; unsigned long num_act_qp; - if (!(IS_QLA27XX(ha) || IS_QLA83XX(ha))) { + if (!(IS_QLA27XX(ha) || IS_QLA83XX(ha) || IS_QLA28XX(ha))) { pr_err("host%ld: this adapter does not support Multi Q.", vha->host_no); return -EINVAL; @@ -438,7 +441,7 @@ qla2x00_dfs_setup(scsi_qla_host_t *vha) struct qla_hw_data *ha = vha->hw; if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha) && - !IS_QLA27XX(ha)) + !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) goto out; if (!ha->fce) goto out; @@ -474,7 +477,7 @@ create_nodes: ha->tgt.dfs_tgt_sess = debugfs_create_file("tgt_sess", S_IRUSR, ha->dfs_dir, vha, &dfs_tgt_sess_ops); - if (IS_QLA27XX(ha) || IS_QLA83XX(ha)) + if (IS_QLA27XX(ha) || IS_QLA83XX(ha) || IS_QLA28XX(ha)) ha->tgt.dfs_naqp = debugfs_create_file("naqp", 0400, ha->dfs_dir, vha, &dfs_naqp_ops); out: diff --git a/drivers/scsi/qla2xxx/qla_dsd.h b/drivers/scsi/qla2xxx/qla_dsd.h new file mode 100644 index 000000000000..7479924ba422 --- /dev/null +++ b/drivers/scsi/qla2xxx/qla_dsd.h @@ -0,0 +1,30 @@ +#ifndef _QLA_DSD_H_ +#define _QLA_DSD_H_ + +/* 32-bit data segment descriptor (8 bytes) */ +struct dsd32 { + __le32 address; + __le32 length; +}; + +static inline void append_dsd32(struct dsd32 **dsd, struct scatterlist *sg) +{ + put_unaligned_le32(sg_dma_address(sg), &(*dsd)->address); + put_unaligned_le32(sg_dma_len(sg), &(*dsd)->length); + (*dsd)++; +} + +/* 64-bit data segment descriptor (12 bytes) */ +struct dsd64 { + __le64 address; + __le32 length; +} __packed; + +static inline void append_dsd64(struct dsd64 **dsd, struct scatterlist *sg) +{ + put_unaligned_le64(sg_dma_address(sg), &(*dsd)->address); + put_unaligned_le32(sg_dma_len(sg), &(*dsd)->length); + (*dsd)++; +} + +#endif diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h index 50c1e6c62e31..df079a8c2b33 100644 --- a/drivers/scsi/qla2xxx/qla_fw.h +++ b/drivers/scsi/qla2xxx/qla_fw.h @@ -10,6 +10,8 @@ #include <linux/nvme.h> #include <linux/nvme-fc.h> +#include "qla_dsd.h" + #define MBS_CHECKSUM_ERROR 0x4010 #define MBS_INVALID_PRODUCT_KEY 0x4020 @@ -339,9 +341,9 @@ struct init_cb_24xx { uint16_t prio_request_q_length; - uint32_t request_q_address[2]; - uint32_t response_q_address[2]; - uint32_t prio_request_q_address[2]; + __le64 request_q_address __packed; + __le64 response_q_address __packed; + __le64 prio_request_q_address __packed; uint16_t msix; uint16_t msix_atio; @@ -349,7 +351,7 @@ struct init_cb_24xx { uint16_t atio_q_inpointer; uint16_t atio_q_length; - uint32_t atio_q_address[2]; + __le64 atio_q_address __packed; uint16_t interrupt_delay_timer; /* 100us increments. */ uint16_t login_timeout; @@ -453,7 +455,7 @@ struct cmd_bidir { #define BD_WRITE_DATA BIT_0 uint16_t fcp_cmnd_dseg_len; /* Data segment length. */ - uint32_t fcp_cmnd_dseg_address[2]; /* Data segment address. */ + __le64 fcp_cmnd_dseg_address __packed;/* Data segment address. */ uint16_t reserved[2]; /* Reserved */ @@ -463,8 +465,7 @@ struct cmd_bidir { uint8_t port_id[3]; /* PortID of destination port.*/ uint8_t vp_index; - uint32_t fcp_data_dseg_address[2]; /* Data segment address. */ - uint16_t fcp_data_dseg_len; /* Data segment length. */ + struct dsd64 fcp_dsd; }; #define COMMAND_TYPE_6 0x48 /* Command Type 6 entry */ @@ -491,18 +492,18 @@ struct cmd_type_6 { #define CF_READ_DATA BIT_1 #define CF_WRITE_DATA BIT_0 - uint16_t fcp_cmnd_dseg_len; /* Data segment length. */ - uint32_t fcp_cmnd_dseg_address[2]; /* Data segment address. */ - - uint32_t fcp_rsp_dseg_address[2]; /* Data segment address. */ + uint16_t fcp_cmnd_dseg_len; /* Data segment length. */ + /* Data segment address. */ + __le64 fcp_cmnd_dseg_address __packed; + /* Data segment address. */ + __le64 fcp_rsp_dseg_address __packed; uint32_t byte_count; /* Total byte count. */ uint8_t port_id[3]; /* PortID of destination port. */ uint8_t vp_index; - uint32_t fcp_data_dseg_address[2]; /* Data segment address. */ - uint32_t fcp_data_dseg_len; /* Data segment length. */ + struct dsd64 fcp_dsd; }; #define COMMAND_TYPE_7 0x18 /* Command Type 7 entry */ @@ -548,8 +549,7 @@ struct cmd_type_7 { uint8_t port_id[3]; /* PortID of destination port. */ uint8_t vp_index; - uint32_t dseg_0_address[2]; /* Data segment 0 address. */ - uint32_t dseg_0_len; /* Data segment 0 length. */ + struct dsd64 dsd; }; #define COMMAND_TYPE_CRC_2 0x6A /* Command Type CRC_2 (Type 6) @@ -573,17 +573,17 @@ struct cmd_type_crc_2 { uint16_t control_flags; /* Control flags. */ - uint16_t fcp_cmnd_dseg_len; /* Data segment length. */ - uint32_t fcp_cmnd_dseg_address[2]; /* Data segment address. */ - - uint32_t fcp_rsp_dseg_address[2]; /* Data segment address. */ + uint16_t fcp_cmnd_dseg_len; /* Data segment length. */ + __le64 fcp_cmnd_dseg_address __packed; + /* Data segment address. */ + __le64 fcp_rsp_dseg_address __packed; uint32_t byte_count; /* Total byte count. */ uint8_t port_id[3]; /* PortID of destination port. */ uint8_t vp_index; - uint32_t crc_context_address[2]; /* Data segment address. */ + __le64 crc_context_address __packed; /* Data segment address. */ uint16_t crc_context_len; /* Data segment length. */ uint16_t reserved_1; /* MUST be set to 0. */ }; @@ -717,10 +717,7 @@ struct ct_entry_24xx { uint32_t rsp_byte_count; uint32_t cmd_byte_count; - uint32_t dseg_0_address[2]; /* Data segment 0 address. */ - uint32_t dseg_0_len; /* Data segment 0 length. */ - uint32_t dseg_1_address[2]; /* Data segment 1 address. */ - uint32_t dseg_1_len; /* Data segment 1 length. */ + struct dsd64 dsd[2]; }; /* @@ -767,9 +764,9 @@ struct els_entry_24xx { uint32_t rx_byte_count; uint32_t tx_byte_count; - uint32_t tx_address[2]; /* Data segment 0 address. */ + __le64 tx_address __packed; /* Data segment 0 address. */ uint32_t tx_len; /* Data segment 0 length. */ - uint32_t rx_address[2]; /* Data segment 1 address. */ + __le64 rx_address __packed; /* Data segment 1 address. */ uint32_t rx_len; /* Data segment 1 length. */ }; @@ -1422,9 +1419,9 @@ struct vf_evfp_entry_24xx { uint16_t control_flags; uint32_t io_parameter_0; uint32_t io_parameter_1; - uint32_t tx_address[2]; /* Data segment 0 address. */ + __le64 tx_address __packed; /* Data segment 0 address. */ uint32_t tx_len; /* Data segment 0 length. */ - uint32_t rx_address[2]; /* Data segment 1 address. */ + __le64 rx_address __packed; /* Data segment 1 address. */ uint32_t rx_len; /* Data segment 1 length. */ }; @@ -1515,13 +1512,31 @@ struct qla_flt_header { #define FLT_REG_VPD_SEC_27XX_2 0xD8 #define FLT_REG_VPD_SEC_27XX_3 0xDA +/* 28xx */ +#define FLT_REG_AUX_IMG_PRI_28XX 0x125 +#define FLT_REG_AUX_IMG_SEC_28XX 0x126 +#define FLT_REG_VPD_SEC_28XX_0 0x10C +#define FLT_REG_VPD_SEC_28XX_1 0x10E +#define FLT_REG_VPD_SEC_28XX_2 0x110 +#define FLT_REG_VPD_SEC_28XX_3 0x112 +#define FLT_REG_NVRAM_SEC_28XX_0 0x10D +#define FLT_REG_NVRAM_SEC_28XX_1 0x10F +#define FLT_REG_NVRAM_SEC_28XX_2 0x111 +#define FLT_REG_NVRAM_SEC_28XX_3 0x113 + struct qla_flt_region { - uint32_t code; + uint16_t code; + uint8_t attribute; + uint8_t reserved; uint32_t size; uint32_t start; uint32_t end; }; +#define FLT_REGION_SIZE 16 +#define FLT_MAX_REGIONS 0xFF +#define FLT_REGIONS_SIZE (FLT_REGION_SIZE * FLT_MAX_REGIONS) + /* Flash NPIV Configuration Table ********************************************/ struct qla_npiv_header { @@ -1588,8 +1603,7 @@ struct verify_chip_entry_84xx { uint32_t fw_seq_size; uint32_t relative_offset; - uint32_t dseg_address[2]; - uint32_t dseg_length; + struct dsd64 dsd; }; struct verify_chip_rsp_84xx { @@ -1646,8 +1660,7 @@ struct access_chip_84xx { uint32_t total_byte_cnt; uint32_t reserved4; - uint32_t dseg_address[2]; - uint32_t dseg_length; + struct dsd64 dsd; }; struct access_chip_rsp_84xx { @@ -1711,6 +1724,10 @@ struct access_chip_rsp_84xx { #define LR_DIST_FW_SHIFT (LR_DIST_FW_POS - LR_DIST_NV_POS) #define LR_DIST_FW_FIELD(x) ((x) << LR_DIST_FW_SHIFT & 0xf000) +/* FAC semaphore defines */ +#define FAC_SEMAPHORE_UNLOCK 0 +#define FAC_SEMAPHORE_LOCK 1 + struct nvram_81xx { /* NVRAM header. */ uint8_t id[4]; @@ -1757,7 +1774,7 @@ struct nvram_81xx { uint16_t reserved_6_3[14]; /* Offset 192. */ - uint8_t min_link_speed; + uint8_t min_supported_speed; uint8_t reserved_7_0; uint16_t reserved_7[31]; @@ -1911,15 +1928,15 @@ struct init_cb_81xx { uint16_t prio_request_q_length; - uint32_t request_q_address[2]; - uint32_t response_q_address[2]; - uint32_t prio_request_q_address[2]; + __le64 request_q_address __packed; + __le64 response_q_address __packed; + __le64 prio_request_q_address __packed; uint8_t reserved_4[8]; uint16_t atio_q_inpointer; uint16_t atio_q_length; - uint32_t atio_q_address[2]; + __le64 atio_q_address __packed; uint16_t interrupt_delay_timer; /* 100us increments. */ uint16_t login_timeout; @@ -2005,6 +2022,8 @@ struct ex_init_cb_81xx { #define FARX_ACCESS_FLASH_CONF_81XX 0x7FFD0000 #define FARX_ACCESS_FLASH_DATA_81XX 0x7F800000 +#define FARX_ACCESS_FLASH_CONF_28XX 0x7FFD0000 +#define FARX_ACCESS_FLASH_DATA_28XX 0x7F7D0000 /* FCP priority config defines *************************************/ /* operations */ @@ -2079,6 +2098,7 @@ struct qla_fcp_prio_cfg { #define FA_NPIV_CONF1_ADDR_81 0xD2000 /* 83XX Flash locations -- occupies second 8MB region. */ -#define FA_FLASH_LAYOUT_ADDR_83 0xFC400 +#define FA_FLASH_LAYOUT_ADDR_83 (0x3F1000/4) +#define FA_FLASH_LAYOUT_ADDR_28 (0x11000/4) #endif diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 4eefe69ca807..bbe69ab5cf3f 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -18,14 +18,14 @@ extern int qla2100_pci_config(struct scsi_qla_host *); extern int qla2300_pci_config(struct scsi_qla_host *); extern int qla24xx_pci_config(scsi_qla_host_t *); extern int qla25xx_pci_config(scsi_qla_host_t *); -extern void qla2x00_reset_chip(struct scsi_qla_host *); -extern void qla24xx_reset_chip(struct scsi_qla_host *); +extern int qla2x00_reset_chip(struct scsi_qla_host *); +extern int qla24xx_reset_chip(struct scsi_qla_host *); extern int qla2x00_chip_diag(struct scsi_qla_host *); extern int qla24xx_chip_diag(struct scsi_qla_host *); extern void qla2x00_config_rings(struct scsi_qla_host *); extern void qla24xx_config_rings(struct scsi_qla_host *); -extern void qla2x00_reset_adapter(struct scsi_qla_host *); -extern void qla24xx_reset_adapter(struct scsi_qla_host *); +extern int qla2x00_reset_adapter(struct scsi_qla_host *); +extern int qla24xx_reset_adapter(struct scsi_qla_host *); extern int qla2x00_nvram_config(struct scsi_qla_host *); extern int qla24xx_nvram_config(struct scsi_qla_host *); extern int qla81xx_nvram_config(struct scsi_qla_host *); @@ -38,8 +38,7 @@ extern int qla81xx_load_risc(scsi_qla_host_t *, uint32_t *); extern int qla2x00_perform_loop_resync(scsi_qla_host_t *); extern int qla2x00_loop_resync(scsi_qla_host_t *); - -extern int qla2x00_find_new_loop_id(scsi_qla_host_t *, fc_port_t *); +extern void qla2x00_clear_loop_id(fc_port_t *fcport); extern int qla2x00_fabric_login(scsi_qla_host_t *, fc_port_t *, uint16_t *); extern int qla2x00_local_device_login(scsi_qla_host_t *, fc_port_t *); @@ -80,6 +79,7 @@ int qla2x00_post_work(struct scsi_qla_host *vha, struct qla_work_evt *e); extern void *qla2x00_alloc_iocbs_ready(struct qla_qpair *, srb_t *); extern int qla24xx_update_fcport_fcp_prio(scsi_qla_host_t *, fc_port_t *); +extern void qla2x00_set_fcport_state(fc_port_t *fcport, int state); extern fc_port_t * qla2x00_alloc_fcport(scsi_qla_host_t *, gfp_t ); @@ -93,7 +93,6 @@ 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 *); extern struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *, int, int, bool); extern int qla2xxx_delete_qpair(struct scsi_qla_host *, struct qla_qpair *); @@ -108,6 +107,11 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *, fc_port_t *); int qla24xx_detect_sfp(scsi_qla_host_t *vha); int qla24xx_post_gpdb_work(struct scsi_qla_host *, fc_port_t *, u8); +extern void qla28xx_get_aux_images(struct scsi_qla_host *, + struct active_regions *); +extern void qla27xx_get_active_image(struct scsi_qla_host *, + struct active_regions *); + void qla2x00_async_prlo_done(struct scsi_qla_host *, fc_port_t *, uint16_t *); extern int qla2x00_post_async_prlo_work(struct scsi_qla_host *, fc_port_t *, @@ -118,6 +122,7 @@ int qla_post_iidma_work(struct scsi_qla_host *vha, fc_port_t *fcport); void qla_do_iidma_work(struct scsi_qla_host *vha, fc_port_t *fcport); int qla2x00_reserve_mgmt_server_loop_id(scsi_qla_host_t *); void qla_rscn_replay(fc_port_t *fcport); +extern bool qla24xx_risc_firmware_invalid(uint32_t *); /* * Global Data in qla_os.c source file. @@ -215,7 +220,6 @@ extern void qla24xx_sched_upd_fcport(fc_port_t *); void qla2x00_handle_login_done_event(struct scsi_qla_host *, fc_port_t *, uint16_t *); int qla24xx_post_gnl_work(struct scsi_qla_host *, fc_port_t *); -int qla24xx_async_abort_cmd(srb_t *, bool); int qla24xx_post_relogin_work(struct scsi_qla_host *vha); void qla2x00_wait_for_sess_deletion(scsi_qla_host_t *); @@ -238,7 +242,7 @@ extern void qla24xx_report_id_acquisition(scsi_qla_host_t *, struct vp_rpt_id_entry_24xx *); extern void qla2x00_do_dpc_all_vps(scsi_qla_host_t *); extern int qla24xx_vport_create_req_sanity_check(struct fc_vport *); -extern scsi_qla_host_t * qla24xx_create_vhost(struct fc_vport *); +extern scsi_qla_host_t *qla24xx_create_vhost(struct fc_vport *); extern void qla2x00_sp_free_dma(void *); extern char *qla2x00_get_fw_version_str(struct scsi_qla_host *, char *); @@ -276,21 +280,20 @@ extern int qla2x00_start_sp(srb_t *); extern int qla24xx_dif_start_scsi(srb_t *); extern int qla2x00_start_bidir(srb_t *, struct scsi_qla_host *, uint32_t); extern int qla2xxx_dif_start_scsi_mq(srb_t *); +extern void qla2x00_init_timer(srb_t *sp, unsigned long tmo); extern unsigned long qla2x00_get_async_timeout(struct scsi_qla_host *); extern void *qla2x00_alloc_iocbs(struct scsi_qla_host *, srb_t *); extern void *__qla2x00_alloc_iocbs(struct qla_qpair *, srb_t *); extern int qla2x00_issue_marker(scsi_qla_host_t *, int); extern int qla24xx_walk_and_build_sglist_no_difb(struct qla_hw_data *, srb_t *, - uint32_t *, uint16_t, struct qla_tc_param *); + struct dsd64 *, uint16_t, struct qla_tc_param *); extern int qla24xx_walk_and_build_sglist(struct qla_hw_data *, srb_t *, - uint32_t *, uint16_t, struct qla_tc_param *); + struct dsd64 *, uint16_t, struct qla_tc_param *); extern int qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *, srb_t *, - uint32_t *, uint16_t, struct qla_tgt_cmd *); + struct dsd64 *, uint16_t, struct qla_tgt_cmd *); extern int qla24xx_get_one_block_sg(uint32_t, struct qla2_sgx *, uint32_t *); extern int qla24xx_configure_prot_mode(srb_t *, uint16_t *); -extern int qla24xx_build_scsi_crc_2_iocbs(srb_t *, - struct cmd_type_crc_2 *, uint16_t, uint16_t, uint16_t); /* * Global Function Prototypes in qla_mbx.c source file. @@ -466,6 +469,8 @@ qla81xx_fac_do_write_enable(scsi_qla_host_t *, int); extern int qla81xx_fac_erase_sector(scsi_qla_host_t *, uint32_t, uint32_t); +extern int qla81xx_fac_semaphore_access(scsi_qla_host_t *, int); + extern int qla2x00_get_xgmac_stats(scsi_qla_host_t *, dma_addr_t, uint16_t, uint16_t *); @@ -511,6 +516,14 @@ extern int qla27xx_get_zio_threshold(scsi_qla_host_t *, uint16_t *); extern int qla27xx_set_zio_threshold(scsi_qla_host_t *, uint16_t); int qla24xx_res_count_wait(struct scsi_qla_host *, uint16_t *, int); +extern int qla28xx_secure_flash_update(scsi_qla_host_t *, uint16_t, uint16_t, + uint32_t, dma_addr_t, uint32_t); + +extern int qla2xxx_read_remote_register(scsi_qla_host_t *, uint32_t, + uint32_t *); +extern int qla2xxx_write_remote_register(scsi_qla_host_t *, uint32_t, + uint32_t); + /* * Global Function Prototypes in qla_isr.c source file. */ @@ -542,19 +555,20 @@ fc_port_t *qla2x00_find_fcport_by_nportid(scsi_qla_host_t *, port_id_t *, u8); */ extern void qla2x00_release_nvram_protection(scsi_qla_host_t *); extern uint32_t *qla24xx_read_flash_data(scsi_qla_host_t *, uint32_t *, - uint32_t, uint32_t); -extern uint8_t *qla2x00_read_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t, - uint32_t); -extern uint8_t *qla24xx_read_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t, - uint32_t); -extern int qla2x00_write_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t, - uint32_t); -extern int qla24xx_write_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t, - uint32_t); -extern uint8_t *qla25xx_read_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t, - uint32_t); -extern int qla25xx_write_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t, - uint32_t); + uint32_t, uint32_t); +extern uint8_t *qla2x00_read_nvram_data(scsi_qla_host_t *, void *, uint32_t, + uint32_t); +extern uint8_t *qla24xx_read_nvram_data(scsi_qla_host_t *, void *, uint32_t, + uint32_t); +extern int qla2x00_write_nvram_data(scsi_qla_host_t *, void *, uint32_t, + uint32_t); +extern int qla24xx_write_nvram_data(scsi_qla_host_t *, void *, uint32_t, + uint32_t); +extern uint8_t *qla25xx_read_nvram_data(scsi_qla_host_t *, void *, uint32_t, + uint32_t); +extern int qla25xx_write_nvram_data(scsi_qla_host_t *, void *, uint32_t, + uint32_t); + extern int qla2x00_is_a_vp_did(scsi_qla_host_t *, uint32_t); bool qla2x00_check_reg32_for_disconnect(scsi_qla_host_t *, uint32_t); bool qla2x00_check_reg16_for_disconnect(scsi_qla_host_t *, uint16_t); @@ -574,18 +588,18 @@ extern int qla83xx_restart_nic_firmware(scsi_qla_host_t *); extern int qla83xx_access_control(scsi_qla_host_t *, uint16_t, uint32_t, uint32_t, uint16_t *); -extern uint8_t *qla2x00_read_optrom_data(struct scsi_qla_host *, uint8_t *, +extern void *qla2x00_read_optrom_data(struct scsi_qla_host *, void *, uint32_t, uint32_t); -extern int qla2x00_write_optrom_data(struct scsi_qla_host *, uint8_t *, +extern int qla2x00_write_optrom_data(struct scsi_qla_host *, void *, uint32_t, uint32_t); -extern uint8_t *qla24xx_read_optrom_data(struct scsi_qla_host *, uint8_t *, +extern void *qla24xx_read_optrom_data(struct scsi_qla_host *, void *, uint32_t, uint32_t); -extern int qla24xx_write_optrom_data(struct scsi_qla_host *, uint8_t *, +extern int qla24xx_write_optrom_data(struct scsi_qla_host *, void *, uint32_t, uint32_t); -extern uint8_t *qla25xx_read_optrom_data(struct scsi_qla_host *, uint8_t *, +extern void *qla25xx_read_optrom_data(struct scsi_qla_host *, void *, uint32_t, uint32_t); -extern uint8_t *qla8044_read_optrom_data(struct scsi_qla_host *, - uint8_t *, uint32_t, uint32_t); +extern void *qla8044_read_optrom_data(struct scsi_qla_host *, + void *, uint32_t, uint32_t); extern void qla8044_watchdog(struct scsi_qla_host *vha); extern int qla2x00_get_flash_version(scsi_qla_host_t *, void *); @@ -610,20 +624,13 @@ extern void qla82xx_fw_dump(scsi_qla_host_t *, int); extern void qla8044_fw_dump(scsi_qla_host_t *, int); extern void qla27xx_fwdump(scsi_qla_host_t *, int); -extern ulong qla27xx_fwdt_calculate_dump_size(struct scsi_qla_host *); +extern ulong qla27xx_fwdt_calculate_dump_size(struct scsi_qla_host *, void *); extern int qla27xx_fwdt_template_valid(void *); extern ulong qla27xx_fwdt_template_size(void *); -extern const void *qla27xx_fwdt_template_default(void); -extern ulong qla27xx_fwdt_template_default_size(void); - -extern void qla2x00_dump_regs(scsi_qla_host_t *); -extern void qla2x00_dump_buffer(uint8_t *, uint32_t); -extern void qla2x00_dump_buffer_zipped(uint8_t *, uint32_t); -extern void ql_dump_regs(uint32_t, scsi_qla_host_t *, int32_t); -extern void ql_dump_buffer(uint32_t, scsi_qla_host_t *, int32_t, - uint8_t *, uint32_t); -extern void qla2xxx_dump_post_process(scsi_qla_host_t *, int); +extern void qla2xxx_dump_post_process(scsi_qla_host_t *, int); +extern void ql_dump_regs(uint, scsi_qla_host_t *, uint); +extern void ql_dump_buffer(uint, scsi_qla_host_t *, uint, void *, uint); /* * Global Function Prototypes in qla_gs.c source file. */ @@ -722,7 +729,7 @@ extern void qla24xx_wrt_rsp_reg(struct qla_hw_data *, uint16_t, uint16_t); /* qlafx00 related functions */ extern int qlafx00_pci_config(struct scsi_qla_host *); extern int qlafx00_initialize_adapter(struct scsi_qla_host *); -extern void qlafx00_soft_reset(scsi_qla_host_t *); +extern int qlafx00_soft_reset(scsi_qla_host_t *); extern int qlafx00_chip_diag(scsi_qla_host_t *); extern void qlafx00_config_rings(struct scsi_qla_host *); extern char *qlafx00_pci_info_str(struct scsi_qla_host *, char *); @@ -765,16 +772,16 @@ extern int qla82xx_pci_region_offset(struct pci_dev *, int); extern int qla82xx_iospace_config(struct qla_hw_data *); /* Initialization related functions */ -extern void qla82xx_reset_chip(struct scsi_qla_host *); +extern int qla82xx_reset_chip(struct scsi_qla_host *); extern void qla82xx_config_rings(struct scsi_qla_host *); extern void qla82xx_watchdog(scsi_qla_host_t *); extern int qla82xx_start_firmware(scsi_qla_host_t *); /* Firmware and flash related functions */ extern int qla82xx_load_risc(scsi_qla_host_t *, uint32_t *); -extern uint8_t *qla82xx_read_optrom_data(struct scsi_qla_host *, uint8_t *, +extern void *qla82xx_read_optrom_data(struct scsi_qla_host *, void *, uint32_t, uint32_t); -extern int qla82xx_write_optrom_data(struct scsi_qla_host *, uint8_t *, +extern int qla82xx_write_optrom_data(struct scsi_qla_host *, void *, uint32_t, uint32_t); /* Mailbox related functions */ @@ -870,7 +877,7 @@ extern void qla8044_clear_drv_active(struct qla_hw_data *); void qla8044_get_minidump(struct scsi_qla_host *vha); int qla8044_collect_md_data(struct scsi_qla_host *vha); extern int qla8044_md_get_template(scsi_qla_host_t *); -extern int qla8044_write_optrom_data(struct scsi_qla_host *, uint8_t *, +extern int qla8044_write_optrom_data(struct scsi_qla_host *, void *, uint32_t, uint32_t); extern irqreturn_t qla8044_intr_handler(int, void *); extern void qla82xx_mbx_completion(scsi_qla_host_t *, uint16_t); diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index c6fdad12428e..9f58e591666d 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -45,13 +45,11 @@ qla2x00_prep_ms_iocb(scsi_qla_host_t *vha, struct ct_arg *arg) ms_pkt->rsp_bytecount = cpu_to_le32(arg->rsp_size); ms_pkt->req_bytecount = cpu_to_le32(arg->req_size); - ms_pkt->dseg_req_address[0] = cpu_to_le32(LSD(arg->req_dma)); - ms_pkt->dseg_req_address[1] = cpu_to_le32(MSD(arg->req_dma)); - ms_pkt->dseg_req_length = ms_pkt->req_bytecount; + put_unaligned_le64(arg->req_dma, &ms_pkt->req_dsd.address); + ms_pkt->req_dsd.length = ms_pkt->req_bytecount; - ms_pkt->dseg_rsp_address[0] = cpu_to_le32(LSD(arg->rsp_dma)); - ms_pkt->dseg_rsp_address[1] = cpu_to_le32(MSD(arg->rsp_dma)); - ms_pkt->dseg_rsp_length = ms_pkt->rsp_bytecount; + put_unaligned_le64(arg->rsp_dma, &ms_pkt->rsp_dsd.address); + ms_pkt->rsp_dsd.length = ms_pkt->rsp_bytecount; vha->qla_stats.control_requests++; @@ -83,13 +81,11 @@ qla24xx_prep_ms_iocb(scsi_qla_host_t *vha, struct ct_arg *arg) ct_pkt->rsp_byte_count = cpu_to_le32(arg->rsp_size); ct_pkt->cmd_byte_count = cpu_to_le32(arg->req_size); - ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(arg->req_dma)); - ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(arg->req_dma)); - ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count; + put_unaligned_le64(arg->req_dma, &ct_pkt->dsd[0].address); + ct_pkt->dsd[0].length = ct_pkt->cmd_byte_count; - ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(arg->rsp_dma)); - ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(arg->rsp_dma)); - ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count; + put_unaligned_le64(arg->rsp_dma, &ct_pkt->dsd[1].address); + ct_pkt->dsd[1].length = ct_pkt->rsp_byte_count; ct_pkt->vp_index = vha->vp_idx; vha->qla_stats.control_requests++; @@ -152,8 +148,8 @@ qla2x00_chk_ms_status(scsi_qla_host_t *vha, ms_iocb_entry_t *ms_pkt, vha->d_id.b.area, vha->d_id.b.al_pa, comp_status, ct_rsp->header.response); ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, - 0x2078, (uint8_t *)&ct_rsp->header, - sizeof(struct ct_rsp_hdr)); + 0x2078, ct_rsp, + offsetof(typeof(*ct_rsp), rsp)); rval = QLA_INVALID_COMMAND; } else rval = QLA_SUCCESS; @@ -1000,8 +996,7 @@ qla2x00_prep_sns_cmd(scsi_qla_host_t *vha, uint16_t cmd, uint16_t scmd_len, memset(sns_cmd, 0, sizeof(struct sns_cmd_pkt)); wc = data_size / 2; /* Size in 16bit words. */ sns_cmd->p.cmd.buffer_length = cpu_to_le16(wc); - sns_cmd->p.cmd.buffer_address[0] = cpu_to_le32(LSD(ha->sns_cmd_dma)); - sns_cmd->p.cmd.buffer_address[1] = cpu_to_le32(MSD(ha->sns_cmd_dma)); + put_unaligned_le64(ha->sns_cmd_dma, &sns_cmd->p.cmd.buffer_address); sns_cmd->p.cmd.subcommand_length = cpu_to_le16(scmd_len); sns_cmd->p.cmd.subcommand = cpu_to_le16(cmd); wc = (data_size - 16) / 4; /* Size in 32bit words. */ @@ -1385,6 +1380,7 @@ qla2x00_mgmt_svr_login(scsi_qla_host_t *vha) int ret, rval; uint16_t mb[MAILBOX_REGISTER_COUNT]; struct qla_hw_data *ha = vha->hw; + ret = QLA_SUCCESS; if (vha->flags.management_server_logged_in) return ret; @@ -1423,6 +1419,7 @@ qla2x00_prep_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size, { ms_iocb_entry_t *ms_pkt; struct qla_hw_data *ha = vha->hw; + ms_pkt = ha->ms_iocb; memset(ms_pkt, 0, sizeof(ms_iocb_entry_t)); @@ -1436,13 +1433,11 @@ qla2x00_prep_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size, ms_pkt->rsp_bytecount = cpu_to_le32(rsp_size); ms_pkt->req_bytecount = cpu_to_le32(req_size); - ms_pkt->dseg_req_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma)); - ms_pkt->dseg_req_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma)); - ms_pkt->dseg_req_length = ms_pkt->req_bytecount; + put_unaligned_le64(ha->ct_sns_dma, &ms_pkt->req_dsd.address); + ms_pkt->req_dsd.length = ms_pkt->req_bytecount; - ms_pkt->dseg_rsp_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma)); - ms_pkt->dseg_rsp_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma)); - ms_pkt->dseg_rsp_length = ms_pkt->rsp_bytecount; + put_unaligned_le64(ha->ct_sns_dma, &ms_pkt->rsp_dsd.address); + ms_pkt->rsp_dsd.length = ms_pkt->rsp_bytecount; return ms_pkt; } @@ -1474,13 +1469,11 @@ qla24xx_prep_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size, ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size); ct_pkt->cmd_byte_count = cpu_to_le32(req_size); - ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma)); - ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma)); - ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count; + put_unaligned_le64(ha->ct_sns_dma, &ct_pkt->dsd[0].address); + ct_pkt->dsd[0].length = ct_pkt->cmd_byte_count; - ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma)); - ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma)); - ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count; + put_unaligned_le64(ha->ct_sns_dma, &ct_pkt->dsd[1].address); + ct_pkt->dsd[1].length = ct_pkt->rsp_byte_count; ct_pkt->vp_index = vha->vp_idx; return ct_pkt; @@ -1495,10 +1488,10 @@ qla2x00_update_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size) if (IS_FWI2_CAPABLE(ha)) { ct_pkt->cmd_byte_count = cpu_to_le32(req_size); - ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count; + ct_pkt->dsd[0].length = ct_pkt->cmd_byte_count; } else { ms_pkt->req_bytecount = cpu_to_le32(req_size); - ms_pkt->dseg_req_length = ms_pkt->req_bytecount; + ms_pkt->req_dsd.length = ms_pkt->req_bytecount; } return ms_pkt; @@ -1794,7 +1787,7 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *vha) if (IS_CNA_CAPABLE(ha)) eiter->a.sup_speed = cpu_to_be32( FDMI_PORT_SPEED_10GB); - else if (IS_QLA27XX(ha)) + else if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) eiter->a.sup_speed = cpu_to_be32( FDMI_PORT_SPEED_32GB| FDMI_PORT_SPEED_16GB| @@ -2373,7 +2366,7 @@ qla2x00_fdmiv2_rpa(scsi_qla_host_t *vha) if (IS_CNA_CAPABLE(ha)) eiter->a.sup_speed = cpu_to_be32( FDMI_PORT_SPEED_10GB); - else if (IS_QLA27XX(ha)) + else if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) eiter->a.sup_speed = cpu_to_be32( FDMI_PORT_SPEED_32GB| FDMI_PORT_SPEED_16GB| @@ -2446,7 +2439,7 @@ qla2x00_fdmiv2_rpa(scsi_qla_host_t *vha) eiter->type = cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE); eiter->len = cpu_to_be16(4 + 4); eiter->a.max_frame_size = IS_FWI2_CAPABLE(ha) ? - le16_to_cpu(icb24->frame_payload_size): + le16_to_cpu(icb24->frame_payload_size) : le16_to_cpu(ha->init_cb->frame_payload_size); eiter->a.max_frame_size = cpu_to_be32(eiter->a.max_frame_size); size += 4 + 4; @@ -2783,6 +2776,31 @@ qla24xx_prep_ct_fm_req(struct ct_sns_pkt *p, uint16_t cmd, return &p->p.req; } +static uint16_t +qla2x00_port_speed_capability(uint16_t speed) +{ + switch (speed) { + case BIT_15: + return PORT_SPEED_1GB; + case BIT_14: + return PORT_SPEED_2GB; + case BIT_13: + return PORT_SPEED_4GB; + case BIT_12: + return PORT_SPEED_10GB; + case BIT_11: + return PORT_SPEED_8GB; + case BIT_10: + return PORT_SPEED_16GB; + case BIT_8: + return PORT_SPEED_32GB; + case BIT_7: + return PORT_SPEED_64GB; + default: + return PORT_SPEED_UNKNOWN; + } +} + /** * qla2x00_gpsc() - FCS Get Port Speed Capabilities (GPSC) query. * @vha: HA context @@ -2855,31 +2873,8 @@ qla2x00_gpsc(scsi_qla_host_t *vha, sw_info_t *list) } rval = QLA_FUNCTION_FAILED; } else { - /* Save port-speed */ - switch (be16_to_cpu(ct_rsp->rsp.gpsc.speed)) { - case BIT_15: - list[i].fp_speed = PORT_SPEED_1GB; - break; - case BIT_14: - list[i].fp_speed = PORT_SPEED_2GB; - break; - case BIT_13: - list[i].fp_speed = PORT_SPEED_4GB; - break; - case BIT_12: - list[i].fp_speed = PORT_SPEED_10GB; - break; - case BIT_11: - list[i].fp_speed = PORT_SPEED_8GB; - break; - case BIT_10: - list[i].fp_speed = PORT_SPEED_16GB; - break; - case BIT_8: - list[i].fp_speed = PORT_SPEED_32GB; - break; - } - + list->fp_speed = qla2x00_port_speed_capability( + be16_to_cpu(ct_rsp->rsp.gpsc.speed)); ql_dbg(ql_dbg_disc, vha, 0x205b, "GPSC ext entry - fpn " "%8phN speeds=%04x speed=%04x.\n", @@ -3031,6 +3026,8 @@ static void qla24xx_async_gpsc_sp_done(void *s, int res) "Async done-%s res %x, WWPN %8phC \n", sp->name, res, fcport->port_name); + fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE); + if (res == QLA_FUNCTION_TIMEOUT) return; @@ -3048,29 +3045,8 @@ static void qla24xx_async_gpsc_sp_done(void *s, int res) goto done; } } else { - switch (be16_to_cpu(ct_rsp->rsp.gpsc.speed)) { - case BIT_15: - fcport->fp_speed = PORT_SPEED_1GB; - break; - case BIT_14: - fcport->fp_speed = PORT_SPEED_2GB; - break; - case BIT_13: - fcport->fp_speed = PORT_SPEED_4GB; - break; - case BIT_12: - fcport->fp_speed = PORT_SPEED_10GB; - break; - case BIT_11: - fcport->fp_speed = PORT_SPEED_8GB; - break; - case BIT_10: - fcport->fp_speed = PORT_SPEED_16GB; - break; - case BIT_8: - fcport->fp_speed = PORT_SPEED_32GB; - break; - } + fcport->fp_speed = qla2x00_port_speed_capability( + be16_to_cpu(ct_rsp->rsp.gpsc.speed)); ql_dbg(ql_dbg_disc, vha, 0x2054, "Async-%s OUT WWPN %8phC speeds=%04x speed=%04x.\n", @@ -4370,6 +4346,7 @@ int qla24xx_async_gnnid(scsi_qla_host_t *vha, fc_port_t *fcport) done_free_sp: sp->free(sp); + fcport->flags &= ~FCF_ASYNC_SENT; done: return rval; } diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 0c700b140ce7..54772d4c377f 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -95,6 +95,79 @@ qla2x00_get_async_timeout(struct scsi_qla_host *vha) return tmo; } +static void qla24xx_abort_iocb_timeout(void *data) +{ + srb_t *sp = data; + struct srb_iocb *abt = &sp->u.iocb_cmd; + + abt->u.abt.comp_status = CS_TIMEOUT; + sp->done(sp, QLA_FUNCTION_TIMEOUT); +} + +static void qla24xx_abort_sp_done(void *ptr, int res) +{ + srb_t *sp = ptr; + struct srb_iocb *abt = &sp->u.iocb_cmd; + + if (del_timer(&sp->u.iocb_cmd.timer)) { + if (sp->flags & SRB_WAKEUP_ON_COMP) + complete(&abt->u.abt.comp); + else + sp->free(sp); + } +} + +static int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool wait) +{ + scsi_qla_host_t *vha = cmd_sp->vha; + struct srb_iocb *abt_iocb; + srb_t *sp; + int rval = QLA_FUNCTION_FAILED; + + sp = qla2xxx_get_qpair_sp(cmd_sp->vha, cmd_sp->qpair, cmd_sp->fcport, + GFP_ATOMIC); + if (!sp) + goto done; + + abt_iocb = &sp->u.iocb_cmd; + sp->type = SRB_ABT_CMD; + sp->name = "abort"; + sp->qpair = cmd_sp->qpair; + if (wait) + sp->flags = SRB_WAKEUP_ON_COMP; + + abt_iocb->timeout = qla24xx_abort_iocb_timeout; + init_completion(&abt_iocb->u.abt.comp); + /* FW can send 2 x ABTS's timeout/20s */ + qla2x00_init_timer(sp, 42); + + abt_iocb->u.abt.cmd_hndl = cmd_sp->handle; + abt_iocb->u.abt.req_que_no = cpu_to_le16(cmd_sp->qpair->req->id); + + sp->done = qla24xx_abort_sp_done; + + ql_dbg(ql_dbg_async, vha, 0x507c, + "Abort command issued - hdl=%x, type=%x\n", cmd_sp->handle, + cmd_sp->type); + + rval = qla2x00_start_sp(sp); + if (rval != QLA_SUCCESS) + goto done_free_sp; + + if (wait) { + wait_for_completion(&abt_iocb->u.abt.comp); + rval = abt_iocb->u.abt.comp_status == CS_COMPLETE ? + QLA_SUCCESS : QLA_FUNCTION_FAILED; + } else { + goto done; + } + +done_free_sp: + sp->free(sp); +done: + return rval; +} + void qla2x00_async_iocb_timeout(void *data) { @@ -514,6 +587,72 @@ done: return rval; } +static bool qla2x00_is_reserved_id(scsi_qla_host_t *vha, uint16_t loop_id) +{ + struct qla_hw_data *ha = vha->hw; + + if (IS_FWI2_CAPABLE(ha)) + return loop_id > NPH_LAST_HANDLE; + + return (loop_id > ha->max_loop_id && loop_id < SNS_FIRST_LOOP_ID) || + loop_id == MANAGEMENT_SERVER || loop_id == BROADCAST; +} + +/** + * qla2x00_find_new_loop_id - scan through our port list and find a new usable loop ID + * @vha: adapter state pointer. + * @dev: port structure pointer. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +static int qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev) +{ + int rval; + struct qla_hw_data *ha = vha->hw; + unsigned long flags = 0; + + rval = QLA_SUCCESS; + + spin_lock_irqsave(&ha->vport_slock, flags); + + dev->loop_id = find_first_zero_bit(ha->loop_id_map, LOOPID_MAP_SIZE); + if (dev->loop_id >= LOOPID_MAP_SIZE || + qla2x00_is_reserved_id(vha, dev->loop_id)) { + dev->loop_id = FC_NO_LOOP_ID; + rval = QLA_FUNCTION_FAILED; + } else { + set_bit(dev->loop_id, ha->loop_id_map); + } + spin_unlock_irqrestore(&ha->vport_slock, flags); + + if (rval == QLA_SUCCESS) + ql_dbg(ql_dbg_disc, dev->vha, 0x2086, + "Assigning new loopid=%x, portid=%x.\n", + dev->loop_id, dev->d_id.b24); + else + ql_log(ql_log_warn, dev->vha, 0x2087, + "No loop_id's available, portid=%x.\n", + dev->d_id.b24); + + return rval; +} + +void qla2x00_clear_loop_id(fc_port_t *fcport) +{ + struct qla_hw_data *ha = fcport->vha->hw; + + if (fcport->loop_id == FC_NO_LOOP_ID || + qla2x00_is_reserved_id(fcport->vha, fcport->loop_id)) + return; + + clear_bit(fcport->loop_id, ha->loop_id_map); + fcport->loop_id = FC_NO_LOOP_ID; +} + static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha, struct event_arg *ea) { @@ -1482,6 +1621,7 @@ int qla24xx_post_newsess_work(struct scsi_qla_host *vha, port_id_t *id, u8 *port_name, u8 *node_name, void *pla, u8 fc4_type) { struct qla_work_evt *e; + e = qla2x00_alloc_work(vha, QLA_EVT_NEW_SESS); if (!e) return QLA_FUNCTION_FAILED; @@ -1558,6 +1698,7 @@ void qla2x00_fcport_event_handler(scsi_qla_host_t *vha, struct event_arg *ea) return; { unsigned long flags; + fcport = qla2x00_find_fcport_by_nportid (vha, &ea->id, 1); if (fcport) { @@ -1620,21 +1761,21 @@ void qla2x00_fcport_event_handler(scsi_qla_host_t *vha, struct event_arg *ea) */ void qla_rscn_replay(fc_port_t *fcport) { - struct event_arg ea; + struct event_arg ea; - switch (fcport->disc_state) { - case DSC_DELETE_PEND: - return; - default: - break; - } + switch (fcport->disc_state) { + case DSC_DELETE_PEND: + return; + default: + break; + } - if (fcport->scan_needed) { - memset(&ea, 0, sizeof(ea)); - ea.event = FCME_RSCN; - ea.id = fcport->d_id; - ea.id.b.rsvd_1 = RSCN_PORT_ADDR; - qla2x00_fcport_event_handler(fcport->vha, &ea); + if (fcport->scan_needed) { + memset(&ea, 0, sizeof(ea)); + ea.event = FCME_RSCN; + ea.id = fcport->d_id; + ea.id.b.rsvd_1 = RSCN_PORT_ADDR; + qla2x00_fcport_event_handler(fcport->vha, &ea); } } @@ -1717,82 +1858,6 @@ done: return rval; } -static void -qla24xx_abort_iocb_timeout(void *data) -{ - srb_t *sp = data; - struct srb_iocb *abt = &sp->u.iocb_cmd; - - abt->u.abt.comp_status = CS_TIMEOUT; - sp->done(sp, QLA_FUNCTION_TIMEOUT); -} - -static void -qla24xx_abort_sp_done(void *ptr, int res) -{ - srb_t *sp = ptr; - struct srb_iocb *abt = &sp->u.iocb_cmd; - - if (del_timer(&sp->u.iocb_cmd.timer)) { - if (sp->flags & SRB_WAKEUP_ON_COMP) - complete(&abt->u.abt.comp); - else - sp->free(sp); - } -} - -int -qla24xx_async_abort_cmd(srb_t *cmd_sp, bool wait) -{ - scsi_qla_host_t *vha = cmd_sp->vha; - struct srb_iocb *abt_iocb; - srb_t *sp; - int rval = QLA_FUNCTION_FAILED; - - sp = qla2xxx_get_qpair_sp(cmd_sp->vha, cmd_sp->qpair, cmd_sp->fcport, - GFP_ATOMIC); - if (!sp) - goto done; - - abt_iocb = &sp->u.iocb_cmd; - sp->type = SRB_ABT_CMD; - sp->name = "abort"; - sp->qpair = cmd_sp->qpair; - if (wait) - sp->flags = SRB_WAKEUP_ON_COMP; - - abt_iocb->timeout = qla24xx_abort_iocb_timeout; - init_completion(&abt_iocb->u.abt.comp); - /* FW can send 2 x ABTS's timeout/20s */ - qla2x00_init_timer(sp, 42); - - abt_iocb->u.abt.cmd_hndl = cmd_sp->handle; - abt_iocb->u.abt.req_que_no = cpu_to_le16(cmd_sp->qpair->req->id); - - sp->done = qla24xx_abort_sp_done; - - ql_dbg(ql_dbg_async, vha, 0x507c, - "Abort command issued - hdl=%x, type=%x\n", - cmd_sp->handle, cmd_sp->type); - - rval = qla2x00_start_sp(sp); - if (rval != QLA_SUCCESS) - goto done_free_sp; - - if (wait) { - wait_for_completion(&abt_iocb->u.abt.comp); - rval = abt_iocb->u.abt.comp_status == CS_COMPLETE ? - QLA_SUCCESS : QLA_FUNCTION_FAILED; - } else { - goto done; - } - -done_free_sp: - sp->free(sp); -done: - return rval; -} - int qla24xx_async_abort_command(srb_t *sp) { @@ -2102,6 +2167,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha) int rval; struct qla_hw_data *ha = vha->hw; struct req_que *req = ha->req_q_map[0]; + struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; memset(&vha->qla_stats, 0, sizeof(vha->qla_stats)); memset(&vha->fc_host_stat, 0, sizeof(vha->fc_host_stat)); @@ -2136,6 +2202,15 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha) ha->isp_ops->reset_chip(vha); + /* Check for secure flash support */ + if (IS_QLA28XX(ha)) { + if (RD_REG_DWORD(®->mailbox12) & BIT_0) { + ql_log(ql_log_info, vha, 0xffff, "Adapter is Secure\n"); + ha->flags.secure_adapter = 1; + } + } + + rval = qla2xxx_get_flash_info(vha); if (rval) { ql_log(ql_log_fatal, vha, 0x004f, @@ -2452,7 +2527,7 @@ qla2x00_isp_firmware(scsi_qla_host_t *vha) * * Returns 0 on success. */ -void +int qla2x00_reset_chip(scsi_qla_host_t *vha) { unsigned long flags = 0; @@ -2460,9 +2535,10 @@ qla2x00_reset_chip(scsi_qla_host_t *vha) struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; uint32_t cnt; uint16_t cmd; + int rval = QLA_FUNCTION_FAILED; if (unlikely(pci_channel_offline(ha->pdev))) - return; + return rval; ha->isp_ops->disable_intrs(ha); @@ -2588,6 +2664,8 @@ qla2x00_reset_chip(scsi_qla_host_t *vha) } spin_unlock_irqrestore(&ha->hardware_lock, flags); + + return QLA_SUCCESS; } /** @@ -2828,14 +2906,15 @@ acquired: * * Returns 0 on success. */ -void +int qla24xx_reset_chip(scsi_qla_host_t *vha) { struct qla_hw_data *ha = vha->hw; + int rval = QLA_FUNCTION_FAILED; if (pci_channel_offline(ha->pdev) && ha->flags.pci_channel_io_perm_failure) { - return; + return rval; } ha->isp_ops->disable_intrs(ha); @@ -2843,7 +2922,9 @@ qla24xx_reset_chip(scsi_qla_host_t *vha) qla25xx_manipulate_risc_semaphore(vha); /* Perform RISC reset. */ - qla24xx_reset_risc(vha); + rval = qla24xx_reset_risc(vha); + + return rval; } /** @@ -3018,7 +3099,7 @@ qla2x00_alloc_offload_mem(scsi_qla_host_t *vha) if (IS_FWI2_CAPABLE(ha)) { /* Allocate memory for Fibre Channel Event Buffer. */ if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha) && - !IS_QLA27XX(ha)) + !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) goto try_eft; if (ha->fce) @@ -3089,12 +3170,15 @@ eft_err: void qla2x00_alloc_fw_dump(scsi_qla_host_t *vha) { + int rval; uint32_t dump_size, fixed_size, mem_size, req_q_size, rsp_q_size, eft_size, fce_size, mq_size; struct qla_hw_data *ha = vha->hw; struct req_que *req = ha->req_q_map[0]; struct rsp_que *rsp = ha->rsp_q_map[0]; struct qla2xxx_fw_dump *fw_dump; + dma_addr_t tc_dma; + void *tc; dump_size = fixed_size = mem_size = eft_size = fce_size = mq_size = 0; req_q_size = rsp_q_size = 0; @@ -3106,7 +3190,7 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha) mem_size = (ha->fw_memory_size - 0x11000 + 1) * sizeof(uint16_t); } else if (IS_FWI2_CAPABLE(ha)) { - if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) fixed_size = offsetof(struct qla83xx_fw_dump, ext_mem); else if (IS_QLA81XX(ha)) fixed_size = offsetof(struct qla81xx_fw_dump, ext_mem); @@ -3118,40 +3202,72 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha) mem_size = (ha->fw_memory_size - 0x100000 + 1) * sizeof(uint32_t); if (ha->mqenable) { - if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha)) + if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha) && + !IS_QLA28XX(ha)) mq_size = sizeof(struct qla2xxx_mq_chain); /* - * Allocate maximum buffer size for all queues. + * Allocate maximum buffer size for all queues - Q0. * Resizing must be done at end-of-dump processing. */ - mq_size += ha->max_req_queues * + mq_size += (ha->max_req_queues - 1) * (req->length * sizeof(request_t)); - mq_size += ha->max_rsp_queues * + mq_size += (ha->max_rsp_queues - 1) * (rsp->length * sizeof(response_t)); } if (ha->tgt.atio_ring) mq_size += ha->tgt.atio_q_length * sizeof(request_t); /* Allocate memory for Fibre Channel Event Buffer. */ if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha) && - !IS_QLA27XX(ha)) + !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) goto try_eft; fce_size = sizeof(struct qla2xxx_fce_chain) + FCE_SIZE; try_eft: + if (ha->eft) + dma_free_coherent(&ha->pdev->dev, + EFT_SIZE, ha->eft, ha->eft_dma); + + /* Allocate memory for Extended Trace Buffer. */ + tc = dma_alloc_coherent(&ha->pdev->dev, EFT_SIZE, &tc_dma, + GFP_KERNEL); + if (!tc) { + ql_log(ql_log_warn, vha, 0x00c1, + "Unable to allocate (%d KB) for EFT.\n", + EFT_SIZE / 1024); + goto allocate; + } + + rval = qla2x00_enable_eft_trace(vha, tc_dma, EFT_NUM_BUFFERS); + if (rval) { + ql_log(ql_log_warn, vha, 0x00c2, + "Unable to initialize EFT (%d).\n", rval); + dma_free_coherent(&ha->pdev->dev, EFT_SIZE, tc, + tc_dma); + } ql_dbg(ql_dbg_init, vha, 0x00c3, "Allocated (%d KB) EFT ...\n", EFT_SIZE / 1024); eft_size = EFT_SIZE; } - if (IS_QLA27XX(ha)) { - if (!ha->fw_dump_template) { - ql_log(ql_log_warn, vha, 0x00ba, - "Failed missing fwdump template\n"); - return; + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { + struct fwdt *fwdt = ha->fwdt; + uint j; + + for (j = 0; j < 2; j++, fwdt++) { + if (!fwdt->template) { + ql_log(ql_log_warn, vha, 0x00ba, + "-> fwdt%u no template\n", j); + continue; + } + ql_dbg(ql_dbg_init, vha, 0x00fa, + "-> fwdt%u calculating fwdump size...\n", j); + fwdt->dump_size = qla27xx_fwdt_calculate_dump_size( + vha, fwdt->template); + ql_dbg(ql_dbg_init, vha, 0x00fa, + "-> fwdt%u calculated fwdump size = %#lx bytes\n", + j, fwdt->dump_size); + dump_size += fwdt->dump_size; } - dump_size = qla27xx_fwdt_calculate_dump_size(vha); - ql_dbg(ql_dbg_init, vha, 0x00fa, - "-> allocating fwdump (%x bytes)...\n", dump_size); goto allocate; } @@ -3170,42 +3286,66 @@ try_eft: ha->exlogin_size; allocate: - if (!ha->fw_dump_len || dump_size != ha->fw_dump_len) { + if (!ha->fw_dump_len || dump_size > ha->fw_dump_alloc_len) { + + ql_dbg(ql_dbg_init, vha, 0x00c5, + "%s dump_size %d fw_dump_len %d fw_dump_alloc_len %d\n", + __func__, dump_size, ha->fw_dump_len, + ha->fw_dump_alloc_len); + fw_dump = vmalloc(dump_size); if (!fw_dump) { ql_log(ql_log_warn, vha, 0x00c4, "Unable to allocate (%d KB) for firmware dump.\n", dump_size / 1024); } else { - if (ha->fw_dump) + mutex_lock(&ha->optrom_mutex); + if (ha->fw_dumped) { + memcpy(fw_dump, ha->fw_dump, ha->fw_dump_len); vfree(ha->fw_dump); - ha->fw_dump = fw_dump; - - ha->fw_dump_len = dump_size; - ql_dbg(ql_dbg_init, vha, 0x00c5, - "Allocated (%d KB) for firmware dump.\n", - dump_size / 1024); - - if (IS_QLA27XX(ha)) - return; - - ha->fw_dump->signature[0] = 'Q'; - ha->fw_dump->signature[1] = 'L'; - ha->fw_dump->signature[2] = 'G'; - ha->fw_dump->signature[3] = 'C'; - ha->fw_dump->version = htonl(1); - - ha->fw_dump->fixed_size = htonl(fixed_size); - ha->fw_dump->mem_size = htonl(mem_size); - ha->fw_dump->req_q_size = htonl(req_q_size); - ha->fw_dump->rsp_q_size = htonl(rsp_q_size); - - ha->fw_dump->eft_size = htonl(eft_size); - ha->fw_dump->eft_addr_l = htonl(LSD(ha->eft_dma)); - ha->fw_dump->eft_addr_h = htonl(MSD(ha->eft_dma)); + ha->fw_dump = fw_dump; + ha->fw_dump_alloc_len = dump_size; + ql_dbg(ql_dbg_init, vha, 0x00c5, + "Re-Allocated (%d KB) and save firmware dump.\n", + dump_size / 1024); + } else { + if (ha->fw_dump) + vfree(ha->fw_dump); + ha->fw_dump = fw_dump; + + ha->fw_dump_len = ha->fw_dump_alloc_len = + dump_size; + ql_dbg(ql_dbg_init, vha, 0x00c5, + "Allocated (%d KB) for firmware dump.\n", + dump_size / 1024); + + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { + mutex_unlock(&ha->optrom_mutex); + return; + } - ha->fw_dump->header_size = - htonl(offsetof(struct qla2xxx_fw_dump, isp)); + ha->fw_dump->signature[0] = 'Q'; + ha->fw_dump->signature[1] = 'L'; + ha->fw_dump->signature[2] = 'G'; + ha->fw_dump->signature[3] = 'C'; + ha->fw_dump->version = htonl(1); + + ha->fw_dump->fixed_size = htonl(fixed_size); + ha->fw_dump->mem_size = htonl(mem_size); + ha->fw_dump->req_q_size = htonl(req_q_size); + ha->fw_dump->rsp_q_size = htonl(rsp_q_size); + + ha->fw_dump->eft_size = htonl(eft_size); + ha->fw_dump->eft_addr_l = + htonl(LSD(ha->eft_dma)); + ha->fw_dump->eft_addr_h = + htonl(MSD(ha->eft_dma)); + + ha->fw_dump->header_size = + htonl(offsetof + (struct qla2xxx_fw_dump, isp)); + } + mutex_unlock(&ha->optrom_mutex); } } } @@ -3498,7 +3638,8 @@ qla2x00_setup_chip(scsi_qla_host_t *vha) if (rval == QLA_SUCCESS) { qla24xx_detect_sfp(vha); - if ((IS_QLA83XX(ha) || IS_QLA27XX(ha)) && + if ((IS_QLA83XX(ha) || IS_QLA27XX(ha) || + IS_QLA28XX(ha)) && (ha->zio_mode == QLA_ZIO_MODE_6)) qla27xx_set_zio_threshold(vha, ha->last_zio_threshold); @@ -3570,7 +3711,7 @@ enable_82xx_npiv: spin_unlock_irqrestore(&ha->hardware_lock, flags); } - if (IS_QLA27XX(ha)) + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) ha->flags.fac_supported = 1; else if (rval == QLA_SUCCESS && IS_FAC_REQUIRED(ha)) { uint32_t size; @@ -3585,7 +3726,8 @@ enable_82xx_npiv: ha->fw_major_version, ha->fw_minor_version, ha->fw_subminor_version); - if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) { + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || + IS_QLA28XX(ha)) { ha->flags.fac_supported = 0; rval = QLA_SUCCESS; } @@ -3647,8 +3789,7 @@ qla2x00_update_fw_options(scsi_qla_host_t *vha) ql_dbg(ql_dbg_init + ql_dbg_buffer, vha, 0x0115, "Serial link options.\n"); ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0109, - (uint8_t *)&ha->fw_seriallink_options, - sizeof(ha->fw_seriallink_options)); + ha->fw_seriallink_options, sizeof(ha->fw_seriallink_options)); ha->fw_options[1] &= ~FO1_SET_EMPHASIS_SWING; if (ha->fw_seriallink_options[3] & BIT_2) { @@ -3738,7 +3879,7 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha) /* Move PUREX, ABTS RX & RIDA to ATIOQ */ if (ql2xmvasynctoatio && - (IS_QLA83XX(ha) || IS_QLA27XX(ha))) { + (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))) { if (qla_tgt_mode_enabled(vha) || qla_dual_mode_enabled(vha)) ha->fw_options[2] |= BIT_11; @@ -3746,7 +3887,8 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha) ha->fw_options[2] &= ~BIT_11; } - if (IS_QLA25XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha)) { + if (IS_QLA25XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha) || + IS_QLA28XX(ha)) { /* * Tell FW to track each exchange to prevent * driver from using stale exchange. @@ -3799,10 +3941,8 @@ qla2x00_config_rings(struct scsi_qla_host *vha) ha->init_cb->response_q_inpointer = cpu_to_le16(0); ha->init_cb->request_q_length = cpu_to_le16(req->length); ha->init_cb->response_q_length = cpu_to_le16(rsp->length); - ha->init_cb->request_q_address[0] = cpu_to_le32(LSD(req->dma)); - ha->init_cb->request_q_address[1] = cpu_to_le32(MSD(req->dma)); - ha->init_cb->response_q_address[0] = cpu_to_le32(LSD(rsp->dma)); - ha->init_cb->response_q_address[1] = cpu_to_le32(MSD(rsp->dma)); + put_unaligned_le64(req->dma, &ha->init_cb->request_q_address); + put_unaligned_le64(rsp->dma, &ha->init_cb->response_q_address); WRT_REG_WORD(ISP_REQ_Q_IN(ha, reg), 0); WRT_REG_WORD(ISP_REQ_Q_OUT(ha, reg), 0); @@ -3829,21 +3969,19 @@ qla24xx_config_rings(struct scsi_qla_host *vha) icb->response_q_inpointer = cpu_to_le16(0); icb->request_q_length = cpu_to_le16(req->length); icb->response_q_length = cpu_to_le16(rsp->length); - icb->request_q_address[0] = cpu_to_le32(LSD(req->dma)); - icb->request_q_address[1] = cpu_to_le32(MSD(req->dma)); - icb->response_q_address[0] = cpu_to_le32(LSD(rsp->dma)); - icb->response_q_address[1] = cpu_to_le32(MSD(rsp->dma)); + put_unaligned_le64(req->dma, &icb->request_q_address); + put_unaligned_le64(rsp->dma, &icb->response_q_address); /* Setup ATIO queue dma pointers for target mode */ icb->atio_q_inpointer = cpu_to_le16(0); icb->atio_q_length = cpu_to_le16(ha->tgt.atio_q_length); - icb->atio_q_address[0] = cpu_to_le32(LSD(ha->tgt.atio_dma)); - icb->atio_q_address[1] = cpu_to_le32(MSD(ha->tgt.atio_dma)); + put_unaligned_le64(ha->tgt.atio_dma, &icb->atio_q_address); if (IS_SHADOW_REG_CAPABLE(ha)) icb->firmware_options_2 |= cpu_to_le32(BIT_30|BIT_29); - if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha)) { + if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha) || + IS_QLA28XX(ha)) { icb->qos = cpu_to_le16(QLA_DEFAULT_QUE_QOS); icb->rid = cpu_to_le16(rid); if (ha->flags.msix_enabled) { @@ -4266,11 +4404,14 @@ qla2x00_set_model_info(scsi_qla_host_t *vha, uint8_t *model, size_t len, { char *st, *en; uint16_t index; + uint64_t zero[2] = { 0 }; struct qla_hw_data *ha = vha->hw; int use_tbl = !IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha) && !IS_CNA_CAPABLE(ha) && !IS_QLA2031(ha); - if (memcmp(model, BINZERO, len) != 0) { + if (len > sizeof(zero)) + len = sizeof(zero); + if (memcmp(model, &zero, len) != 0) { strncpy(ha->model_number, model, len); st = en = ha->model_number; en += len - 1; @@ -4357,7 +4498,7 @@ qla2x00_nvram_config(scsi_qla_host_t *vha) rval = QLA_SUCCESS; /* Determine NVRAM starting address. */ - ha->nvram_size = sizeof(nvram_t); + ha->nvram_size = sizeof(*nv); ha->nvram_base = 0; if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA2300(ha)) if ((RD_REG_WORD(®->ctrl_status) >> 14) == 1) @@ -4371,16 +4512,15 @@ qla2x00_nvram_config(scsi_qla_host_t *vha) ql_dbg(ql_dbg_init + ql_dbg_buffer, vha, 0x010f, "Contents of NVRAM.\n"); ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0110, - (uint8_t *)nv, ha->nvram_size); + nv, ha->nvram_size); /* Bad NVRAM data, set defaults parameters. */ - if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' || - nv->id[2] != 'P' || nv->id[3] != ' ' || nv->nvram_version < 1) { + if (chksum || memcmp("ISP ", nv->id, sizeof(nv->id)) || + nv->nvram_version < 1) { /* Reset NVRAM data. */ ql_log(ql_log_warn, vha, 0x0064, - "Inconsistent NVRAM " - "detected: checksum=0x%x id=%c version=0x%x.\n", - chksum, nv->id[0], nv->nvram_version); + "Inconsistent NVRAM detected: checksum=%#x id=%.4s version=%#x.\n", + chksum, nv->id, nv->nvram_version); ql_log(ql_log_warn, vha, 0x0065, "Falling back to " "functioning (yet invalid -- WWPN) defaults.\n"); @@ -4629,7 +4769,7 @@ qla2x00_nvram_config(scsi_qla_host_t *vha) ha->zio_mode = icb->add_firmware_options[0] & (BIT_3 | BIT_2 | BIT_1 | BIT_0); ha->zio_timer = icb->interrupt_delay_timer ? - icb->interrupt_delay_timer: 2; + icb->interrupt_delay_timer : 2; } icb->add_firmware_options[0] &= ~(BIT_3 | BIT_2 | BIT_1 | BIT_0); @@ -4662,7 +4802,7 @@ qla2x00_rport_del(void *data) unsigned long flags; spin_lock_irqsave(fcport->vha->host->host_lock, flags); - rport = fcport->drport ? fcport->drport: fcport->rport; + rport = fcport->drport ? fcport->drport : fcport->rport; fcport->drport = NULL; spin_unlock_irqrestore(fcport->vha->host->host_lock, flags); if (rport) { @@ -4675,6 +4815,23 @@ qla2x00_rport_del(void *data) } } +void qla2x00_set_fcport_state(fc_port_t *fcport, int state) +{ + int old_state; + + old_state = atomic_read(&fcport->state); + atomic_set(&fcport->state, state); + + /* Don't print state transitions during initial allocation of fcport */ + if (old_state && old_state != state) { + ql_dbg(ql_dbg_disc, fcport->vha, 0x207d, + "FCPort %8phC state transitioned from %s to %s - portid=%02x%02x%02x.\n", + fcport->port_name, port_state_str[old_state], + port_state_str[state], fcport->d_id.b.domain, + fcport->d_id.b.area, fcport->d_id.b.al_pa); + } +} + /** * qla2x00_alloc_fcport() - Allocate a generic fcport. * @vha: HA context @@ -4741,6 +4898,8 @@ qla2x00_free_fcport(fc_port_t *fcport) fcport->ct_desc.ct_sns = NULL; } + list_del(&fcport->list); + qla2x00_clear_loop_id(fcport); kfree(fcport); } @@ -4762,6 +4921,7 @@ qla2x00_configure_loop(scsi_qla_host_t *vha) int rval; unsigned long flags, save_flags; struct qla_hw_data *ha = vha->hw; + rval = QLA_SUCCESS; /* Get Initiator ID */ @@ -4943,8 +5103,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha) ql_dbg(ql_dbg_disc, vha, 0x2011, "Entries in ID list (%d).\n", entries); ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2075, - (uint8_t *)ha->gid_list, - entries * sizeof(struct gid_list_info)); + ha->gid_list, entries * sizeof(*ha->gid_list)); if (entries == 0) { spin_lock_irqsave(&vha->work_lock, flags); @@ -5194,16 +5353,23 @@ qla2x00_reg_remote_port(scsi_qla_host_t *vha, fc_port_t *fcport) rport->supported_classes = fcport->supported_classes; - rport_ids.roles = FC_RPORT_ROLE_UNKNOWN; + rport_ids.roles = FC_PORT_ROLE_UNKNOWN; if (fcport->port_type == FCT_INITIATOR) - rport_ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR; + rport_ids.roles |= FC_PORT_ROLE_FCP_INITIATOR; if (fcport->port_type == FCT_TARGET) - rport_ids.roles |= FC_RPORT_ROLE_FCP_TARGET; + rport_ids.roles |= FC_PORT_ROLE_FCP_TARGET; + if (fcport->port_type & FCT_NVME_INITIATOR) + rport_ids.roles |= FC_PORT_ROLE_NVME_INITIATOR; + if (fcport->port_type & FCT_NVME_TARGET) + rport_ids.roles |= FC_PORT_ROLE_NVME_TARGET; + if (fcport->port_type & FCT_NVME_DISCOVERY) + rport_ids.roles |= FC_PORT_ROLE_NVME_DISCOVERY; ql_dbg(ql_dbg_disc, vha, 0x20ee, "%s %8phN. rport %p is %s mode\n", __func__, fcport->port_name, rport, - (fcport->port_type == FCT_TARGET) ? "tgt" : "ini"); + (fcport->port_type == FCT_TARGET) ? "tgt" : + ((fcport->port_type & FCT_NVME) ? "nvme" :"ini")); fc_remote_port_rolechg(rport, rport_ids.roles); } @@ -5778,55 +5944,6 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha) return (rval); } -/* - * qla2x00_find_new_loop_id - * Scan through our port list and find a new usable loop ID. - * - * Input: - * ha: adapter state pointer. - * dev: port structure pointer. - * - * Returns: - * qla2x00 local function return status code. - * - * Context: - * Kernel context. - */ -int -qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev) -{ - int rval; - struct qla_hw_data *ha = vha->hw; - unsigned long flags = 0; - - rval = QLA_SUCCESS; - - spin_lock_irqsave(&ha->vport_slock, flags); - - dev->loop_id = find_first_zero_bit(ha->loop_id_map, - LOOPID_MAP_SIZE); - if (dev->loop_id >= LOOPID_MAP_SIZE || - qla2x00_is_reserved_id(vha, dev->loop_id)) { - dev->loop_id = FC_NO_LOOP_ID; - rval = QLA_FUNCTION_FAILED; - } else - set_bit(dev->loop_id, ha->loop_id_map); - - spin_unlock_irqrestore(&ha->vport_slock, flags); - - if (rval == QLA_SUCCESS) - ql_dbg(ql_dbg_disc, dev->vha, 0x2086, - "Assigning new loopid=%x, portid=%x.\n", - dev->loop_id, dev->d_id.b24); - else - ql_log(ql_log_warn, dev->vha, 0x2087, - "No loop_id's available, portid=%x.\n", - dev->d_id.b24); - - return (rval); -} - - /* FW does not set aside Loop id for MGMT Server/FFFFFAh */ int qla2x00_reserve_mgmt_server_loop_id(scsi_qla_host_t *vha) @@ -6318,6 +6435,7 @@ qla83xx_initiating_reset(scsi_qla_host_t *vha) qla83xx_idc_audit(vha, IDC_AUDIT_TIMESTAMP); } else { const char *state = qla83xx_dev_state_to_string(dev_state); + ql_log(ql_log_info, vha, 0xb057, "HW State: %s.\n", state); /* SV: XXX: Is timeout required here? */ @@ -6639,6 +6757,14 @@ qla2x00_abort_isp(scsi_qla_host_t *vha) if (vha->flags.online) { qla2x00_abort_isp_cleanup(vha); + if (test_and_clear_bit(ISP_ABORT_TO_ROM, &vha->dpc_flags)) { + ha->flags.chip_reset_done = 1; + vha->flags.online = 1; + status = 0; + clear_bit(ISP_ABORT_RETRY, &vha->dpc_flags); + return status; + } + if (IS_QLA8031(ha)) { ql_dbg(ql_dbg_p3p, vha, 0xb05c, "Clearing fcoe driver presence.\n"); @@ -6879,7 +7005,7 @@ qla25xx_init_queues(struct qla_hw_data *ha) * Input: * ha = adapter block pointer. */ -void +int qla2x00_reset_adapter(scsi_qla_host_t *vha) { unsigned long flags = 0; @@ -6895,17 +7021,20 @@ qla2x00_reset_adapter(scsi_qla_host_t *vha) WRT_REG_WORD(®->hccr, HCCR_RELEASE_RISC); RD_REG_WORD(®->hccr); /* PCI Posting. */ spin_unlock_irqrestore(&ha->hardware_lock, flags); + + return QLA_SUCCESS; } -void +int qla24xx_reset_adapter(scsi_qla_host_t *vha) { unsigned long flags = 0; struct qla_hw_data *ha = vha->hw; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; + int rval = QLA_SUCCESS; if (IS_P3P_TYPE(ha)) - return; + return rval; vha->flags.online = 0; ha->isp_ops->disable_intrs(ha); @@ -6919,6 +7048,8 @@ qla24xx_reset_adapter(scsi_qla_host_t *vha) if (IS_NOPOLLING_TYPE(ha)) ha->isp_ops->enable_intrs(ha); + + return rval; } /* On sparc systems, obtain port and node WWN from firmware @@ -6969,34 +7100,33 @@ qla24xx_nvram_config(scsi_qla_host_t *vha) ha->vpd_base = FA_NVRAM_VPD1_ADDR; } - ha->nvram_size = sizeof(struct nvram_24xx); + ha->nvram_size = sizeof(*nv); ha->vpd_size = FA_NVRAM_VPD_SIZE; /* Get VPD data into cache */ ha->vpd = ha->nvram + VPD_OFFSET; - ha->isp_ops->read_nvram(vha, (uint8_t *)ha->vpd, + ha->isp_ops->read_nvram(vha, ha->vpd, ha->nvram_base - FA_NVRAM_FUNC0_ADDR, FA_NVRAM_VPD_SIZE * 4); /* Get NVRAM data into cache and calculate checksum. */ dptr = (uint32_t *)nv; - ha->isp_ops->read_nvram(vha, (uint8_t *)dptr, ha->nvram_base, - ha->nvram_size); + ha->isp_ops->read_nvram(vha, dptr, ha->nvram_base, ha->nvram_size); 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"); ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x010d, - (uint8_t *)nv, ha->nvram_size); + nv, ha->nvram_size); /* Bad NVRAM data, set defaults parameters. */ - if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' || nv->id[2] != 'P' - || nv->id[3] != ' ' || - nv->nvram_version < cpu_to_le16(ICB_VERSION)) { + if (chksum || memcmp("ISP ", nv->id, sizeof(nv->id)) || + le16_to_cpu(nv->nvram_version) < ICB_VERSION) { /* Reset NVRAM data. */ ql_log(ql_log_warn, vha, 0x006b, - "Inconsistent NVRAM detected: checksum=0x%x id=%c " - "version=0x%x.\n", chksum, nv->id[0], nv->nvram_version); + "Inconsistent NVRAM checksum=%#x id=%.4s version=%#x.\n", + chksum, nv->id, nv->nvram_version); + ql_dump_buffer(ql_dbg_init, vha, 0x006b, nv, sizeof(*nv)); ql_log(ql_log_warn, vha, 0x006c, "Falling back to functioning (yet invalid -- WWPN) " "defaults.\n"); @@ -7104,11 +7234,11 @@ qla24xx_nvram_config(scsi_qla_host_t *vha) ha->flags.disable_risc_code_load = 0; ha->flags.enable_lip_reset = 0; ha->flags.enable_lip_full_login = - le32_to_cpu(nv->host_p) & BIT_10 ? 1: 0; + le32_to_cpu(nv->host_p) & BIT_10 ? 1 : 0; ha->flags.enable_target_reset = - le32_to_cpu(nv->host_p) & BIT_11 ? 1: 0; + le32_to_cpu(nv->host_p) & BIT_11 ? 1 : 0; ha->flags.enable_led_scheme = 0; - ha->flags.disable_serdes = le32_to_cpu(nv->host_p) & BIT_5 ? 1: 0; + ha->flags.disable_serdes = le32_to_cpu(nv->host_p) & BIT_5 ? 1 : 0; ha->operating_mode = (le32_to_cpu(icb->firmware_options_2) & (BIT_6 | BIT_5 | BIT_4)) >> 4; @@ -7182,7 +7312,7 @@ qla24xx_nvram_config(scsi_qla_host_t *vha) ha->zio_mode = le32_to_cpu(icb->firmware_options_2) & (BIT_3 | BIT_2 | BIT_1 | BIT_0); ha->zio_timer = le16_to_cpu(icb->interrupt_delay_timer) ? - le16_to_cpu(icb->interrupt_delay_timer): 2; + le16_to_cpu(icb->interrupt_delay_timer) : 2; } icb->firmware_options_2 &= cpu_to_le32( ~(BIT_3 | BIT_2 | BIT_1 | BIT_0)); @@ -7205,128 +7335,311 @@ qla24xx_nvram_config(scsi_qla_host_t *vha) return (rval); } -uint8_t qla27xx_find_valid_image(struct scsi_qla_host *vha) +static void +qla27xx_print_image(struct scsi_qla_host *vha, char *name, + struct qla27xx_image_status *image_status) +{ + ql_dbg(ql_dbg_init, vha, 0x018b, + "%s %s: mask=%#02x gen=%#04x ver=%u.%u map=%#01x sum=%#08x sig=%#08x\n", + name, "status", + image_status->image_status_mask, + le16_to_cpu(image_status->generation), + image_status->ver_major, + image_status->ver_minor, + image_status->bitmap, + le32_to_cpu(image_status->checksum), + le32_to_cpu(image_status->signature)); +} + +static bool +qla28xx_check_aux_image_status_signature( + struct qla27xx_image_status *image_status) +{ + ulong signature = le32_to_cpu(image_status->signature); + + return signature != QLA28XX_AUX_IMG_STATUS_SIGN; +} + +static bool +qla27xx_check_image_status_signature(struct qla27xx_image_status *image_status) +{ + ulong signature = le32_to_cpu(image_status->signature); + + return + signature != QLA27XX_IMG_STATUS_SIGN && + signature != QLA28XX_IMG_STATUS_SIGN; +} + +static ulong +qla27xx_image_status_checksum(struct qla27xx_image_status *image_status) +{ + uint32_t *p = (void *)image_status; + uint n = sizeof(*image_status) / sizeof(*p); + uint32_t sum = 0; + + for ( ; n--; p++) + sum += le32_to_cpup(p); + + return sum; +} + +static inline uint +qla28xx_component_bitmask(struct qla27xx_image_status *aux, uint bitmask) +{ + return aux->bitmap & bitmask ? + QLA27XX_SECONDARY_IMAGE : QLA27XX_PRIMARY_IMAGE; +} + +static void +qla28xx_component_status( + struct active_regions *active_regions, struct qla27xx_image_status *aux) +{ + active_regions->aux.board_config = + qla28xx_component_bitmask(aux, QLA28XX_AUX_IMG_BOARD_CONFIG); + + active_regions->aux.vpd_nvram = + qla28xx_component_bitmask(aux, QLA28XX_AUX_IMG_VPD_NVRAM); + + active_regions->aux.npiv_config_0_1 = + qla28xx_component_bitmask(aux, QLA28XX_AUX_IMG_NPIV_CONFIG_0_1); + + active_regions->aux.npiv_config_2_3 = + qla28xx_component_bitmask(aux, QLA28XX_AUX_IMG_NPIV_CONFIG_2_3); +} + +static int +qla27xx_compare_image_generation( + struct qla27xx_image_status *pri_image_status, + struct qla27xx_image_status *sec_image_status) +{ + /* calculate generation delta as uint16 (this accounts for wrap) */ + int16_t delta = + le16_to_cpu(pri_image_status->generation) - + le16_to_cpu(sec_image_status->generation); + + ql_dbg(ql_dbg_init, NULL, 0x0180, "generation delta = %d\n", delta); + + return delta; +} + +void +qla28xx_get_aux_images( + struct scsi_qla_host *vha, struct active_regions *active_regions) { - 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; + struct qla27xx_image_status pri_aux_image_status, sec_aux_image_status; + bool valid_pri_image = false, valid_sec_image = false; + bool active_pri_image = false, active_sec_image = false; + + if (!ha->flt_region_aux_img_status_pri) { + ql_dbg(ql_dbg_init, vha, 0x018a, "Primary aux image not addressed\n"); + goto check_sec_image; + } - valid_pri_image = valid_sec_image = 1; - ha->active_image = 0; - size = sizeof(struct qla27xx_image_status) / sizeof(uint32_t); + qla24xx_read_flash_data(vha, (void *)&pri_aux_image_status, + ha->flt_region_aux_img_status_pri, + sizeof(pri_aux_image_status) >> 2); + qla27xx_print_image(vha, "Primary aux image", &pri_aux_image_status); - if (!ha->flt_region_img_status_pri) { - valid_pri_image = 0; + if (qla28xx_check_aux_image_status_signature(&pri_aux_image_status)) { + ql_dbg(ql_dbg_init, vha, 0x018b, + "Primary aux image signature (%#x) not valid\n", + le32_to_cpu(pri_aux_image_status.signature)); goto check_sec_image; } - qla24xx_read_flash_data(vha, (uint32_t *)(&pri_image_status), - ha->flt_region_img_status_pri, size); + if (qla27xx_image_status_checksum(&pri_aux_image_status)) { + ql_dbg(ql_dbg_init, vha, 0x018c, + "Primary aux image checksum failed\n"); + goto check_sec_image; + } + + valid_pri_image = true; + + if (pri_aux_image_status.image_status_mask & 1) { + ql_dbg(ql_dbg_init, vha, 0x018d, + "Primary aux image is active\n"); + active_pri_image = true; + } + +check_sec_image: + if (!ha->flt_region_aux_img_status_sec) { + ql_dbg(ql_dbg_init, vha, 0x018a, + "Secondary aux image not addressed\n"); + goto check_valid_image; + } + + qla24xx_read_flash_data(vha, (void *)&sec_aux_image_status, + ha->flt_region_aux_img_status_sec, + sizeof(sec_aux_image_status) >> 2); + qla27xx_print_image(vha, "Secondary aux image", &sec_aux_image_status); - if (pri_image_status.signature != QLA27XX_IMG_STATUS_SIGN) { + if (qla28xx_check_aux_image_status_signature(&sec_aux_image_status)) { ql_dbg(ql_dbg_init, vha, 0x018b, - "Primary image signature (0x%x) not valid\n", - pri_image_status.signature); - valid_pri_image = 0; + "Secondary aux image signature (%#x) not valid\n", + le32_to_cpu(sec_aux_image_status.signature)); + goto check_valid_image; + } + + if (qla27xx_image_status_checksum(&sec_aux_image_status)) { + ql_dbg(ql_dbg_init, vha, 0x018c, + "Secondary aux image checksum failed\n"); + goto check_valid_image; + } + + valid_sec_image = true; + + if (sec_aux_image_status.image_status_mask & 1) { + ql_dbg(ql_dbg_init, vha, 0x018d, + "Secondary aux image is active\n"); + active_sec_image = true; + } + +check_valid_image: + if (valid_pri_image && active_pri_image && + valid_sec_image && active_sec_image) { + if (qla27xx_compare_image_generation(&pri_aux_image_status, + &sec_aux_image_status) >= 0) { + qla28xx_component_status(active_regions, + &pri_aux_image_status); + } else { + qla28xx_component_status(active_regions, + &sec_aux_image_status); + } + } else if (valid_pri_image && active_pri_image) { + qla28xx_component_status(active_regions, &pri_aux_image_status); + } else if (valid_sec_image && active_sec_image) { + qla28xx_component_status(active_regions, &sec_aux_image_status); + } + + ql_dbg(ql_dbg_init, vha, 0x018f, + "aux images active: BCFG=%u VPD/NVR=%u NPIV0/1=%u NPIV2/3=%u\n", + active_regions->aux.board_config, + active_regions->aux.vpd_nvram, + active_regions->aux.npiv_config_0_1, + active_regions->aux.npiv_config_2_3); +} + +void +qla27xx_get_active_image(struct scsi_qla_host *vha, + struct active_regions *active_regions) +{ + struct qla_hw_data *ha = vha->hw; + struct qla27xx_image_status pri_image_status, sec_image_status; + bool valid_pri_image = false, valid_sec_image = false; + bool active_pri_image = false, active_sec_image = false; + + if (!ha->flt_region_img_status_pri) { + ql_dbg(ql_dbg_init, vha, 0x018a, "Primary image not addressed\n"); goto check_sec_image; } - wptr = (uint32_t *)(&pri_image_status); - cnt = size; + qla24xx_read_flash_data(vha, (void *)(&pri_image_status), + ha->flt_region_img_status_pri, sizeof(pri_image_status) >> 2); + qla27xx_print_image(vha, "Primary image", &pri_image_status); - for (chksum = 0; cnt--; wptr++) - chksum += le32_to_cpu(*wptr); + if (qla27xx_check_image_status_signature(&pri_image_status)) { + ql_dbg(ql_dbg_init, vha, 0x018b, + "Primary image signature (%#x) not valid\n", + le32_to_cpu(pri_image_status.signature)); + goto check_sec_image; + } - if (chksum) { + if (qla27xx_image_status_checksum(&pri_image_status)) { ql_dbg(ql_dbg_init, vha, 0x018c, - "Checksum validation failed for primary image (0x%x)\n", - chksum); - valid_pri_image = 0; + "Primary image checksum failed\n"); + goto check_sec_image; + } + + valid_pri_image = true; + + if (pri_image_status.image_status_mask & 1) { + ql_dbg(ql_dbg_init, vha, 0x018d, + "Primary image is active\n"); + active_pri_image = true; } check_sec_image: if (!ha->flt_region_img_status_sec) { - valid_sec_image = 0; + ql_dbg(ql_dbg_init, vha, 0x018a, "Secondary image not addressed\n"); goto check_valid_image; } qla24xx_read_flash_data(vha, (uint32_t *)(&sec_image_status), - ha->flt_region_img_status_sec, size); + ha->flt_region_img_status_sec, sizeof(sec_image_status) >> 2); + qla27xx_print_image(vha, "Secondary image", &sec_image_status); - 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; + if (qla27xx_check_image_status_signature(&sec_image_status)) { + ql_dbg(ql_dbg_init, vha, 0x018b, + "Secondary image signature (%#x) not valid\n", + le32_to_cpu(sec_image_status.signature)); 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; + if (qla27xx_image_status_checksum(&sec_image_status)) { + ql_dbg(ql_dbg_init, vha, 0x018c, + "Secondary image checksum failed\n"); + goto check_valid_image; + } + + valid_sec_image = true; + + if (sec_image_status.image_status_mask & 1) { + ql_dbg(ql_dbg_init, vha, 0x018d, + "Secondary image is active\n"); + active_sec_image = true; } 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; + if (valid_pri_image && active_pri_image) + active_regions->global = QLA27XX_PRIMARY_IMAGE; + + if (valid_sec_image && active_sec_image) { + if (!active_regions->global || + qla27xx_compare_image_generation( + &pri_image_status, &sec_image_status) < 0) { + active_regions->global = QLA27XX_SECONDARY_IMAGE; + } } - ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x018f, "%s image\n", - ha->active_image == 0 ? "default bootld and fw" : - ha->active_image == 1 ? "primary" : - ha->active_image == 2 ? "secondary" : - "Invalid"); + ql_dbg(ql_dbg_init, vha, 0x018f, "active image %s (%u)\n", + active_regions->global == QLA27XX_DEFAULT_IMAGE ? + "default (boot/fw)" : + active_regions->global == QLA27XX_PRIMARY_IMAGE ? + "primary" : + active_regions->global == QLA27XX_SECONDARY_IMAGE ? + "secondary" : "invalid", + active_regions->global); +} - return ha->active_image; +bool qla24xx_risc_firmware_invalid(uint32_t *dword) +{ + return + !(dword[4] | dword[5] | dword[6] | dword[7]) || + !(~dword[4] | ~dword[5] | ~dword[6] | ~dword[7]); } static int qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr, uint32_t faddr) { - int rval = QLA_SUCCESS; - int segments, fragment; - uint32_t *dcode, dlen; - uint32_t risc_addr; - uint32_t risc_size; - uint32_t i; + int rval; + uint templates, segments, fragment; + ulong i; + uint j; + ulong dlen; + uint32_t *dcode; + uint32_t risc_addr, risc_size, risc_attr = 0; struct qla_hw_data *ha = vha->hw; struct req_que *req = ha->req_q_map[0]; + struct fwdt *fwdt = ha->fwdt; ql_dbg(ql_dbg_init, vha, 0x008b, "FW: Loading firmware from flash (%x).\n", faddr); - rval = QLA_SUCCESS; - - segments = FA_RISC_CODE_SEGMENTS; - 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++) - dcode[i] = be32_to_cpu(dcode[i]); - if ((dcode[0] == 0xffffffff && dcode[1] == 0xffffffff && - dcode[2] == 0xffffffff && dcode[3] == 0xffffffff) || - (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 && - dcode[3] == 0)) { + dcode = (void *)req->ring; + qla24xx_read_flash_data(vha, dcode, faddr, 8); + if (qla24xx_risc_firmware_invalid(dcode)) { ql_log(ql_log_fatal, vha, 0x008c, "Unable to verify the integrity of flash firmware " "image.\n"); @@ -7337,34 +7650,36 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr, return QLA_FUNCTION_FAILED; } - while (segments && rval == QLA_SUCCESS) { - /* Read segment's load information. */ - qla24xx_read_flash_data(vha, dcode, faddr, 4); - + dcode = (void *)req->ring; + *srisc_addr = 0; + segments = FA_RISC_CODE_SEGMENTS; + for (j = 0; j < segments; j++) { + ql_dbg(ql_dbg_init, vha, 0x008d, + "-> Loading segment %u...\n", j); + qla24xx_read_flash_data(vha, dcode, faddr, 10); risc_addr = be32_to_cpu(dcode[2]); - *srisc_addr = *srisc_addr == 0 ? risc_addr : *srisc_addr; risc_size = be32_to_cpu(dcode[3]); + if (!*srisc_addr) { + *srisc_addr = risc_addr; + risc_attr = be32_to_cpu(dcode[9]); + } - fragment = 0; - while (risc_size > 0 && rval == QLA_SUCCESS) { - dlen = (uint32_t)(ha->fw_transfer_size >> 2); + dlen = ha->fw_transfer_size >> 2; + for (fragment = 0; risc_size; fragment++) { if (dlen > risc_size) dlen = risc_size; ql_dbg(ql_dbg_init, vha, 0x008e, - "Loading risc segment@ risc addr %x " - "number of dwords 0x%x offset 0x%x.\n", - risc_addr, dlen, faddr); - + "-> Loading fragment %u: %#x <- %#x (%#lx dwords)...\n", + fragment, risc_addr, faddr, dlen); qla24xx_read_flash_data(vha, dcode, faddr, dlen); for (i = 0; i < dlen; i++) dcode[i] = swab32(dcode[i]); - rval = qla2x00_load_ram(vha, req->dma, risc_addr, - dlen); + rval = qla2x00_load_ram(vha, req->dma, risc_addr, dlen); if (rval) { ql_log(ql_log_fatal, vha, 0x008f, - "Failed to load segment %d of firmware.\n", + "-> Failed load firmware fragment %u.\n", fragment); return QLA_FUNCTION_FAILED; } @@ -7372,107 +7687,82 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr, faddr += dlen; risc_addr += dlen; risc_size -= dlen; - fragment++; } - - /* Next segment. */ - segments--; } - if (!IS_QLA27XX(ha)) - return rval; + if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) + return QLA_SUCCESS; - if (ha->fw_dump_template) - vfree(ha->fw_dump_template); - ha->fw_dump_template = NULL; - ha->fw_dump_template_len = 0; - - ql_dbg(ql_dbg_init, vha, 0x0161, - "Loading fwdump template from %x\n", faddr); - qla24xx_read_flash_data(vha, dcode, faddr, 7); - risc_size = be32_to_cpu(dcode[2]); - ql_dbg(ql_dbg_init, vha, 0x0162, - "-> array size %x dwords\n", risc_size); - if (risc_size == 0 || risc_size == ~0) - goto default_template; - - dlen = (risc_size - 8) * sizeof(*dcode); - ql_dbg(ql_dbg_init, vha, 0x0163, - "-> template allocating %x bytes...\n", dlen); - ha->fw_dump_template = vmalloc(dlen); - if (!ha->fw_dump_template) { - ql_log(ql_log_warn, vha, 0x0164, - "Failed fwdump template allocate %x bytes.\n", risc_size); - goto default_template; - } - - faddr += 7; - risc_size -= 8; - dcode = ha->fw_dump_template; - qla24xx_read_flash_data(vha, dcode, faddr, risc_size); - for (i = 0; i < risc_size; i++) - dcode[i] = le32_to_cpu(dcode[i]); - - if (!qla27xx_fwdt_template_valid(dcode)) { - ql_log(ql_log_warn, vha, 0x0165, - "Failed fwdump template validate\n"); - goto default_template; - } - - dlen = qla27xx_fwdt_template_size(dcode); - ql_dbg(ql_dbg_init, vha, 0x0166, - "-> template size %x bytes\n", dlen); - if (dlen > risc_size * sizeof(*dcode)) { - ql_log(ql_log_warn, vha, 0x0167, - "Failed fwdump template exceeds array by %zx bytes\n", - (size_t)(dlen - risc_size * sizeof(*dcode))); - goto default_template; - } - ha->fw_dump_template_len = dlen; - return rval; + templates = (risc_attr & BIT_9) ? 2 : 1; + ql_dbg(ql_dbg_init, vha, 0x0160, "-> templates = %u\n", templates); + for (j = 0; j < templates; j++, fwdt++) { + if (fwdt->template) + vfree(fwdt->template); + fwdt->template = NULL; + fwdt->length = 0; + + dcode = (void *)req->ring; + qla24xx_read_flash_data(vha, dcode, faddr, 7); + risc_size = be32_to_cpu(dcode[2]); + ql_dbg(ql_dbg_init, vha, 0x0161, + "-> fwdt%u template array at %#x (%#x dwords)\n", + j, faddr, risc_size); + if (!risc_size || !~risc_size) { + ql_dbg(ql_dbg_init, vha, 0x0162, + "-> fwdt%u failed to read array\n", j); + goto failed; + } -default_template: - ql_log(ql_log_warn, vha, 0x0168, "Using default fwdump template\n"); - if (ha->fw_dump_template) - vfree(ha->fw_dump_template); - ha->fw_dump_template = NULL; - ha->fw_dump_template_len = 0; - - dlen = qla27xx_fwdt_template_default_size(); - ql_dbg(ql_dbg_init, vha, 0x0169, - "-> template allocating %x bytes...\n", dlen); - ha->fw_dump_template = vmalloc(dlen); - if (!ha->fw_dump_template) { - ql_log(ql_log_warn, vha, 0x016a, - "Failed fwdump template allocate %x bytes.\n", risc_size); - goto failed_template; - } - - dcode = ha->fw_dump_template; - risc_size = dlen / sizeof(*dcode); - memcpy(dcode, qla27xx_fwdt_template_default(), dlen); - for (i = 0; i < risc_size; i++) - dcode[i] = be32_to_cpu(dcode[i]); - - if (!qla27xx_fwdt_template_valid(ha->fw_dump_template)) { - ql_log(ql_log_warn, vha, 0x016b, - "Failed fwdump template validate\n"); - goto failed_template; - } - - dlen = qla27xx_fwdt_template_size(ha->fw_dump_template); - ql_dbg(ql_dbg_init, vha, 0x016c, - "-> template size %x bytes\n", dlen); - ha->fw_dump_template_len = dlen; - return rval; + /* skip header and ignore checksum */ + faddr += 7; + risc_size -= 8; + + ql_dbg(ql_dbg_init, vha, 0x0163, + "-> fwdt%u template allocate template %#x words...\n", + j, risc_size); + fwdt->template = vmalloc(risc_size * sizeof(*dcode)); + if (!fwdt->template) { + ql_log(ql_log_warn, vha, 0x0164, + "-> fwdt%u failed allocate template.\n", j); + goto failed; + } -failed_template: - ql_log(ql_log_warn, vha, 0x016d, "Failed default fwdump template\n"); - if (ha->fw_dump_template) - vfree(ha->fw_dump_template); - ha->fw_dump_template = NULL; - ha->fw_dump_template_len = 0; - return rval; + dcode = fwdt->template; + qla24xx_read_flash_data(vha, dcode, faddr, risc_size); + + if (!qla27xx_fwdt_template_valid(dcode)) { + ql_log(ql_log_warn, vha, 0x0165, + "-> fwdt%u failed template validate\n", j); + goto failed; + } + + dlen = qla27xx_fwdt_template_size(dcode); + ql_dbg(ql_dbg_init, vha, 0x0166, + "-> fwdt%u template size %#lx bytes (%#lx words)\n", + j, dlen, dlen / sizeof(*dcode)); + if (dlen > risc_size * sizeof(*dcode)) { + ql_log(ql_log_warn, vha, 0x0167, + "-> fwdt%u template exceeds array (%-lu bytes)\n", + j, dlen - risc_size * sizeof(*dcode)); + goto failed; + } + + fwdt->length = dlen; + ql_dbg(ql_dbg_init, vha, 0x0168, + "-> fwdt%u loaded template ok\n", j); + + faddr += risc_size + 1; + } + + return QLA_SUCCESS; + +failed: + if (fwdt->template) + vfree(fwdt->template); + fwdt->template = NULL; + fwdt->length = 0; + + return QLA_SUCCESS; } #define QLA_FW_URL "http://ldriver.qlogic.com/firmware/" @@ -7580,94 +7870,73 @@ static int qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr) { int rval; - int segments, fragment; - uint32_t *dcode, dlen; - uint32_t risc_addr; - uint32_t risc_size; - uint32_t i; + uint templates, segments, fragment; + uint32_t *dcode; + ulong dlen; + uint32_t risc_addr, risc_size, risc_attr = 0; + ulong i; + uint j; struct fw_blob *blob; - const uint32_t *fwcode; - uint32_t fwclen; + uint32_t *fwcode; struct qla_hw_data *ha = vha->hw; struct req_que *req = ha->req_q_map[0]; + struct fwdt *fwdt = ha->fwdt; + + ql_dbg(ql_dbg_init, vha, 0x0090, + "-> FW: Loading via request-firmware.\n"); - /* Load firmware blob. */ blob = qla2x00_request_firmware(vha); if (!blob) { - ql_log(ql_log_warn, vha, 0x0090, - "Firmware image unavailable.\n"); - ql_log(ql_log_warn, vha, 0x0091, - "Firmware images can be retrieved from: " - QLA_FW_URL ".\n"); + ql_log(ql_log_warn, vha, 0x0092, + "-> Firmware file not found.\n"); return QLA_FUNCTION_FAILED; } - ql_dbg(ql_dbg_init, vha, 0x0092, - "FW: Loading via request-firmware.\n"); - - rval = QLA_SUCCESS; - - segments = FA_RISC_CODE_SEGMENTS; - dcode = (uint32_t *)req->ring; - *srisc_addr = 0; - fwcode = (uint32_t *)blob->fw->data; - fwclen = 0; - - /* Validate firmware image by checking version. */ - if (blob->fw->size < 8 * sizeof(uint32_t)) { + fwcode = (void *)blob->fw->data; + dcode = fwcode; + if (qla24xx_risc_firmware_invalid(dcode)) { ql_log(ql_log_fatal, vha, 0x0093, "Unable to verify integrity of firmware image (%zd).\n", blob->fw->size); - return QLA_FUNCTION_FAILED; - } - for (i = 0; i < 4; i++) - dcode[i] = be32_to_cpu(fwcode[i + 4]); - if ((dcode[0] == 0xffffffff && dcode[1] == 0xffffffff && - dcode[2] == 0xffffffff && dcode[3] == 0xffffffff) || - (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 && - dcode[3] == 0)) { - ql_log(ql_log_fatal, vha, 0x0094, - "Unable to verify integrity of firmware image (%zd).\n", - blob->fw->size); ql_log(ql_log_fatal, vha, 0x0095, "Firmware data: %08x %08x %08x %08x.\n", dcode[0], dcode[1], dcode[2], dcode[3]); return QLA_FUNCTION_FAILED; } - while (segments && rval == QLA_SUCCESS) { + dcode = (void *)req->ring; + *srisc_addr = 0; + segments = FA_RISC_CODE_SEGMENTS; + for (j = 0; j < segments; j++) { + ql_dbg(ql_dbg_init, vha, 0x0096, + "-> Loading segment %u...\n", j); risc_addr = be32_to_cpu(fwcode[2]); - *srisc_addr = *srisc_addr == 0 ? risc_addr : *srisc_addr; risc_size = be32_to_cpu(fwcode[3]); - /* Validate firmware image size. */ - fwclen += risc_size * sizeof(uint32_t); - if (blob->fw->size < fwclen) { - ql_log(ql_log_fatal, vha, 0x0096, - "Unable to verify integrity of firmware image " - "(%zd).\n", blob->fw->size); - return QLA_FUNCTION_FAILED; + if (!*srisc_addr) { + *srisc_addr = risc_addr; + risc_attr = be32_to_cpu(fwcode[9]); } - fragment = 0; - while (risc_size > 0 && rval == QLA_SUCCESS) { - dlen = (uint32_t)(ha->fw_transfer_size >> 2); + dlen = ha->fw_transfer_size >> 2; + for (fragment = 0; risc_size; fragment++) { if (dlen > risc_size) dlen = risc_size; ql_dbg(ql_dbg_init, vha, 0x0097, - "Loading risc segment@ risc addr %x " - "number of dwords 0x%x.\n", risc_addr, dlen); + "-> Loading fragment %u: %#x <- %#x (%#lx words)...\n", + fragment, risc_addr, + (uint32_t)(fwcode - (typeof(fwcode))blob->fw->data), + dlen); for (i = 0; i < dlen; i++) dcode[i] = swab32(fwcode[i]); - rval = qla2x00_load_ram(vha, req->dma, risc_addr, - dlen); + rval = qla2x00_load_ram(vha, req->dma, risc_addr, dlen); if (rval) { ql_log(ql_log_fatal, vha, 0x0098, - "Failed to load segment %d of firmware.\n", + "-> Failed load firmware fragment %u.\n", fragment); return QLA_FUNCTION_FAILED; } @@ -7675,106 +7944,82 @@ qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr) fwcode += dlen; risc_addr += dlen; risc_size -= dlen; - fragment++; } - - /* Next segment. */ - segments--; } - if (!IS_QLA27XX(ha)) - return rval; + if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) + return QLA_SUCCESS; - if (ha->fw_dump_template) - vfree(ha->fw_dump_template); - ha->fw_dump_template = NULL; - ha->fw_dump_template_len = 0; - - ql_dbg(ql_dbg_init, vha, 0x171, - "Loading fwdump template from %x\n", - (uint32_t)((void *)fwcode - (void *)blob->fw->data)); - risc_size = be32_to_cpu(fwcode[2]); - ql_dbg(ql_dbg_init, vha, 0x172, - "-> array size %x dwords\n", risc_size); - if (risc_size == 0 || risc_size == ~0) - goto default_template; - - dlen = (risc_size - 8) * sizeof(*fwcode); - ql_dbg(ql_dbg_init, vha, 0x0173, - "-> template allocating %x bytes...\n", dlen); - ha->fw_dump_template = vmalloc(dlen); - if (!ha->fw_dump_template) { - ql_log(ql_log_warn, vha, 0x0174, - "Failed fwdump template allocate %x bytes.\n", risc_size); - goto default_template; - } - - fwcode += 7; - risc_size -= 8; - dcode = ha->fw_dump_template; - for (i = 0; i < risc_size; i++) - dcode[i] = le32_to_cpu(fwcode[i]); - - if (!qla27xx_fwdt_template_valid(dcode)) { - ql_log(ql_log_warn, vha, 0x0175, - "Failed fwdump template validate\n"); - goto default_template; - } - - dlen = qla27xx_fwdt_template_size(dcode); - ql_dbg(ql_dbg_init, vha, 0x0176, - "-> template size %x bytes\n", dlen); - if (dlen > risc_size * sizeof(*fwcode)) { - ql_log(ql_log_warn, vha, 0x0177, - "Failed fwdump template exceeds array by %zx bytes\n", - (size_t)(dlen - risc_size * sizeof(*fwcode))); - goto default_template; - } - ha->fw_dump_template_len = dlen; - return rval; + templates = (risc_attr & BIT_9) ? 2 : 1; + ql_dbg(ql_dbg_init, vha, 0x0170, "-> templates = %u\n", templates); + for (j = 0; j < templates; j++, fwdt++) { + if (fwdt->template) + vfree(fwdt->template); + fwdt->template = NULL; + fwdt->length = 0; + + risc_size = be32_to_cpu(fwcode[2]); + ql_dbg(ql_dbg_init, vha, 0x0171, + "-> fwdt%u template array at %#x (%#x dwords)\n", + j, (uint32_t)((void *)fwcode - (void *)blob->fw->data), + risc_size); + if (!risc_size || !~risc_size) { + ql_dbg(ql_dbg_init, vha, 0x0172, + "-> fwdt%u failed to read array\n", j); + goto failed; + } -default_template: - ql_log(ql_log_warn, vha, 0x0178, "Using default fwdump template\n"); - if (ha->fw_dump_template) - vfree(ha->fw_dump_template); - ha->fw_dump_template = NULL; - ha->fw_dump_template_len = 0; - - dlen = qla27xx_fwdt_template_default_size(); - ql_dbg(ql_dbg_init, vha, 0x0179, - "-> template allocating %x bytes...\n", dlen); - ha->fw_dump_template = vmalloc(dlen); - if (!ha->fw_dump_template) { - ql_log(ql_log_warn, vha, 0x017a, - "Failed fwdump template allocate %x bytes.\n", risc_size); - goto failed_template; - } - - dcode = ha->fw_dump_template; - risc_size = dlen / sizeof(*fwcode); - fwcode = qla27xx_fwdt_template_default(); - for (i = 0; i < risc_size; i++) - dcode[i] = be32_to_cpu(fwcode[i]); - - if (!qla27xx_fwdt_template_valid(ha->fw_dump_template)) { - ql_log(ql_log_warn, vha, 0x017b, - "Failed fwdump template validate\n"); - goto failed_template; - } - - dlen = qla27xx_fwdt_template_size(ha->fw_dump_template); - ql_dbg(ql_dbg_init, vha, 0x017c, - "-> template size %x bytes\n", dlen); - ha->fw_dump_template_len = dlen; - return rval; + /* skip header and ignore checksum */ + fwcode += 7; + risc_size -= 8; + + ql_dbg(ql_dbg_init, vha, 0x0173, + "-> fwdt%u template allocate template %#x words...\n", + j, risc_size); + fwdt->template = vmalloc(risc_size * sizeof(*dcode)); + if (!fwdt->template) { + ql_log(ql_log_warn, vha, 0x0174, + "-> fwdt%u failed allocate template.\n", j); + goto failed; + } -failed_template: - ql_log(ql_log_warn, vha, 0x017d, "Failed default fwdump template\n"); - if (ha->fw_dump_template) - vfree(ha->fw_dump_template); - ha->fw_dump_template = NULL; - ha->fw_dump_template_len = 0; - return rval; + dcode = fwdt->template; + for (i = 0; i < risc_size; i++) + dcode[i] = fwcode[i]; + + if (!qla27xx_fwdt_template_valid(dcode)) { + ql_log(ql_log_warn, vha, 0x0175, + "-> fwdt%u failed template validate\n", j); + goto failed; + } + + dlen = qla27xx_fwdt_template_size(dcode); + ql_dbg(ql_dbg_init, vha, 0x0176, + "-> fwdt%u template size %#lx bytes (%#lx words)\n", + j, dlen, dlen / sizeof(*dcode)); + if (dlen > risc_size * sizeof(*dcode)) { + ql_log(ql_log_warn, vha, 0x0177, + "-> fwdt%u template exceeds array (%-lu bytes)\n", + j, dlen - risc_size * sizeof(*dcode)); + goto failed; + } + + fwdt->length = dlen; + ql_dbg(ql_dbg_init, vha, 0x0178, + "-> fwdt%u loaded template ok\n", j); + + fwcode += risc_size + 1; + } + + return QLA_SUCCESS; + +failed: + if (fwdt->template) + vfree(fwdt->template); + fwdt->template = NULL; + fwdt->length = 0; + + return QLA_SUCCESS; } int @@ -7803,32 +8048,50 @@ qla81xx_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr) { int rval; struct qla_hw_data *ha = vha->hw; + struct active_regions active_regions = { }; if (ql2xfwloadbin == 2) goto try_blob_fw; - /* - * FW Load priority: + /* FW Load priority: * 1) Firmware residing in flash. * 2) Firmware via request-firmware interface (.bin file). - * 3) Golden-Firmware residing in flash -- limited operation. + * 3) Golden-Firmware residing in flash -- (limited operation). */ + + if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) + goto try_primary_fw; + + qla27xx_get_active_image(vha, &active_regions); + + if (active_regions.global != QLA27XX_SECONDARY_IMAGE) + goto try_primary_fw; + + ql_dbg(ql_dbg_init, vha, 0x008b, + "Loading secondary firmware image.\n"); + rval = qla24xx_load_risc_flash(vha, srisc_addr, ha->flt_region_fw_sec); + if (!rval) + return rval; + +try_primary_fw: + ql_dbg(ql_dbg_init, vha, 0x008b, + "Loading primary firmware image.\n"); rval = qla24xx_load_risc_flash(vha, srisc_addr, ha->flt_region_fw); - if (rval == QLA_SUCCESS) + if (!rval) return rval; try_blob_fw: rval = qla24xx_load_risc_blob(vha, srisc_addr); - if (rval == QLA_SUCCESS || !ha->flt_region_gold_fw) + if (!rval || !ha->flt_region_gold_fw) return rval; ql_log(ql_log_info, vha, 0x0099, "Attempting to fallback to golden firmware.\n"); rval = qla24xx_load_risc_flash(vha, srisc_addr, ha->flt_region_gold_fw); - if (rval != QLA_SUCCESS) + if (rval) return rval; - ql_log(ql_log_info, vha, 0x009a, "Update operational firmware.\n"); + ql_log(ql_log_info, vha, 0x009a, "Need firmware flash update.\n"); ha->flags.running_gold_fw = 1; return rval; } @@ -7963,6 +8226,7 @@ void qla84xx_put_chip(struct scsi_qla_host *vha) { struct qla_hw_data *ha = vha->hw; + if (ha->cs84xx) kref_put(&ha->cs84xx->kref, __qla84xx_chip_release); } @@ -7980,7 +8244,7 @@ qla84xx_init_chip(scsi_qla_host_t *vha) mutex_unlock(&ha->cs84xx->fw_update_mutex); - return rval != QLA_SUCCESS || status[0] ? QLA_FUNCTION_FAILED: + return rval != QLA_SUCCESS || status[0] ? QLA_FUNCTION_FAILED : QLA_SUCCESS; } @@ -7997,25 +8261,48 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) uint32_t chksum; uint16_t cnt; struct qla_hw_data *ha = vha->hw; + uint32_t faddr; + struct active_regions active_regions = { }; rval = QLA_SUCCESS; icb = (struct init_cb_81xx *)ha->init_cb; nv = ha->nvram; /* Determine NVRAM starting address. */ - ha->nvram_size = sizeof(struct nvram_81xx); + ha->nvram_size = sizeof(*nv); ha->vpd_size = FA_NVRAM_VPD_SIZE; if (IS_P3P_TYPE(ha) || IS_QLA8031(ha)) ha->vpd_size = FA_VPD_SIZE_82XX; + if (IS_QLA28XX(ha) || IS_QLA27XX(ha)) + qla28xx_get_aux_images(vha, &active_regions); + /* Get VPD data into cache */ ha->vpd = ha->nvram + VPD_OFFSET; - ha->isp_ops->read_optrom(vha, ha->vpd, ha->flt_region_vpd << 2, - ha->vpd_size); + + faddr = ha->flt_region_vpd; + if (IS_QLA28XX(ha)) { + if (active_regions.aux.vpd_nvram == QLA27XX_SECONDARY_IMAGE) + faddr = ha->flt_region_vpd_sec; + ql_dbg(ql_dbg_init, vha, 0x0110, + "Loading %s nvram image.\n", + active_regions.aux.vpd_nvram == QLA27XX_PRIMARY_IMAGE ? + "primary" : "secondary"); + } + qla24xx_read_flash_data(vha, ha->vpd, faddr, ha->vpd_size >> 2); /* Get NVRAM data into cache and calculate checksum. */ - ha->isp_ops->read_optrom(vha, ha->nvram, ha->flt_region_nvram << 2, - ha->nvram_size); + faddr = ha->flt_region_nvram; + if (IS_QLA28XX(ha)) { + if (active_regions.aux.vpd_nvram == QLA27XX_SECONDARY_IMAGE) + faddr = ha->flt_region_nvram_sec; + } + ql_dbg(ql_dbg_init, vha, 0x0110, + "Loading %s nvram image.\n", + active_regions.aux.vpd_nvram == QLA27XX_PRIMARY_IMAGE ? + "primary" : "secondary"); + qla24xx_read_flash_data(vha, ha->nvram, faddr, ha->nvram_size >> 2); + dptr = (uint32_t *)nv; for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++, dptr++) chksum += le32_to_cpu(*dptr); @@ -8023,17 +8310,16 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) ql_dbg(ql_dbg_init + ql_dbg_buffer, vha, 0x0111, "Contents of NVRAM:\n"); ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0112, - (uint8_t *)nv, ha->nvram_size); + nv, ha->nvram_size); /* Bad NVRAM data, set defaults parameters. */ - if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' || nv->id[2] != 'P' - || nv->id[3] != ' ' || - nv->nvram_version < cpu_to_le16(ICB_VERSION)) { + if (chksum || memcmp("ISP ", nv->id, sizeof(nv->id)) || + le16_to_cpu(nv->nvram_version) < ICB_VERSION) { /* Reset NVRAM data. */ ql_log(ql_log_info, vha, 0x0073, - "Inconsistent NVRAM detected: checksum=0x%x id=%c " - "version=0x%x.\n", chksum, nv->id[0], - le16_to_cpu(nv->nvram_version)); + "Inconsistent NVRAM checksum=%#x id=%.4s version=%#x.\n", + chksum, nv->id, le16_to_cpu(nv->nvram_version)); + ql_dump_buffer(ql_dbg_init, vha, 0x0073, nv, sizeof(*nv)); ql_log(ql_log_info, vha, 0x0074, "Falling back to functioning (yet invalid -- WWPN) " "defaults.\n"); @@ -8154,11 +8440,11 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) ha->flags.disable_risc_code_load = 0; ha->flags.enable_lip_reset = 0; ha->flags.enable_lip_full_login = - le32_to_cpu(nv->host_p) & BIT_10 ? 1: 0; + le32_to_cpu(nv->host_p) & BIT_10 ? 1 : 0; ha->flags.enable_target_reset = - le32_to_cpu(nv->host_p) & BIT_11 ? 1: 0; + le32_to_cpu(nv->host_p) & BIT_11 ? 1 : 0; ha->flags.enable_led_scheme = 0; - ha->flags.disable_serdes = le32_to_cpu(nv->host_p) & BIT_5 ? 1: 0; + ha->flags.disable_serdes = le32_to_cpu(nv->host_p) & BIT_5 ? 1 : 0; ha->operating_mode = (le32_to_cpu(icb->firmware_options_2) & (BIT_6 | BIT_5 | BIT_4)) >> 4; @@ -8222,7 +8508,8 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) ha->login_retry_count = ql2xloginretrycount; /* if not running MSI-X we need handshaking on interrupts */ - if (!vha->hw->flags.msix_enabled && (IS_QLA83XX(ha) || IS_QLA27XX(ha))) + if (!vha->hw->flags.msix_enabled && + (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))) icb->firmware_options_2 |= cpu_to_le32(BIT_22); /* Enable ZIO. */ @@ -8230,7 +8517,7 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) ha->zio_mode = le32_to_cpu(icb->firmware_options_2) & (BIT_3 | BIT_2 | BIT_1 | BIT_0); ha->zio_timer = le16_to_cpu(icb->interrupt_delay_timer) ? - le16_to_cpu(icb->interrupt_delay_timer): 2; + le16_to_cpu(icb->interrupt_delay_timer) : 2; } icb->firmware_options_2 &= cpu_to_le32( ~(BIT_3 | BIT_2 | BIT_1 | BIT_0)); @@ -8255,12 +8542,6 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) /* N2N: driver will initiate Login instead of FW */ icb->firmware_options_3 |= BIT_8; - if (IS_QLA27XX(ha)) { - icb->firmware_options_3 |= BIT_8; - ql_dbg(ql_log_info, vha, 0x0075, - "Enabling direct connection.\n"); - } - if (rval) { ql_log(ql_log_warn, vha, 0x0076, "NVRAM configuration failed.\n"); @@ -8621,7 +8902,6 @@ struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha, int qos, "Failed to allocate memory for queue pair.\n"); return NULL; } - memset(qpair, 0, sizeof(struct qla_qpair)); qpair->hw = vha->hw; qpair->vha = vha; @@ -8668,7 +8948,7 @@ struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha, int qos, qpair->msix->in_use = 1; list_add_tail(&qpair->qp_list_elem, &vha->qp_list); qpair->pdev = ha->pdev; - if (IS_QLA27XX(ha) || IS_QLA83XX(ha)) + if (IS_QLA27XX(ha) || IS_QLA83XX(ha) || IS_QLA28XX(ha)) qpair->reqq_start_iocbs = qla_83xx_start_iocbs; mutex_unlock(&ha->mq_lock); diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h index 512c3c37b447..bf063c664352 100644 --- a/drivers/scsi/qla2xxx/qla_inline.h +++ b/drivers/scsi/qla2xxx/qla_inline.h @@ -91,43 +91,6 @@ host_to_adap(uint8_t *src, uint8_t *dst, uint32_t bsize) } static inline void -qla2x00_set_reserved_loop_ids(struct qla_hw_data *ha) -{ - int i; - - if (IS_FWI2_CAPABLE(ha)) - return; - - for (i = 0; i < SNS_FIRST_LOOP_ID; i++) - set_bit(i, ha->loop_id_map); - set_bit(MANAGEMENT_SERVER, ha->loop_id_map); - set_bit(BROADCAST, ha->loop_id_map); -} - -static inline int -qla2x00_is_reserved_id(scsi_qla_host_t *vha, uint16_t loop_id) -{ - struct qla_hw_data *ha = vha->hw; - if (IS_FWI2_CAPABLE(ha)) - return (loop_id > NPH_LAST_HANDLE); - - return ((loop_id > ha->max_loop_id && loop_id < SNS_FIRST_LOOP_ID) || - loop_id == MANAGEMENT_SERVER || loop_id == BROADCAST); -} - -static inline void -qla2x00_clear_loop_id(fc_port_t *fcport) { - struct qla_hw_data *ha = fcport->vha->hw; - - if (fcport->loop_id == FC_NO_LOOP_ID || - qla2x00_is_reserved_id(fcport->vha, fcport->loop_id)) - return; - - clear_bit(fcport->loop_id, ha->loop_id_map); - fcport->loop_id = FC_NO_LOOP_ID; -} - -static inline void qla2x00_clean_dsd_pool(struct qla_hw_data *ha, struct crc_context *ctx) { struct dsd_dma *dsd, *tdsd; @@ -142,25 +105,6 @@ qla2x00_clean_dsd_pool(struct qla_hw_data *ha, struct crc_context *ctx) INIT_LIST_HEAD(&ctx->dsd_list); } -static inline void -qla2x00_set_fcport_state(fc_port_t *fcport, int state) -{ - int old_state; - - old_state = atomic_read(&fcport->state); - atomic_set(&fcport->state, state); - - /* Don't print state transitions during initial allocation of fcport */ - if (old_state && old_state != state) { - ql_dbg(ql_dbg_disc, fcport->vha, 0x207d, - "FCPort %8phC state transitioned from %s to %s - " - "portid=%02x%02x%02x.\n", fcport->port_name, - port_state_str[old_state], port_state_str[state], - fcport->d_id.b.domain, fcport->d_id.b.area, - fcport->d_id.b.al_pa); - } -} - static inline int qla2x00_hba_err_chk_enabled(srb_t *sp) { @@ -240,6 +184,7 @@ done: static inline void qla2xxx_rel_qpair_sp(struct qla_qpair *qpair, srb_t *sp) { + sp->qpair = NULL; mempool_free(sp, qpair->srb_mempool); QLA_QPAIR_MARK_NOT_BUSY(qpair); } @@ -274,18 +219,6 @@ qla2x00_rel_sp(srb_t *sp) qla2xxx_rel_qpair_sp(sp->qpair, sp); } -static inline void -qla2x00_init_timer(srb_t *sp, unsigned long tmo) -{ - timer_setup(&sp->u.iocb_cmd.timer, qla2x00_sp_timeout, 0); - sp->u.iocb_cmd.timer.expires = jiffies + tmo * HZ; - sp->free = qla2x00_sp_free; - init_completion(&sp->comp); - if (IS_QLAFX00(sp->vha->hw) && (sp->type == SRB_FXIOCB_DCMD)) - init_completion(&sp->u.iocb_cmd.u.fxiocb.fxiocb_comp); - add_timer(&sp->u.iocb_cmd.timer); -} - static inline int qla2x00_gid_list_size(struct qla_hw_data *ha) { diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 456a41d2e2c6..9312b19ed708 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -107,7 +107,7 @@ qla2x00_prep_cont_type0_iocb(struct scsi_qla_host *vha) cont_pkt = (cont_entry_t *)req->ring_ptr; /* Load packet defaults. */ - *((uint32_t *)(&cont_pkt->entry_type)) = cpu_to_le32(CONTINUE_TYPE); + put_unaligned_le32(CONTINUE_TYPE, &cont_pkt->entry_type); return (cont_pkt); } @@ -136,9 +136,8 @@ qla2x00_prep_cont_type1_iocb(scsi_qla_host_t *vha, struct req_que *req) cont_pkt = (cont_a64_entry_t *)req->ring_ptr; /* Load packet defaults. */ - *((uint32_t *)(&cont_pkt->entry_type)) = IS_QLAFX00(vha->hw) ? - cpu_to_le32(CONTINUE_A64_TYPE_FX00) : - cpu_to_le32(CONTINUE_A64_TYPE); + put_unaligned_le32(IS_QLAFX00(vha->hw) ? CONTINUE_A64_TYPE_FX00 : + CONTINUE_A64_TYPE, &cont_pkt->entry_type); return (cont_pkt); } @@ -193,7 +192,7 @@ void qla2x00_build_scsi_iocbs_32(srb_t *sp, cmd_entry_t *cmd_pkt, uint16_t tot_dsds) { uint16_t avail_dsds; - uint32_t *cur_dsd; + struct dsd32 *cur_dsd; scsi_qla_host_t *vha; struct scsi_cmnd *cmd; struct scatterlist *sg; @@ -202,8 +201,7 @@ void qla2x00_build_scsi_iocbs_32(srb_t *sp, cmd_entry_t *cmd_pkt, cmd = GET_CMD_SP(sp); /* Update entry type to indicate Command Type 2 IOCB */ - *((uint32_t *)(&cmd_pkt->entry_type)) = - cpu_to_le32(COMMAND_TYPE); + put_unaligned_le32(COMMAND_TYPE, &cmd_pkt->entry_type); /* No data transfer */ if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) { @@ -215,8 +213,8 @@ void qla2x00_build_scsi_iocbs_32(srb_t *sp, cmd_entry_t *cmd_pkt, cmd_pkt->control_flags |= cpu_to_le16(qla2x00_get_cmd_direction(sp)); /* Three DSDs are available in the Command Type 2 IOCB */ - avail_dsds = 3; - cur_dsd = (uint32_t *)&cmd_pkt->dseg_0_address; + avail_dsds = ARRAY_SIZE(cmd_pkt->dsd32); + cur_dsd = cmd_pkt->dsd32; /* Load data segments */ scsi_for_each_sg(cmd, sg, tot_dsds, i) { @@ -229,12 +227,11 @@ void qla2x00_build_scsi_iocbs_32(srb_t *sp, cmd_entry_t *cmd_pkt, * Type 0 IOCB. */ cont_pkt = qla2x00_prep_cont_type0_iocb(vha); - cur_dsd = (uint32_t *)&cont_pkt->dseg_0_address; - avail_dsds = 7; + cur_dsd = cont_pkt->dsd; + avail_dsds = ARRAY_SIZE(cont_pkt->dsd); } - *cur_dsd++ = cpu_to_le32(sg_dma_address(sg)); - *cur_dsd++ = cpu_to_le32(sg_dma_len(sg)); + append_dsd32(&cur_dsd, sg); avail_dsds--; } } @@ -251,7 +248,7 @@ void qla2x00_build_scsi_iocbs_64(srb_t *sp, cmd_entry_t *cmd_pkt, uint16_t tot_dsds) { uint16_t avail_dsds; - uint32_t *cur_dsd; + struct dsd64 *cur_dsd; scsi_qla_host_t *vha; struct scsi_cmnd *cmd; struct scatterlist *sg; @@ -260,7 +257,7 @@ void qla2x00_build_scsi_iocbs_64(srb_t *sp, cmd_entry_t *cmd_pkt, cmd = GET_CMD_SP(sp); /* Update entry type to indicate Command Type 3 IOCB */ - *((uint32_t *)(&cmd_pkt->entry_type)) = cpu_to_le32(COMMAND_A64_TYPE); + put_unaligned_le32(COMMAND_A64_TYPE, &cmd_pkt->entry_type); /* No data transfer */ if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) { @@ -272,12 +269,11 @@ void qla2x00_build_scsi_iocbs_64(srb_t *sp, cmd_entry_t *cmd_pkt, cmd_pkt->control_flags |= cpu_to_le16(qla2x00_get_cmd_direction(sp)); /* Two DSDs are available in the Command Type 3 IOCB */ - avail_dsds = 2; - cur_dsd = (uint32_t *)&cmd_pkt->dseg_0_address; + avail_dsds = ARRAY_SIZE(cmd_pkt->dsd64); + cur_dsd = cmd_pkt->dsd64; /* Load data segments */ scsi_for_each_sg(cmd, sg, tot_dsds, i) { - dma_addr_t sle_dma; cont_a64_entry_t *cont_pkt; /* Allocate additional continuation packets? */ @@ -287,14 +283,11 @@ void qla2x00_build_scsi_iocbs_64(srb_t *sp, cmd_entry_t *cmd_pkt, * Type 1 IOCB. */ cont_pkt = qla2x00_prep_cont_type1_iocb(vha, vha->req); - cur_dsd = (uint32_t *)cont_pkt->dseg_0_address; - avail_dsds = 5; + cur_dsd = cont_pkt->dsd; + avail_dsds = ARRAY_SIZE(cont_pkt->dsd); } - sle_dma = sg_dma_address(sg); - *cur_dsd++ = cpu_to_le32(LSD(sle_dma)); - *cur_dsd++ = cpu_to_le32(MSD(sle_dma)); - *cur_dsd++ = cpu_to_le32(sg_dma_len(sg)); + append_dsd64(&cur_dsd, sg); avail_dsds--; } } @@ -467,7 +460,7 @@ qla2x00_start_iocbs(struct scsi_qla_host *vha, struct req_que *req) req->ring_ptr++; /* Set chip new ring index. */ - if (ha->mqenable || IS_QLA27XX(ha)) { + if (ha->mqenable || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { WRT_REG_DWORD(req->req_q_in, req->ring_index); } else if (IS_QLA83XX(ha)) { WRT_REG_DWORD(req->req_q_in, req->ring_index); @@ -580,13 +573,11 @@ static inline int qla24xx_build_scsi_type_6_iocbs(srb_t *sp, struct cmd_type_6 *cmd_pkt, uint16_t tot_dsds) { - uint32_t *cur_dsd = NULL; + struct dsd64 *cur_dsd = NULL, *next_dsd; scsi_qla_host_t *vha; struct qla_hw_data *ha; struct scsi_cmnd *cmd; struct scatterlist *cur_seg; - uint32_t *dsd_seg; - void *next_dsd; uint8_t avail_dsds; uint8_t first_iocb = 1; uint32_t dsd_list_len; @@ -596,7 +587,7 @@ qla24xx_build_scsi_type_6_iocbs(srb_t *sp, struct cmd_type_6 *cmd_pkt, cmd = GET_CMD_SP(sp); /* Update entry type to indicate Command Type 3 IOCB */ - *((uint32_t *)(&cmd_pkt->entry_type)) = cpu_to_le32(COMMAND_TYPE_6); + put_unaligned_le32(COMMAND_TYPE_6, &cmd_pkt->entry_type); /* No data transfer */ if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) { @@ -638,32 +629,27 @@ qla24xx_build_scsi_type_6_iocbs(srb_t *sp, struct cmd_type_6 *cmd_pkt, if (first_iocb) { first_iocb = 0; - dsd_seg = (uint32_t *)&cmd_pkt->fcp_data_dseg_address; - *dsd_seg++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma)); - *dsd_seg++ = cpu_to_le32(MSD(dsd_ptr->dsd_list_dma)); - cmd_pkt->fcp_data_dseg_len = cpu_to_le32(dsd_list_len); + put_unaligned_le64(dsd_ptr->dsd_list_dma, + &cmd_pkt->fcp_dsd.address); + cmd_pkt->fcp_dsd.length = cpu_to_le32(dsd_list_len); } else { - *cur_dsd++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma)); - *cur_dsd++ = cpu_to_le32(MSD(dsd_ptr->dsd_list_dma)); - *cur_dsd++ = cpu_to_le32(dsd_list_len); + put_unaligned_le64(dsd_ptr->dsd_list_dma, + &cur_dsd->address); + cur_dsd->length = cpu_to_le32(dsd_list_len); + cur_dsd++; } - cur_dsd = (uint32_t *)next_dsd; + cur_dsd = next_dsd; while (avail_dsds) { - dma_addr_t sle_dma; - - sle_dma = sg_dma_address(cur_seg); - *cur_dsd++ = cpu_to_le32(LSD(sle_dma)); - *cur_dsd++ = cpu_to_le32(MSD(sle_dma)); - *cur_dsd++ = cpu_to_le32(sg_dma_len(cur_seg)); + append_dsd64(&cur_dsd, cur_seg); cur_seg = sg_next(cur_seg); avail_dsds--; } } /* Null termination */ - *cur_dsd++ = 0; - *cur_dsd++ = 0; - *cur_dsd++ = 0; + cur_dsd->address = 0; + cur_dsd->length = 0; + cur_dsd++; cmd_pkt->control_flags |= CF_DATA_SEG_DESCR_ENABLE; return 0; } @@ -702,7 +688,7 @@ qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt, uint16_t tot_dsds, struct req_que *req) { uint16_t avail_dsds; - uint32_t *cur_dsd; + struct dsd64 *cur_dsd; scsi_qla_host_t *vha; struct scsi_cmnd *cmd; struct scatterlist *sg; @@ -711,7 +697,7 @@ qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt, cmd = GET_CMD_SP(sp); /* Update entry type to indicate Command Type 3 IOCB */ - *((uint32_t *)(&cmd_pkt->entry_type)) = cpu_to_le32(COMMAND_TYPE_7); + put_unaligned_le32(COMMAND_TYPE_7, &cmd_pkt->entry_type); /* No data transfer */ if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) { @@ -734,12 +720,11 @@ qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt, /* One DSD is available in the Command Type 3 IOCB */ avail_dsds = 1; - cur_dsd = (uint32_t *)&cmd_pkt->dseg_0_address; + cur_dsd = &cmd_pkt->dsd; /* Load data segments */ scsi_for_each_sg(cmd, sg, tot_dsds, i) { - dma_addr_t sle_dma; cont_a64_entry_t *cont_pkt; /* Allocate additional continuation packets? */ @@ -749,14 +734,11 @@ qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt, * Type 1 IOCB. */ cont_pkt = qla2x00_prep_cont_type1_iocb(vha, req); - cur_dsd = (uint32_t *)cont_pkt->dseg_0_address; - avail_dsds = 5; + cur_dsd = cont_pkt->dsd; + avail_dsds = ARRAY_SIZE(cont_pkt->dsd); } - sle_dma = sg_dma_address(sg); - *cur_dsd++ = cpu_to_le32(LSD(sle_dma)); - *cur_dsd++ = cpu_to_le32(MSD(sle_dma)); - *cur_dsd++ = cpu_to_le32(sg_dma_len(sg)); + append_dsd64(&cur_dsd, sg); avail_dsds--; } } @@ -892,14 +874,14 @@ qla24xx_get_one_block_sg(uint32_t blk_sz, struct qla2_sgx *sgx, int qla24xx_walk_and_build_sglist_no_difb(struct qla_hw_data *ha, srb_t *sp, - uint32_t *dsd, uint16_t tot_dsds, struct qla_tc_param *tc) + struct dsd64 *dsd, uint16_t tot_dsds, struct qla_tc_param *tc) { void *next_dsd; uint8_t avail_dsds = 0; uint32_t dsd_list_len; struct dsd_dma *dsd_ptr; struct scatterlist *sg_prot; - uint32_t *cur_dsd = dsd; + struct dsd64 *cur_dsd = dsd; uint16_t used_dsds = tot_dsds; uint32_t prot_int; /* protection interval */ uint32_t partial; @@ -973,14 +955,14 @@ alloc_and_fill: /* add new list to cmd iocb or last list */ - *cur_dsd++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma)); - *cur_dsd++ = cpu_to_le32(MSD(dsd_ptr->dsd_list_dma)); - *cur_dsd++ = dsd_list_len; - cur_dsd = (uint32_t *)next_dsd; + put_unaligned_le64(dsd_ptr->dsd_list_dma, + &cur_dsd->address); + cur_dsd->length = cpu_to_le32(dsd_list_len); + cur_dsd = next_dsd; } - *cur_dsd++ = cpu_to_le32(LSD(sle_dma)); - *cur_dsd++ = cpu_to_le32(MSD(sle_dma)); - *cur_dsd++ = cpu_to_le32(sle_dma_len); + put_unaligned_le64(sle_dma, &cur_dsd->address); + cur_dsd->length = cpu_to_le32(sle_dma_len); + cur_dsd++; avail_dsds--; if (partial == 0) { @@ -999,22 +981,22 @@ alloc_and_fill: } } /* Null termination */ - *cur_dsd++ = 0; - *cur_dsd++ = 0; - *cur_dsd++ = 0; + cur_dsd->address = 0; + cur_dsd->length = 0; + cur_dsd++; return 0; } int -qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, uint32_t *dsd, - uint16_t tot_dsds, struct qla_tc_param *tc) +qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, + struct dsd64 *dsd, uint16_t tot_dsds, struct qla_tc_param *tc) { void *next_dsd; uint8_t avail_dsds = 0; uint32_t dsd_list_len; struct dsd_dma *dsd_ptr; struct scatterlist *sg, *sgl; - uint32_t *cur_dsd = dsd; + struct dsd64 *cur_dsd = dsd; int i; uint16_t used_dsds = tot_dsds; struct scsi_cmnd *cmd; @@ -1031,8 +1013,6 @@ qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, uint32_t *dsd, for_each_sg(sgl, sg, tot_dsds, i) { - dma_addr_t sle_dma; - /* Allocate additional continuation packets? */ if (avail_dsds == 0) { avail_dsds = (used_dsds > QLA_DSDS_PER_IOCB) ? @@ -1072,29 +1052,25 @@ qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, uint32_t *dsd, } /* add new list to cmd iocb or last list */ - *cur_dsd++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma)); - *cur_dsd++ = cpu_to_le32(MSD(dsd_ptr->dsd_list_dma)); - *cur_dsd++ = dsd_list_len; - cur_dsd = (uint32_t *)next_dsd; + put_unaligned_le64(dsd_ptr->dsd_list_dma, + &cur_dsd->address); + cur_dsd->length = cpu_to_le32(dsd_list_len); + cur_dsd = next_dsd; } - sle_dma = sg_dma_address(sg); - - *cur_dsd++ = cpu_to_le32(LSD(sle_dma)); - *cur_dsd++ = cpu_to_le32(MSD(sle_dma)); - *cur_dsd++ = cpu_to_le32(sg_dma_len(sg)); + append_dsd64(&cur_dsd, sg); avail_dsds--; } /* Null termination */ - *cur_dsd++ = 0; - *cur_dsd++ = 0; - *cur_dsd++ = 0; + cur_dsd->address = 0; + cur_dsd->length = 0; + cur_dsd++; return 0; } int qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *ha, srb_t *sp, - uint32_t *cur_dsd, uint16_t tot_dsds, struct qla_tgt_cmd *tc) + struct dsd64 *cur_dsd, uint16_t tot_dsds, struct qla_tgt_cmd *tc) { struct dsd_dma *dsd_ptr = NULL, *dif_dsd, *nxt_dsd; struct scatterlist *sg, *sgl; @@ -1109,6 +1085,7 @@ qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *ha, srb_t *sp, if (sp) { struct scsi_cmnd *cmd = GET_CMD_SP(sp); + sgl = scsi_prot_sglist(cmd); vha = sp->vha; difctx = sp->u.scmd.ctx; @@ -1314,16 +1291,15 @@ qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *ha, srb_t *sp, } /* add new list to cmd iocb or last list */ - *cur_dsd++ = - cpu_to_le32(LSD(dsd_ptr->dsd_list_dma)); - *cur_dsd++ = - cpu_to_le32(MSD(dsd_ptr->dsd_list_dma)); - *cur_dsd++ = dsd_list_len; + put_unaligned_le64(dsd_ptr->dsd_list_dma, + &cur_dsd->address); + cur_dsd->length = cpu_to_le32(dsd_list_len); cur_dsd = dsd_ptr->dsd_addr; } - *cur_dsd++ = cpu_to_le32(LSD(dif_dsd->dsd_list_dma)); - *cur_dsd++ = cpu_to_le32(MSD(dif_dsd->dsd_list_dma)); - *cur_dsd++ = cpu_to_le32(sglen); + put_unaligned_le64(dif_dsd->dsd_list_dma, + &cur_dsd->address); + cur_dsd->length = cpu_to_le32(sglen); + cur_dsd++; avail_dsds--; difctx->dif_bundl_len -= sglen; track_difbundl_buf--; @@ -1334,8 +1310,6 @@ qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *ha, srb_t *sp, difctx->no_ldif_dsd, difctx->no_dif_bundl); } else { for_each_sg(sgl, sg, tot_dsds, i) { - dma_addr_t sle_dma; - /* Allocate additional continuation packets? */ if (avail_dsds == 0) { avail_dsds = (used_dsds > QLA_DSDS_PER_IOCB) ? @@ -1375,24 +1349,19 @@ qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *ha, srb_t *sp, } /* add new list to cmd iocb or last list */ - *cur_dsd++ = - cpu_to_le32(LSD(dsd_ptr->dsd_list_dma)); - *cur_dsd++ = - cpu_to_le32(MSD(dsd_ptr->dsd_list_dma)); - *cur_dsd++ = dsd_list_len; + put_unaligned_le64(dsd_ptr->dsd_list_dma, + &cur_dsd->address); + cur_dsd->length = cpu_to_le32(dsd_list_len); cur_dsd = dsd_ptr->dsd_addr; } - sle_dma = sg_dma_address(sg); - *cur_dsd++ = cpu_to_le32(LSD(sle_dma)); - *cur_dsd++ = cpu_to_le32(MSD(sle_dma)); - *cur_dsd++ = cpu_to_le32(sg_dma_len(sg)); + append_dsd64(&cur_dsd, sg); avail_dsds--; } } /* Null termination */ - *cur_dsd++ = 0; - *cur_dsd++ = 0; - *cur_dsd++ = 0; + cur_dsd->address = 0; + cur_dsd->length = 0; + cur_dsd++; return 0; } /** @@ -1405,11 +1374,12 @@ qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *ha, srb_t *sp, * @tot_prot_dsds: Total number of segments with protection information * @fw_prot_opts: Protection options to be passed to firmware */ -inline int +static inline int qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, uint16_t tot_dsds, uint16_t tot_prot_dsds, uint16_t fw_prot_opts) { - uint32_t *cur_dsd, *fcp_dl; + struct dsd64 *cur_dsd; + uint32_t *fcp_dl; scsi_qla_host_t *vha; struct scsi_cmnd *cmd; uint32_t total_bytes = 0; @@ -1427,7 +1397,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, cmd = GET_CMD_SP(sp); /* Update entry type to indicate Command Type CRC_2 IOCB */ - *((uint32_t *)(&cmd_pkt->entry_type)) = cpu_to_le32(COMMAND_TYPE_CRC_2); + put_unaligned_le32(COMMAND_TYPE_CRC_2, &cmd_pkt->entry_type); vha = sp->vha; ha = vha->hw; @@ -1475,8 +1445,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, qla24xx_set_t10dif_tags(sp, (struct fw_dif_context *) &crc_ctx_pkt->ref_tag, tot_prot_dsds); - cmd_pkt->crc_context_address[0] = cpu_to_le32(LSD(crc_ctx_dma)); - cmd_pkt->crc_context_address[1] = cpu_to_le32(MSD(crc_ctx_dma)); + put_unaligned_le64(crc_ctx_dma, &cmd_pkt->crc_context_address); cmd_pkt->crc_context_len = CRC_CONTEXT_LEN_FW; /* Determine SCSI command length -- align to 4 byte boundary */ @@ -1503,10 +1472,8 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, int_to_scsilun(cmd->device->lun, &fcp_cmnd->lun); memcpy(fcp_cmnd->cdb, cmd->cmnd, cmd->cmd_len); cmd_pkt->fcp_cmnd_dseg_len = cpu_to_le16(fcp_cmnd_len); - cmd_pkt->fcp_cmnd_dseg_address[0] = cpu_to_le32( - LSD(crc_ctx_dma + CRC_CONTEXT_FCPCMND_OFF)); - cmd_pkt->fcp_cmnd_dseg_address[1] = cpu_to_le32( - MSD(crc_ctx_dma + CRC_CONTEXT_FCPCMND_OFF)); + put_unaligned_le64(crc_ctx_dma + CRC_CONTEXT_FCPCMND_OFF, + &cmd_pkt->fcp_cmnd_dseg_address); fcp_cmnd->task_management = 0; fcp_cmnd->task_attribute = TSK_SIMPLE; @@ -1520,18 +1487,18 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, switch (scsi_get_prot_op(GET_CMD_SP(sp))) { case SCSI_PROT_READ_INSERT: case SCSI_PROT_WRITE_STRIP: - total_bytes = data_bytes; - data_bytes += dif_bytes; - break; + total_bytes = data_bytes; + data_bytes += dif_bytes; + break; case SCSI_PROT_READ_STRIP: case SCSI_PROT_WRITE_INSERT: case SCSI_PROT_READ_PASS: case SCSI_PROT_WRITE_PASS: - total_bytes = data_bytes + dif_bytes; - break; + total_bytes = data_bytes + dif_bytes; + break; default: - BUG(); + BUG(); } if (!qla2x00_hba_err_chk_enabled(sp)) @@ -1548,7 +1515,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, } if (!bundling) { - cur_dsd = (uint32_t *) &crc_ctx_pkt->u.nobundling.data_address; + cur_dsd = &crc_ctx_pkt->u.nobundling.data_dsd; } else { /* * Configure Bundling if we need to fetch interlaving @@ -1558,7 +1525,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, crc_ctx_pkt->u.bundling.dif_byte_count = cpu_to_le32(dif_bytes); crc_ctx_pkt->u.bundling.dseg_count = cpu_to_le16(tot_dsds - tot_prot_dsds); - cur_dsd = (uint32_t *) &crc_ctx_pkt->u.bundling.data_address; + cur_dsd = &crc_ctx_pkt->u.bundling.data_dsd; } /* Finish the common fields of CRC pkt */ @@ -1591,7 +1558,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, if (bundling && tot_prot_dsds) { /* Walks dif segments */ cmd_pkt->control_flags |= cpu_to_le16(CF_DIF_SEG_DESCR_ENABLE); - cur_dsd = (uint32_t *) &crc_ctx_pkt->u.bundling.dif_address; + cur_dsd = &crc_ctx_pkt->u.bundling.dif_dsd; if (qla24xx_walk_and_build_prot_sglist(ha, sp, cur_dsd, tot_prot_dsds, NULL)) goto crc_queuing_error; @@ -2325,7 +2292,8 @@ __qla2x00_alloc_iocbs(struct qla_qpair *qpair, srb_t *sp) if (req->cnt < req_cnt + 2) { if (qpair->use_shadow_reg) cnt = *req->out_ptr; - else if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha)) + else if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha) || + IS_QLA28XX(ha)) cnt = RD_REG_DWORD(®->isp25mq.req_q_out); else if (IS_P3P_TYPE(ha)) cnt = RD_REG_DWORD(®->isp82.req_q_out); @@ -2494,7 +2462,7 @@ qla2x00_logout_iocb(srb_t *sp, struct mbx_entry *mbx) SET_TARGET_ID(ha, mbx->loop_id, sp->fcport->loop_id); mbx->mb0 = cpu_to_le16(MBC_LOGOUT_FABRIC_PORT); mbx->mb1 = HAS_EXTENDED_IDS(ha) ? - cpu_to_le16(sp->fcport->loop_id): + cpu_to_le16(sp->fcport->loop_id) : cpu_to_le16(sp->fcport->loop_id << 8); mbx->mb2 = cpu_to_le16(sp->fcport->d_id.b.domain); mbx->mb3 = cpu_to_le16(sp->fcport->d_id.b.area << 8 | @@ -2565,6 +2533,16 @@ qla24xx_tm_iocb(srb_t *sp, struct tsk_mgmt_entry *tsk) } } +void qla2x00_init_timer(srb_t *sp, unsigned long tmo) +{ + timer_setup(&sp->u.iocb_cmd.timer, qla2x00_sp_timeout, 0); + sp->u.iocb_cmd.timer.expires = jiffies + tmo * HZ; + sp->free = qla2x00_sp_free; + if (IS_QLAFX00(sp->vha->hw) && sp->type == SRB_FXIOCB_DCMD) + init_completion(&sp->u.iocb_cmd.u.fxiocb.fxiocb_comp); + add_timer(&sp->u.iocb_cmd.timer); +} + static void qla2x00_els_dcmd_sp_free(void *data) { @@ -2726,18 +2704,13 @@ qla24xx_els_logo_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) if (elsio->u.els_logo.els_cmd == ELS_DCMD_PLOGI) { els_iocb->tx_byte_count = els_iocb->tx_len = sizeof(struct els_plogi_payload); - els_iocb->tx_address[0] = - cpu_to_le32(LSD(elsio->u.els_plogi.els_plogi_pyld_dma)); - els_iocb->tx_address[1] = - cpu_to_le32(MSD(elsio->u.els_plogi.els_plogi_pyld_dma)); - + put_unaligned_le64(elsio->u.els_plogi.els_plogi_pyld_dma, + &els_iocb->tx_address); els_iocb->rx_dsd_count = 1; els_iocb->rx_byte_count = els_iocb->rx_len = sizeof(struct els_plogi_payload); - els_iocb->rx_address[0] = - cpu_to_le32(LSD(elsio->u.els_plogi.els_resp_pyld_dma)); - els_iocb->rx_address[1] = - cpu_to_le32(MSD(elsio->u.els_plogi.els_resp_pyld_dma)); + put_unaligned_le64(elsio->u.els_plogi.els_resp_pyld_dma, + &els_iocb->rx_address); ql_dbg(ql_dbg_io + ql_dbg_buffer, vha, 0x3073, "PLOGI ELS IOCB:\n"); @@ -2745,15 +2718,12 @@ qla24xx_els_logo_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) (uint8_t *)els_iocb, 0x70); } else { els_iocb->tx_byte_count = sizeof(struct els_logo_payload); - els_iocb->tx_address[0] = - cpu_to_le32(LSD(elsio->u.els_logo.els_logo_pyld_dma)); - els_iocb->tx_address[1] = - cpu_to_le32(MSD(elsio->u.els_logo.els_logo_pyld_dma)); + put_unaligned_le64(elsio->u.els_logo.els_logo_pyld_dma, + &els_iocb->tx_address); els_iocb->tx_len = cpu_to_le32(sizeof(struct els_logo_payload)); els_iocb->rx_byte_count = 0; - els_iocb->rx_address[0] = 0; - els_iocb->rx_address[1] = 0; + els_iocb->rx_address = 0; els_iocb->rx_len = 0; } @@ -2976,17 +2946,13 @@ qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) els_iocb->tx_byte_count = cpu_to_le32(bsg_job->request_payload.payload_len); - els_iocb->tx_address[0] = cpu_to_le32(LSD(sg_dma_address - (bsg_job->request_payload.sg_list))); - els_iocb->tx_address[1] = cpu_to_le32(MSD(sg_dma_address - (bsg_job->request_payload.sg_list))); + put_unaligned_le64(sg_dma_address(bsg_job->request_payload.sg_list), + &els_iocb->tx_address); els_iocb->tx_len = cpu_to_le32(sg_dma_len (bsg_job->request_payload.sg_list)); - els_iocb->rx_address[0] = cpu_to_le32(LSD(sg_dma_address - (bsg_job->reply_payload.sg_list))); - els_iocb->rx_address[1] = cpu_to_le32(MSD(sg_dma_address - (bsg_job->reply_payload.sg_list))); + put_unaligned_le64(sg_dma_address(bsg_job->reply_payload.sg_list), + &els_iocb->rx_address); els_iocb->rx_len = cpu_to_le32(sg_dma_len (bsg_job->reply_payload.sg_list)); @@ -2997,14 +2963,13 @@ static void qla2x00_ct_iocb(srb_t *sp, ms_iocb_entry_t *ct_iocb) { uint16_t avail_dsds; - uint32_t *cur_dsd; + struct dsd64 *cur_dsd; struct scatterlist *sg; int index; uint16_t tot_dsds; scsi_qla_host_t *vha = sp->vha; struct qla_hw_data *ha = vha->hw; struct bsg_job *bsg_job = sp->u.bsg_job; - int loop_iterartion = 0; int entry_count = 1; memset(ct_iocb, 0, sizeof(ms_iocb_entry_t)); @@ -3024,25 +2989,20 @@ qla2x00_ct_iocb(srb_t *sp, ms_iocb_entry_t *ct_iocb) ct_iocb->rsp_bytecount = cpu_to_le32(bsg_job->reply_payload.payload_len); - ct_iocb->dseg_req_address[0] = cpu_to_le32(LSD(sg_dma_address - (bsg_job->request_payload.sg_list))); - ct_iocb->dseg_req_address[1] = cpu_to_le32(MSD(sg_dma_address - (bsg_job->request_payload.sg_list))); - ct_iocb->dseg_req_length = ct_iocb->req_bytecount; + put_unaligned_le64(sg_dma_address(bsg_job->request_payload.sg_list), + &ct_iocb->req_dsd.address); + ct_iocb->req_dsd.length = ct_iocb->req_bytecount; - ct_iocb->dseg_rsp_address[0] = cpu_to_le32(LSD(sg_dma_address - (bsg_job->reply_payload.sg_list))); - ct_iocb->dseg_rsp_address[1] = cpu_to_le32(MSD(sg_dma_address - (bsg_job->reply_payload.sg_list))); - ct_iocb->dseg_rsp_length = ct_iocb->rsp_bytecount; + put_unaligned_le64(sg_dma_address(bsg_job->reply_payload.sg_list), + &ct_iocb->rsp_dsd.address); + ct_iocb->rsp_dsd.length = ct_iocb->rsp_bytecount; avail_dsds = 1; - cur_dsd = (uint32_t *)ct_iocb->dseg_rsp_address; + cur_dsd = &ct_iocb->rsp_dsd; index = 0; tot_dsds = bsg_job->reply_payload.sg_cnt; for_each_sg(bsg_job->reply_payload.sg_list, sg, tot_dsds, index) { - dma_addr_t sle_dma; cont_a64_entry_t *cont_pkt; /* Allocate additional continuation packets? */ @@ -3053,16 +3013,12 @@ qla2x00_ct_iocb(srb_t *sp, ms_iocb_entry_t *ct_iocb) */ cont_pkt = qla2x00_prep_cont_type1_iocb(vha, vha->hw->req_q_map[0]); - cur_dsd = (uint32_t *) cont_pkt->dseg_0_address; + cur_dsd = cont_pkt->dsd; avail_dsds = 5; entry_count++; } - sle_dma = sg_dma_address(sg); - *cur_dsd++ = cpu_to_le32(LSD(sle_dma)); - *cur_dsd++ = cpu_to_le32(MSD(sle_dma)); - *cur_dsd++ = cpu_to_le32(sg_dma_len(sg)); - loop_iterartion++; + append_dsd64(&cur_dsd, sg); avail_dsds--; } ct_iocb->entry_count = entry_count; @@ -3074,7 +3030,7 @@ static void qla24xx_ct_iocb(srb_t *sp, struct ct_entry_24xx *ct_iocb) { uint16_t avail_dsds; - uint32_t *cur_dsd; + struct dsd64 *cur_dsd; struct scatterlist *sg; int index; uint16_t cmd_dsds, rsp_dsds; @@ -3103,12 +3059,10 @@ qla24xx_ct_iocb(srb_t *sp, struct ct_entry_24xx *ct_iocb) cpu_to_le32(bsg_job->request_payload.payload_len); avail_dsds = 2; - cur_dsd = (uint32_t *)ct_iocb->dseg_0_address; + cur_dsd = ct_iocb->dsd; index = 0; for_each_sg(bsg_job->request_payload.sg_list, sg, cmd_dsds, index) { - dma_addr_t sle_dma; - /* Allocate additional continuation packets? */ if (avail_dsds == 0) { /* @@ -3117,23 +3071,18 @@ qla24xx_ct_iocb(srb_t *sp, struct ct_entry_24xx *ct_iocb) */ cont_pkt = qla2x00_prep_cont_type1_iocb( vha, ha->req_q_map[0]); - cur_dsd = (uint32_t *) cont_pkt->dseg_0_address; + cur_dsd = cont_pkt->dsd; avail_dsds = 5; entry_count++; } - sle_dma = sg_dma_address(sg); - *cur_dsd++ = cpu_to_le32(LSD(sle_dma)); - *cur_dsd++ = cpu_to_le32(MSD(sle_dma)); - *cur_dsd++ = cpu_to_le32(sg_dma_len(sg)); + append_dsd64(&cur_dsd, sg); avail_dsds--; } index = 0; for_each_sg(bsg_job->reply_payload.sg_list, sg, rsp_dsds, index) { - dma_addr_t sle_dma; - /* Allocate additional continuation packets? */ if (avail_dsds == 0) { /* @@ -3142,15 +3091,12 @@ qla24xx_ct_iocb(srb_t *sp, struct ct_entry_24xx *ct_iocb) */ cont_pkt = qla2x00_prep_cont_type1_iocb(vha, ha->req_q_map[0]); - cur_dsd = (uint32_t *) cont_pkt->dseg_0_address; + cur_dsd = cont_pkt->dsd; avail_dsds = 5; entry_count++; } - sle_dma = sg_dma_address(sg); - *cur_dsd++ = cpu_to_le32(LSD(sle_dma)); - *cur_dsd++ = cpu_to_le32(MSD(sle_dma)); - *cur_dsd++ = cpu_to_le32(sg_dma_len(sg)); + append_dsd64(&cur_dsd, sg); avail_dsds--; } ct_iocb->entry_count = entry_count; @@ -3371,10 +3317,8 @@ sufficient_dsds: *fcp_dl = htonl((uint32_t)scsi_bufflen(cmd)); cmd_pkt->fcp_cmnd_dseg_len = cpu_to_le16(ctx->fcp_cmnd_len); - cmd_pkt->fcp_cmnd_dseg_address[0] = - cpu_to_le32(LSD(ctx->fcp_cmnd_dma)); - cmd_pkt->fcp_cmnd_dseg_address[1] = - cpu_to_le32(MSD(ctx->fcp_cmnd_dma)); + put_unaligned_le64(ctx->fcp_cmnd_dma, + &cmd_pkt->fcp_cmnd_dseg_address); sp->flags |= SRB_FCP_CMND_DMA_VALID; cmd_pkt->byte_count = cpu_to_le32((uint32_t)scsi_bufflen(cmd)); @@ -3386,6 +3330,7 @@ sufficient_dsds: cmd_pkt->entry_status = (uint8_t) rsp->id; } else { struct cmd_type_7 *cmd_pkt; + req_cnt = qla24xx_calc_iocbs(vha, tot_dsds); if (req->cnt < (req_cnt + 2)) { cnt = (uint16_t)RD_REG_DWORD_RELAXED( @@ -3590,15 +3535,13 @@ qla_nvme_ls(srb_t *sp, struct pt_ls4_request *cmd_pkt) cmd_pkt->tx_dseg_count = 1; cmd_pkt->tx_byte_count = nvme->u.nvme.cmd_len; - cmd_pkt->dseg0_len = nvme->u.nvme.cmd_len; - cmd_pkt->dseg0_address[0] = cpu_to_le32(LSD(nvme->u.nvme.cmd_dma)); - cmd_pkt->dseg0_address[1] = cpu_to_le32(MSD(nvme->u.nvme.cmd_dma)); + cmd_pkt->dsd[0].length = nvme->u.nvme.cmd_len; + put_unaligned_le64(nvme->u.nvme.cmd_dma, &cmd_pkt->dsd[0].address); cmd_pkt->rx_dseg_count = 1; cmd_pkt->rx_byte_count = nvme->u.nvme.rsp_len; - cmd_pkt->dseg1_len = nvme->u.nvme.rsp_len; - cmd_pkt->dseg1_address[0] = cpu_to_le32(LSD(nvme->u.nvme.rsp_dma)); - cmd_pkt->dseg1_address[1] = cpu_to_le32(MSD(nvme->u.nvme.rsp_dma)); + cmd_pkt->dsd[1].length = nvme->u.nvme.rsp_len; + put_unaligned_le64(nvme->u.nvme.rsp_dma, &cmd_pkt->dsd[1].address); return rval; } @@ -3737,7 +3680,7 @@ qla25xx_build_bidir_iocb(srb_t *sp, struct scsi_qla_host *vha, struct cmd_bidir *cmd_pkt, uint32_t tot_dsds) { uint16_t avail_dsds; - uint32_t *cur_dsd; + struct dsd64 *cur_dsd; uint32_t req_data_len = 0; uint32_t rsp_data_len = 0; struct scatterlist *sg; @@ -3746,8 +3689,7 @@ qla25xx_build_bidir_iocb(srb_t *sp, struct scsi_qla_host *vha, struct bsg_job *bsg_job = sp->u.bsg_job; /*Update entry type to indicate bidir command */ - *((uint32_t *)(&cmd_pkt->entry_type)) = - cpu_to_le32(COMMAND_BIDIRECTIONAL); + put_unaligned_le32(COMMAND_BIDIRECTIONAL, &cmd_pkt->entry_type); /* Set the transfer direction, in this set both flags * Also set the BD_WRAP_BACK flag, firmware will take care @@ -3773,13 +3715,12 @@ qla25xx_build_bidir_iocb(srb_t *sp, struct scsi_qla_host *vha, * are bundled in continuation iocb */ avail_dsds = 1; - cur_dsd = (uint32_t *)&cmd_pkt->fcp_data_dseg_address; + cur_dsd = &cmd_pkt->fcp_dsd; index = 0; for_each_sg(bsg_job->request_payload.sg_list, sg, bsg_job->request_payload.sg_cnt, index) { - dma_addr_t sle_dma; cont_a64_entry_t *cont_pkt; /* Allocate additional continuation packets */ @@ -3788,14 +3729,11 @@ qla25xx_build_bidir_iocb(srb_t *sp, struct scsi_qla_host *vha, * 5 DSDS */ cont_pkt = qla2x00_prep_cont_type1_iocb(vha, vha->req); - cur_dsd = (uint32_t *) cont_pkt->dseg_0_address; + cur_dsd = cont_pkt->dsd; avail_dsds = 5; entry_count++; } - sle_dma = sg_dma_address(sg); - *cur_dsd++ = cpu_to_le32(LSD(sle_dma)); - *cur_dsd++ = cpu_to_le32(MSD(sle_dma)); - *cur_dsd++ = cpu_to_le32(sg_dma_len(sg)); + append_dsd64(&cur_dsd, sg); avail_dsds--; } /* For read request DSD will always goes to continuation IOCB @@ -3805,7 +3743,6 @@ qla25xx_build_bidir_iocb(srb_t *sp, struct scsi_qla_host *vha, */ for_each_sg(bsg_job->reply_payload.sg_list, sg, bsg_job->reply_payload.sg_cnt, index) { - dma_addr_t sle_dma; cont_a64_entry_t *cont_pkt; /* Allocate additional continuation packets */ @@ -3814,14 +3751,11 @@ qla25xx_build_bidir_iocb(srb_t *sp, struct scsi_qla_host *vha, * 5 DSDS */ cont_pkt = qla2x00_prep_cont_type1_iocb(vha, vha->req); - cur_dsd = (uint32_t *) cont_pkt->dseg_0_address; + cur_dsd = cont_pkt->dsd; avail_dsds = 5; entry_count++; } - sle_dma = sg_dma_address(sg); - *cur_dsd++ = cpu_to_le32(LSD(sle_dma)); - *cur_dsd++ = cpu_to_le32(MSD(sle_dma)); - *cur_dsd++ = cpu_to_le32(sg_dma_len(sg)); + append_dsd64(&cur_dsd, sg); avail_dsds--; } /* This value should be same as number of IOCB required for this cmd */ diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 69bbea9239cc..78aec50abe0f 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -23,6 +23,14 @@ static void qla2x00_status_cont_entry(struct rsp_que *, sts_cont_entry_t *); static int qla2x00_error_entry(scsi_qla_host_t *, struct rsp_que *, sts_entry_t *); +const char *const port_state_str[] = { + "Unknown", + "UNCONFIGURED", + "DEAD", + "LOST", + "ONLINE" +}; + /** * qla2100_intr_handler() - Process interrupts for the ISP2100 and ISP2200. * @irq: interrupt number @@ -41,7 +49,7 @@ qla2100_intr_handler(int irq, void *dev_id) int status; unsigned long iter; uint16_t hccr; - uint16_t mb[4]; + uint16_t mb[8]; struct rsp_que *rsp; unsigned long flags; @@ -160,7 +168,7 @@ qla2300_intr_handler(int irq, void *dev_id) unsigned long iter; uint32_t stat; uint16_t hccr; - uint16_t mb[4]; + uint16_t mb[8]; struct rsp_que *rsp; struct qla_hw_data *ha; unsigned long flags; @@ -366,7 +374,7 @@ qla2x00_get_link_speed_str(struct qla_hw_data *ha, uint16_t speed) static const char *const link_speeds[] = { "1", "2", "?", "4", "8", "16", "32", "10" }; -#define QLA_LAST_SPEED 7 +#define QLA_LAST_SPEED (ARRAY_SIZE(link_speeds) - 1) if (IS_QLA2100(ha) || IS_QLA2200(ha)) return link_speeds[0]; @@ -708,12 +716,15 @@ skip_rio: break; case MBA_SYSTEM_ERR: /* System Error */ - mbx = (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha)) ? + mbx = (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha) || + IS_QLA28XX(ha)) ? RD_REG_WORD(®24->mailbox7) : 0; ql_log(ql_log_warn, vha, 0x5003, "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh " "mbx7=%xh.\n", mb[1], mb[2], mb[3], mbx); - + ha->fw_dump_mpi = + (IS_QLA27XX(ha) || IS_QLA28XX(ha)) && + RD_REG_WORD(®24->mailbox7) & BIT_8; ha->isp_ops->fw_dump(vha, 1); ha->flags.fw_init_done = 0; QLA_FW_STOPPED(ha); @@ -837,6 +848,7 @@ skip_rio: if (ha->flags.fawwpn_enabled && (ha->current_topology == ISP_CFG_F)) { void *wwpn = ha->init_cb->port_name; + memcpy(vha->port_name, wwpn, WWN_SIZE); fc_host_port_name(vha->host) = wwn_to_u64(vha->port_name); @@ -1372,7 +1384,7 @@ qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, le16_to_cpu(mbx->status_flags)); ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5029, - (uint8_t *)mbx, sizeof(*mbx)); + mbx, sizeof(*mbx)); goto logio_done; } @@ -1516,7 +1528,7 @@ qla2x00_ct_entry(scsi_qla_host_t *vha, struct req_que *req, bsg_reply->reply_payload_rcv_len = 0; } ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5035, - (uint8_t *)pkt, sizeof(*pkt)); + pkt, sizeof(*pkt)); } else { res = DID_OK << 16; bsg_reply->reply_payload_rcv_len = @@ -1591,8 +1603,8 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req, } comp_status = fw_status[0] = le16_to_cpu(pkt->comp_status); - fw_status[1] = le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->error_subcode_1); - fw_status[2] = le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->error_subcode_2); + fw_status[1] = le16_to_cpu(((struct els_sts_entry_24xx *)pkt)->error_subcode_1); + fw_status[2] = le16_to_cpu(((struct els_sts_entry_24xx *)pkt)->error_subcode_2); if (iocb_type == ELS_IOCB_TYPE) { els = &sp->u.iocb_cmd; @@ -1613,7 +1625,7 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req, res = DID_ERROR << 16; } } - ql_log(ql_log_info, vha, 0x503f, + ql_dbg(ql_dbg_user, vha, 0x503f, "ELS IOCB Done -%s error hdl=%x comp_status=0x%x error subcode 1=0x%x error subcode 2=0x%x total_byte=0x%x\n", type, sp->handle, comp_status, fw_status[1], fw_status[2], le16_to_cpu(((struct els_sts_entry_24xx *) @@ -1656,7 +1668,7 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req, memcpy(bsg_job->reply + sizeof(struct fc_bsg_reply), fw_status, sizeof(fw_status)); ql_dump_buffer(ql_dbg_user + ql_dbg_buffer, vha, 0x5056, - (uint8_t *)pkt, sizeof(*pkt)); + pkt, sizeof(*pkt)); } else { res = DID_OK << 16; @@ -1700,7 +1712,7 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req, fcport->d_id.b.area, fcport->d_id.b.al_pa, logio->entry_status); ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x504d, - (uint8_t *)logio, sizeof(*logio)); + logio, sizeof(*logio)); goto logio_done; } @@ -1846,8 +1858,8 @@ qla24xx_tm_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, void *tsk) } if (iocb->u.tmf.data != QLA_SUCCESS) - ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5055, - (uint8_t *)sts, sizeof(*sts)); + ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, sp->vha, 0x5055, + sts, sizeof(*sts)); sp->done(sp, 0); } @@ -1969,6 +1981,52 @@ static void qla_ctrlvp_completed(scsi_qla_host_t *vha, struct req_que *req, sp->done(sp, rval); } +/* Process a single response queue entry. */ +static void qla2x00_process_response_entry(struct scsi_qla_host *vha, + struct rsp_que *rsp, + sts_entry_t *pkt) +{ + sts21_entry_t *sts21_entry; + sts22_entry_t *sts22_entry; + uint16_t handle_cnt; + uint16_t cnt; + + switch (pkt->entry_type) { + case STATUS_TYPE: + qla2x00_status_entry(vha, rsp, pkt); + break; + case STATUS_TYPE_21: + sts21_entry = (sts21_entry_t *)pkt; + handle_cnt = sts21_entry->handle_count; + for (cnt = 0; cnt < handle_cnt; cnt++) + qla2x00_process_completed_request(vha, rsp->req, + sts21_entry->handle[cnt]); + break; + case STATUS_TYPE_22: + sts22_entry = (sts22_entry_t *)pkt; + handle_cnt = sts22_entry->handle_count; + for (cnt = 0; cnt < handle_cnt; cnt++) + qla2x00_process_completed_request(vha, rsp->req, + sts22_entry->handle[cnt]); + break; + case STATUS_CONT_TYPE: + qla2x00_status_cont_entry(rsp, (sts_cont_entry_t *)pkt); + break; + case MBX_IOCB_TYPE: + qla2x00_mbx_iocb_entry(vha, rsp->req, (struct mbx_entry *)pkt); + break; + case CT_IOCB_TYPE: + qla2x00_ct_entry(vha, rsp->req, pkt, CT_IOCB_TYPE); + break; + default: + /* Type Not Supported. */ + ql_log(ql_log_warn, vha, 0x504a, + "Received unknown response pkt type %x entry status=%x.\n", + pkt->entry_type, pkt->entry_status); + break; + } +} + /** * qla2x00_process_response_queue() - Process response queue entries. * @rsp: response queue @@ -1980,8 +2038,6 @@ qla2x00_process_response_queue(struct rsp_que *rsp) struct qla_hw_data *ha = rsp->hw; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; sts_entry_t *pkt; - uint16_t handle_cnt; - uint16_t cnt; vha = pci_get_drvdata(ha->pdev); @@ -2006,42 +2062,7 @@ qla2x00_process_response_queue(struct rsp_que *rsp) continue; } - switch (pkt->entry_type) { - case STATUS_TYPE: - qla2x00_status_entry(vha, rsp, pkt); - break; - case STATUS_TYPE_21: - handle_cnt = ((sts21_entry_t *)pkt)->handle_count; - for (cnt = 0; cnt < handle_cnt; cnt++) { - qla2x00_process_completed_request(vha, rsp->req, - ((sts21_entry_t *)pkt)->handle[cnt]); - } - break; - case STATUS_TYPE_22: - handle_cnt = ((sts22_entry_t *)pkt)->handle_count; - for (cnt = 0; cnt < handle_cnt; cnt++) { - qla2x00_process_completed_request(vha, rsp->req, - ((sts22_entry_t *)pkt)->handle[cnt]); - } - break; - case STATUS_CONT_TYPE: - qla2x00_status_cont_entry(rsp, (sts_cont_entry_t *)pkt); - break; - case MBX_IOCB_TYPE: - qla2x00_mbx_iocb_entry(vha, rsp->req, - (struct mbx_entry *)pkt); - break; - case CT_IOCB_TYPE: - qla2x00_ct_entry(vha, rsp->req, pkt, CT_IOCB_TYPE); - break; - default: - /* Type Not Supported. */ - ql_log(ql_log_warn, vha, 0x504a, - "Received unknown response pkt type %x " - "entry status=%x.\n", - pkt->entry_type, pkt->entry_status); - break; - } + qla2x00_process_response_entry(vha, rsp, pkt); ((response_t *)pkt)->signature = RESPONSE_PROCESSED; wmb(); } @@ -2238,6 +2259,7 @@ qla25xx_process_bidir_status_iocb(scsi_qla_host_t *vha, void *pkt, struct fc_bsg_reply *bsg_reply; sts_entry_t *sts; struct sts_entry_24xx *sts24; + sts = (sts_entry_t *) pkt; sts24 = (struct sts_entry_24xx *) pkt; @@ -3014,7 +3036,8 @@ process_err: qla24xx_els_ct_entry(vha, rsp->req, pkt, ELS_IOCB_TYPE); break; case ABTS_RECV_24XX: - if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) { + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || + IS_QLA28XX(ha)) { /* ensure that the ATIO queue is empty */ qlt_handle_abts_recv(vha, rsp, (response_t *)pkt); @@ -3072,6 +3095,7 @@ process_err: /* Adjust ring index */ if (IS_P3P_TYPE(ha)) { struct device_reg_82xx __iomem *reg = &ha->iobase->isp82; + WRT_REG_DWORD(®->rsp_q_out[0], rsp->ring_index); } else { WRT_REG_DWORD(rsp->rsp_q_out, rsp->ring_index); @@ -3087,7 +3111,7 @@ qla2xxx_check_risc_status(scsi_qla_host_t *vha) struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha) && - !IS_QLA27XX(ha)) + !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) return; rval = QLA_SUCCESS; @@ -3475,7 +3499,7 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp) ql_log(ql_log_fatal, vha, 0x00c8, "Failed to allocate memory for ha->msix_entries.\n"); ret = -ENOMEM; - goto msix_out; + goto free_irqs; } ha->flags.msix_enabled = 1; @@ -3539,7 +3563,7 @@ msix_register_fail: } /* Enable MSI-X vector for response queue update for queue 0 */ - if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) { + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { if (ha->msixbase && ha->mqiobase && (ha->max_rsp_queues > 1 || ha->max_req_queues > 1 || ql2xmqsupport)) @@ -3558,6 +3582,10 @@ msix_register_fail: msix_out: return ret; + +free_irqs: + pci_free_irq_vectors(ha->pdev); + goto msix_out; } int @@ -3570,7 +3598,7 @@ qla2x00_request_irqs(struct qla_hw_data *ha, struct rsp_que *rsp) /* If possible, enable MSI-X. */ if (ql2xenablemsix == 0 || (!IS_QLA2432(ha) && !IS_QLA2532(ha) && !IS_QLA8432(ha) && !IS_CNA_CAPABLE(ha) && !IS_QLA2031(ha) && - !IS_QLAFX00(ha) && !IS_QLA27XX(ha))) + !IS_QLAFX00(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha))) goto skip_msi; if (ql2xenablemsix == 2) @@ -3609,7 +3637,7 @@ skip_msix: if (!IS_QLA24XX(ha) && !IS_QLA2532(ha) && !IS_QLA8432(ha) && !IS_QLA8001(ha) && !IS_P3P_TYPE(ha) && !IS_QLAFX00(ha) && - !IS_QLA27XX(ha)) + !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) goto skip_msi; ret = pci_alloc_irq_vectors(ha->pdev, 1, 1, PCI_IRQ_MSI); diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 5400696e1f6b..133f5f6270ff 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -567,9 +567,9 @@ mbx_done: mcp->mb[0]); } else if (rval) { if (ql2xextended_error_logging & (ql_dbg_disc|ql_dbg_mbx)) { - pr_warn("%s [%s]-%04x:%ld: **** Failed", QL_MSGHDR, + pr_warn("%s [%s]-%04x:%ld: **** Failed=%x", QL_MSGHDR, dev_name(&ha->pdev->dev), 0x1020+0x800, - vha->host_no); + vha->host_no, rval); mboxes = mcp->in_mb; cnt = 4; for (i = 0; i < ha->mbx_count && cnt; i++, mboxes >>= 1) @@ -634,14 +634,15 @@ qla2x00_load_ram(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t risc_addr, mcp->out_mb |= MBX_4; } - mcp->in_mb = MBX_0; + mcp->in_mb = MBX_1|MBX_0; mcp->tov = MBX_TOV_SECONDS; mcp->flags = 0; rval = qla2x00_mailbox_command(vha, mcp); if (rval != QLA_SUCCESS) { ql_dbg(ql_dbg_mbx, vha, 0x1023, - "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); + "Failed=%x mb[0]=%x mb[1]=%x.\n", + rval, mcp->mb[0], mcp->mb[1]); } else { ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1024, "Done %s.\n", __func__); @@ -656,7 +657,7 @@ static inline uint16_t qla25xx_set_sfp_lr_dist(struct qla_hw_data *ha) { uint16_t mb4 = BIT_0; - if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) mb4 |= ha->long_range_distance << LR_DIST_FW_POS; return mb4; @@ -666,7 +667,7 @@ static inline uint16_t qla25xx_set_nvr_lr_dist(struct qla_hw_data *ha) { uint16_t mb4 = BIT_0; - if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) { + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { struct nvram_81xx *nv = ha->nvram; mb4 |= LR_DIST_FW_FIELD(nv->enhanced_features); @@ -711,7 +712,7 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr) mcp->mb[4] = 0; ha->flags.using_lr_setting = 0; if (IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) || - IS_QLA27XX(ha)) { + IS_QLA27XX(ha) || IS_QLA28XX(ha)) { if (ql2xautodetectsfp) { if (ha->flags.detected_lr_sfp) { mcp->mb[4] |= @@ -730,19 +731,20 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr) } } - if (ql2xnvmeenable && IS_QLA27XX(ha)) + if (ql2xnvmeenable && (IS_QLA27XX(ha) || IS_QLA28XX(ha))) mcp->mb[4] |= NVME_ENABLE_FLAG; - if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) { + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { struct nvram_81xx *nv = ha->nvram; /* set minimum speed if specified in nvram */ - if (nv->min_link_speed >= 2 && - nv->min_link_speed <= 5) { + if (nv->min_supported_speed >= 2 && + nv->min_supported_speed <= 5) { mcp->mb[4] |= BIT_4; - mcp->mb[11] = nv->min_link_speed; + mcp->mb[11] |= nv->min_supported_speed & 0xF; mcp->out_mb |= MBX_11; mcp->in_mb |= BIT_5; - vha->min_link_speed_feat = nv->min_link_speed; + vha->min_supported_speed = + nv->min_supported_speed; } } @@ -770,34 +772,39 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr) if (rval != QLA_SUCCESS) { ql_dbg(ql_dbg_mbx, vha, 0x1026, "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); - } else { - if (IS_FWI2_CAPABLE(ha)) { - ha->fw_ability_mask = mcp->mb[3] << 16 | mcp->mb[2]; - ql_dbg(ql_dbg_mbx, vha, 0x119a, - "fw_ability_mask=%x.\n", ha->fw_ability_mask); - ql_dbg(ql_dbg_mbx, vha, 0x1027, - "exchanges=%x.\n", mcp->mb[1]); - if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) { - ha->max_speed_sup = mcp->mb[2] & BIT_0; - ql_dbg(ql_dbg_mbx, vha, 0x119b, - "Maximum speed supported=%s.\n", - ha->max_speed_sup ? "32Gps" : "16Gps"); - if (vha->min_link_speed_feat) { - ha->min_link_speed = mcp->mb[5]; - ql_dbg(ql_dbg_mbx, vha, 0x119c, - "Minimum speed set=%s.\n", - mcp->mb[5] == 5 ? "32Gps" : - mcp->mb[5] == 4 ? "16Gps" : - mcp->mb[5] == 3 ? "8Gps" : - mcp->mb[5] == 2 ? "4Gps" : - "unknown"); - } - } + return rval; + } + + if (!IS_FWI2_CAPABLE(ha)) + goto done; + + ha->fw_ability_mask = mcp->mb[3] << 16 | mcp->mb[2]; + ql_dbg(ql_dbg_mbx, vha, 0x119a, + "fw_ability_mask=%x.\n", ha->fw_ability_mask); + ql_dbg(ql_dbg_mbx, vha, 0x1027, "exchanges=%x.\n", mcp->mb[1]); + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { + ha->max_supported_speed = mcp->mb[2] & (BIT_0|BIT_1); + ql_dbg(ql_dbg_mbx, vha, 0x119b, "max_supported_speed=%s.\n", + ha->max_supported_speed == 0 ? "16Gps" : + ha->max_supported_speed == 1 ? "32Gps" : + ha->max_supported_speed == 2 ? "64Gps" : "unknown"); + if (vha->min_supported_speed) { + ha->min_supported_speed = mcp->mb[5] & + (BIT_0 | BIT_1 | BIT_2); + ql_dbg(ql_dbg_mbx, vha, 0x119c, + "min_supported_speed=%s.\n", + ha->min_supported_speed == 6 ? "64Gps" : + ha->min_supported_speed == 5 ? "32Gps" : + ha->min_supported_speed == 4 ? "16Gps" : + ha->min_supported_speed == 3 ? "8Gps" : + ha->min_supported_speed == 2 ? "4Gps" : "unknown"); } - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1028, - "Done.\n"); } +done: + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1028, + "Done %s.\n", __func__); + return rval; } @@ -1053,10 +1060,10 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha) mcp->in_mb |= MBX_13|MBX_12|MBX_11|MBX_10|MBX_9|MBX_8; if (IS_FWI2_CAPABLE(ha)) mcp->in_mb |= MBX_17|MBX_16|MBX_15; - if (IS_QLA27XX(ha)) + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) mcp->in_mb |= MBX_25|MBX_24|MBX_23|MBX_22|MBX_21|MBX_20|MBX_19|MBX_18| - MBX_14|MBX_13|MBX_11|MBX_10|MBX_9|MBX_8; + MBX_14|MBX_13|MBX_11|MBX_10|MBX_9|MBX_8|MBX_7; mcp->flags = 0; mcp->tov = MBX_TOV_SECONDS; @@ -1122,7 +1129,10 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha) } } - if (IS_QLA27XX(ha)) { + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { + ha->serdes_version[0] = mcp->mb[7] & 0xff; + ha->serdes_version[1] = mcp->mb[8] >> 8; + ha->serdes_version[2] = mcp->mb[8] & 0xff; ha->mpi_version[0] = mcp->mb[10] & 0xff; ha->mpi_version[1] = mcp->mb[11] >> 8; ha->mpi_version[2] = mcp->mb[11] & 0xff; @@ -1133,6 +1143,13 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha) ha->fw_shared_ram_end = (mcp->mb[21] << 16) | mcp->mb[20]; ha->fw_ddr_ram_start = (mcp->mb[23] << 16) | mcp->mb[22]; ha->fw_ddr_ram_end = (mcp->mb[25] << 16) | mcp->mb[24]; + if (IS_QLA28XX(ha)) { + if (mcp->mb[16] & BIT_10) { + ql_log(ql_log_info, vha, 0xffff, + "FW support secure flash updates\n"); + ha->flags.secure_fw = 1; + } + } } failed: @@ -1638,7 +1655,7 @@ 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)) + if (IS_QLA27XX(vha->hw) || IS_QLA28XX(vha->hw)) mcp->in_mb |= MBX_15; mcp->tov = MBX_TOV_SECONDS; mcp->flags = 0; @@ -1692,7 +1709,7 @@ qla2x00_get_adapter_id(scsi_qla_host_t *vha, uint16_t *id, uint8_t *al_pa, } } - if (IS_QLA27XX(vha->hw)) + if (IS_QLA27XX(vha->hw) || IS_QLA28XX(vha->hw)) vha->bbcr = mcp->mb[15]; } @@ -1808,7 +1825,7 @@ qla2x00_init_firmware(scsi_qla_host_t *vha, uint16_t size) } /* 1 and 2 should normally be captured. */ mcp->in_mb = MBX_2|MBX_1|MBX_0; - if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) /* mb3 is additional info about the installed SFP. */ mcp->in_mb |= MBX_3; mcp->buf_size = size; @@ -1819,10 +1836,20 @@ qla2x00_init_firmware(scsi_qla_host_t *vha, uint16_t size) if (rval != QLA_SUCCESS) { /*EMPTY*/ ql_dbg(ql_dbg_mbx, vha, 0x104d, - "Failed=%x mb[0]=%x, mb[1]=%x, mb[2]=%x, mb[3]=%x,.\n", + "Failed=%x mb[0]=%x, mb[1]=%x, mb[2]=%x, mb[3]=%x.\n", rval, mcp->mb[0], mcp->mb[1], mcp->mb[2], mcp->mb[3]); + if (ha->init_cb) { + ql_dbg(ql_dbg_mbx, vha, 0x104d, "init_cb:\n"); + ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, + 0x0104d, ha->init_cb, sizeof(*ha->init_cb)); + } + if (ha->ex_init_cb && ha->ex_init_cb->ex_version) { + ql_dbg(ql_dbg_mbx, vha, 0x104d, "ex_init_cb:\n"); + ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, + 0x0104d, ha->ex_init_cb, sizeof(*ha->ex_init_cb)); + } } else { - if (IS_QLA27XX(ha)) { + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { if (mcp->mb[2] == 6 || mcp->mb[3] == 2) ql_dbg(ql_dbg_mbx, vha, 0x119d, "Invalid SFP/Validation Failed\n"); @@ -2006,7 +2033,7 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt) /* Passback COS information. */ fcport->supported_classes = (pd->options & BIT_4) ? - FC_COS_CLASS2: FC_COS_CLASS3; + FC_COS_CLASS2 : FC_COS_CLASS3; } gpd_error_out: @@ -2076,7 +2103,7 @@ qla2x00_get_firmware_state(scsi_qla_host_t *vha, uint16_t *states) /*EMPTY*/ ql_dbg(ql_dbg_mbx, vha, 0x1055, "Failed=%x.\n", rval); } else { - if (IS_QLA27XX(ha)) { + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { if (mcp->mb[2] == 6 || mcp->mb[3] == 2) ql_dbg(ql_dbg_mbx, vha, 0x119e, "Invalid SFP/Validation Failed\n"); @@ -2859,7 +2886,8 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *vha) mcp->mb[0] = MBC_GET_RESOURCE_COUNTS; mcp->out_mb = MBX_0; mcp->in_mb = MBX_11|MBX_10|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; - if (IS_QLA81XX(vha->hw) || IS_QLA83XX(vha->hw) || IS_QLA27XX(vha->hw)) + if (IS_QLA81XX(ha) || IS_QLA83XX(ha) || + IS_QLA27XX(ha) || IS_QLA28XX(ha)) mcp->in_mb |= MBX_12; mcp->tov = MBX_TOV_SECONDS; mcp->flags = 0; @@ -2884,7 +2912,8 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *vha) ha->orig_fw_iocb_count = mcp->mb[10]; if (ha->flags.npiv_supported) ha->max_npiv_vports = mcp->mb[11]; - if (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha)) + if (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha) || + IS_QLA28XX(ha)) ha->fw_max_fcf_count = mcp->mb[12]; } @@ -3248,7 +3277,7 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport, /* Issue marker IOCB. */ rval2 = qla2x00_marker(vha, ha->base_qpair, fcport->loop_id, l, - type == TCF_LUN_RESET ? MK_SYNC_ID_LUN: MK_SYNC_ID); + type == TCF_LUN_RESET ? MK_SYNC_ID_LUN : MK_SYNC_ID); if (rval2 != QLA_SUCCESS) { ql_dbg(ql_dbg_mbx, vha, 0x1099, "Failed to issue marker IOCB (%x).\n", rval2); @@ -3323,7 +3352,7 @@ qla2x00_write_serdes_word(scsi_qla_host_t *vha, uint16_t addr, uint16_t data) mbx_cmd_t *mcp = &mc; if (!IS_QLA25XX(vha->hw) && !IS_QLA2031(vha->hw) && - !IS_QLA27XX(vha->hw)) + !IS_QLA27XX(vha->hw) && !IS_QLA28XX(vha->hw)) return QLA_FUNCTION_FAILED; ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1182, @@ -3362,7 +3391,7 @@ qla2x00_read_serdes_word(scsi_qla_host_t *vha, uint16_t addr, uint16_t *data) mbx_cmd_t *mcp = &mc; if (!IS_QLA25XX(vha->hw) && !IS_QLA2031(vha->hw) && - !IS_QLA27XX(vha->hw)) + !IS_QLA27XX(vha->hw) && !IS_QLA28XX(vha->hw)) return QLA_FUNCTION_FAILED; ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1185, @@ -3631,7 +3660,8 @@ qla2x00_enable_fce_trace(scsi_qla_host_t *vha, dma_addr_t fce_dma, "Entered %s.\n", __func__); if (!IS_QLA25XX(vha->hw) && !IS_QLA81XX(vha->hw) && - !IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw)) + !IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw) && + !IS_QLA28XX(vha->hw)) return QLA_FUNCTION_FAILED; if (unlikely(pci_channel_offline(vha->hw->pdev))) @@ -3744,7 +3774,7 @@ qla2x00_get_idma_speed(scsi_qla_host_t *vha, uint16_t loop_id, rval = qla2x00_mailbox_command(vha, mcp); /* Return mailbox statuses. */ - if (mb != NULL) { + if (mb) { mb[0] = mcp->mb[0]; mb[1] = mcp->mb[1]; mb[3] = mcp->mb[3]; @@ -3779,7 +3809,7 @@ qla2x00_set_idma_speed(scsi_qla_host_t *vha, uint16_t loop_id, mcp->mb[0] = MBC_PORT_PARAMS; mcp->mb[1] = loop_id; mcp->mb[2] = BIT_0; - mcp->mb[3] = port_speed & (BIT_5|BIT_4|BIT_3|BIT_2|BIT_1|BIT_0); + mcp->mb[3] = port_speed & 0x3F; mcp->mb[9] = vha->vp_idx; mcp->out_mb = MBX_9|MBX_3|MBX_2|MBX_1|MBX_0; mcp->in_mb = MBX_3|MBX_1|MBX_0; @@ -3788,7 +3818,7 @@ qla2x00_set_idma_speed(scsi_qla_host_t *vha, uint16_t loop_id, rval = qla2x00_mailbox_command(vha, mcp); /* Return mailbox statuses. */ - if (mb != NULL) { + if (mb) { mb[0] = mcp->mb[0]; mb[1] = mcp->mb[1]; mb[3] = mcp->mb[3]; @@ -4230,7 +4260,7 @@ qla84xx_verify_chip(struct scsi_qla_host *vha, uint16_t *status) ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x111c, "Dump of Verify Request.\n"); ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, vha, 0x111e, - (uint8_t *)mn, sizeof(*mn)); + mn, sizeof(*mn)); rval = qla2x00_issue_iocb_timeout(vha, mn, mn_dma, 0, 120); if (rval != QLA_SUCCESS) { @@ -4242,7 +4272,7 @@ qla84xx_verify_chip(struct scsi_qla_host *vha, uint16_t *status) ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1110, "Dump of Verify Response.\n"); ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1118, - (uint8_t *)mn, sizeof(*mn)); + mn, sizeof(*mn)); status[0] = le16_to_cpu(mn->p.rsp.comp_status); status[1] = status[0] == CS_VCS_CHIP_FAILURE ? @@ -4318,7 +4348,7 @@ qla25xx_init_req_que(struct scsi_qla_host *vha, struct req_que *req) mcp->mb[12] = req->qos; mcp->mb[11] = req->vp_idx; mcp->mb[13] = req->rid; - if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) mcp->mb[15] = 0; mcp->mb[4] = req->id; @@ -4332,9 +4362,10 @@ qla25xx_init_req_que(struct scsi_qla_host *vha, struct req_que *req) mcp->flags = MBX_DMA_OUT; mcp->tov = MBX_TOV_SECONDS * 2; - if (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha)) + if (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha) || + IS_QLA28XX(ha)) mcp->in_mb |= MBX_1; - if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) { + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { mcp->out_mb |= MBX_15; /* debug q create issue in SR-IOV */ mcp->in_mb |= MBX_9 | MBX_8 | MBX_7; @@ -4343,7 +4374,7 @@ qla25xx_init_req_que(struct scsi_qla_host *vha, struct req_que *req) spin_lock_irqsave(&ha->hardware_lock, flags); if (!(req->options & BIT_0)) { WRT_REG_DWORD(req->req_q_in, 0); - if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha)) + if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) WRT_REG_DWORD(req->req_q_out, 0); } spin_unlock_irqrestore(&ha->hardware_lock, flags); @@ -4387,7 +4418,7 @@ qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp) mcp->mb[5] = rsp->length; mcp->mb[14] = rsp->msix->entry; mcp->mb[13] = rsp->rid; - if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) mcp->mb[15] = 0; mcp->mb[4] = rsp->id; @@ -4404,7 +4435,7 @@ qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp) if (IS_QLA81XX(ha)) { mcp->out_mb |= MBX_12|MBX_11|MBX_10; mcp->in_mb |= MBX_1; - } else if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) { + } else if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { mcp->out_mb |= MBX_15|MBX_12|MBX_11|MBX_10; mcp->in_mb |= MBX_1; /* debug q create issue in SR-IOV */ @@ -4414,7 +4445,7 @@ qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp) spin_lock_irqsave(&ha->hardware_lock, flags); if (!(rsp->options & BIT_0)) { WRT_REG_DWORD(rsp->rsp_q_out, 0); - if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha)) + if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) WRT_REG_DWORD(rsp->rsp_q_in, 0); } @@ -4472,7 +4503,7 @@ qla81xx_fac_get_sector_size(scsi_qla_host_t *vha, uint32_t *sector_size) "Entered %s.\n", __func__); if (!IS_QLA81XX(vha->hw) && !IS_QLA83XX(vha->hw) && - !IS_QLA27XX(vha->hw)) + !IS_QLA27XX(vha->hw) && !IS_QLA28XX(vha->hw)) return QLA_FUNCTION_FAILED; mcp->mb[0] = MBC_FLASH_ACCESS_CTRL; @@ -4504,7 +4535,7 @@ qla81xx_fac_do_write_enable(scsi_qla_host_t *vha, int enable) mbx_cmd_t *mcp = &mc; if (!IS_QLA81XX(vha->hw) && !IS_QLA83XX(vha->hw) && - !IS_QLA27XX(vha->hw)) + !IS_QLA27XX(vha->hw) && !IS_QLA28XX(vha->hw)) return QLA_FUNCTION_FAILED; ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10df, @@ -4539,7 +4570,7 @@ qla81xx_fac_erase_sector(scsi_qla_host_t *vha, uint32_t start, uint32_t finish) mbx_cmd_t *mcp = &mc; if (!IS_QLA81XX(vha->hw) && !IS_QLA83XX(vha->hw) && - !IS_QLA27XX(vha->hw)) + !IS_QLA27XX(vha->hw) && !IS_QLA28XX(vha->hw)) return QLA_FUNCTION_FAILED; ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e2, @@ -4570,6 +4601,42 @@ qla81xx_fac_erase_sector(scsi_qla_host_t *vha, uint32_t start, uint32_t finish) } int +qla81xx_fac_semaphore_access(scsi_qla_host_t *vha, int lock) +{ + int rval = QLA_SUCCESS; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + struct qla_hw_data *ha = vha->hw; + + if (!IS_QLA81XX(ha) && !IS_QLA83XX(ha) && + !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) + return rval; + + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e2, + "Entered %s.\n", __func__); + + mcp->mb[0] = MBC_FLASH_ACCESS_CTRL; + mcp->mb[1] = (lock ? FAC_OPT_CMD_LOCK_SEMAPHORE : + FAC_OPT_CMD_UNLOCK_SEMAPHORE); + mcp->out_mb = MBX_1|MBX_0; + mcp->in_mb = MBX_1|MBX_0; + mcp->tov = MBX_TOV_SECONDS; + mcp->flags = 0; + rval = qla2x00_mailbox_command(vha, mcp); + + if (rval != QLA_SUCCESS) { + ql_dbg(ql_dbg_mbx, vha, 0x10e3, + "Failed=%x mb[0]=%x mb[1]=%x mb[2]=%x.\n", + rval, mcp->mb[0], mcp->mb[1], mcp->mb[2]); + } else { + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e4, + "Done %s.\n", __func__); + } + + return rval; +} + +int qla81xx_restart_mpi_firmware(scsi_qla_host_t *vha) { int rval = 0; @@ -4818,10 +4885,10 @@ qla2x00_read_sfp(scsi_qla_host_t *vha, dma_addr_t sfp_dma, uint8_t *sfp, if (rval != QLA_SUCCESS) { ql_dbg(ql_dbg_mbx, vha, 0x10e9, "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); - if (mcp->mb[0] == MBS_COMMAND_ERROR && - mcp->mb[1] == 0x22) + if (mcp->mb[0] == MBS_COMMAND_ERROR && mcp->mb[1] == 0x22) { /* sfp is not there */ rval = QLA_INTERFACE_ERROR; + } } else { ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ea, "Done %s.\n", __func__); @@ -5161,13 +5228,14 @@ qla2x00_write_ram_word(scsi_qla_host_t *vha, uint32_t risc_addr, uint32_t data) mcp->mb[3] = MSW(data); mcp->mb[8] = MSW(risc_addr); mcp->out_mb = MBX_8|MBX_3|MBX_2|MBX_1|MBX_0; - mcp->in_mb = MBX_0; + mcp->in_mb = MBX_1|MBX_0; mcp->tov = 30; mcp->flags = 0; rval = qla2x00_mailbox_command(vha, mcp); if (rval != QLA_SUCCESS) { ql_dbg(ql_dbg_mbx, vha, 0x1101, - "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); + "Failed=%x mb[0]=%x mb[1]=%x.\n", + rval, mcp->mb[0], mcp->mb[1]); } else { ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1102, "Done %s.\n", __func__); @@ -5278,7 +5346,7 @@ qla2x00_set_data_rate(scsi_qla_host_t *vha, uint16_t mode) mcp->out_mb = MBX_2|MBX_1|MBX_0; mcp->in_mb = MBX_2|MBX_1|MBX_0; - if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) mcp->in_mb |= MBX_4|MBX_3; mcp->tov = MBX_TOV_SECONDS; mcp->flags = 0; @@ -5316,7 +5384,7 @@ qla2x00_get_data_rate(scsi_qla_host_t *vha) mcp->mb[1] = QLA_GET_DATA_RATE; mcp->out_mb = MBX_1|MBX_0; mcp->in_mb = MBX_2|MBX_1|MBX_0; - if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) mcp->in_mb |= MBX_3; mcp->tov = MBX_TOV_SECONDS; mcp->flags = 0; @@ -5346,7 +5414,7 @@ qla81xx_get_port_config(scsi_qla_host_t *vha, uint16_t *mb) "Entered %s.\n", __func__); if (!IS_QLA81XX(ha) && !IS_QLA83XX(ha) && !IS_QLA8044(ha) && - !IS_QLA27XX(ha)) + !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) return QLA_FUNCTION_FAILED; mcp->mb[0] = MBC_GET_PORT_CONFIG; mcp->out_mb = MBX_0; @@ -5662,6 +5730,7 @@ qla8044_md_get_template(scsi_qla_host_t *vha) mbx_cmd_t *mcp = &mc; int rval = QLA_FUNCTION_FAILED; int offset = 0, size = MINIDUMP_SIZE_36K; + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0xb11f, "Entered %s.\n", __func__); @@ -5842,7 +5911,7 @@ qla83xx_wr_reg(scsi_qla_host_t *vha, uint32_t reg, uint32_t data) mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha)) + if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) return QLA_FUNCTION_FAILED; ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1130, @@ -5917,7 +5986,7 @@ qla83xx_rd_reg(scsi_qla_host_t *vha, uint32_t reg, uint32_t *data) struct qla_hw_data *ha = vha->hw; unsigned long retry_max_time = jiffies + (2 * HZ); - if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha)) + if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) return QLA_FUNCTION_FAILED; ql_dbg(ql_dbg_mbx, vha, 0x114b, "Entered %s.\n", __func__); @@ -5967,7 +6036,7 @@ qla83xx_restart_nic_firmware(scsi_qla_host_t *vha) mbx_cmd_t *mcp = &mc; struct qla_hw_data *ha = vha->hw; - if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha)) + if (!IS_QLA83XX(ha)) return QLA_FUNCTION_FAILED; ql_dbg(ql_dbg_mbx, vha, 0x1143, "Entered %s.\n", __func__); @@ -6101,7 +6170,8 @@ qla26xx_dport_diagnostics(scsi_qla_host_t *vha, mbx_cmd_t *mcp = &mc; dma_addr_t dd_dma; - if (!IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw)) + if (!IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw) && + !IS_QLA28XX(vha->hw)) return QLA_FUNCTION_FAILED; ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x119f, @@ -6318,7 +6388,13 @@ int __qla24xx_parse_gpdb(struct scsi_qla_host *vha, fc_port_t *fcport, fcport->d_id.b.rsvd_1 = 0; if (fcport->fc4f_nvme) { - fcport->port_type = FCT_NVME; + fcport->port_type = 0; + if ((pd->prli_svc_param_word_3[0] & BIT_5) == 0) + fcport->port_type |= FCT_NVME_INITIATOR; + if ((pd->prli_svc_param_word_3[0] & BIT_4) == 0) + fcport->port_type |= FCT_NVME_TARGET; + if ((pd->prli_svc_param_word_3[0] & BIT_3) == 0) + fcport->port_type |= FCT_NVME_DISCOVERY; } else { /* If not target must be initiator or unknown type. */ if ((pd->prli_svc_param_word_3[0] & BIT_4) == 0) @@ -6507,3 +6583,101 @@ int qla24xx_res_count_wait(struct scsi_qla_host *vha, done: return rval; } + +int qla28xx_secure_flash_update(scsi_qla_host_t *vha, uint16_t opts, + uint16_t region, uint32_t len, dma_addr_t sfub_dma_addr, + uint32_t sfub_len) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + mcp->mb[0] = MBC_SECURE_FLASH_UPDATE; + mcp->mb[1] = opts; + mcp->mb[2] = region; + mcp->mb[3] = MSW(len); + mcp->mb[4] = LSW(len); + mcp->mb[5] = MSW(sfub_dma_addr); + mcp->mb[6] = LSW(sfub_dma_addr); + mcp->mb[7] = MSW(MSD(sfub_dma_addr)); + mcp->mb[8] = LSW(MSD(sfub_dma_addr)); + mcp->mb[9] = sfub_len; + mcp->out_mb = + MBX_9|MBX_8|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_2|MBX_1|MBX_0; + mcp->tov = MBX_TOV_SECONDS; + mcp->flags = 0; + rval = qla2x00_mailbox_command(vha, mcp); + + if (rval != QLA_SUCCESS) { + ql_dbg(ql_dbg_mbx, vha, 0xffff, "%s(%ld): failed rval 0x%x, %x %x %x", + __func__, vha->host_no, rval, mcp->mb[0], mcp->mb[1], + mcp->mb[2]); + } + + return rval; +} + +int qla2xxx_write_remote_register(scsi_qla_host_t *vha, uint32_t addr, + uint32_t data) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e8, + "Entered %s.\n", __func__); + + mcp->mb[0] = MBC_WRITE_REMOTE_REG; + mcp->mb[1] = LSW(addr); + mcp->mb[2] = MSW(addr); + mcp->mb[3] = LSW(data); + mcp->mb[4] = MSW(data); + mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_1|MBX_0; + mcp->tov = MBX_TOV_SECONDS; + mcp->flags = 0; + rval = qla2x00_mailbox_command(vha, mcp); + + if (rval != QLA_SUCCESS) { + ql_dbg(ql_dbg_mbx, vha, 0x10e9, + "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); + } else { + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ea, + "Done %s.\n", __func__); + } + + return rval; +} + +int qla2xxx_read_remote_register(scsi_qla_host_t *vha, uint32_t addr, + uint32_t *data) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e8, + "Entered %s.\n", __func__); + + mcp->mb[0] = MBC_READ_REMOTE_REG; + mcp->mb[1] = LSW(addr); + mcp->mb[2] = MSW(addr); + mcp->out_mb = MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->tov = MBX_TOV_SECONDS; + mcp->flags = 0; + rval = qla2x00_mailbox_command(vha, mcp); + + *data = (uint32_t)((((uint32_t)mcp->mb[4]) << 16) | mcp->mb[3]); + + if (rval != QLA_SUCCESS) { + ql_dbg(ql_dbg_mbx, vha, 0x10e9, + "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); + } else { + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ea, + "Done %s.\n", __func__); + } + + return rval; +} diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index 099d8e9851cb..b2977e49356b 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c @@ -905,7 +905,8 @@ static void qla_ctrlvp_sp_done(void *s, int res) { struct srb *sp = s; - complete(&sp->comp); + if (sp->comp) + complete(sp->comp); /* don't free sp here. Let the caller do the free */ } @@ -922,6 +923,7 @@ int qla24xx_control_vp(scsi_qla_host_t *vha, int cmd) struct qla_hw_data *ha = vha->hw; int vp_index = vha->vp_idx; struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); + DECLARE_COMPLETION_ONSTACK(comp); srb_t *sp; ql_dbg(ql_dbg_vport, vha, 0x10c1, @@ -936,6 +938,7 @@ int qla24xx_control_vp(scsi_qla_host_t *vha, int cmd) sp->type = SRB_CTRL_VP; sp->name = "ctrl_vp"; + sp->comp = ∁ sp->done = qla_ctrlvp_sp_done; sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout; qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2); @@ -953,7 +956,9 @@ int qla24xx_control_vp(scsi_qla_host_t *vha, int cmd) ql_dbg(ql_dbg_vport, vha, 0x113f, "%s hndl %x submitted\n", sp->name, sp->handle); - wait_for_completion(&sp->comp); + wait_for_completion(&comp); + sp->comp = NULL; + rval = sp->rc; switch (rval) { case QLA_FUNCTION_TIMEOUT: diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c index 60f964c53c01..942ee13b96a4 100644 --- a/drivers/scsi/qla2xxx/qla_mr.c +++ b/drivers/scsi/qla2xxx/qla_mr.c @@ -273,9 +273,9 @@ premature_exit: if (rval) { ql_log(ql_log_warn, base_vha, 0x1163, - "**** Failed mbx[0]=%x, mb[1]=%x, mb[2]=%x, " - "mb[3]=%x, cmd=%x ****.\n", - mcp->mb[0], mcp->mb[1], mcp->mb[2], mcp->mb[3], command); + "**** Failed=%x mbx[0]=%x, mb[1]=%x, mb[2]=%x, mb[3]=%x, cmd=%x ****.\n", + rval, mcp->mb[0], mcp->mb[1], mcp->mb[2], mcp->mb[3], + command); } else { ql_dbg(ql_dbg_mbx, base_vha, 0x1164, "Done %s.\n", __func__); } @@ -629,17 +629,20 @@ qlafx00_soc_cpu_reset(scsi_qla_host_t *vha) * * Returns 0 on success. */ -void +int qlafx00_soft_reset(scsi_qla_host_t *vha) { struct qla_hw_data *ha = vha->hw; + int rval = QLA_FUNCTION_FAILED; if (unlikely(pci_channel_offline(ha->pdev) && ha->flags.pci_channel_io_perm_failure)) - return; + return rval; ha->isp_ops->disable_intrs(ha); qlafx00_soc_cpu_reset(vha); + + return QLA_SUCCESS; } /** @@ -1138,8 +1141,8 @@ qlafx00_find_all_targets(scsi_qla_host_t *vha, ql_dbg(ql_dbg_disc + ql_dbg_init, vha, 0x2088, "Listing Target bit map...\n"); - ql_dump_buffer(ql_dbg_disc + ql_dbg_init, vha, - 0x2089, (uint8_t *)ha->gid_list, 32); + ql_dump_buffer(ql_dbg_disc + ql_dbg_init, vha, 0x2089, + ha->gid_list, 32); /* Allocate temporary rmtport for any new rmtports discovered. */ new_fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL); @@ -1320,6 +1323,7 @@ qlafx00_configure_devices(scsi_qla_host_t *vha) { int rval; unsigned long flags; + rval = QLA_SUCCESS; flags = vha->dpc_flags; @@ -1913,8 +1917,7 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type) phost_info->domainname, phost_info->hostdriver); ql_dump_buffer(ql_dbg_init + ql_dbg_disc, vha, 0x014d, - (uint8_t *)phost_info, - sizeof(struct host_system_info)); + phost_info, sizeof(*phost_info)); } } @@ -1968,7 +1971,7 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type) vha->d_id.b.al_pa = pinfo->port_id[2]; qlafx00_update_host_attr(vha, pinfo); ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0141, - (uint8_t *)pinfo, 16); + pinfo, 16); } else if (fx_type == FXDISC_GET_TGT_NODE_INFO) { struct qlafx00_tgt_node_info *pinfo = (struct qlafx00_tgt_node_info *) fdisc->u.fxiocb.rsp_addr; @@ -1976,12 +1979,12 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type) memcpy(fcport->port_name, pinfo->tgt_node_wwpn, WWN_SIZE); fcport->port_type = FCT_TARGET; ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0144, - (uint8_t *)pinfo, 16); + pinfo, 16); } else if (fx_type == FXDISC_GET_TGT_NODE_LIST) { struct qlafx00_tgt_node_info *pinfo = (struct qlafx00_tgt_node_info *) fdisc->u.fxiocb.rsp_addr; ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0146, - (uint8_t *)pinfo, 16); + pinfo, 16); memcpy(vha->hw->gid_list, pinfo, QLAFX00_TGT_NODE_LIST_SIZE); } else if (fx_type == FXDISC_ABORT_IOCTL) fdisc->u.fxiocb.result = @@ -2248,18 +2251,16 @@ qlafx00_ioctl_iosb_entry(scsi_qla_host_t *vha, struct req_que *req, fw_sts_ptr = bsg_job->reply + sizeof(struct fc_bsg_reply); - memcpy(fw_sts_ptr, (uint8_t *)&fstatus, - sizeof(struct qla_mt_iocb_rsp_fx00)); + memcpy(fw_sts_ptr, &fstatus, sizeof(fstatus)); bsg_job->reply_len = sizeof(struct fc_bsg_reply) + sizeof(struct qla_mt_iocb_rsp_fx00) + sizeof(uint8_t); ql_dump_buffer(ql_dbg_user + ql_dbg_verbose, - sp->fcport->vha, 0x5080, - (uint8_t *)pkt, sizeof(struct ioctl_iocb_entry_fx00)); + sp->vha, 0x5080, pkt, sizeof(*pkt)); ql_dump_buffer(ql_dbg_user + ql_dbg_verbose, - sp->fcport->vha, 0x5074, - (uint8_t *)fw_sts_ptr, sizeof(struct qla_mt_iocb_rsp_fx00)); + sp->vha, 0x5074, + fw_sts_ptr, sizeof(fstatus)); res = bsg_reply->result = DID_OK << 16; bsg_reply->reply_payload_rcv_len = @@ -2597,7 +2598,7 @@ qlafx00_status_cont_entry(struct rsp_que *rsp, sts_cont_entry_t *pkt) /* Move sense data. */ ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x304e, - (uint8_t *)pkt, sizeof(sts_cont_entry_t)); + pkt, sizeof(*pkt)); memcpy(sense_ptr, pkt->data, sense_sz); ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x304a, sense_ptr, sense_sz); @@ -2992,7 +2993,7 @@ qlafx00_build_scsi_iocbs(srb_t *sp, struct cmd_type_7_fx00 *cmd_pkt, uint16_t tot_dsds, struct cmd_type_7_fx00 *lcmd_pkt) { uint16_t avail_dsds; - __le32 *cur_dsd; + struct dsd64 *cur_dsd; scsi_qla_host_t *vha; struct scsi_cmnd *cmd; struct scatterlist *sg; @@ -3028,12 +3029,10 @@ qlafx00_build_scsi_iocbs(srb_t *sp, struct cmd_type_7_fx00 *cmd_pkt, /* One DSD is available in the Command Type 3 IOCB */ avail_dsds = 1; - cur_dsd = (__le32 *)&lcmd_pkt->dseg_0_address; + cur_dsd = &lcmd_pkt->dsd; /* Load data segments */ scsi_for_each_sg(cmd, sg, tot_dsds, i) { - dma_addr_t sle_dma; - /* Allocate additional continuation packets? */ if (avail_dsds == 0) { /* @@ -3043,26 +3042,23 @@ qlafx00_build_scsi_iocbs(srb_t *sp, struct cmd_type_7_fx00 *cmd_pkt, memset(&lcont_pkt, 0, REQUEST_ENTRY_SIZE); cont_pkt = qlafx00_prep_cont_type1_iocb(req, &lcont_pkt); - cur_dsd = (__le32 *)lcont_pkt.dseg_0_address; + cur_dsd = lcont_pkt.dsd; avail_dsds = 5; cont = 1; } - sle_dma = sg_dma_address(sg); - *cur_dsd++ = cpu_to_le32(LSD(sle_dma)); - *cur_dsd++ = cpu_to_le32(MSD(sle_dma)); - *cur_dsd++ = cpu_to_le32(sg_dma_len(sg)); + append_dsd64(&cur_dsd, sg); avail_dsds--; if (avail_dsds == 0 && cont == 1) { cont = 0; memcpy_toio((void __iomem *)cont_pkt, &lcont_pkt, - REQUEST_ENTRY_SIZE); + sizeof(lcont_pkt)); } } if (avail_dsds != 0 && cont == 1) { memcpy_toio((void __iomem *)cont_pkt, &lcont_pkt, - REQUEST_ENTRY_SIZE); + sizeof(lcont_pkt)); } } @@ -3172,9 +3168,9 @@ qlafx00_start_scsi(srb_t *sp) lcmd_pkt.entry_status = (uint8_t) rsp->id; ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x302e, - (uint8_t *)cmd->cmnd, cmd->cmd_len); + cmd->cmnd, cmd->cmd_len); ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x3032, - (uint8_t *)&lcmd_pkt, REQUEST_ENTRY_SIZE); + &lcmd_pkt, sizeof(lcmd_pkt)); memcpy_toio((void __iomem *)cmd_pkt, &lcmd_pkt, REQUEST_ENTRY_SIZE); wmb(); @@ -3282,11 +3278,9 @@ qlafx00_fxdisc_iocb(srb_t *sp, struct fxdisc_entry_fx00 *pfxiocb) fx_iocb.req_dsdcnt = cpu_to_le16(1); fx_iocb.req_xfrcnt = cpu_to_le16(fxio->u.fxiocb.req_len); - fx_iocb.dseg_rq_address[0] = - cpu_to_le32(LSD(fxio->u.fxiocb.req_dma_handle)); - fx_iocb.dseg_rq_address[1] = - cpu_to_le32(MSD(fxio->u.fxiocb.req_dma_handle)); - fx_iocb.dseg_rq_len = + put_unaligned_le64(fxio->u.fxiocb.req_dma_handle, + &fx_iocb.dseg_rq.address); + fx_iocb.dseg_rq.length = cpu_to_le32(fxio->u.fxiocb.req_len); } @@ -3294,11 +3288,9 @@ qlafx00_fxdisc_iocb(srb_t *sp, struct fxdisc_entry_fx00 *pfxiocb) fx_iocb.rsp_dsdcnt = cpu_to_le16(1); fx_iocb.rsp_xfrcnt = cpu_to_le16(fxio->u.fxiocb.rsp_len); - fx_iocb.dseg_rsp_address[0] = - cpu_to_le32(LSD(fxio->u.fxiocb.rsp_dma_handle)); - fx_iocb.dseg_rsp_address[1] = - cpu_to_le32(MSD(fxio->u.fxiocb.rsp_dma_handle)); - fx_iocb.dseg_rsp_len = + put_unaligned_le64(fxio->u.fxiocb.rsp_dma_handle, + &fx_iocb.dseg_rsp.address); + fx_iocb.dseg_rsp.length = cpu_to_le32(fxio->u.fxiocb.rsp_len); } @@ -3308,6 +3300,7 @@ qlafx00_fxdisc_iocb(srb_t *sp, struct fxdisc_entry_fx00 *pfxiocb) fx_iocb.flags = fxio->u.fxiocb.flags; } else { struct scatterlist *sg; + bsg_job = sp->u.bsg_job; bsg_request = bsg_job->request; piocb_rqst = (struct qla_mt_iocb_rqst_fx00 *) @@ -3327,19 +3320,17 @@ qlafx00_fxdisc_iocb(srb_t *sp, struct fxdisc_entry_fx00 *pfxiocb) int avail_dsds, tot_dsds; cont_a64_entry_t lcont_pkt; cont_a64_entry_t *cont_pkt = NULL; - __le32 *cur_dsd; + struct dsd64 *cur_dsd; int index = 0, cont = 0; fx_iocb.req_dsdcnt = cpu_to_le16(bsg_job->request_payload.sg_cnt); tot_dsds = bsg_job->request_payload.sg_cnt; - cur_dsd = (__le32 *)&fx_iocb.dseg_rq_address[0]; + cur_dsd = &fx_iocb.dseg_rq; avail_dsds = 1; for_each_sg(bsg_job->request_payload.sg_list, sg, tot_dsds, index) { - dma_addr_t sle_dma; - /* Allocate additional continuation packets? */ if (avail_dsds == 0) { /* @@ -3351,17 +3342,13 @@ qlafx00_fxdisc_iocb(srb_t *sp, struct fxdisc_entry_fx00 *pfxiocb) cont_pkt = qlafx00_prep_cont_type1_iocb( sp->vha->req, &lcont_pkt); - cur_dsd = (__le32 *) - lcont_pkt.dseg_0_address; + cur_dsd = lcont_pkt.dsd; avail_dsds = 5; cont = 1; entry_cnt++; } - sle_dma = sg_dma_address(sg); - *cur_dsd++ = cpu_to_le32(LSD(sle_dma)); - *cur_dsd++ = cpu_to_le32(MSD(sle_dma)); - *cur_dsd++ = cpu_to_le32(sg_dma_len(sg)); + append_dsd64(&cur_dsd, sg); avail_dsds--; if (avail_dsds == 0 && cont == 1) { @@ -3389,19 +3376,17 @@ qlafx00_fxdisc_iocb(srb_t *sp, struct fxdisc_entry_fx00 *pfxiocb) int avail_dsds, tot_dsds; cont_a64_entry_t lcont_pkt; cont_a64_entry_t *cont_pkt = NULL; - __le32 *cur_dsd; + struct dsd64 *cur_dsd; int index = 0, cont = 0; fx_iocb.rsp_dsdcnt = cpu_to_le16(bsg_job->reply_payload.sg_cnt); tot_dsds = bsg_job->reply_payload.sg_cnt; - cur_dsd = (__le32 *)&fx_iocb.dseg_rsp_address[0]; + cur_dsd = &fx_iocb.dseg_rsp; avail_dsds = 1; for_each_sg(bsg_job->reply_payload.sg_list, sg, tot_dsds, index) { - dma_addr_t sle_dma; - /* Allocate additional continuation packets? */ if (avail_dsds == 0) { /* @@ -3413,17 +3398,13 @@ qlafx00_fxdisc_iocb(srb_t *sp, struct fxdisc_entry_fx00 *pfxiocb) cont_pkt = qlafx00_prep_cont_type1_iocb( sp->vha->req, &lcont_pkt); - cur_dsd = (__le32 *) - lcont_pkt.dseg_0_address; + cur_dsd = lcont_pkt.dsd; avail_dsds = 5; cont = 1; entry_cnt++; } - sle_dma = sg_dma_address(sg); - *cur_dsd++ = cpu_to_le32(LSD(sle_dma)); - *cur_dsd++ = cpu_to_le32(MSD(sle_dma)); - *cur_dsd++ = cpu_to_le32(sg_dma_len(sg)); + append_dsd64(&cur_dsd, sg); avail_dsds--; if (avail_dsds == 0 && cont == 1) { @@ -3454,10 +3435,8 @@ qlafx00_fxdisc_iocb(srb_t *sp, struct fxdisc_entry_fx00 *pfxiocb) } ql_dump_buffer(ql_dbg_user + ql_dbg_verbose, - sp->vha, 0x3047, - (uint8_t *)&fx_iocb, sizeof(struct fxdisc_entry_fx00)); + sp->vha, 0x3047, &fx_iocb, sizeof(fx_iocb)); - memcpy_toio((void __iomem *)pfxiocb, &fx_iocb, - sizeof(struct fxdisc_entry_fx00)); + memcpy_toio((void __iomem *)pfxiocb, &fx_iocb, sizeof(fx_iocb)); wmb(); } diff --git a/drivers/scsi/qla2xxx/qla_mr.h b/drivers/scsi/qla2xxx/qla_mr.h index aeaa1b40b1fc..4567f0c42486 100644 --- a/drivers/scsi/qla2xxx/qla_mr.h +++ b/drivers/scsi/qla2xxx/qla_mr.h @@ -7,6 +7,8 @@ #ifndef __QLA_MR_H #define __QLA_MR_H +#include "qla_dsd.h" + /* * The PCI VendorID and DeviceID for our board. */ @@ -46,8 +48,7 @@ struct cmd_type_7_fx00 { uint8_t fcp_cdb[MAX_CMDSZ]; /* SCSI command words. */ __le32 byte_count; /* Total byte count. */ - uint32_t dseg_0_address[2]; /* Data segment 0 address. */ - uint32_t dseg_0_len; /* Data segment 0 length. */ + struct dsd64 dsd; }; #define STATUS_TYPE_FX00 0x01 /* Status entry. */ @@ -176,10 +177,8 @@ struct fxdisc_entry_fx00 { uint8_t flags; uint8_t reserved_1; - __le32 dseg_rq_address[2]; /* Data segment 0 address. */ - __le32 dseg_rq_len; /* Data segment 0 length. */ - __le32 dseg_rsp_address[2]; /* Data segment 1 address. */ - __le32 dseg_rsp_len; /* Data segment 1 length. */ + struct dsd64 dseg_rq; + struct dsd64 dseg_rsp; __le32 dataword; __le32 adapid; diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c index 41c85da3ab32..22e3fba28e51 100644 --- a/drivers/scsi/qla2xxx/qla_nvme.c +++ b/drivers/scsi/qla2xxx/qla_nvme.c @@ -131,14 +131,10 @@ static void qla_nvme_sp_ls_done(void *ptr, int res) struct nvmefc_ls_req *fd; struct nvme_private *priv; - if (atomic_read(&sp->ref_count) == 0) { - ql_log(ql_log_warn, sp->fcport->vha, 0x2123, - "SP reference-count to ZERO on LS_done -- sp=%p.\n", sp); + if (WARN_ON_ONCE(atomic_read(&sp->ref_count) == 0)) return; - } - if (!atomic_dec_and_test(&sp->ref_count)) - return; + atomic_dec(&sp->ref_count); if (res) res = -EINVAL; @@ -161,15 +157,18 @@ static void qla_nvme_sp_done(void *ptr, int res) nvme = &sp->u.iocb_cmd; fd = nvme->u.nvme.desc; - if (!atomic_dec_and_test(&sp->ref_count)) + if (WARN_ON_ONCE(atomic_read(&sp->ref_count) == 0)) return; - if (res == QLA_SUCCESS) - fd->status = 0; - else - fd->status = NVME_SC_INTERNAL; + atomic_dec(&sp->ref_count); - fd->rcv_rsplen = nvme->u.nvme.rsp_pyld_len; + if (res == QLA_SUCCESS) { + fd->rcv_rsplen = nvme->u.nvme.rsp_pyld_len; + } else { + fd->rcv_rsplen = 0; + fd->transferred_length = 0; + } + fd->status = 0; fd->done(fd); qla2xxx_rel_qpair_sp(sp->qpair, sp); @@ -185,14 +184,24 @@ static void qla_nvme_abort_work(struct work_struct *work) struct qla_hw_data *ha = fcport->vha->hw; int rval; - if (fcport) - ql_dbg(ql_dbg_io, fcport->vha, 0xffff, - "%s called for sp=%p, hndl=%x on fcport=%p deleted=%d\n", - __func__, sp, sp->handle, fcport, fcport->deleted); + ql_dbg(ql_dbg_io, fcport->vha, 0xffff, + "%s called for sp=%p, hndl=%x on fcport=%p deleted=%d\n", + __func__, sp, sp->handle, fcport, fcport->deleted); if (!ha->flags.fw_started && (fcport && fcport->deleted)) return; + if (ha->flags.host_shutting_down) { + ql_log(ql_log_info, sp->fcport->vha, 0xffff, + "%s Calling done on sp: %p, type: 0x%x, sp->ref_count: 0x%x\n", + __func__, sp, sp->type, atomic_read(&sp->ref_count)); + sp->done(sp, 0); + return; + } + + if (WARN_ON_ONCE(atomic_read(&sp->ref_count) == 0)) + return; + rval = ha->isp_ops->abort_command(sp); ql_dbg(ql_dbg_io, fcport->vha, 0x212b, @@ -291,7 +300,7 @@ static inline int qla2x00_start_nvme_mq(srb_t *sp) uint16_t req_cnt; uint16_t tot_dsds; uint16_t avail_dsds; - uint32_t *cur_dsd; + struct dsd64 *cur_dsd; struct req_que *req = NULL; struct scsi_qla_host *vha = sp->fcport->vha; struct qla_hw_data *ha = vha->hw; @@ -340,6 +349,7 @@ static inline int qla2x00_start_nvme_mq(srb_t *sp) if (unlikely(!fd->sqid)) { struct nvme_fc_cmd_iu *cmd = fd->cmdaddr; + if (cmd->sqe.common.opcode == nvme_admin_async_event) { nvme->u.nvme.aen_op = 1; atomic_inc(&ha->nvme_active_aen_cnt); @@ -395,25 +405,22 @@ static inline int qla2x00_start_nvme_mq(srb_t *sp) /* NVME RSP IU */ cmd_pkt->nvme_rsp_dsd_len = cpu_to_le16(fd->rsplen); - cmd_pkt->nvme_rsp_dseg_address[0] = cpu_to_le32(LSD(fd->rspdma)); - cmd_pkt->nvme_rsp_dseg_address[1] = cpu_to_le32(MSD(fd->rspdma)); + put_unaligned_le64(fd->rspdma, &cmd_pkt->nvme_rsp_dseg_address); /* NVME CNMD IU */ cmd_pkt->nvme_cmnd_dseg_len = cpu_to_le16(fd->cmdlen); - cmd_pkt->nvme_cmnd_dseg_address[0] = cpu_to_le32(LSD(fd->cmddma)); - cmd_pkt->nvme_cmnd_dseg_address[1] = cpu_to_le32(MSD(fd->cmddma)); + cmd_pkt->nvme_cmnd_dseg_address = cpu_to_le64(fd->cmddma); cmd_pkt->dseg_count = cpu_to_le16(tot_dsds); cmd_pkt->byte_count = cpu_to_le32(fd->payload_length); /* One DSD is available in the Command Type NVME IOCB */ avail_dsds = 1; - cur_dsd = (uint32_t *)&cmd_pkt->nvme_data_dseg_address[0]; + cur_dsd = &cmd_pkt->nvme_dsd; sgl = fd->first_sgl; /* Load data segments */ for_each_sg(sgl, sg, tot_dsds, i) { - dma_addr_t sle_dma; cont_a64_entry_t *cont_pkt; /* Allocate additional continuation packets? */ @@ -432,17 +439,14 @@ static inline int qla2x00_start_nvme_mq(srb_t *sp) req->ring_ptr++; } cont_pkt = (cont_a64_entry_t *)req->ring_ptr; - *((uint32_t *)(&cont_pkt->entry_type)) = - cpu_to_le32(CONTINUE_A64_TYPE); + put_unaligned_le32(CONTINUE_A64_TYPE, + &cont_pkt->entry_type); - cur_dsd = (uint32_t *)cont_pkt->dseg_0_address; - avail_dsds = 5; + cur_dsd = cont_pkt->dsd; + avail_dsds = ARRAY_SIZE(cont_pkt->dsd); } - sle_dma = sg_dma_address(sg); - *cur_dsd++ = cpu_to_le32(LSD(sle_dma)); - *cur_dsd++ = cpu_to_le32(MSD(sle_dma)); - *cur_dsd++ = cpu_to_le32(sg_dma_len(sg)); + append_dsd64(&cur_dsd, sg); avail_dsds--; } @@ -573,7 +577,7 @@ static struct nvme_fc_port_template qla_nvme_fc_transport = { .fcp_io = qla_nvme_post_cmd, .fcp_abort = qla_nvme_fcp_abort, .max_hw_queues = 8, - .max_sgl_segments = 128, + .max_sgl_segments = 1024, .max_dif_sgl_segments = 64, .dma_boundary = 0xFFFFFFFF, .local_priv_sz = 8, @@ -582,40 +586,11 @@ static struct nvme_fc_port_template qla_nvme_fc_transport = { .fcprqst_priv_sz = sizeof(struct nvme_private), }; -#define NVME_ABORT_POLLING_PERIOD 2 -static int qla_nvme_wait_on_command(srb_t *sp) -{ - int ret = QLA_SUCCESS; - - wait_event_timeout(sp->nvme_ls_waitq, (atomic_read(&sp->ref_count) > 1), - NVME_ABORT_POLLING_PERIOD*HZ); - - if (atomic_read(&sp->ref_count) > 1) - ret = QLA_FUNCTION_FAILED; - - return ret; -} - -void qla_nvme_abort(struct qla_hw_data *ha, struct srb *sp, int res) -{ - int rval; - - if (ha->flags.fw_started) { - rval = ha->isp_ops->abort_command(sp); - if (!rval && !qla_nvme_wait_on_command(sp)) - ql_log(ql_log_warn, NULL, 0x2112, - "timed out waiting on sp=%p\n", sp); - } else { - sp->done(sp, res); - } -} - static void qla_nvme_unregister_remote_port(struct work_struct *work) { struct fc_port *fcport = container_of(work, struct fc_port, nvme_del_work); struct qla_nvme_rport *qla_rport, *trport; - scsi_qla_host_t *base_vha; if (!IS_ENABLED(CONFIG_NVME_FC)) return; @@ -623,23 +598,19 @@ static void qla_nvme_unregister_remote_port(struct work_struct *work) ql_log(ql_log_warn, NULL, 0x2112, "%s: unregister remoteport on %p\n",__func__, fcport); - base_vha = pci_get_drvdata(fcport->vha->hw->pdev); - if (test_bit(PFLG_DRIVER_REMOVING, &base_vha->pci_flags)) { - ql_dbg(ql_dbg_disc, fcport->vha, 0x2114, - "%s: Notify FC-NVMe transport, set devloss=0\n", - __func__); - - nvme_fc_set_remoteport_devloss(fcport->nvme_remote_port, 0); - } - list_for_each_entry_safe(qla_rport, trport, &fcport->vha->nvme_rport_list, list) { if (qla_rport->fcport == fcport) { ql_log(ql_log_info, fcport->vha, 0x2113, "%s: fcport=%p\n", __func__, fcport); + nvme_fc_set_remoteport_devloss + (fcport->nvme_remote_port, 0); init_completion(&fcport->nvme_del_done); - nvme_fc_unregister_remoteport( - fcport->nvme_remote_port); + if (nvme_fc_unregister_remoteport + (fcport->nvme_remote_port)) + ql_log(ql_log_info, fcport->vha, 0x2114, + "%s: Failed to unregister nvme_remote_port\n", + __func__); wait_for_completion(&fcport->nvme_del_done); break; } diff --git a/drivers/scsi/qla2xxx/qla_nvme.h b/drivers/scsi/qla2xxx/qla_nvme.h index da8dad5ad693..d3b8a6440113 100644 --- a/drivers/scsi/qla2xxx/qla_nvme.h +++ b/drivers/scsi/qla2xxx/qla_nvme.h @@ -13,6 +13,7 @@ #include <linux/nvme-fc-driver.h> #include "qla_def.h" +#include "qla_dsd.h" /* default dev loss time (seconds) before transport tears down ctrl */ #define NVME_FC_DEV_LOSS_TMO 30 @@ -64,16 +65,15 @@ struct cmd_nvme { #define CF_WRITE_DATA BIT_0 uint16_t nvme_cmnd_dseg_len; /* Data segment length. */ - uint32_t nvme_cmnd_dseg_address[2]; /* Data segment address. */ - uint32_t nvme_rsp_dseg_address[2]; /* Data segment address. */ + __le64 nvme_cmnd_dseg_address __packed;/* Data segment address. */ + __le64 nvme_rsp_dseg_address __packed; /* Data segment address. */ uint32_t byte_count; /* Total byte count. */ uint8_t port_id[3]; /* PortID of destination port. */ uint8_t vp_index; - uint32_t nvme_data_dseg_address[2]; /* Data segment address. */ - uint32_t nvme_data_dseg_len; /* Data segment length. */ + struct dsd64 nvme_dsd; }; #define PT_LS4_REQUEST 0x89 /* Link Service pass-through IOCB (request) */ @@ -101,10 +101,7 @@ struct pt_ls4_request { uint32_t rsvd3; uint32_t rx_byte_count; uint32_t tx_byte_count; - uint32_t dseg0_address[2]; - uint32_t dseg0_len; - uint32_t dseg1_address[2]; - uint32_t dseg1_len; + struct dsd64 dsd[2]; }; #define PT_LS4_UNSOL 0x56 /* pass-up unsolicited rec FC-NVMe request */ @@ -145,7 +142,6 @@ struct pt_ls4_rx_unsol { int qla_nvme_register_hba(struct scsi_qla_host *); int qla_nvme_register_remote(struct scsi_qla_host *, struct fc_port *); void qla_nvme_delete(struct scsi_qla_host *); -void qla_nvme_abort(struct qla_hw_data *, struct srb *sp, int res); void qla24xx_nvme_ls4_iocb(struct scsi_qla_host *, struct pt_ls4_request *, struct req_que *); void qla24xx_async_gffid_sp_done(void *, int); diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index f2f54806f4da..c760ae354174 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -6,6 +6,7 @@ */ #include "qla_def.h" #include <linux/delay.h> +#include <linux/io-64-nonatomic-lo-hi.h> #include <linux/pci.h> #include <linux/ratelimit.h> #include <linux/vmalloc.h> @@ -608,6 +609,7 @@ qla82xx_pci_set_window(struct qla_hw_data *ha, unsigned long long addr) } else if (addr_in_range(addr, QLA82XX_ADDR_OCM0, QLA82XX_ADDR_OCM0_MAX)) { unsigned int temp1; + if ((addr & 0x00ff800) == 0xff800) { ql_log(ql_log_warn, vha, 0xb004, "%s: QM access not handled.\n", __func__); @@ -990,6 +992,7 @@ static int qla82xx_read_status_reg(struct qla_hw_data *ha, uint32_t *val) { scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev); + qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, M25P_INSTR_RDSR); qla82xx_wait_rom_busy(ha); if (qla82xx_wait_rom_done(ha)) { @@ -1030,6 +1033,7 @@ static int qla82xx_flash_set_write_enable(struct qla_hw_data *ha) { uint32_t val; + qla82xx_wait_rom_busy(ha); qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_ABYTE_CNT, 0); qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, M25P_INSTR_WREN); @@ -1047,6 +1051,7 @@ static int qla82xx_write_status_reg(struct qla_hw_data *ha, uint32_t val) { scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev); + if (qla82xx_flash_set_write_enable(ha)) return -1; qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_WDATA, val); @@ -1063,6 +1068,7 @@ static int qla82xx_write_disable_flash(struct qla_hw_data *ha) { scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev); + qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, M25P_INSTR_WRDI); if (qla82xx_wait_rom_done(ha)) { ql_log(ql_log_warn, vha, 0xb00f, @@ -1435,6 +1441,7 @@ qla82xx_fw_load_from_flash(struct qla_hw_data *ha) long memaddr = BOOTLD_START; u64 data; u32 high, low; + size = (IMAGE_START - BOOTLD_START) / 8; for (i = 0; i < size; i++) { @@ -1757,11 +1764,14 @@ qla82xx_pci_config(scsi_qla_host_t *vha) * * Returns 0 on success. */ -void +int qla82xx_reset_chip(scsi_qla_host_t *vha) { struct qla_hw_data *ha = vha->hw; + ha->isp_ops->disable_intrs(ha); + + return QLA_SUCCESS; } void qla82xx_config_rings(struct scsi_qla_host *vha) @@ -1778,10 +1788,8 @@ void qla82xx_config_rings(struct scsi_qla_host *vha) icb->response_q_inpointer = cpu_to_le16(0); icb->request_q_length = cpu_to_le16(req->length); icb->response_q_length = cpu_to_le16(rsp->length); - icb->request_q_address[0] = cpu_to_le32(LSD(req->dma)); - icb->request_q_address[1] = cpu_to_le32(MSD(req->dma)); - icb->response_q_address[0] = cpu_to_le32(LSD(rsp->dma)); - icb->response_q_address[1] = cpu_to_le32(MSD(rsp->dma)); + put_unaligned_le64(req->dma, &icb->request_q_address); + put_unaligned_le64(rsp->dma, &icb->response_q_address); WRT_REG_DWORD(®->req_q_out[0], 0); WRT_REG_DWORD(®->rsp_q_in[0], 0); @@ -1992,6 +2000,7 @@ qla82xx_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0) uint16_t __iomem *wptr; struct qla_hw_data *ha = vha->hw; struct device_reg_82xx __iomem *reg = &ha->iobase->isp82; + wptr = (uint16_t __iomem *)®->mailbox_out[1]; /* Load return mailbox registers. */ @@ -2028,7 +2037,7 @@ qla82xx_intr_handler(int irq, void *dev_id) unsigned long flags; unsigned long iter; uint32_t stat = 0; - uint16_t mb[4]; + uint16_t mb[8]; rsp = (struct rsp_que *) dev_id; if (!rsp) { @@ -2112,7 +2121,7 @@ qla82xx_msix_default(int irq, void *dev_id) unsigned long flags; uint32_t stat = 0; uint32_t host_int = 0; - uint16_t mb[4]; + uint16_t mb[8]; rsp = (struct rsp_que *) dev_id; if (!rsp) { @@ -2208,7 +2217,7 @@ qla82xx_poll(int irq, void *dev_id) int status = 0; uint32_t stat; uint32_t host_int = 0; - uint16_t mb[4]; + uint16_t mb[8]; unsigned long flags; rsp = (struct rsp_que *) dev_id; @@ -2262,6 +2271,7 @@ void qla82xx_enable_intrs(struct qla_hw_data *ha) { scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev); + qla82xx_mbx_intr_enable(vha); spin_lock_irq(&ha->hardware_lock); if (IS_QLA8044(ha)) @@ -2276,6 +2286,7 @@ void qla82xx_disable_intrs(struct qla_hw_data *ha) { scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev); + qla82xx_mbx_intr_disable(vha); spin_lock_irq(&ha->hardware_lock); if (IS_QLA8044(ha)) @@ -2658,8 +2669,8 @@ done: /* * Address and length are byte address */ -uint8_t * -qla82xx_read_optrom_data(struct scsi_qla_host *vha, uint8_t *buf, +void * +qla82xx_read_optrom_data(struct scsi_qla_host *vha, void *buf, uint32_t offset, uint32_t length) { scsi_block_requests(vha->host); @@ -2767,15 +2778,14 @@ write_done: } int -qla82xx_write_optrom_data(struct scsi_qla_host *vha, uint8_t *buf, +qla82xx_write_optrom_data(struct scsi_qla_host *vha, void *buf, uint32_t offset, uint32_t length) { int rval; /* Suspend HBA. */ scsi_block_requests(vha->host); - rval = qla82xx_write_flash_data(vha, (uint32_t *)buf, offset, - length >> 2); + rval = qla82xx_write_flash_data(vha, buf, offset, length >> 2); scsi_unblock_requests(vha->host); /* Convert return ISP82xx to generic */ @@ -4464,6 +4474,7 @@ qla82xx_beacon_on(struct scsi_qla_host *vha) int rval; struct qla_hw_data *ha = vha->hw; + qla82xx_idc_lock(ha); rval = qla82xx_mbx_beacon_ctl(vha, 1); @@ -4484,6 +4495,7 @@ qla82xx_beacon_off(struct scsi_qla_host *vha) int rval; struct qla_hw_data *ha = vha->hw; + qla82xx_idc_lock(ha); rval = qla82xx_mbx_beacon_ctl(vha, 0); diff --git a/drivers/scsi/qla2xxx/qla_nx.h b/drivers/scsi/qla2xxx/qla_nx.h index 71a41093530e..3c7beef92c35 100644 --- a/drivers/scsi/qla2xxx/qla_nx.h +++ b/drivers/scsi/qla2xxx/qla_nx.h @@ -7,7 +7,7 @@ #ifndef __QLA_NX_H #define __QLA_NX_H -#include <linux/io-64-nonatomic-lo-hi.h> +#include <scsi/scsi.h> /* * Following are the states of the Phantom. Phantom will set them and diff --git a/drivers/scsi/qla2xxx/qla_nx2.c b/drivers/scsi/qla2xxx/qla_nx2.c index fe856b602e03..369ac04d0454 100644 --- a/drivers/scsi/qla2xxx/qla_nx2.c +++ b/drivers/scsi/qla2xxx/qla_nx2.c @@ -559,12 +559,12 @@ exit_lock_error: /* * Address and length are byte address */ -uint8_t * -qla8044_read_optrom_data(struct scsi_qla_host *vha, uint8_t *buf, +void * +qla8044_read_optrom_data(struct scsi_qla_host *vha, void *buf, uint32_t offset, uint32_t length) { scsi_block_requests(vha->host); - if (qla8044_read_flash_data(vha, (uint8_t *)buf, offset, length / 4) + if (qla8044_read_flash_data(vha, buf, offset, length / 4) != QLA_SUCCESS) { ql_log(ql_log_warn, vha, 0xb08d, "%s: Failed to read from flash\n", @@ -3007,10 +3007,9 @@ qla8044_minidump_process_rddfe(struct scsi_qla_host *vha, uint16_t count; uint32_t poll, mask, modify_mask; uint32_t wait_count = 0; - uint32_t *data_ptr = *d_ptr; - struct qla8044_minidump_entry_rddfe *rddfe; + rddfe = (struct qla8044_minidump_entry_rddfe *) entry_hdr; addr1 = rddfe->addr_1; @@ -3797,7 +3796,7 @@ qla8044_write_flash_dword_mode(scsi_qla_host_t *vha, uint32_t *dwptr, } int -qla8044_write_optrom_data(struct scsi_qla_host *vha, uint8_t *buf, +qla8044_write_optrom_data(struct scsi_qla_host *vha, void *buf, uint32_t offset, uint32_t length) { int rval = QLA_FUNCTION_FAILED, i, burst_iter_count; @@ -3896,7 +3895,7 @@ qla8044_intr_handler(int irq, void *dev_id) unsigned long flags; unsigned long iter; uint32_t stat; - uint16_t mb[4]; + uint16_t mb[8]; uint32_t leg_int_ptr = 0, pf_bit; rsp = (struct rsp_que *) dev_id; diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 91f576d743fe..e1c82a0a9745 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -42,7 +42,7 @@ static struct kmem_cache *ctx_cachep; /* * error level for logging */ -int ql_errlev = ql_log_all; +uint ql_errlev = 0x8001; static int ql2xenableclass2; module_param(ql2xenableclass2, int, S_IRUGO|S_IRUSR); @@ -108,7 +108,7 @@ MODULE_PARM_DESC(ql2xshiftctondsd, "Set to control shifting of command type processing " "based on total number of SG elements."); -int ql2xfdmienable=1; +int ql2xfdmienable = 1; module_param(ql2xfdmienable, int, S_IRUGO|S_IWUSR); module_param_named(fdmi, ql2xfdmienable, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(ql2xfdmienable, @@ -154,7 +154,7 @@ MODULE_PARM_DESC(ql2xenablehba_err_chk, " 1 -- Error isolation enabled only for DIX Type 0\n" " 2 -- Error isolation enabled for all Types\n"); -int ql2xiidmaenable=1; +int ql2xiidmaenable = 1; module_param(ql2xiidmaenable, int, S_IRUGO); MODULE_PARM_DESC(ql2xiidmaenable, "Enables iIDMA settings " @@ -285,14 +285,14 @@ MODULE_PARM_DESC(qla2xuseresexchforels, "Reserve 1/2 of emergency exchanges for ELS.\n" " 0 (default): disabled"); -int ql2xprotmask; +static int ql2xprotmask; module_param(ql2xprotmask, int, 0644); MODULE_PARM_DESC(ql2xprotmask, "Override DIF/DIX protection capabilities mask\n" "Default is 0 which sets protection mask based on " "capabilities reported by HBA firmware.\n"); -int ql2xprotguard; +static int ql2xprotguard; module_param(ql2xprotguard, int, 0644); MODULE_PARM_DESC(ql2xprotguard, "Override choice of DIX checksum\n" " 0 -- Let HBA firmware decide\n" @@ -306,58 +306,12 @@ MODULE_PARM_DESC(ql2xdifbundlinginternalbuffers, "0 (Default). Based on check.\n" "1 Force using internal buffers\n"); -/* - * SCSI host template entry points - */ -static int qla2xxx_slave_configure(struct scsi_device * device); -static int qla2xxx_slave_alloc(struct scsi_device *); -static int qla2xxx_scan_finished(struct Scsi_Host *, unsigned long time); -static void qla2xxx_scan_start(struct Scsi_Host *); -static void qla2xxx_slave_destroy(struct scsi_device *); -static int qla2xxx_queuecommand(struct Scsi_Host *h, struct scsi_cmnd *cmd); -static int qla2xxx_eh_abort(struct scsi_cmnd *); -static int qla2xxx_eh_device_reset(struct scsi_cmnd *); -static int qla2xxx_eh_target_reset(struct scsi_cmnd *); -static int qla2xxx_eh_bus_reset(struct scsi_cmnd *); -static int qla2xxx_eh_host_reset(struct scsi_cmnd *); - static void qla2x00_clear_drv_active(struct qla_hw_data *); static void qla2x00_free_device(scsi_qla_host_t *); static int qla2xxx_map_queues(struct Scsi_Host *shost); static void qla2x00_destroy_deferred_work(struct qla_hw_data *); -struct scsi_host_template qla2xxx_driver_template = { - .module = THIS_MODULE, - .name = QLA2XXX_DRIVER_NAME, - .queuecommand = qla2xxx_queuecommand, - - .eh_timed_out = fc_eh_timed_out, - .eh_abort_handler = qla2xxx_eh_abort, - .eh_device_reset_handler = qla2xxx_eh_device_reset, - .eh_target_reset_handler = qla2xxx_eh_target_reset, - .eh_bus_reset_handler = qla2xxx_eh_bus_reset, - .eh_host_reset_handler = qla2xxx_eh_host_reset, - - .slave_configure = qla2xxx_slave_configure, - - .slave_alloc = qla2xxx_slave_alloc, - .slave_destroy = qla2xxx_slave_destroy, - .scan_finished = qla2xxx_scan_finished, - .scan_start = qla2xxx_scan_start, - .change_queue_depth = scsi_change_queue_depth, - .map_queues = qla2xxx_map_queues, - .this_id = -1, - .cmd_per_lun = 3, - .sg_tablesize = SG_ALL, - - .max_sectors = 0xFFFF, - .shost_attrs = qla2x00_host_attrs, - - .supported_mode = MODE_INITIATOR, - .track_queue_depth = 1, -}; - static struct scsi_transport_template *qla2xxx_transport_template = NULL; struct scsi_transport_template *qla2xxx_transport_vport_template = NULL; @@ -411,6 +365,7 @@ static void qla_init_base_qpair(struct scsi_qla_host *vha, struct req_que *req, struct rsp_que *rsp) { struct qla_hw_data *ha = vha->hw; + rsp->qpair = ha->base_qpair; rsp->req = req; ha->base_qpair->hw = ha; @@ -427,7 +382,7 @@ static void qla_init_base_qpair(struct scsi_qla_host *vha, struct req_que *req, qla_cpu_update(rsp->qpair, raw_smp_processor_id()); ha->base_qpair->pdev = ha->pdev; - if (IS_QLA27XX(ha) || IS_QLA83XX(ha)) + if (IS_QLA27XX(ha) || IS_QLA83XX(ha) || IS_QLA28XX(ha)) ha->base_qpair->reqq_start_iocbs = qla_83xx_start_iocbs; } @@ -435,6 +390,7 @@ static int qla2x00_alloc_queues(struct qla_hw_data *ha, struct req_que *req, struct rsp_que *rsp) { scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev); + ha->req_q_map = kcalloc(ha->max_req_queues, sizeof(struct req_que *), GFP_KERNEL); if (!ha->req_q_map) { @@ -726,7 +682,7 @@ qla2x00_sp_free_dma(void *ptr) } if (!ctx) - goto end; + return; if (sp->flags & SRB_CRC_CTX_DSD_VALID) { /* List assured to be having elements */ @@ -751,12 +707,6 @@ qla2x00_sp_free_dma(void *ptr) ha->gbl_dsd_avail += ctx1->dsd_use_cnt; mempool_free(ctx1, ha->ctx_mempool); } - -end: - if (sp->type != SRB_NVME_CMD && sp->type != SRB_NVME_LS) { - CMD_SP(cmd) = NULL; - qla2x00_rel_sp(sp); - } } void @@ -764,22 +714,20 @@ qla2x00_sp_compl(void *ptr, int res) { srb_t *sp = ptr; struct scsi_cmnd *cmd = GET_CMD_SP(sp); + struct completion *comp = sp->comp; - cmd->result = res; - - if (atomic_read(&sp->ref_count) == 0) { - ql_dbg(ql_dbg_io, sp->vha, 0x3015, - "SP reference-count to ZERO -- sp=%p cmd=%p.\n", - sp, GET_CMD_SP(sp)); - if (ql2xextended_error_logging & ql_dbg_io) - WARN_ON(atomic_read(&sp->ref_count) == 0); - return; - } - if (!atomic_dec_and_test(&sp->ref_count)) + if (WARN_ON_ONCE(atomic_read(&sp->ref_count) == 0)) return; + atomic_dec(&sp->ref_count); + sp->free(sp); + cmd->result = res; + CMD_SP(cmd) = NULL; cmd->scsi_done(cmd); + if (comp) + complete(comp); + qla2x00_rel_sp(sp); } void @@ -802,7 +750,7 @@ qla2xxx_qpair_sp_free_dma(void *ptr) } if (!ctx) - goto end; + return; if (sp->flags & SRB_CRC_CTX_DSD_VALID) { /* List assured to be having elements */ @@ -810,25 +758,8 @@ qla2xxx_qpair_sp_free_dma(void *ptr) sp->flags &= ~SRB_CRC_CTX_DSD_VALID; } - if (sp->flags & SRB_CRC_CTX_DMA_VALID) { - struct crc_context *ctx0 = ctx; - - dma_pool_free(ha->dl_dma_pool, ctx, ctx0->crc_ctx_dma); - sp->flags &= ~SRB_CRC_CTX_DMA_VALID; - } - - if (sp->flags & SRB_FCP_CMND_DMA_VALID) { - struct ct6_dsd *ctx1 = ctx; - dma_pool_free(ha->fcp_cmnd_dma_pool, ctx1->fcp_cmnd, - ctx1->fcp_cmnd_dma); - list_splice(&ctx1->dsd_list, &ha->gbl_dsd_list); - ha->gbl_dsd_inuse -= ctx1->dsd_use_cnt; - ha->gbl_dsd_avail += ctx1->dsd_use_cnt; - mempool_free(ctx1, ha->ctx_mempool); - sp->flags &= ~SRB_FCP_CMND_DMA_VALID; - } if (sp->flags & SRB_DIF_BUNDL_DMA_VALID) { - struct crc_context *difctx = sp->u.scmd.ctx; + struct crc_context *difctx = ctx; struct dsd_dma *dif_dsd, *nxt_dsd; list_for_each_entry_safe(dif_dsd, nxt_dsd, @@ -863,9 +794,24 @@ qla2xxx_qpair_sp_free_dma(void *ptr) sp->flags &= ~SRB_DIF_BUNDL_DMA_VALID; } -end: - CMD_SP(cmd) = NULL; - qla2xxx_rel_qpair_sp(sp->qpair, sp); + if (sp->flags & SRB_FCP_CMND_DMA_VALID) { + struct ct6_dsd *ctx1 = ctx; + + dma_pool_free(ha->fcp_cmnd_dma_pool, ctx1->fcp_cmnd, + ctx1->fcp_cmnd_dma); + list_splice(&ctx1->dsd_list, &ha->gbl_dsd_list); + ha->gbl_dsd_inuse -= ctx1->dsd_use_cnt; + ha->gbl_dsd_avail += ctx1->dsd_use_cnt; + mempool_free(ctx1, ha->ctx_mempool); + sp->flags &= ~SRB_FCP_CMND_DMA_VALID; + } + + if (sp->flags & SRB_CRC_CTX_DMA_VALID) { + struct crc_context *ctx0 = ctx; + + dma_pool_free(ha->dl_dma_pool, ctx, ctx0->crc_ctx_dma); + sp->flags &= ~SRB_CRC_CTX_DMA_VALID; + } } void @@ -873,27 +819,22 @@ qla2xxx_qpair_sp_compl(void *ptr, int res) { srb_t *sp = ptr; struct scsi_cmnd *cmd = GET_CMD_SP(sp); + struct completion *comp = sp->comp; - cmd->result = res; - - if (atomic_read(&sp->ref_count) == 0) { - ql_dbg(ql_dbg_io, sp->fcport->vha, 0x3079, - "SP reference-count to ZERO -- sp=%p cmd=%p.\n", - sp, GET_CMD_SP(sp)); - if (ql2xextended_error_logging & ql_dbg_io) - WARN_ON(atomic_read(&sp->ref_count) == 0); - return; - } - if (!atomic_dec_and_test(&sp->ref_count)) + if (WARN_ON_ONCE(atomic_read(&sp->ref_count) == 0)) return; + atomic_dec(&sp->ref_count); + sp->free(sp); + cmd->result = res; + CMD_SP(cmd) = NULL; cmd->scsi_done(cmd); + if (comp) + complete(comp); + qla2xxx_rel_qpair_sp(sp->qpair, sp); } -/* If we are SP1 here, we need to still take and release the host_lock as SP1 - * does not have the changes necessary to avoid taking host->host_lock. - */ static int qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) { @@ -908,7 +849,8 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) uint32_t tag; uint16_t hwq; - if (unlikely(test_bit(UNLOADING, &base_vha->dpc_flags))) { + if (unlikely(test_bit(UNLOADING, &base_vha->dpc_flags)) || + WARN_ON_ONCE(!rport)) { cmd->result = DID_NO_CONNECT << 16; goto qc24_fail_command; } @@ -1031,7 +973,7 @@ qla2xxx_mqueuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd, srb_t *sp; int rval; - rval = fc_remote_port_chkready(rport); + rval = rport ? fc_remote_port_chkready(rport) : FC_PORTSTATE_OFFLINE; if (rval) { cmd->result = rval; ql_dbg(ql_dbg_io + ql_dbg_verbose, vha, 0x3076, @@ -1272,7 +1214,7 @@ qla2x00_wait_for_chip_reset(scsi_qla_host_t *vha) static int sp_get(struct srb *sp) { - if (!refcount_inc_not_zero((refcount_t*)&sp->ref_count)) + if (!refcount_inc_not_zero((refcount_t *)&sp->ref_count)) /* kref get fail */ return ENXIO; else @@ -1332,7 +1274,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) unsigned int id; uint64_t lun; unsigned long flags; - int rval, wait = 0; + int rval; struct qla_hw_data *ha = vha->hw; struct qla_qpair *qpair; @@ -1345,7 +1287,6 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) ret = fc_block_scsi_eh(cmd); if (ret != 0) return ret; - ret = SUCCESS; sp = (srb_t *) CMD_SP(cmd); if (!sp) @@ -1356,7 +1297,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) return SUCCESS; spin_lock_irqsave(qpair->qp_lock_ptr, flags); - if (!CMD_SP(cmd)) { + if (sp->type != SRB_SCSI_CMD || GET_CMD_SP(sp) != cmd) { /* there's a chance an interrupt could clear the ptr as part of done & free */ spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); @@ -1377,58 +1318,31 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) "Aborting from RISC nexus=%ld:%d:%llu sp=%p cmd=%p handle=%x\n", vha->host_no, id, lun, sp, cmd, sp->handle); - /* Get a reference to the sp and drop the lock.*/ - rval = ha->isp_ops->abort_command(sp); - if (rval) { - if (rval == QLA_FUNCTION_PARAMETER_ERROR) - ret = SUCCESS; - else - ret = FAILED; - - ql_dbg(ql_dbg_taskm, vha, 0x8003, - "Abort command mbx failed cmd=%p, rval=%x.\n", cmd, rval); - } else { - ql_dbg(ql_dbg_taskm, vha, 0x8004, - "Abort command mbx success cmd=%p.\n", cmd); - wait = 1; - } - - spin_lock_irqsave(qpair->qp_lock_ptr, flags); - /* - * Clear the slot in the oustanding_cmds array if we can't find the - * command to reclaim the resources. - */ - if (rval == QLA_FUNCTION_PARAMETER_ERROR) - vha->req->outstanding_cmds[sp->handle] = NULL; + ql_dbg(ql_dbg_taskm, vha, 0x8003, + "Abort command mbx cmd=%p, rval=%x.\n", cmd, rval); - /* - * sp->done will do ref_count-- - * sp_get() took an extra count above - */ - sp->done(sp, DID_RESET << 16); - - /* Did the command return during mailbox execution? */ - if (ret == FAILED && !CMD_SP(cmd)) + switch (rval) { + case QLA_SUCCESS: + /* + * The command has been aborted. That means that the firmware + * won't report a completion. + */ + sp->done(sp, DID_ABORT << 16); ret = SUCCESS; - - if (!CMD_SP(cmd)) - wait = 0; - - spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); - - /* Wait for the command to be returned. */ - if (wait) { - if (qla2x00_eh_wait_on_command(cmd) != QLA_SUCCESS) { - ql_log(ql_log_warn, vha, 0x8006, - "Abort handler timed out cmd=%p.\n", cmd); - ret = FAILED; - } + break; + default: + /* + * Either abort failed or abort and completion raced. Let + * the SCSI core retry the abort in the former case. + */ + ret = FAILED; + break; } ql_log(ql_log_info, vha, 0x801c, - "Abort command issued nexus=%ld:%d:%llu -- %d %x.\n", - vha->host_no, id, lun, wait, ret); + "Abort command issued nexus=%ld:%d:%llu -- %x.\n", + vha->host_no, id, lun, ret); return ret; } @@ -1804,42 +1718,34 @@ static void qla2x00_abort_srb(struct qla_qpair *qp, srb_t *sp, const int res, __releases(qp->qp_lock_ptr) __acquires(qp->qp_lock_ptr) { + DECLARE_COMPLETION_ONSTACK(comp); scsi_qla_host_t *vha = qp->vha; struct qla_hw_data *ha = vha->hw; + int rval; - if (sp->type == SRB_NVME_CMD || sp->type == SRB_NVME_LS) { - if (!sp_get(sp)) { - /* got sp */ - spin_unlock_irqrestore(qp->qp_lock_ptr, *flags); - qla_nvme_abort(ha, sp, res); - spin_lock_irqsave(qp->qp_lock_ptr, *flags); - } - } else if (GET_CMD_SP(sp) && !ha->flags.eeh_busy && - !test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) && - !qla2x00_isp_reg_stat(ha) && sp->type == SRB_SCSI_CMD) { - /* - * Don't abort commands in adapter during EEH recovery as it's - * not accessible/responding. - * - * Get a reference to the sp and drop the lock. The reference - * ensures this sp->done() call and not the call in - * qla2xxx_eh_abort() ends the SCSI cmd (with result 'res'). - */ - if (!sp_get(sp)) { - int status; + if (sp_get(sp)) + return; - spin_unlock_irqrestore(qp->qp_lock_ptr, *flags); - status = qla2xxx_eh_abort(GET_CMD_SP(sp)); - spin_lock_irqsave(qp->qp_lock_ptr, *flags); - /* - * Get rid of extra reference caused - * by early exit from qla2xxx_eh_abort - */ - if (status == FAST_IO_FAIL) - atomic_dec(&sp->ref_count); + if (sp->type == SRB_NVME_CMD || sp->type == SRB_NVME_LS || + (sp->type == SRB_SCSI_CMD && !ha->flags.eeh_busy && + !test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) && + !qla2x00_isp_reg_stat(ha))) { + sp->comp = ∁ + rval = ha->isp_ops->abort_command(sp); + spin_unlock_irqrestore(qp->qp_lock_ptr, *flags); + + switch (rval) { + case QLA_SUCCESS: + sp->done(sp, res); + break; + case QLA_FUNCTION_PARAMETER_ERROR: + wait_for_completion(&comp); + break; } + + spin_lock_irqsave(qp->qp_lock_ptr, *flags); + sp->comp = NULL; } - sp->done(sp, res); } static void @@ -1875,15 +1781,10 @@ __qla2x00_abort_all_cmds(struct qla_qpair *qp, int res) continue; } cmd = (struct qla_tgt_cmd *)sp; - qlt_abort_cmd_on_host_reset(cmd->vha, cmd); + cmd->aborted = 1; break; case TYPE_TGT_TMCMD: - /* - * Currently, only ABTS response gets on the - * outstanding_cmds[] - */ - ha->tgt.tgt_ops->free_mcmd( - (struct qla_tgt_mgmt_cmd *)sp); + /* Skip task management functions. */ break; default: break; @@ -2753,6 +2654,24 @@ qla2x00_set_isp_flags(struct qla_hw_data *ha) ha->device_type |= DT_T10_PI; ha->fw_srisc_address = RISC_START_ADDRESS_2400; break; + case PCI_DEVICE_ID_QLOGIC_ISP2081: + case PCI_DEVICE_ID_QLOGIC_ISP2089: + ha->isp_type |= DT_ISP2081; + 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_ISP2281: + case PCI_DEVICE_ID_QLOGIC_ISP2289: + ha->isp_type |= DT_ISP2281; + 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; } if (IS_QLA82XX(ha)) @@ -2760,7 +2679,8 @@ qla2x00_set_isp_flags(struct qla_hw_data *ha) else { /* Get adapter physical port no from interrupt pin register. */ pci_read_config_byte(ha->pdev, PCI_INTERRUPT_PIN, &ha->port_no); - if (IS_QLA27XX(ha)) + if (IS_QLA25XX(ha) || IS_QLA2031(ha) || + IS_QLA27XX(ha) || IS_QLA28XX(ha)) ha->port_no--; else ha->port_no = !(ha->port_no & 1); @@ -2857,7 +2777,11 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8044 || pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2071 || pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2271 || - pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2261) { + pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2261 || + pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2081 || + pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2281 || + pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2089 || + pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2289) { bars = pci_select_bars(pdev, IORESOURCE_MEM); mem_only = 1; ql_dbg_pci(ql_dbg_init, pdev, 0x0007, @@ -2877,6 +2801,10 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) /* This may fail but that's ok */ pci_enable_pcie_error_reporting(pdev); + /* Turn off T10-DIF when FC-NVMe is enabled */ + if (ql2xnvmeenable) + ql2xenabledif = 0; + ha = kzalloc(sizeof(struct qla_hw_data), GFP_KERNEL); if (!ha) { ql_log_pci(ql_log_fatal, pdev, 0x0009, @@ -2906,7 +2834,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) /* Set EEH reset type to fundamental if required by hba */ if (IS_QLA24XX(ha) || IS_QLA25XX(ha) || IS_QLA81XX(ha) || - IS_QLA83XX(ha) || IS_QLA27XX(ha)) + IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) pdev->needs_freset = 1; ha->prev_topology = 0; @@ -3085,6 +3013,23 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ha->flash_data_off = FARX_ACCESS_FLASH_DATA_81XX; ha->nvram_conf_off = ~0; ha->nvram_data_off = ~0; + } else if (IS_QLA28XX(ha)) { + ha->portnum = PCI_FUNC(ha->pdev->devfn); + ha->max_fibre_devices = MAX_FIBRE_DEVICES_2400; + ha->mbx_count = MAILBOX_REGISTER_COUNT; + req_length = REQUEST_ENTRY_CNT_24XX; + rsp_length = RESPONSE_ENTRY_CNT_2300; + ha->tgt.atio_q_length = ATIO_ENTRY_CNT_24XX; + ha->max_loop_id = SNS_LAST_LOOP_ID_2300; + ha->init_cb_size = sizeof(struct mid_init_cb_81xx); + ha->gid_list_info_size = 8; + ha->optrom_size = OPTROM_SIZE_28XX; + ha->nvram_npiv_size = QLA_MAX_VPORTS_QLA25XX; + ha->isp_ops = &qla27xx_isp_ops; + ha->flash_conf_off = FARX_ACCESS_FLASH_CONF_28XX; + ha->flash_data_off = FARX_ACCESS_FLASH_DATA_28XX; + ha->nvram_conf_off = ~0; + ha->nvram_data_off = ~0; } ql_dbg_pci(ql_dbg_init, pdev, 0x001e, @@ -3250,7 +3195,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) req->req_q_out = &ha->iobase->isp24.req_q_out; rsp->rsp_q_in = &ha->iobase->isp24.rsp_q_in; rsp->rsp_q_out = &ha->iobase->isp24.rsp_q_out; - if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha)) { + if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha) || + IS_QLA28XX(ha)) { req->req_q_in = &ha->mqiobase->isp25mq.req_q_in; req->req_q_out = &ha->mqiobase->isp25mq.req_q_out; rsp->rsp_q_in = &ha->mqiobase->isp25mq.rsp_q_in; @@ -3395,6 +3341,7 @@ skip_dpc: if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif) { if (ha->fw_attributes & BIT_4) { int prot = 0, guard; + base_vha->flags.difdix_supported = 1; ql_dbg(ql_dbg_init, base_vha, 0x00f1, "Registering for DIF/DIX type 1 and 3 protection.\n"); @@ -3576,7 +3523,8 @@ qla2x00_shutdown(struct pci_dev *pdev) if (ha->eft) qla2x00_disable_eft_trace(vha); - if (IS_QLA25XX(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha)) { + if (IS_QLA25XX(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha) || + IS_QLA28XX(ha)) { if (ha->flags.fw_started) qla2x00_abort_isp_cleanup(vha); } else { @@ -3681,7 +3629,8 @@ qla2x00_unmap_iobases(struct qla_hw_data *ha) if (ha->mqiobase) iounmap(ha->mqiobase); - if ((IS_QLA83XX(ha) || IS_QLA27XX(ha)) && ha->msixbase) + if ((IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) && + ha->msixbase) iounmap(ha->msixbase); } } @@ -3732,7 +3681,8 @@ qla2x00_remove_one(struct pci_dev *pdev) } qla2x00_wait_for_hba_ready(base_vha); - if (IS_QLA25XX(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha)) { + if (IS_QLA25XX(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha) || + IS_QLA28XX(ha)) { if (ha->flags.fw_started) qla2x00_abort_isp_cleanup(base_vha); } else if (!IS_QLAFX00(ha)) { @@ -3770,8 +3720,6 @@ qla2x00_remove_one(struct pci_dev *pdev) qla2x00_delete_all_vps(ha, base_vha); - qla2x00_abort_all_cmds(base_vha, DID_NO_CONNECT << 16); - qla2x00_dfs_remove(base_vha); qla84xx_put_chip(base_vha); @@ -3860,11 +3808,8 @@ void qla2x00_free_fcports(struct scsi_qla_host *vha) { fc_port_t *fcport, *tfcport; - list_for_each_entry_safe(fcport, tfcport, &vha->vp_fcports, list) { - list_del(&fcport->list); - qla2x00_clear_loop_id(fcport); - kfree(fcport); - } + list_for_each_entry_safe(fcport, tfcport, &vha->vp_fcports, list) + qla2x00_free_fcport(fcport); } static inline void @@ -3889,6 +3834,7 @@ qla2x00_schedule_rport_del(struct scsi_qla_host *vha, fc_port_t *fcport, qla2xxx_wake_dpc(base_vha); } else { int now; + if (rport) { ql_dbg(ql_dbg_disc, fcport->vha, 0x2109, "%s %8phN. rport %p roles %x\n", @@ -3980,6 +3926,19 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *vha, int defer) } } +static void qla2x00_set_reserved_loop_ids(struct qla_hw_data *ha) +{ + int i; + + if (IS_FWI2_CAPABLE(ha)) + return; + + for (i = 0; i < SNS_FIRST_LOOP_ID; i++) + set_bit(i, ha->loop_id_map); + set_bit(MANAGEMENT_SERVER, ha->loop_id_map); + set_bit(BROADCAST, ha->loop_id_map); +} + /* * qla2x00_mem_alloc * Allocates adapter memory. @@ -4222,7 +4181,8 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len, ha->npiv_info = NULL; /* Get consistent memory allocated for EX-INIT-CB. */ - if (IS_CNA_CAPABLE(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha)) { + if (IS_CNA_CAPABLE(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha) || + IS_QLA28XX(ha)) { ha->ex_init_cb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &ha->ex_init_cb_dma); if (!ha->ex_init_cb) @@ -4265,8 +4225,20 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len, goto fail_sfp_data; } + ha->flt = dma_alloc_coherent(&ha->pdev->dev, + sizeof(struct qla_flt_header) + FLT_REGIONS_SIZE, &ha->flt_dma, + GFP_KERNEL); + if (!ha->flt) { + ql_dbg_pci(ql_dbg_init, ha->pdev, 0x011b, + "Unable to allocate memory for FLT.\n"); + goto fail_flt_buffer; + } + return 0; +fail_flt_buffer: + dma_free_coherent(&ha->pdev->dev, SFP_DEV_SIZE, + ha->sfp_data, ha->sfp_data_dma); fail_sfp_data: kfree(ha->loop_id_map); fail_loop_id_map: @@ -4602,6 +4574,9 @@ qla2x00_free_exchoffld_buffer(struct qla_hw_data *ha) static void qla2x00_free_fw_dump(struct qla_hw_data *ha) { + struct fwdt *fwdt = ha->fwdt; + uint j; + if (ha->fce) dma_free_coherent(&ha->pdev->dev, FCE_SIZE, ha->fce, ha->fce_dma); @@ -4612,8 +4587,6 @@ qla2x00_free_fw_dump(struct qla_hw_data *ha) if (ha->fw_dump) vfree(ha->fw_dump); - if (ha->fw_dump_template) - vfree(ha->fw_dump_template); ha->fce = NULL; ha->fce_dma = 0; @@ -4624,8 +4597,13 @@ qla2x00_free_fw_dump(struct qla_hw_data *ha) ha->fw_dump_reading = 0; ha->fw_dump = NULL; ha->fw_dump_len = 0; - ha->fw_dump_template = NULL; - ha->fw_dump_template_len = 0; + + for (j = 0; j < 2; j++, fwdt++) { + if (fwdt->template) + vfree(fwdt->template); + fwdt->template = NULL; + fwdt->length = 0; + } } /* @@ -4643,44 +4621,68 @@ qla2x00_mem_free(struct qla_hw_data *ha) if (ha->mctp_dump) dma_free_coherent(&ha->pdev->dev, MCTP_DUMP_SIZE, ha->mctp_dump, ha->mctp_dump_dma); + ha->mctp_dump = NULL; mempool_destroy(ha->srb_mempool); + ha->srb_mempool = NULL; if (ha->dcbx_tlv) dma_free_coherent(&ha->pdev->dev, DCBX_TLV_DATA_SIZE, ha->dcbx_tlv, ha->dcbx_tlv_dma); + ha->dcbx_tlv = NULL; if (ha->xgmac_data) dma_free_coherent(&ha->pdev->dev, XGMAC_DATA_SIZE, ha->xgmac_data, ha->xgmac_data_dma); + ha->xgmac_data = NULL; if (ha->sns_cmd) dma_free_coherent(&ha->pdev->dev, sizeof(struct sns_cmd_pkt), ha->sns_cmd, ha->sns_cmd_dma); + ha->sns_cmd = NULL; + ha->sns_cmd_dma = 0; if (ha->ct_sns) dma_free_coherent(&ha->pdev->dev, sizeof(struct ct_sns_pkt), ha->ct_sns, ha->ct_sns_dma); + ha->ct_sns = NULL; + ha->ct_sns_dma = 0; if (ha->sfp_data) dma_free_coherent(&ha->pdev->dev, SFP_DEV_SIZE, ha->sfp_data, ha->sfp_data_dma); + ha->sfp_data = NULL; + + if (ha->flt) + dma_free_coherent(&ha->pdev->dev, SFP_DEV_SIZE, + ha->flt, ha->flt_dma); + ha->flt = NULL; + ha->flt_dma = 0; if (ha->ms_iocb) dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma); + ha->ms_iocb = NULL; + ha->ms_iocb_dma = 0; if (ha->ex_init_cb) dma_pool_free(ha->s_dma_pool, ha->ex_init_cb, ha->ex_init_cb_dma); + ha->ex_init_cb = NULL; + ha->ex_init_cb_dma = 0; if (ha->async_pd) dma_pool_free(ha->s_dma_pool, ha->async_pd, ha->async_pd_dma); + ha->async_pd = NULL; + ha->async_pd_dma = 0; dma_pool_destroy(ha->s_dma_pool); + ha->s_dma_pool = NULL; if (ha->gid_list) dma_free_coherent(&ha->pdev->dev, qla2x00_gid_list_size(ha), ha->gid_list, ha->gid_list_dma); + ha->gid_list = NULL; + ha->gid_list_dma = 0; if (IS_QLA82XX(ha)) { if (!list_empty(&ha->gbl_dsd_list)) { @@ -4698,10 +4700,13 @@ qla2x00_mem_free(struct qla_hw_data *ha) } dma_pool_destroy(ha->dl_dma_pool); + ha->dl_dma_pool = NULL; dma_pool_destroy(ha->fcp_cmnd_dma_pool); + ha->fcp_cmnd_dma_pool = NULL; mempool_destroy(ha->ctx_mempool); + ha->ctx_mempool = NULL; if (ql2xenabledif) { struct dsd_dma *dsd, *nxt; @@ -4728,53 +4733,26 @@ qla2x00_mem_free(struct qla_hw_data *ha) if (ha->dif_bundl_pool) dma_pool_destroy(ha->dif_bundl_pool); + ha->dif_bundl_pool = NULL; qlt_mem_free(ha); if (ha->init_cb) dma_free_coherent(&ha->pdev->dev, ha->init_cb_size, ha->init_cb, ha->init_cb_dma); + ha->init_cb = NULL; + ha->init_cb_dma = 0; vfree(ha->optrom_buffer); + ha->optrom_buffer = NULL; kfree(ha->nvram); + ha->nvram = NULL; kfree(ha->npiv_info); + ha->npiv_info = NULL; kfree(ha->swl); + ha->swl = NULL; kfree(ha->loop_id_map); - - ha->srb_mempool = NULL; - ha->ctx_mempool = NULL; - ha->sns_cmd = NULL; - ha->sns_cmd_dma = 0; - ha->ct_sns = NULL; - ha->ct_sns_dma = 0; - ha->ms_iocb = NULL; - ha->ms_iocb_dma = 0; - ha->init_cb = NULL; - ha->init_cb_dma = 0; - ha->ex_init_cb = NULL; - ha->ex_init_cb_dma = 0; - ha->async_pd = NULL; - ha->async_pd_dma = 0; ha->loop_id_map = NULL; - ha->npiv_info = NULL; - ha->optrom_buffer = NULL; - ha->swl = NULL; - ha->nvram = NULL; - ha->mctp_dump = NULL; - ha->dcbx_tlv = NULL; - ha->xgmac_data = NULL; - ha->sfp_data = NULL; - - ha->s_dma_pool = NULL; - ha->dl_dma_pool = NULL; - ha->fcp_cmnd_dma_pool = NULL; - - ha->gid_list = NULL; - ha->gid_list_dma = 0; - - ha->tgt.atio_ring = NULL; - ha->tgt.atio_dma = 0; - ha->tgt.tgt_vp_map = NULL; } struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht, @@ -5608,6 +5586,7 @@ qla83xx_force_lock_recovery(scsi_qla_host_t *base_vha) uint32_t idc_lck_rcvry_stage_mask = 0x3; uint32_t idc_lck_rcvry_owner_mask = 0x3c; struct qla_hw_data *ha = base_vha->hw; + ql_dbg(ql_dbg_p3p, base_vha, 0xb086, "Trying force recovery of the IDC lock.\n"); @@ -6677,8 +6656,10 @@ qla2x00_timer(struct timer_list *t) * FC-NVME * see if the active AEN count has changed from what was last reported. */ - if (!vha->vp_idx && (atomic_read(&ha->nvme_active_aen_cnt) != - ha->nvme_last_rptd_aen) && ha->zio_mode == QLA_ZIO_MODE_6) { + if (!vha->vp_idx && + (atomic_read(&ha->nvme_active_aen_cnt) != ha->nvme_last_rptd_aen) && + ha->zio_mode == QLA_ZIO_MODE_6 && + !ha->flags.host_shutting_down) { ql_log(ql_log_info, vha, 0x3002, "nvme: Sched: Set ZIO exchange threshold to %d.\n", ha->nvme_last_rptd_aen); @@ -6690,7 +6671,7 @@ qla2x00_timer(struct timer_list *t) if (!vha->vp_idx && (atomic_read(&ha->zio_threshold) != ha->last_zio_threshold) && (ha->zio_mode == QLA_ZIO_MODE_6) && - (IS_QLA83XX(ha) || IS_QLA27XX(ha))) { + (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))) { ql_log(ql_log_info, vha, 0x3002, "Sched: Set ZIO exchange threshold to %d.\n", ha->last_zio_threshold); @@ -6736,7 +6717,6 @@ qla2x00_timer(struct timer_list *t) /* Firmware interface routines. */ -#define FW_BLOBS 11 #define FW_ISP21XX 0 #define FW_ISP22XX 1 #define FW_ISP2300 2 @@ -6748,6 +6728,7 @@ qla2x00_timer(struct timer_list *t) #define FW_ISP2031 8 #define FW_ISP8031 9 #define FW_ISP27XX 10 +#define FW_ISP28XX 11 #define FW_FILE_ISP21XX "ql2100_fw.bin" #define FW_FILE_ISP22XX "ql2200_fw.bin" @@ -6760,11 +6741,12 @@ qla2x00_timer(struct timer_list *t) #define FW_FILE_ISP2031 "ql2600_fw.bin" #define FW_FILE_ISP8031 "ql8300_fw.bin" #define FW_FILE_ISP27XX "ql2700_fw.bin" +#define FW_FILE_ISP28XX "ql2800_fw.bin" static DEFINE_MUTEX(qla_fw_lock); -static struct fw_blob qla_fw_blobs[FW_BLOBS] = { +static struct fw_blob qla_fw_blobs[] = { { .name = FW_FILE_ISP21XX, .segs = { 0x1000, 0 }, }, { .name = FW_FILE_ISP22XX, .segs = { 0x1000, 0 }, }, { .name = FW_FILE_ISP2300, .segs = { 0x800, 0 }, }, @@ -6776,6 +6758,8 @@ static struct fw_blob qla_fw_blobs[FW_BLOBS] = { { .name = FW_FILE_ISP2031, }, { .name = FW_FILE_ISP8031, }, { .name = FW_FILE_ISP27XX, }, + { .name = FW_FILE_ISP28XX, }, + { .name = NULL, }, }; struct fw_blob * @@ -6806,10 +6790,15 @@ qla2x00_request_firmware(scsi_qla_host_t *vha) blob = &qla_fw_blobs[FW_ISP8031]; } else if (IS_QLA27XX(ha)) { blob = &qla_fw_blobs[FW_ISP27XX]; + } else if (IS_QLA28XX(ha)) { + blob = &qla_fw_blobs[FW_ISP28XX]; } else { return NULL; } + if (!blob->name) + return NULL; + mutex_lock(&qla_fw_lock); if (blob->fw) goto out; @@ -6819,7 +6808,6 @@ qla2x00_request_firmware(scsi_qla_host_t *vha) "Failed to load firmware image (%s).\n", blob->name); blob->fw = NULL; blob = NULL; - goto out; } out: @@ -6830,11 +6818,11 @@ out: static void qla2x00_release_firmware(void) { - int idx; + struct fw_blob *blob; mutex_lock(&qla_fw_lock); - for (idx = 0; idx < FW_BLOBS; idx++) - release_firmware(qla_fw_blobs[idx].fw); + for (blob = qla_fw_blobs; blob->name; blob++) + release_firmware(blob->fw); mutex_unlock(&qla_fw_lock); } @@ -7179,7 +7167,7 @@ static int qla2xxx_map_queues(struct Scsi_Host *shost) { int rc; scsi_qla_host_t *vha = (scsi_qla_host_t *)shost->hostdata; - struct blk_mq_queue_map *qmap = &shost->tag_set.map[0]; + struct blk_mq_queue_map *qmap = &shost->tag_set.map[HCTX_TYPE_DEFAULT]; if (USER_CTRL_IRQ(vha->hw) || !vha->hw->mqiobase) rc = blk_mq_map_queues(qmap); @@ -7188,6 +7176,37 @@ static int qla2xxx_map_queues(struct Scsi_Host *shost) return rc; } +struct scsi_host_template qla2xxx_driver_template = { + .module = THIS_MODULE, + .name = QLA2XXX_DRIVER_NAME, + .queuecommand = qla2xxx_queuecommand, + + .eh_timed_out = fc_eh_timed_out, + .eh_abort_handler = qla2xxx_eh_abort, + .eh_device_reset_handler = qla2xxx_eh_device_reset, + .eh_target_reset_handler = qla2xxx_eh_target_reset, + .eh_bus_reset_handler = qla2xxx_eh_bus_reset, + .eh_host_reset_handler = qla2xxx_eh_host_reset, + + .slave_configure = qla2xxx_slave_configure, + + .slave_alloc = qla2xxx_slave_alloc, + .slave_destroy = qla2xxx_slave_destroy, + .scan_finished = qla2xxx_scan_finished, + .scan_start = qla2xxx_scan_start, + .change_queue_depth = scsi_change_queue_depth, + .map_queues = qla2xxx_map_queues, + .this_id = -1, + .cmd_per_lun = 3, + .sg_tablesize = SG_ALL, + + .max_sectors = 0xFFFF, + .shost_attrs = qla2x00_host_attrs, + + .supported_mode = MODE_INITIATOR, + .track_queue_depth = 1, +}; + static const struct pci_error_handlers qla2xxx_err_handler = { .error_detected = qla2xxx_pci_error_detected, .mmio_enabled = qla2xxx_pci_mmio_enabled, @@ -7220,6 +7239,11 @@ static struct pci_device_id qla2xxx_pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2071) }, { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2271) }, { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2261) }, + { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2061) }, + { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2081) }, + { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2281) }, + { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2089) }, + { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2289) }, { 0 }, }; MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl); @@ -7249,6 +7273,30 @@ qla2x00_module_init(void) { int ret = 0; + BUILD_BUG_ON(sizeof(cmd_entry_t) != 64); + BUILD_BUG_ON(sizeof(cont_a64_entry_t) != 64); + BUILD_BUG_ON(sizeof(cont_entry_t) != 64); + BUILD_BUG_ON(sizeof(init_cb_t) != 96); + BUILD_BUG_ON(sizeof(ms_iocb_entry_t) != 64); + BUILD_BUG_ON(sizeof(request_t) != 64); + BUILD_BUG_ON(sizeof(struct access_chip_84xx) != 64); + BUILD_BUG_ON(sizeof(struct cmd_bidir) != 64); + BUILD_BUG_ON(sizeof(struct cmd_nvme) != 64); + BUILD_BUG_ON(sizeof(struct cmd_type_6) != 64); + BUILD_BUG_ON(sizeof(struct cmd_type_7) != 64); + BUILD_BUG_ON(sizeof(struct cmd_type_7_fx00) != 64); + BUILD_BUG_ON(sizeof(struct cmd_type_crc_2) != 64); + BUILD_BUG_ON(sizeof(struct ct_entry_24xx) != 64); + BUILD_BUG_ON(sizeof(struct ctio_crc2_to_fw) != 64); + BUILD_BUG_ON(sizeof(struct els_entry_24xx) != 64); + BUILD_BUG_ON(sizeof(struct fxdisc_entry_fx00) != 64); + BUILD_BUG_ON(sizeof(struct init_cb_24xx) != 128); + BUILD_BUG_ON(sizeof(struct init_cb_81xx) != 128); + BUILD_BUG_ON(sizeof(struct pt_ls4_request) != 64); + BUILD_BUG_ON(sizeof(struct sns_cmd_pkt) != 2064); + BUILD_BUG_ON(sizeof(struct verify_chip_entry_84xx) != 64); + BUILD_BUG_ON(sizeof(struct vf_evfp_entry_24xx) != 56); + /* Allocate cache for SRBs. */ srb_cachep = kmem_cache_create("qla2xxx_srbs", sizeof(srb_t), 0, SLAB_HWCACHE_ALIGN, NULL); @@ -7261,8 +7309,7 @@ qla2x00_module_init(void) /* Initialize target kmem_cache and mem_pools */ ret = qlt_init(); if (ret < 0) { - kmem_cache_destroy(srb_cachep); - return ret; + goto destroy_cache; } else if (ret > 0) { /* * If initiator mode is explictly disabled by qlt_init(), @@ -7286,11 +7333,10 @@ qla2x00_module_init(void) qla2xxx_transport_template = fc_attach_transport(&qla2xxx_transport_functions); if (!qla2xxx_transport_template) { - kmem_cache_destroy(srb_cachep); ql_log(ql_log_fatal, NULL, 0x0002, "fc_attach_transport failed...Failing load!.\n"); - qlt_exit(); - return -ENODEV; + ret = -ENODEV; + goto qlt_exit; } apidev_major = register_chrdev(0, QLA2XXX_APIDEV, &apidev_fops); @@ -7302,27 +7348,37 @@ qla2x00_module_init(void) qla2xxx_transport_vport_template = fc_attach_transport(&qla2xxx_transport_vport_functions); if (!qla2xxx_transport_vport_template) { - kmem_cache_destroy(srb_cachep); - qlt_exit(); - fc_release_transport(qla2xxx_transport_template); ql_log(ql_log_fatal, NULL, 0x0004, "fc_attach_transport vport failed...Failing load!.\n"); - return -ENODEV; + ret = -ENODEV; + goto unreg_chrdev; } ql_log(ql_log_info, NULL, 0x0005, "QLogic Fibre Channel HBA Driver: %s.\n", qla2x00_version_str); ret = pci_register_driver(&qla2xxx_pci_driver); if (ret) { - kmem_cache_destroy(srb_cachep); - qlt_exit(); - fc_release_transport(qla2xxx_transport_template); - fc_release_transport(qla2xxx_transport_vport_template); ql_log(ql_log_fatal, NULL, 0x0006, "pci_register_driver failed...ret=%d Failing load!.\n", ret); + goto release_vport_transport; } return ret; + +release_vport_transport: + fc_release_transport(qla2xxx_transport_vport_template); + +unreg_chrdev: + if (apidev_major >= 0) + unregister_chrdev(apidev_major, QLA2XXX_APIDEV); + fc_release_transport(qla2xxx_transport_template); + +qlt_exit: + qlt_exit(); + +destroy_cache: + kmem_cache_destroy(srb_cachep); + return ret; } /** @@ -7331,14 +7387,15 @@ qla2x00_module_init(void) static void __exit qla2x00_module_exit(void) { - unregister_chrdev(apidev_major, QLA2XXX_APIDEV); pci_unregister_driver(&qla2xxx_pci_driver); qla2x00_release_firmware(); - kmem_cache_destroy(srb_cachep); - qlt_exit(); kmem_cache_destroy(ctx_cachep); - fc_release_transport(qla2xxx_transport_template); fc_release_transport(qla2xxx_transport_vport_template); + if (apidev_major >= 0) + unregister_chrdev(apidev_major, QLA2XXX_APIDEV); + fc_release_transport(qla2xxx_transport_template); + qlt_exit(); + kmem_cache_destroy(srb_cachep); } module_init(qla2x00_module_init); diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index 2a3055c799fb..1eb82384d933 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c @@ -429,66 +429,64 @@ qla2x00_set_nvram_protection(struct qla_hw_data *ha, int stat) static inline uint32_t flash_conf_addr(struct qla_hw_data *ha, uint32_t faddr) { - return ha->flash_conf_off | faddr; + return ha->flash_conf_off + faddr; } static inline uint32_t flash_data_addr(struct qla_hw_data *ha, uint32_t faddr) { - return ha->flash_data_off | faddr; + return ha->flash_data_off + faddr; } static inline uint32_t nvram_conf_addr(struct qla_hw_data *ha, uint32_t naddr) { - return ha->nvram_conf_off | naddr; + return ha->nvram_conf_off + naddr; } static inline uint32_t nvram_data_addr(struct qla_hw_data *ha, uint32_t naddr) { - return ha->nvram_data_off | naddr; + return ha->nvram_data_off + naddr; } -static uint32_t -qla24xx_read_flash_dword(struct qla_hw_data *ha, uint32_t addr) +static int +qla24xx_read_flash_dword(struct qla_hw_data *ha, uint32_t addr, uint32_t *data) { - int rval; - uint32_t cnt, data; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; + ulong cnt = 30000; WRT_REG_DWORD(®->flash_addr, addr & ~FARX_DATA_FLAG); - /* Wait for READ cycle to complete. */ - rval = QLA_SUCCESS; - for (cnt = 3000; - (RD_REG_DWORD(®->flash_addr) & FARX_DATA_FLAG) == 0 && - rval == QLA_SUCCESS; cnt--) { - if (cnt) - udelay(10); - else - rval = QLA_FUNCTION_TIMEOUT; + + while (cnt--) { + if (RD_REG_DWORD(®->flash_addr) & FARX_DATA_FLAG) { + *data = RD_REG_DWORD(®->flash_data); + return QLA_SUCCESS; + } + udelay(10); cond_resched(); } - /* TODO: What happens if we time out? */ - data = 0xDEADDEAD; - if (rval == QLA_SUCCESS) - data = RD_REG_DWORD(®->flash_data); - - return data; + ql_log(ql_log_warn, pci_get_drvdata(ha->pdev), 0x7090, + "Flash read dword at %x timeout.\n", addr); + *data = 0xDEADDEAD; + return QLA_FUNCTION_TIMEOUT; } uint32_t * qla24xx_read_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr, uint32_t dwords) { - uint32_t i; + ulong i; struct qla_hw_data *ha = vha->hw; /* Dword reads to flash. */ - for (i = 0; i < dwords; i++, faddr++) - dwptr[i] = cpu_to_le32(qla24xx_read_flash_dword(ha, - flash_data_addr(ha, faddr))); + faddr = flash_data_addr(ha, faddr); + for (i = 0; i < dwords; i++, faddr++, dwptr++) { + if (qla24xx_read_flash_dword(ha, faddr, dwptr)) + break; + cpu_to_le32s(dwptr); + } return dwptr; } @@ -496,35 +494,37 @@ qla24xx_read_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr, static int qla24xx_write_flash_dword(struct qla_hw_data *ha, uint32_t addr, uint32_t data) { - int rval; - uint32_t cnt; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; + ulong cnt = 500000; WRT_REG_DWORD(®->flash_data, data); - RD_REG_DWORD(®->flash_data); /* PCI Posting. */ WRT_REG_DWORD(®->flash_addr, addr | FARX_DATA_FLAG); - /* Wait for Write cycle to complete. */ - rval = QLA_SUCCESS; - for (cnt = 500000; (RD_REG_DWORD(®->flash_addr) & FARX_DATA_FLAG) && - rval == QLA_SUCCESS; cnt--) { - if (cnt) - udelay(10); - else - rval = QLA_FUNCTION_TIMEOUT; + + while (cnt--) { + if (!(RD_REG_DWORD(®->flash_addr) & FARX_DATA_FLAG)) + return QLA_SUCCESS; + udelay(10); cond_resched(); } - return rval; + + ql_log(ql_log_warn, pci_get_drvdata(ha->pdev), 0x7090, + "Flash write dword at %x timeout.\n", addr); + return QLA_FUNCTION_TIMEOUT; } static void qla24xx_get_flash_manufacturer(struct qla_hw_data *ha, uint8_t *man_id, uint8_t *flash_id) { - uint32_t ids; + uint32_t faddr, ids = 0; - ids = qla24xx_read_flash_dword(ha, flash_conf_addr(ha, 0x03ab)); - *man_id = LSB(ids); - *flash_id = MSB(ids); + *man_id = *flash_id = 0; + + faddr = flash_conf_addr(ha, 0x03ab); + if (!qla24xx_read_flash_dword(ha, faddr, &ids)) { + *man_id = LSB(ids); + *flash_id = MSB(ids); + } /* Check if man_id and flash_id are valid. */ if (ids != 0xDEADDEAD && (*man_id == 0 || *flash_id == 0)) { @@ -534,9 +534,11 @@ qla24xx_get_flash_manufacturer(struct qla_hw_data *ha, uint8_t *man_id, * Example: ATMEL 0x00 01 45 1F * Extract MFG and Dev ID from last two bytes. */ - ids = qla24xx_read_flash_dword(ha, flash_conf_addr(ha, 0x009f)); - *man_id = LSB(ids); - *flash_id = MSB(ids); + faddr = flash_conf_addr(ha, 0x009f); + if (!qla24xx_read_flash_dword(ha, faddr, &ids)) { + *man_id = LSB(ids); + *flash_id = MSB(ids); + } } } @@ -545,12 +547,12 @@ qla2xxx_find_flt_start(scsi_qla_host_t *vha, uint32_t *start) { const char *loc, *locations[] = { "DEF", "PCI" }; uint32_t pcihdr, pcids; - uint32_t *dcode; - uint8_t *buf, *bcode, last_image; uint16_t cnt, chksum, *wptr; - struct qla_flt_location *fltl; struct qla_hw_data *ha = vha->hw; struct req_que *req = ha->req_q_map[0]; + struct qla_flt_location *fltl = (void *)req->ring; + uint32_t *dcode = (void *)req->ring; + uint8_t *buf = (void *)req->ring, *bcode, last_image; /* * FLT-location structure resides after the last PCI region. @@ -571,12 +573,13 @@ qla2xxx_find_flt_start(scsi_qla_host_t *vha, uint32_t *start) } else if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) { *start = FA_FLASH_LAYOUT_ADDR_83; goto end; + } else if (IS_QLA28XX(ha)) { + *start = FA_FLASH_LAYOUT_ADDR_28; + goto end; } + /* Begin with first PCI expansion ROM header. */ - buf = (uint8_t *)req->ring; - dcode = (uint32_t *)req->ring; pcihdr = 0; - last_image = 1; do { /* Verify PCI expansion ROM header. */ qla24xx_read_flash_data(vha, dcode, pcihdr >> 2, 0x20); @@ -601,22 +604,19 @@ qla2xxx_find_flt_start(scsi_qla_host_t *vha, uint32_t *start) } while (!last_image); /* Now verify FLT-location structure. */ - fltl = (struct qla_flt_location *)req->ring; - qla24xx_read_flash_data(vha, dcode, pcihdr >> 2, - sizeof(struct qla_flt_location) >> 2); - if (fltl->sig[0] != 'Q' || fltl->sig[1] != 'F' || - fltl->sig[2] != 'L' || fltl->sig[3] != 'T') + qla24xx_read_flash_data(vha, dcode, pcihdr >> 2, sizeof(*fltl) >> 2); + if (memcmp(fltl->sig, "QFLT", 4)) goto end; - wptr = (uint16_t *)req->ring; - cnt = sizeof(struct qla_flt_location) >> 1; + wptr = (void *)req->ring; + cnt = sizeof(*fltl) / sizeof(*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); ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x010e, - buf, sizeof(struct qla_flt_location)); + fltl, sizeof(*fltl)); return QLA_FUNCTION_FAILED; } @@ -634,7 +634,7 @@ end: static void qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr) { - const char *loc, *locations[] = { "DEF", "FLT" }; + const char *locations[] = { "DEF", "FLT" }, *loc = locations[1]; const uint32_t def_fw[] = { FA_RISC_CODE_ADDR, FA_RISC_CODE_ADDR, FA_RISC_CODE_ADDR_81 }; const uint32_t def_boot[] = @@ -664,20 +664,13 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr) const uint32_t fcp_prio_cfg1[] = { FA_FCP_PRIO1_ADDR, FA_FCP_PRIO1_ADDR_25, 0 }; - uint32_t def; - uint16_t *wptr; - uint16_t cnt, chksum; - uint32_t start; - struct qla_flt_header *flt; - struct qla_flt_region *region; - struct qla_hw_data *ha = vha->hw; - struct req_que *req = ha->req_q_map[0]; - def = 0; - if (IS_QLA25XX(ha)) - def = 1; - else if (IS_QLA81XX(ha)) - def = 2; + struct qla_hw_data *ha = vha->hw; + uint32_t def = IS_QLA81XX(ha) ? 2 : IS_QLA25XX(ha) ? 1 : 0; + struct qla_flt_header *flt = (void *)ha->flt; + struct qla_flt_region *region = (void *)&flt[1]; + uint16_t *wptr, cnt, chksum; + uint32_t start; /* Assign FCP prio region since older adapters may not have FLT, or FCP prio region in it's FLT. @@ -686,12 +679,11 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr) fcp_prio_cfg0[def] : fcp_prio_cfg1[def]; ha->flt_region_flt = flt_addr; - wptr = (uint16_t *)req->ring; - flt = (struct qla_flt_header *)req->ring; - region = (struct qla_flt_region *)&flt[1]; - ha->isp_ops->read_optrom(vha, (uint8_t *)req->ring, - flt_addr << 2, OPTROM_BURST_SIZE); - if (*wptr == cpu_to_le16(0xffff)) + wptr = (uint16_t *)ha->flt; + qla24xx_read_flash_data(vha, (void *)flt, flt_addr, + (sizeof(struct qla_flt_header) + FLT_REGIONS_SIZE) >> 2); + + if (le16_to_cpu(*wptr) == 0xffff) goto no_flash_data; if (flt->version != cpu_to_le16(1)) { ql_log(ql_log_warn, vha, 0x0047, @@ -701,7 +693,7 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr) goto no_flash_data; } - cnt = (sizeof(struct qla_flt_header) + le16_to_cpu(flt->length)) >> 1; + cnt = (sizeof(*flt) + le16_to_cpu(flt->length)) / sizeof(*wptr); for (chksum = 0; cnt--; wptr++) chksum += le16_to_cpu(*wptr); if (chksum) { @@ -712,18 +704,20 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr) goto no_flash_data; } - loc = locations[1]; - cnt = le16_to_cpu(flt->length) / sizeof(struct qla_flt_region); + cnt = le16_to_cpu(flt->length) / sizeof(*region); for ( ; cnt; cnt--, region++) { /* Store addresses as DWORD offsets. */ start = le32_to_cpu(region->start) >> 2; ql_dbg(ql_dbg_init, vha, 0x0049, - "FLT[%02x]: start=0x%x " - "end=0x%x size=0x%x.\n", le32_to_cpu(region->code) & 0xff, - start, le32_to_cpu(region->end) >> 2, - le32_to_cpu(region->size)); - - switch (le32_to_cpu(region->code) & 0xff) { + "FLT[%#x]: start=%#x end=%#x size=%#x.\n", + le16_to_cpu(region->code), start, + le32_to_cpu(region->end) >> 2, + le32_to_cpu(region->size) >> 2); + if (region->attribute) + ql_log(ql_dbg_init, vha, 0xffff, + "Region %x is secure\n", region->code); + + switch (le16_to_cpu(region->code)) { case FLT_REG_FCOE_FW: if (!IS_QLA8031(ha)) break; @@ -753,13 +747,13 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr) ha->flt_region_vpd = start; break; case FLT_REG_VPD_2: - if (!IS_QLA27XX(ha)) + if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) break; if (ha->port_no == 2) ha->flt_region_vpd = start; break; case FLT_REG_VPD_3: - if (!IS_QLA27XX(ha)) + if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) break; if (ha->port_no == 3) ha->flt_region_vpd = start; @@ -777,13 +771,13 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr) ha->flt_region_nvram = start; break; case FLT_REG_NVRAM_2: - if (!IS_QLA27XX(ha)) + if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) break; if (ha->port_no == 2) ha->flt_region_nvram = start; break; case FLT_REG_NVRAM_3: - if (!IS_QLA27XX(ha)) + if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) break; if (ha->port_no == 3) ha->flt_region_nvram = start; @@ -847,36 +841,74 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr) ha->flt_region_nvram = start; break; case FLT_REG_IMG_PRI_27XX: - if (IS_QLA27XX(ha)) + if (IS_QLA27XX(ha) && !IS_QLA28XX(ha)) ha->flt_region_img_status_pri = start; break; case FLT_REG_IMG_SEC_27XX: - if (IS_QLA27XX(ha)) + if (IS_QLA27XX(ha) && !IS_QLA28XX(ha)) ha->flt_region_img_status_sec = start; break; case FLT_REG_FW_SEC_27XX: - if (IS_QLA27XX(ha)) + if (IS_QLA27XX(ha) && !IS_QLA28XX(ha)) ha->flt_region_fw_sec = start; break; case FLT_REG_BOOTLOAD_SEC_27XX: - if (IS_QLA27XX(ha)) + if (IS_QLA27XX(ha) && !IS_QLA28XX(ha)) ha->flt_region_boot_sec = start; break; + case FLT_REG_AUX_IMG_PRI_28XX: + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) + ha->flt_region_aux_img_status_pri = start; + break; + case FLT_REG_AUX_IMG_SEC_28XX: + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) + ha->flt_region_aux_img_status_sec = start; + break; + case FLT_REG_NVRAM_SEC_28XX_0: + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) + if (ha->port_no == 0) + ha->flt_region_nvram_sec = start; + break; + case FLT_REG_NVRAM_SEC_28XX_1: + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) + if (ha->port_no == 1) + ha->flt_region_nvram_sec = start; + break; + case FLT_REG_NVRAM_SEC_28XX_2: + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) + if (ha->port_no == 2) + ha->flt_region_nvram_sec = start; + break; + case FLT_REG_NVRAM_SEC_28XX_3: + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) + if (ha->port_no == 3) + ha->flt_region_nvram_sec = start; + break; case FLT_REG_VPD_SEC_27XX_0: - if (IS_QLA27XX(ha)) - ha->flt_region_vpd_sec = start; + case FLT_REG_VPD_SEC_28XX_0: + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { + ha->flt_region_vpd_nvram_sec = start; + if (ha->port_no == 0) + ha->flt_region_vpd_sec = start; + } break; case FLT_REG_VPD_SEC_27XX_1: - if (IS_QLA27XX(ha)) - ha->flt_region_vpd_sec = start; + case FLT_REG_VPD_SEC_28XX_1: + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) + if (ha->port_no == 1) + ha->flt_region_vpd_sec = start; break; case FLT_REG_VPD_SEC_27XX_2: - if (IS_QLA27XX(ha)) - ha->flt_region_vpd_sec = start; + case FLT_REG_VPD_SEC_28XX_2: + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) + if (ha->port_no == 2) + ha->flt_region_vpd_sec = start; break; case FLT_REG_VPD_SEC_27XX_3: - if (IS_QLA27XX(ha)) - ha->flt_region_vpd_sec = start; + case FLT_REG_VPD_SEC_28XX_3: + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) + if (ha->port_no == 3) + ha->flt_region_vpd_sec = start; break; } } @@ -912,22 +944,19 @@ qla2xxx_get_fdt_info(scsi_qla_host_t *vha) #define FLASH_BLK_SIZE_32K 0x8000 #define FLASH_BLK_SIZE_64K 0x10000 const char *loc, *locations[] = { "MID", "FDT" }; + struct qla_hw_data *ha = vha->hw; + struct req_que *req = ha->req_q_map[0]; uint16_t cnt, chksum; - uint16_t *wptr; - struct qla_fdt_layout *fdt; + uint16_t *wptr = (void *)req->ring; + struct qla_fdt_layout *fdt = (void *)req->ring; uint8_t man_id, flash_id; uint16_t mid = 0, fid = 0; - struct qla_hw_data *ha = vha->hw; - struct req_que *req = ha->req_q_map[0]; - wptr = (uint16_t *)req->ring; - fdt = (struct qla_fdt_layout *)req->ring; - ha->isp_ops->read_optrom(vha, (uint8_t *)req->ring, - ha->flt_region_fdt << 2, OPTROM_BURST_SIZE); - if (*wptr == cpu_to_le16(0xffff)) + qla24xx_read_flash_data(vha, (void *)fdt, ha->flt_region_fdt, + OPTROM_BURST_DWORDS); + if (le16_to_cpu(*wptr) == 0xffff) goto no_flash_data; - if (fdt->sig[0] != 'Q' || fdt->sig[1] != 'L' || fdt->sig[2] != 'I' || - fdt->sig[3] != 'D') + if (memcmp(fdt->sig, "QLID", 4)) goto no_flash_data; for (cnt = 0, chksum = 0; cnt < sizeof(*fdt) >> 1; cnt++, wptr++) @@ -938,7 +967,7 @@ qla2xxx_get_fdt_info(scsi_qla_host_t *vha) " checksum=0x%x id=%c version0x%x.\n", chksum, fdt->sig[0], le16_to_cpu(fdt->version)); ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0113, - (uint8_t *)fdt, sizeof(*fdt)); + fdt, sizeof(*fdt)); goto no_flash_data; } @@ -958,7 +987,7 @@ qla2xxx_get_fdt_info(scsi_qla_host_t *vha) ha->fdt_unprotect_sec_cmd = flash_conf_addr(ha, 0x0300 | fdt->unprotect_sec_cmd); ha->fdt_protect_sec_cmd = fdt->protect_sec_cmd ? - flash_conf_addr(ha, 0x0300 | fdt->protect_sec_cmd): + flash_conf_addr(ha, 0x0300 | fdt->protect_sec_cmd) : flash_conf_addr(ha, 0x0336); } goto done; @@ -1019,8 +1048,7 @@ qla2xxx_get_idc_param(scsi_qla_host_t *vha) return; wptr = (uint32_t *)req->ring; - ha->isp_ops->read_optrom(vha, (uint8_t *)req->ring, - QLA82XX_IDC_PARAM_ADDR , 8); + ha->isp_ops->read_optrom(vha, req->ring, QLA82XX_IDC_PARAM_ADDR, 8); if (*wptr == cpu_to_le32(0xffffffff)) { ha->fcoe_dev_init_timeout = QLA82XX_ROM_DEV_INIT_TIMEOUT; @@ -1045,7 +1073,8 @@ qla2xxx_get_flash_info(scsi_qla_host_t *vha) struct qla_hw_data *ha = vha->hw; if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha) && - !IS_CNA_CAPABLE(ha) && !IS_QLA2031(ha) && !IS_QLA27XX(ha)) + !IS_CNA_CAPABLE(ha) && !IS_QLA2031(ha) && + !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) return QLA_SUCCESS; ret = qla2xxx_find_flt_start(vha, &flt_addr); @@ -1081,8 +1110,8 @@ qla2xxx_flash_npiv_conf(scsi_qla_host_t *vha) if (IS_QLA8044(ha)) return; - ha->isp_ops->read_optrom(vha, (uint8_t *)&hdr, - ha->flt_region_npiv_conf << 2, sizeof(struct qla_npiv_header)); + ha->isp_ops->read_optrom(vha, &hdr, ha->flt_region_npiv_conf << 2, + sizeof(struct qla_npiv_header)); if (hdr.version == cpu_to_le16(0xffff)) return; if (hdr.version != cpu_to_le16(1)) { @@ -1101,8 +1130,8 @@ qla2xxx_flash_npiv_conf(scsi_qla_host_t *vha) return; } - ha->isp_ops->read_optrom(vha, (uint8_t *)data, - ha->flt_region_npiv_conf << 2, NPIV_CONFIG_SIZE); + ha->isp_ops->read_optrom(vha, data, ha->flt_region_npiv_conf << 2, + NPIV_CONFIG_SIZE); cnt = (sizeof(hdr) + le16_to_cpu(hdr.entries) * sizeof(*entry)) >> 1; for (wptr = data, chksum = 0; cnt--; wptr++) @@ -1139,10 +1168,8 @@ qla2xxx_flash_npiv_conf(scsi_qla_host_t *vha) vid.node_name = wwn_to_u64(entry->node_name); ql_dbg(ql_dbg_user, vha, 0x7093, - "NPIV[%02x]: wwpn=%llx " - "wwnn=%llx vf_id=0x%x Q_qos=0x%x F_qos=0x%x.\n", cnt, - (unsigned long long)vid.port_name, - (unsigned long long)vid.node_name, + "NPIV[%02x]: wwpn=%llx wwnn=%llx vf_id=%#x Q_qos=%#x F_qos=%#x.\n", + cnt, vid.port_name, vid.node_name, le16_to_cpu(entry->vf_id), entry->q_qos, entry->f_qos); @@ -1150,10 +1177,8 @@ qla2xxx_flash_npiv_conf(scsi_qla_host_t *vha) vport = fc_vport_create(vha->host, 0, &vid); if (!vport) ql_log(ql_log_warn, vha, 0x7094, - "NPIV-Config Failed to create vport [%02x]: " - "wwpn=%llx wwnn=%llx.\n", cnt, - (unsigned long long)vid.port_name, - (unsigned long long)vid.node_name); + "NPIV-Config Failed to create vport [%02x]: wwpn=%llx wwnn=%llx.\n", + cnt, vid.port_name, vid.node_name); } } done: @@ -1188,9 +1213,10 @@ done: static int qla24xx_protect_flash(scsi_qla_host_t *vha) { - uint32_t cnt; struct qla_hw_data *ha = vha->hw; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; + ulong cnt = 300; + uint32_t faddr, dword; if (ha->flags.fac_supported) return qla81xx_fac_do_write_enable(vha, 0); @@ -1199,11 +1225,14 @@ qla24xx_protect_flash(scsi_qla_host_t *vha) goto skip_wrt_protect; /* Enable flash write-protection and wait for completion. */ - qla24xx_write_flash_dword(ha, flash_conf_addr(ha, 0x101), - ha->fdt_wrt_disable); - for (cnt = 300; cnt && - qla24xx_read_flash_dword(ha, flash_conf_addr(ha, 0x005)) & BIT_0; - cnt--) { + faddr = flash_conf_addr(ha, 0x101); + qla24xx_write_flash_dword(ha, faddr, ha->fdt_wrt_disable); + faddr = flash_conf_addr(ha, 0x5); + while (cnt--) { + if (!qla24xx_read_flash_dword(ha, faddr, &dword)) { + if (!(dword & BIT_0)) + break; + } udelay(10); } @@ -1211,7 +1240,6 @@ skip_wrt_protect: /* Disable flash write. */ WRT_REG_DWORD(®->ctrl_status, RD_REG_DWORD(®->ctrl_status) & ~CSRX_FLASH_ENABLE); - RD_REG_DWORD(®->ctrl_status); /* PCI Posting. */ return QLA_SUCCESS; } @@ -1239,107 +1267,103 @@ qla24xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr, uint32_t dwords) { int ret; - uint32_t liter; - uint32_t sec_mask, rest_addr; - uint32_t fdata; + ulong liter; + ulong dburst = OPTROM_BURST_DWORDS; /* burst size in dwords */ + uint32_t sec_mask, rest_addr, fdata; dma_addr_t optrom_dma; void *optrom = NULL; struct qla_hw_data *ha = vha->hw; - /* Prepare burst-capable write on supported ISPs. */ - if ((IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) || - IS_QLA27XX(ha)) && - !(faddr & 0xfff) && dwords > OPTROM_BURST_DWORDS) { - optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE, - &optrom_dma, GFP_KERNEL); - if (!optrom) { - ql_log(ql_log_warn, vha, 0x7095, - "Unable to allocate " - "memory for optrom burst write (%x KB).\n", - OPTROM_BURST_SIZE / 1024); - } - } + if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha) && + !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) + goto next; - rest_addr = (ha->fdt_block_size >> 2) - 1; - sec_mask = ~rest_addr; + /* Allocate dma buffer for burst write */ + optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE, + &optrom_dma, GFP_KERNEL); + if (!optrom) { + ql_log(ql_log_warn, vha, 0x7095, + "Failed allocate burst (%x bytes)\n", OPTROM_BURST_SIZE); + } +next: + ql_log(ql_log_warn + ql_dbg_verbose, vha, 0x7095, + "Unprotect flash...\n"); ret = qla24xx_unprotect_flash(vha); - if (ret != QLA_SUCCESS) { + if (ret) { ql_log(ql_log_warn, vha, 0x7096, - "Unable to unprotect flash for update.\n"); + "Failed to unprotect flash.\n"); goto done; } + rest_addr = (ha->fdt_block_size >> 2) - 1; + sec_mask = ~rest_addr; for (liter = 0; liter < dwords; liter++, faddr++, dwptr++) { fdata = (faddr & sec_mask) << 2; /* Are we at the beginning of a sector? */ - if ((faddr & rest_addr) == 0) { - /* Do sector unprotect. */ - if (ha->fdt_unprotect_sec_cmd) - qla24xx_write_flash_dword(ha, - ha->fdt_unprotect_sec_cmd, - (fdata & 0xff00) | ((fdata << 16) & - 0xff0000) | ((fdata >> 16) & 0xff)); + if (!(faddr & rest_addr)) { + ql_log(ql_log_warn + ql_dbg_verbose, vha, 0x7095, + "Erase sector %#x...\n", faddr); + ret = qla24xx_erase_sector(vha, fdata); - if (ret != QLA_SUCCESS) { + if (ret) { ql_dbg(ql_dbg_user, vha, 0x7007, - "Unable to erase erase sector: address=%x.\n", - faddr); + "Failed to erase sector %x.\n", faddr); break; } } - /* Go with burst-write. */ - if (optrom && (liter + OPTROM_BURST_DWORDS) <= dwords) { - /* Copy data to DMA'ble buffer. */ - memcpy(optrom, dwptr, OPTROM_BURST_SIZE); + if (optrom) { + /* If smaller than a burst remaining */ + if (dwords - liter < dburst) + dburst = dwords - liter; + /* Copy to dma buffer */ + memcpy(optrom, dwptr, dburst << 2); + + /* Burst write */ + ql_log(ql_log_warn + ql_dbg_verbose, vha, 0x7095, + "Write burst (%#lx dwords)...\n", dburst); ret = qla2x00_load_ram(vha, optrom_dma, - flash_data_addr(ha, faddr), - OPTROM_BURST_DWORDS); - if (ret != QLA_SUCCESS) { - ql_log(ql_log_warn, vha, 0x7097, - "Unable to burst-write optrom segment " - "(%x/%x/%llx).\n", ret, - flash_data_addr(ha, faddr), - (unsigned long long)optrom_dma); - ql_log(ql_log_warn, vha, 0x7098, - "Reverting to slow-write.\n"); - - dma_free_coherent(&ha->pdev->dev, - OPTROM_BURST_SIZE, optrom, optrom_dma); - optrom = NULL; - } else { - liter += OPTROM_BURST_DWORDS - 1; - faddr += OPTROM_BURST_DWORDS - 1; - dwptr += OPTROM_BURST_DWORDS - 1; + flash_data_addr(ha, faddr), dburst); + if (!ret) { + liter += dburst - 1; + faddr += dburst - 1; + dwptr += dburst - 1; continue; } + + ql_log(ql_log_warn, vha, 0x7097, + "Failed burst-write at %x (%p/%#llx)....\n", + flash_data_addr(ha, faddr), optrom, + (u64)optrom_dma); + + dma_free_coherent(&ha->pdev->dev, + OPTROM_BURST_SIZE, optrom, optrom_dma); + optrom = NULL; + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) + break; + ql_log(ql_log_warn, vha, 0x7098, + "Reverting to slow write...\n"); } + /* Slow write */ ret = qla24xx_write_flash_dword(ha, flash_data_addr(ha, faddr), cpu_to_le32(*dwptr)); - if (ret != QLA_SUCCESS) { + if (ret) { ql_dbg(ql_dbg_user, vha, 0x7006, - "Unable to program flash address=%x data=%x.\n", - faddr, *dwptr); + "Failed slopw write %x (%x)\n", faddr, *dwptr); break; } - - /* Do sector protect. */ - if (ha->fdt_unprotect_sec_cmd && - ((faddr & rest_addr) == rest_addr)) - qla24xx_write_flash_dword(ha, - ha->fdt_protect_sec_cmd, - (fdata & 0xff00) | ((fdata << 16) & - 0xff0000) | ((fdata >> 16) & 0xff)); } + ql_log(ql_log_warn + ql_dbg_verbose, vha, 0x7095, + "Protect flash...\n"); ret = qla24xx_protect_flash(vha); - if (ret != QLA_SUCCESS) + if (ret) ql_log(ql_log_warn, vha, 0x7099, - "Unable to protect flash after update.\n"); + "Failed to protect flash\n"); done: if (optrom) dma_free_coherent(&ha->pdev->dev, @@ -1349,7 +1373,7 @@ done: } uint8_t * -qla2x00_read_nvram_data(scsi_qla_host_t *vha, uint8_t *buf, uint32_t naddr, +qla2x00_read_nvram_data(scsi_qla_host_t *vha, void *buf, uint32_t naddr, uint32_t bytes) { uint32_t i; @@ -1368,27 +1392,30 @@ qla2x00_read_nvram_data(scsi_qla_host_t *vha, uint8_t *buf, uint32_t naddr, } uint8_t * -qla24xx_read_nvram_data(scsi_qla_host_t *vha, uint8_t *buf, uint32_t naddr, +qla24xx_read_nvram_data(scsi_qla_host_t *vha, void *buf, uint32_t naddr, uint32_t bytes) { - uint32_t i; - uint32_t *dwptr; struct qla_hw_data *ha = vha->hw; + uint32_t *dwptr = buf; + uint32_t i; if (IS_P3P_TYPE(ha)) return buf; /* Dword reads to flash. */ - dwptr = (uint32_t *)buf; - for (i = 0; i < bytes >> 2; i++, naddr++) - dwptr[i] = cpu_to_le32(qla24xx_read_flash_dword(ha, - nvram_data_addr(ha, naddr))); + naddr = nvram_data_addr(ha, naddr); + bytes >>= 2; + for (i = 0; i < bytes; i++, naddr++, dwptr++) { + if (qla24xx_read_flash_dword(ha, naddr, dwptr)) + break; + cpu_to_le32s(dwptr); + } return buf; } int -qla2x00_write_nvram_data(scsi_qla_host_t *vha, uint8_t *buf, uint32_t naddr, +qla2x00_write_nvram_data(scsi_qla_host_t *vha, void *buf, uint32_t naddr, uint32_t bytes) { int ret, stat; @@ -1422,14 +1449,14 @@ qla2x00_write_nvram_data(scsi_qla_host_t *vha, uint8_t *buf, uint32_t naddr, } int -qla24xx_write_nvram_data(scsi_qla_host_t *vha, uint8_t *buf, uint32_t naddr, +qla24xx_write_nvram_data(scsi_qla_host_t *vha, void *buf, uint32_t naddr, uint32_t bytes) { - int ret; - uint32_t i; - uint32_t *dwptr; struct qla_hw_data *ha = vha->hw; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; + uint32_t *dwptr = buf; + uint32_t i; + int ret; ret = QLA_SUCCESS; @@ -1446,11 +1473,10 @@ qla24xx_write_nvram_data(scsi_qla_host_t *vha, uint8_t *buf, uint32_t naddr, qla24xx_write_flash_dword(ha, nvram_conf_addr(ha, 0x101), 0); /* Dword writes to flash. */ - dwptr = (uint32_t *)buf; - for (i = 0; i < bytes >> 2; i++, naddr++, dwptr++) { - ret = qla24xx_write_flash_dword(ha, - nvram_data_addr(ha, naddr), cpu_to_le32(*dwptr)); - if (ret != QLA_SUCCESS) { + naddr = nvram_data_addr(ha, naddr); + bytes >>= 2; + for (i = 0; i < bytes; i++, naddr++, dwptr++) { + if (qla24xx_write_flash_dword(ha, naddr, cpu_to_le32(*dwptr))) { ql_dbg(ql_dbg_user, vha, 0x709a, "Unable to program nvram address=%x data=%x.\n", naddr, *dwptr); @@ -1470,31 +1496,34 @@ qla24xx_write_nvram_data(scsi_qla_host_t *vha, uint8_t *buf, uint32_t naddr, } uint8_t * -qla25xx_read_nvram_data(scsi_qla_host_t *vha, uint8_t *buf, uint32_t naddr, +qla25xx_read_nvram_data(scsi_qla_host_t *vha, void *buf, uint32_t naddr, uint32_t bytes) { - uint32_t i; - uint32_t *dwptr; struct qla_hw_data *ha = vha->hw; + uint32_t *dwptr = buf; + uint32_t i; /* Dword reads to flash. */ - dwptr = (uint32_t *)buf; - for (i = 0; i < bytes >> 2; i++, naddr++) - dwptr[i] = cpu_to_le32(qla24xx_read_flash_dword(ha, - flash_data_addr(ha, ha->flt_region_vpd_nvram | naddr))); + naddr = flash_data_addr(ha, ha->flt_region_vpd_nvram | naddr); + bytes >>= 2; + for (i = 0; i < bytes; i++, naddr++, dwptr++) { + if (qla24xx_read_flash_dword(ha, naddr, dwptr)) + break; + + cpu_to_le32s(dwptr); + } return buf; } +#define RMW_BUFFER_SIZE (64 * 1024) int -qla25xx_write_nvram_data(scsi_qla_host_t *vha, uint8_t *buf, uint32_t naddr, +qla25xx_write_nvram_data(scsi_qla_host_t *vha, void *buf, uint32_t naddr, uint32_t bytes) { struct qla_hw_data *ha = vha->hw; -#define RMW_BUFFER_SIZE (64 * 1024) - uint8_t *dbuf; + uint8_t *dbuf = vmalloc(RMW_BUFFER_SIZE); - dbuf = vmalloc(RMW_BUFFER_SIZE); if (!dbuf) return QLA_MEMORY_ALLOC_FAILED; ha->isp_ops->read_optrom(vha, dbuf, ha->flt_region_vpd_nvram << 2, @@ -1728,7 +1757,7 @@ qla83xx_select_led_port(struct qla_hw_data *ha) { uint32_t led_select_value = 0; - if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha)) + if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) goto out; if (ha->port_no == 0) @@ -1749,13 +1778,14 @@ qla83xx_beacon_blink(struct scsi_qla_host *vha) uint16_t orig_led_cfg[6]; uint32_t led_10_value, led_43_value; - if (!IS_QLA83XX(ha) && !IS_QLA81XX(ha) && !IS_QLA27XX(ha)) + if (!IS_QLA83XX(ha) && !IS_QLA81XX(ha) && !IS_QLA27XX(ha) && + !IS_QLA28XX(ha)) return; if (!ha->beacon_blink_led) return; - if (IS_QLA27XX(ha)) { + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { qla2x00_write_ram_word(vha, 0x1003, 0x40000230); qla2x00_write_ram_word(vha, 0x1004, 0x40000230); } else if (IS_QLA2031(ha)) { @@ -1845,7 +1875,7 @@ qla24xx_beacon_on(struct scsi_qla_host *vha) return QLA_FUNCTION_FAILED; } - if (IS_QLA2031(ha) || IS_QLA27XX(ha)) + if (IS_QLA2031(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) goto skip_gpio; spin_lock_irqsave(&ha->hardware_lock, flags); @@ -1885,7 +1915,7 @@ qla24xx_beacon_off(struct scsi_qla_host *vha) ha->beacon_blink_led = 0; - if (IS_QLA2031(ha) || IS_QLA27XX(ha)) + if (IS_QLA2031(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) goto set_fw_options; if (IS_QLA8031(ha) || IS_QLA81XX(ha)) @@ -2314,8 +2344,8 @@ qla2x00_resume_hba(struct scsi_qla_host *vha) scsi_unblock_requests(vha->host); } -uint8_t * -qla2x00_read_optrom_data(struct scsi_qla_host *vha, uint8_t *buf, +void * +qla2x00_read_optrom_data(struct scsi_qla_host *vha, void *buf, uint32_t offset, uint32_t length) { uint32_t addr, midpoint; @@ -2349,12 +2379,12 @@ qla2x00_read_optrom_data(struct scsi_qla_host *vha, uint8_t *buf, } int -qla2x00_write_optrom_data(struct scsi_qla_host *vha, uint8_t *buf, +qla2x00_write_optrom_data(struct scsi_qla_host *vha, void *buf, uint32_t offset, uint32_t length) { int rval; - uint8_t man_id, flash_id, sec_number, data; + uint8_t man_id, flash_id, sec_number, *data; uint16_t wd; uint32_t addr, liter, sec_mask, rest_addr; struct qla_hw_data *ha = vha->hw; @@ -2483,7 +2513,7 @@ update_flash: for (addr = offset, liter = 0; liter < length; liter++, addr++) { - data = buf[liter]; + data = buf + liter; /* Are we at the beginning of a sector? */ if ((addr & rest_addr) == 0) { if (IS_QLA2322(ha) || IS_QLA6322(ha)) { @@ -2551,7 +2581,7 @@ update_flash: } } - if (qla2x00_program_flash_address(ha, addr, data, + if (qla2x00_program_flash_address(ha, addr, *data, man_id, flash_id)) { rval = QLA_FUNCTION_FAILED; break; @@ -2567,8 +2597,8 @@ update_flash: return rval; } -uint8_t * -qla24xx_read_optrom_data(struct scsi_qla_host *vha, uint8_t *buf, +void * +qla24xx_read_optrom_data(struct scsi_qla_host *vha, void *buf, uint32_t offset, uint32_t length) { struct qla_hw_data *ha = vha->hw; @@ -2578,7 +2608,7 @@ qla24xx_read_optrom_data(struct scsi_qla_host *vha, uint8_t *buf, set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); /* Go with read. */ - qla24xx_read_flash_data(vha, (uint32_t *)buf, offset >> 2, length >> 2); + qla24xx_read_flash_data(vha, (void *)buf, offset >> 2, length >> 2); /* Resume HBA. */ clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); @@ -2587,8 +2617,340 @@ qla24xx_read_optrom_data(struct scsi_qla_host *vha, uint8_t *buf, return buf; } +static int +qla28xx_extract_sfub_and_verify(struct scsi_qla_host *vha, uint32_t *buf, + uint32_t len, uint32_t buf_size_without_sfub, uint8_t *sfub_buf) +{ + uint32_t *p, check_sum = 0; + int i; + + p = buf + buf_size_without_sfub; + + /* Extract SFUB from end of file */ + memcpy(sfub_buf, (uint8_t *)p, + sizeof(struct secure_flash_update_block)); + + for (i = 0; i < (sizeof(struct secure_flash_update_block) >> 2); i++) + check_sum += p[i]; + + check_sum = (~check_sum) + 1; + + if (check_sum != p[i]) { + ql_log(ql_log_warn, vha, 0x7097, + "SFUB checksum failed, 0x%x, 0x%x\n", + check_sum, p[i]); + return QLA_COMMAND_ERROR; + } + + return QLA_SUCCESS; +} + +static int +qla28xx_get_flash_region(struct scsi_qla_host *vha, uint32_t start, + struct qla_flt_region *region) +{ + struct qla_hw_data *ha = vha->hw; + struct qla_flt_header *flt; + struct qla_flt_region *flt_reg; + uint16_t cnt; + int rval = QLA_FUNCTION_FAILED; + + if (!ha->flt) + return QLA_FUNCTION_FAILED; + + flt = (struct qla_flt_header *)ha->flt; + flt_reg = (struct qla_flt_region *)&flt[1]; + cnt = le16_to_cpu(flt->length) / sizeof(struct qla_flt_region); + + for (; cnt; cnt--, flt_reg++) { + if (flt_reg->start == start) { + memcpy((uint8_t *)region, flt_reg, + sizeof(struct qla_flt_region)); + rval = QLA_SUCCESS; + break; + } + } + + return rval; +} + +static int +qla28xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr, + uint32_t dwords) +{ + struct qla_hw_data *ha = vha->hw; + ulong liter; + ulong dburst = OPTROM_BURST_DWORDS; /* burst size in dwords */ + uint32_t sec_mask, rest_addr, fdata; + void *optrom = NULL; + dma_addr_t optrom_dma; + int rval; + struct secure_flash_update_block *sfub; + dma_addr_t sfub_dma; + uint32_t offset = faddr << 2; + uint32_t buf_size_without_sfub = 0; + struct qla_flt_region region; + bool reset_to_rom = false; + uint32_t risc_size, risc_attr = 0; + uint32_t *fw_array = NULL; + + /* Retrieve region info - must be a start address passed in */ + rval = qla28xx_get_flash_region(vha, offset, ®ion); + + if (rval != QLA_SUCCESS) { + ql_log(ql_log_warn, vha, 0xffff, + "Invalid address %x - not a region start address\n", + offset); + goto done; + } + + /* Allocate dma buffer for burst write */ + optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE, + &optrom_dma, GFP_KERNEL); + if (!optrom) { + ql_log(ql_log_warn, vha, 0x7095, + "Failed allocate burst (%x bytes)\n", OPTROM_BURST_SIZE); + rval = QLA_COMMAND_ERROR; + goto done; + } + + /* + * If adapter supports secure flash and region is secure + * extract secure flash update block (SFUB) and verify + */ + if (ha->flags.secure_adapter && region.attribute) { + + ql_log(ql_log_warn + ql_dbg_verbose, vha, 0xffff, + "Region %x is secure\n", region.code); + + if (region.code == FLT_REG_FW || + region.code == FLT_REG_FW_SEC_27XX) { + fw_array = dwptr; + + /* 1st fw array */ + risc_size = be32_to_cpu(fw_array[3]); + risc_attr = be32_to_cpu(fw_array[9]); + + buf_size_without_sfub = risc_size; + fw_array += risc_size; + + /* 2nd fw array */ + risc_size = be32_to_cpu(fw_array[3]); + + buf_size_without_sfub += risc_size; + fw_array += risc_size; + + /* 1st dump template */ + risc_size = be32_to_cpu(fw_array[2]); + + /* skip header and ignore checksum */ + buf_size_without_sfub += risc_size; + fw_array += risc_size; + + if (risc_attr & BIT_9) { + /* 2nd dump template */ + risc_size = be32_to_cpu(fw_array[2]); + + /* skip header and ignore checksum */ + buf_size_without_sfub += risc_size; + fw_array += risc_size; + } + } else { + ql_log(ql_log_warn + ql_dbg_verbose, vha, 0xffff, + "Secure region %x not supported\n", + region.code); + rval = QLA_COMMAND_ERROR; + goto done; + } + + sfub = dma_alloc_coherent(&ha->pdev->dev, + sizeof(struct secure_flash_update_block), &sfub_dma, + GFP_KERNEL); + if (!sfub) { + ql_log(ql_log_warn, vha, 0xffff, + "Unable to allocate memory for SFUB\n"); + rval = QLA_COMMAND_ERROR; + goto done; + } + + rval = qla28xx_extract_sfub_and_verify(vha, dwptr, dwords, + buf_size_without_sfub, (uint8_t *)sfub); + + if (rval != QLA_SUCCESS) + goto done; + + ql_log(ql_log_warn + ql_dbg_verbose, vha, 0xffff, + "SFUB extract and verify successful\n"); + } + + rest_addr = (ha->fdt_block_size >> 2) - 1; + sec_mask = ~rest_addr; + + /* Lock semaphore */ + rval = qla81xx_fac_semaphore_access(vha, FAC_SEMAPHORE_LOCK); + if (rval != QLA_SUCCESS) { + ql_log(ql_log_warn, vha, 0xffff, + "Unable to lock flash semaphore."); + goto done; + } + + ql_log(ql_log_warn + ql_dbg_verbose, vha, 0x7095, + "Unprotect flash...\n"); + rval = qla24xx_unprotect_flash(vha); + if (rval) { + qla81xx_fac_semaphore_access(vha, FAC_SEMAPHORE_UNLOCK); + ql_log(ql_log_warn, vha, 0x7096, "Failed unprotect flash\n"); + goto done; + } + + for (liter = 0; liter < dwords; liter++, faddr++) { + fdata = (faddr & sec_mask) << 2; + + /* If start of sector */ + if (!(faddr & rest_addr)) { + ql_log(ql_log_warn + ql_dbg_verbose, vha, 0x7095, + "Erase sector %#x...\n", faddr); + rval = qla24xx_erase_sector(vha, fdata); + if (rval) { + ql_dbg(ql_dbg_user, vha, 0x7007, + "Failed erase sector %#x\n", faddr); + goto write_protect; + } + } + } + + if (ha->flags.secure_adapter) { + /* + * If adapter supports secure flash but FW doesn't, + * disable write protect, release semaphore and reset + * chip to execute ROM code in order to update region securely + */ + if (!ha->flags.secure_fw) { + ql_log(ql_log_warn + ql_dbg_verbose, vha, 0xffff, + "Disable Write and Release Semaphore."); + rval = qla24xx_protect_flash(vha); + if (rval != QLA_SUCCESS) { + qla81xx_fac_semaphore_access(vha, + FAC_SEMAPHORE_UNLOCK); + ql_log(ql_log_warn, vha, 0xffff, + "Unable to protect flash."); + goto done; + } + + ql_log(ql_log_warn + ql_dbg_verbose, vha, 0xffff, + "Reset chip to ROM."); + set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); + set_bit(ISP_ABORT_TO_ROM, &vha->dpc_flags); + qla2xxx_wake_dpc(vha); + rval = qla2x00_wait_for_chip_reset(vha); + if (rval != QLA_SUCCESS) { + ql_log(ql_log_warn, vha, 0xffff, + "Unable to reset to ROM code."); + goto done; + } + reset_to_rom = true; + ha->flags.fac_supported = 0; + + ql_log(ql_log_warn + ql_dbg_verbose, vha, 0xffff, + "Lock Semaphore"); + rval = qla2xxx_write_remote_register(vha, + FLASH_SEMAPHORE_REGISTER_ADDR, 0x00020002); + if (rval != QLA_SUCCESS) { + ql_log(ql_log_warn, vha, 0xffff, + "Unable to lock flash semaphore."); + goto done; + } + + /* Unprotect flash */ + ql_log(ql_log_warn + ql_dbg_verbose, vha, 0xffff, + "Enable Write."); + rval = qla2x00_write_ram_word(vha, 0x7ffd0101, 0); + if (rval) { + ql_log(ql_log_warn, vha, 0x7096, + "Failed unprotect flash\n"); + goto done; + } + } + + /* If region is secure, send Secure Flash MB Cmd */ + if (region.attribute && buf_size_without_sfub) { + ql_log(ql_log_warn + ql_dbg_verbose, vha, 0xffff, + "Sending Secure Flash MB Cmd\n"); + rval = qla28xx_secure_flash_update(vha, 0, region.code, + buf_size_without_sfub, sfub_dma, + sizeof(struct secure_flash_update_block)); + if (rval != QLA_SUCCESS) { + ql_log(ql_log_warn, vha, 0xffff, + "Secure Flash MB Cmd failed %x.", rval); + goto write_protect; + } + } + + } + + /* re-init flash offset */ + faddr = offset >> 2; + + for (liter = 0; liter < dwords; liter++, faddr++, dwptr++) { + fdata = (faddr & sec_mask) << 2; + + /* If smaller than a burst remaining */ + if (dwords - liter < dburst) + dburst = dwords - liter; + + /* Copy to dma buffer */ + memcpy(optrom, dwptr, dburst << 2); + + /* Burst write */ + ql_log(ql_log_warn + ql_dbg_verbose, vha, 0x7095, + "Write burst (%#lx dwords)...\n", dburst); + rval = qla2x00_load_ram(vha, optrom_dma, + flash_data_addr(ha, faddr), dburst); + if (rval != QLA_SUCCESS) { + ql_log(ql_log_warn, vha, 0x7097, + "Failed burst write at %x (%p/%#llx)...\n", + flash_data_addr(ha, faddr), optrom, + (u64)optrom_dma); + break; + } + + liter += dburst - 1; + faddr += dburst - 1; + dwptr += dburst - 1; + continue; + } + +write_protect: + ql_log(ql_log_warn + ql_dbg_verbose, vha, 0x7095, + "Protect flash...\n"); + rval = qla24xx_protect_flash(vha); + if (rval) { + qla81xx_fac_semaphore_access(vha, FAC_SEMAPHORE_UNLOCK); + ql_log(ql_log_warn, vha, 0x7099, + "Failed protect flash\n"); + } + + if (reset_to_rom == true) { + /* Schedule DPC to restart the RISC */ + set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); + qla2xxx_wake_dpc(vha); + + rval = qla2x00_wait_for_hba_online(vha); + if (rval != QLA_SUCCESS) + ql_log(ql_log_warn, vha, 0xffff, + "Adapter did not come out of reset\n"); + } + +done: + if (optrom) + dma_free_coherent(&ha->pdev->dev, + OPTROM_BURST_SIZE, optrom, optrom_dma); + + return rval; +} + int -qla24xx_write_optrom_data(struct scsi_qla_host *vha, uint8_t *buf, +qla24xx_write_optrom_data(struct scsi_qla_host *vha, void *buf, uint32_t offset, uint32_t length) { int rval; @@ -2599,8 +2961,12 @@ qla24xx_write_optrom_data(struct scsi_qla_host *vha, uint8_t *buf, set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); /* Go with write. */ - rval = qla24xx_write_flash_data(vha, (uint32_t *)buf, offset >> 2, - length >> 2); + if (IS_QLA28XX(ha)) + rval = qla28xx_write_flash_data(vha, (uint32_t *)buf, + offset >> 2, length >> 2); + else + rval = qla24xx_write_flash_data(vha, (uint32_t *)buf, + offset >> 2, length >> 2); clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); scsi_unblock_requests(vha->host); @@ -2608,8 +2974,8 @@ qla24xx_write_optrom_data(struct scsi_qla_host *vha, uint8_t *buf, return rval; } -uint8_t * -qla25xx_read_optrom_data(struct scsi_qla_host *vha, uint8_t *buf, +void * +qla25xx_read_optrom_data(struct scsi_qla_host *vha, void *buf, uint32_t offset, uint32_t length) { int rval; @@ -2620,7 +2986,7 @@ qla25xx_read_optrom_data(struct scsi_qla_host *vha, uint8_t *buf, struct qla_hw_data *ha = vha->hw; if (IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) || - IS_QLA27XX(ha)) + IS_QLA27XX(ha) || IS_QLA28XX(ha)) goto try_fast; if (offset & 0xfff) goto slow_read; @@ -2628,6 +2994,8 @@ qla25xx_read_optrom_data(struct scsi_qla_host *vha, uint8_t *buf, goto slow_read; try_fast: + if (offset & 0xff) + goto slow_read; optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE, &optrom_dma, GFP_KERNEL); if (!optrom) { @@ -2874,7 +3242,7 @@ qla2x00_get_flash_version(scsi_qla_host_t *vha, void *mbuf) "Dumping fw " "ver from flash:.\n"); ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x010b, - (uint8_t *)dbyte, 8); + dbyte, 32); if ((dcode[0] == 0xffff && dcode[1] == 0xffff && dcode[2] == 0xffff && dcode[3] == 0xffff) || @@ -2905,8 +3273,8 @@ qla82xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf) { int ret = QLA_SUCCESS; uint32_t pcihdr, pcids; - uint32_t *dcode; - uint8_t *bcode; + uint32_t *dcode = mbuf; + uint8_t *bcode = mbuf; uint8_t code_type, last_image; struct qla_hw_data *ha = vha->hw; @@ -2918,17 +3286,14 @@ qla82xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf) memset(ha->fcode_revision, 0, sizeof(ha->fcode_revision)); memset(ha->fw_revision, 0, sizeof(ha->fw_revision)); - dcode = mbuf; - /* Begin with first PCI expansion ROM header. */ pcihdr = ha->flt_region_boot << 2; last_image = 1; do { /* Verify PCI expansion ROM header. */ - ha->isp_ops->read_optrom(vha, (uint8_t *)dcode, pcihdr, - 0x20 * 4); + ha->isp_ops->read_optrom(vha, dcode, pcihdr, 0x20 * 4); bcode = mbuf + (pcihdr % 4); - if (bcode[0x0] != 0x55 || bcode[0x1] != 0xaa) { + if (memcmp(bcode, "\x55\xaa", 2)) { /* No signature */ ql_log(ql_log_fatal, vha, 0x0154, "No matching ROM signature.\n"); @@ -2939,13 +3304,11 @@ qla82xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf) /* Locate PCI data structure. */ pcids = pcihdr + ((bcode[0x19] << 8) | bcode[0x18]); - ha->isp_ops->read_optrom(vha, (uint8_t *)dcode, pcids, - 0x20 * 4); + ha->isp_ops->read_optrom(vha, dcode, pcids, 0x20 * 4); bcode = mbuf + (pcihdr % 4); /* Validate signature of PCI data structure. */ - if (bcode[0x0] != 'P' || bcode[0x1] != 'C' || - bcode[0x2] != 'I' || bcode[0x3] != 'R') { + if (memcmp(bcode, "PCIR", 4)) { /* Incorrect header. */ ql_log(ql_log_fatal, vha, 0x0155, "PCI data struct not found pcir_adr=%x.\n", pcids); @@ -2996,8 +3359,7 @@ qla82xx_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; - ha->isp_ops->read_optrom(vha, (uint8_t *)dcode, ha->flt_region_fw << 2, - 0x20); + ha->isp_ops->read_optrom(vha, dcode, ha->flt_region_fw << 2, 0x20); bcode = mbuf + (pcihdr % 4); /* Validate signature of PCI data structure. */ @@ -3019,15 +3381,14 @@ int qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf) { int ret = QLA_SUCCESS; - uint32_t pcihdr, pcids; - uint32_t *dcode; - uint8_t *bcode; + uint32_t pcihdr = 0, pcids = 0; + uint32_t *dcode = mbuf; + uint8_t *bcode = mbuf; uint8_t code_type, last_image; int i; struct qla_hw_data *ha = vha->hw; uint32_t faddr = 0; - - pcihdr = pcids = 0; + struct active_regions active_regions = { }; if (IS_P3P_TYPE(ha)) return ret; @@ -3040,18 +3401,19 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf) memset(ha->fcode_revision, 0, sizeof(ha->fcode_revision)); memset(ha->fw_revision, 0, sizeof(ha->fw_revision)); - dcode = mbuf; 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; + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { + qla27xx_get_active_image(vha, &active_regions); + if (active_regions.global == QLA27XX_SECONDARY_IMAGE) { + pcihdr = ha->flt_region_boot_sec << 2; + } + } - last_image = 1; do { /* Verify PCI expansion ROM header. */ qla24xx_read_flash_data(vha, dcode, pcihdr >> 2, 0x20); bcode = mbuf + (pcihdr % 4); - if (bcode[0x0] != 0x55 || bcode[0x1] != 0xaa) { + if (memcmp(bcode, "\x55\xaa", 2)) { /* No signature */ ql_log(ql_log_fatal, vha, 0x0059, "No matching ROM signature.\n"); @@ -3066,11 +3428,11 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf) bcode = mbuf + (pcihdr % 4); /* Validate signature of PCI data structure. */ - if (bcode[0x0] != 'P' || bcode[0x1] != 'C' || - bcode[0x2] != 'I' || bcode[0x3] != 'R') { + if (memcmp(bcode, "PCIR", 4)) { /* Incorrect header. */ ql_log(ql_log_fatal, vha, 0x005a, "PCI data struct not found pcir_adr=%x.\n", pcids); + ql_dump_buffer(ql_dbg_init, vha, 0x0059, dcode, 32); ret = QLA_FUNCTION_FAILED; break; } @@ -3117,30 +3479,24 @@ 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, faddr + 4, 4); - for (i = 0; i < 4; i++) - dcode[i] = be32_to_cpu(dcode[i]); + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { + qla27xx_get_active_image(vha, &active_regions); + if (active_regions.global == QLA27XX_SECONDARY_IMAGE) + faddr = ha->flt_region_fw_sec; + } - if ((dcode[0] == 0xffffffff && dcode[1] == 0xffffffff && - dcode[2] == 0xffffffff && dcode[3] == 0xffffffff) || - (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 && - dcode[3] == 0)) { + qla24xx_read_flash_data(vha, dcode, faddr, 8); + if (qla24xx_risc_firmware_invalid(dcode)) { ql_log(ql_log_warn, vha, 0x005f, "Unrecognized fw revision at %x.\n", ha->flt_region_fw * 4); + ql_dump_buffer(ql_dbg_init, vha, 0x005f, dcode, 32); } else { - ha->fw_revision[0] = dcode[0]; - ha->fw_revision[1] = dcode[1]; - ha->fw_revision[2] = dcode[2]; - ha->fw_revision[3] = dcode[3]; + for (i = 0; i < 4; i++) + ha->fw_revision[i] = be32_to_cpu(dcode[4+i]); ql_dbg(ql_dbg_init, vha, 0x0060, - "Firmware revision %d.%d.%d (%x).\n", + "Firmware revision (flash) %u.%u.%u (%x).\n", ha->fw_revision[0], ha->fw_revision[1], ha->fw_revision[2], ha->fw_revision[3]); } @@ -3152,20 +3508,17 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf) } memset(ha->gold_fw_version, 0, sizeof(ha->gold_fw_version)); - dcode = mbuf; - ha->isp_ops->read_optrom(vha, (uint8_t *)dcode, - ha->flt_region_gold_fw << 2, 32); - - if (dcode[4] == 0xFFFFFFFF && dcode[5] == 0xFFFFFFFF && - dcode[6] == 0xFFFFFFFF && dcode[7] == 0xFFFFFFFF) { + faddr = ha->flt_region_gold_fw; + qla24xx_read_flash_data(vha, (void *)dcode, ha->flt_region_gold_fw, 8); + if (qla24xx_risc_firmware_invalid(dcode)) { ql_log(ql_log_warn, vha, 0x0056, - "Unrecognized golden fw at 0x%x.\n", - ha->flt_region_gold_fw * 4); + "Unrecognized golden fw at %#x.\n", faddr); + ql_dump_buffer(ql_dbg_init, vha, 0x0056, dcode, 32); return ret; } - for (i = 4; i < 8; i++) - ha->gold_fw_version[i-4] = be32_to_cpu(dcode[i]); + for (i = 0; i < 4; i++) + ha->gold_fw_version[i] = be32_to_cpu(dcode[4+i]); return ret; } @@ -3237,7 +3590,7 @@ qla24xx_read_fcp_prio_cfg(scsi_qla_host_t *vha) fcp_prio_addr = ha->flt_region_fcp_prio; /* first read the fcp priority data header from flash */ - ha->isp_ops->read_optrom(vha, (uint8_t *)ha->fcp_prio_cfg, + ha->isp_ops->read_optrom(vha, ha->fcp_prio_cfg, fcp_prio_addr << 2, FCP_PRIO_CFG_HDR_SIZE); if (!qla24xx_fcp_prio_cfg_valid(vha, ha->fcp_prio_cfg, 0)) @@ -3248,7 +3601,7 @@ qla24xx_read_fcp_prio_cfg(scsi_qla_host_t *vha) len = ha->fcp_prio_cfg->num_entries * FCP_PRIO_CFG_ENTRY_SIZE; max_len = FCP_PRIO_CFG_SIZE - FCP_PRIO_CFG_HDR_SIZE; - ha->isp_ops->read_optrom(vha, (uint8_t *)&ha->fcp_prio_cfg->entry[0], + ha->isp_ops->read_optrom(vha, &ha->fcp_prio_cfg->entry[0], fcp_prio_addr << 2, (len < max_len ? len : max_len)); /* revalidate the entire FCP priority config data, including entries */ diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 582d1663f971..3eeae72793bc 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -184,6 +184,7 @@ static inline int qlt_issue_marker(struct scsi_qla_host *vha, int vha_locked) /* Send marker if required */ if (unlikely(vha->marker_needed != 0)) { int rc = qla2x00_issue_marker(vha, vha_locked); + if (rc != QLA_SUCCESS) { ql_dbg(ql_dbg_tgt, vha, 0xe03d, "qla_target(%d): issue_marker() failed\n", @@ -557,6 +558,7 @@ static int qla24xx_post_nack_work(struct scsi_qla_host *vha, fc_port_t *fcport, struct imm_ntfy_from_isp *ntfy, int type) { struct qla_work_evt *e; + e = qla2x00_alloc_work(vha, QLA_EVT_NACK); if (!e) return QLA_FUNCTION_FAILED; @@ -680,7 +682,6 @@ done: void qla24xx_do_nack_work(struct scsi_qla_host *vha, struct qla_work_evt *e) { fc_port_t *t; - unsigned long flags; switch (e->u.nack.type) { case SRB_NACK_PRLI: @@ -693,24 +694,19 @@ void qla24xx_do_nack_work(struct scsi_qla_host *vha, struct qla_work_evt *e) if (t) { ql_log(ql_log_info, vha, 0xd034, "%s create sess success %p", __func__, t); - spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); /* create sess has an extra kref */ vha->hw->tgt.tgt_ops->put_sess(e->u.nack.fcport); - spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); } break; } qla24xx_async_notify_ack(vha, e->u.nack.fcport, - (struct imm_ntfy_from_isp*)e->u.nack.iocb, e->u.nack.type); + (struct imm_ntfy_from_isp *)e->u.nack.iocb, e->u.nack.type); } void qla24xx_delete_sess_fn(struct work_struct *work) { fc_port_t *fcport = container_of(work, struct fc_port, del_work); struct qla_hw_data *ha = fcport->vha->hw; - unsigned long flags; - - spin_lock_irqsave(&ha->tgt.sess_lock, flags); if (fcport->se_sess) { ha->tgt.tgt_ops->shutdown_sess(fcport); @@ -718,7 +714,6 @@ void qla24xx_delete_sess_fn(struct work_struct *work) } else { qlt_unreg_sess(fcport); } - spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); } /* @@ -787,8 +782,9 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport) fcport->port_name, sess->loop_id); sess->local = 0; } - ha->tgt.tgt_ops->put_sess(sess); spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); + + ha->tgt.tgt_ops->put_sess(sess); } /* @@ -980,6 +976,8 @@ void qlt_free_session_done(struct work_struct *work) sess->send_els_logo); if (!IS_SW_RESV_ADDR(sess->d_id)) { + qla2x00_mark_device_lost(vha, sess, 0, 0); + if (sess->send_els_logo) { qlt_port_logo_t logo; @@ -1076,6 +1074,7 @@ void qlt_free_session_done(struct work_struct *work) struct qlt_plogi_ack_t *con = sess->plogi_link[QLT_PLOGI_LINK_CONFLICT]; struct imm_ntfy_from_isp *iocb; + own = sess->plogi_link[QLT_PLOGI_LINK_SAME_WWN]; if (con) { @@ -1160,8 +1159,6 @@ void qlt_unreg_sess(struct fc_port *sess) if (sess->se_sess) vha->hw->tgt.tgt_ops->clear_nacl_from_fcport_map(sess); - qla2x00_mark_device_lost(vha, sess, 0, 0); - sess->deleted = QLA_SESS_DELETION_IN_PROGRESS; sess->disc_state = DSC_DELETE_PEND; sess->last_rscn_gen = sess->rscn_gen; @@ -1329,6 +1326,7 @@ static int qla24xx_get_loop_id(struct scsi_qla_host *vha, const uint8_t *s_id, res = -ENOENT; for (i = 0; i < entries; i++) { struct gid_list_info *gid = (struct gid_list_info *)id_iter; + if ((gid->al_pa == s_id[2]) && (gid->area == s_id[1]) && (gid->domain == s_id[0])) { @@ -2331,14 +2329,14 @@ void qlt_send_resp_ctio(struct qla_qpair *qpair, struct qla_tgt_cmd *cmd, ctio->u.status1.scsi_status |= cpu_to_le16(SS_RESIDUAL_UNDER); - /* Response code and sense key */ - put_unaligned_le32(((0x70 << 24) | (sense_key << 8)), - (&ctio->u.status1.sense_data)[0]); + /* Fixed format sense data. */ + ctio->u.status1.sense_data[0] = 0x70; + ctio->u.status1.sense_data[2] = sense_key; /* Additional sense length */ - put_unaligned_le32(0x0a, (&ctio->u.status1.sense_data)[1]); + ctio->u.status1.sense_data[7] = 0xa; /* ASC and ASCQ */ - put_unaligned_le32(((asc << 24) | (ascq << 16)), - (&ctio->u.status1.sense_data)[3]); + ctio->u.status1.sense_data[12] = asc; + ctio->u.status1.sense_data[13] = ascq; /* Memory Barrier */ wmb(); @@ -2387,7 +2385,7 @@ void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *mcmd) case ELS_PRLO: case ELS_TPRLO: ql_dbg(ql_dbg_disc, vha, 0x2106, - "TM response logo %phC status %#x state %#x", + "TM response logo %8phC status %#x state %#x", mcmd->sess->port_name, mcmd->fc_tm_rsp, mcmd->flags); qlt_schedule_sess_for_deletion(mcmd->sess); @@ -2485,6 +2483,7 @@ static void qlt_unmap_sg(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd) { struct qla_hw_data *ha; struct qla_qpair *qpair; + if (!cmd->sg_mapped) return; @@ -2635,7 +2634,7 @@ static int qlt_24xx_build_ctio_pkt(struct qla_qpair *qpair, static void qlt_load_cont_data_segments(struct qla_tgt_prm *prm) { int cnt; - uint32_t *dword_ptr; + struct dsd64 *cur_dsd; /* Build continuation packets */ while (prm->seg_cnt > 0) { @@ -2656,19 +2655,13 @@ static void qlt_load_cont_data_segments(struct qla_tgt_prm *prm) cont_pkt64->sys_define = 0; cont_pkt64->entry_type = CONTINUE_A64_TYPE; - dword_ptr = (uint32_t *)&cont_pkt64->dseg_0_address; + cur_dsd = cont_pkt64->dsd; /* Load continuation entry data segments */ for (cnt = 0; cnt < QLA_TGT_DATASEGS_PER_CONT_24XX && prm->seg_cnt; cnt++, prm->seg_cnt--) { - *dword_ptr++ = - cpu_to_le32(lower_32_bits - (sg_dma_address(prm->sg))); - *dword_ptr++ = cpu_to_le32(upper_32_bits - (sg_dma_address(prm->sg))); - *dword_ptr++ = cpu_to_le32(sg_dma_len(prm->sg)); - + append_dsd64(&cur_dsd, prm->sg); prm->sg = sg_next(prm->sg); } } @@ -2681,13 +2674,13 @@ static void qlt_load_cont_data_segments(struct qla_tgt_prm *prm) static void qlt_load_data_segments(struct qla_tgt_prm *prm) { int cnt; - uint32_t *dword_ptr; + struct dsd64 *cur_dsd; struct ctio7_to_24xx *pkt24 = (struct ctio7_to_24xx *)prm->pkt; pkt24->u.status0.transfer_length = cpu_to_le32(prm->cmd->bufflen); /* Setup packet address segment pointer */ - dword_ptr = pkt24->u.status0.dseg_0_address; + cur_dsd = &pkt24->u.status0.dsd; /* Set total data segment count */ if (prm->seg_cnt) @@ -2695,8 +2688,8 @@ static void qlt_load_data_segments(struct qla_tgt_prm *prm) if (prm->seg_cnt == 0) { /* No data transfer */ - *dword_ptr++ = 0; - *dword_ptr = 0; + cur_dsd->address = 0; + cur_dsd->length = 0; return; } @@ -2706,14 +2699,7 @@ static void qlt_load_data_segments(struct qla_tgt_prm *prm) for (cnt = 0; (cnt < QLA_TGT_DATASEGS_PER_CMD_24XX) && prm->seg_cnt; cnt++, prm->seg_cnt--) { - *dword_ptr++ = - cpu_to_le32(lower_32_bits(sg_dma_address(prm->sg))); - - *dword_ptr++ = cpu_to_le32(upper_32_bits( - sg_dma_address(prm->sg))); - - *dword_ptr++ = cpu_to_le32(sg_dma_len(prm->sg)); - + append_dsd64(&cur_dsd, prm->sg); prm->sg = sg_next(prm->sg); } @@ -3037,7 +3023,7 @@ qla_tgt_set_dif_tags(struct qla_tgt_cmd *cmd, struct crc_context *ctx, static inline int qlt_build_ctio_crc2_pkt(struct qla_qpair *qpair, struct qla_tgt_prm *prm) { - uint32_t *cur_dsd; + struct dsd64 *cur_dsd; uint32_t transfer_length = 0; uint32_t data_bytes; uint32_t dif_bytes; @@ -3183,12 +3169,11 @@ qlt_build_ctio_crc2_pkt(struct qla_qpair *qpair, struct qla_tgt_prm *prm) qla_tgt_set_dif_tags(cmd, crc_ctx_pkt, &fw_prot_opts); - pkt->crc_context_address[0] = cpu_to_le32(LSD(crc_ctx_dma)); - pkt->crc_context_address[1] = cpu_to_le32(MSD(crc_ctx_dma)); + put_unaligned_le64(crc_ctx_dma, &pkt->crc_context_address); pkt->crc_context_len = CRC_CONTEXT_LEN_FW; if (!bundling) { - cur_dsd = (uint32_t *) &crc_ctx_pkt->u.nobundling.data_address; + cur_dsd = &crc_ctx_pkt->u.nobundling.data_dsd; } else { /* * Configure Bundling if we need to fetch interlaving @@ -3198,7 +3183,7 @@ qlt_build_ctio_crc2_pkt(struct qla_qpair *qpair, struct qla_tgt_prm *prm) crc_ctx_pkt->u.bundling.dif_byte_count = cpu_to_le32(dif_bytes); crc_ctx_pkt->u.bundling.dseg_count = cpu_to_le16(prm->tot_dsds - prm->prot_seg_cnt); - cur_dsd = (uint32_t *) &crc_ctx_pkt->u.bundling.data_address; + cur_dsd = &crc_ctx_pkt->u.bundling.data_dsd; } /* Finish the common fields of CRC pkt */ @@ -3231,7 +3216,7 @@ qlt_build_ctio_crc2_pkt(struct qla_qpair *qpair, struct qla_tgt_prm *prm) /* Walks dif segments */ pkt->add_flags |= CTIO_CRC2_AF_DIF_DSD_ENA; - cur_dsd = (uint32_t *) &crc_ctx_pkt->u.bundling.dif_address; + cur_dsd = &crc_ctx_pkt->u.bundling.dif_dsd; if (qla24xx_walk_and_build_prot_sglist(ha, NULL, cur_dsd, prm->prot_seg_cnt, cmd)) goto crc_queuing_error; @@ -3263,7 +3248,6 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type, if (!qpair->fw_started || (cmd->reset_count != qpair->chip_reset) || (cmd->sess && cmd->sess->deleted)) { cmd->state = QLA_TGT_STATE_PROCESSED; - qlt_abort_cmd_on_host_reset(cmd->vha, cmd); return 0; } @@ -3292,7 +3276,6 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type, * previous life, just abort the processing. */ cmd->state = QLA_TGT_STATE_PROCESSED; - qlt_abort_cmd_on_host_reset(cmd->vha, cmd); ql_dbg_qp(ql_dbg_async, qpair, 0xe101, "RESET-RSP online/active/old-count/new-count = %d/%d/%d/%d.\n", vha->flags.online, qla2x00_reset_active(vha), @@ -3384,9 +3367,7 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type, cmd->state = QLA_TGT_STATE_PROCESSED; /* Mid-level is done processing */ - spin_lock(&cmd->cmd_lock); cmd->cmd_sent_to_fw = 1; - spin_unlock(&cmd->cmd_lock); cmd->ctio_flags = le16_to_cpu(pkt->u.status0.flags); /* Memory Barrier */ @@ -3433,8 +3414,10 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd) * Either the port is not online or this request was from * previous life, just abort the processing. */ - cmd->state = QLA_TGT_STATE_NEED_DATA; - qlt_abort_cmd_on_host_reset(cmd->vha, cmd); + cmd->aborted = 1; + cmd->write_data_transferred = 0; + cmd->state = QLA_TGT_STATE_DATA_IN; + vha->hw->tgt.tgt_ops->handle_data(cmd); ql_dbg_qp(ql_dbg_async, qpair, 0xe102, "RESET-XFR online/active/old-count/new-count = %d/%d/%d/%d.\n", vha->flags.online, qla2x00_reset_active(vha), @@ -3465,9 +3448,7 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd) qlt_load_data_segments(&prm); cmd->state = QLA_TGT_STATE_NEED_DATA; - spin_lock(&cmd->cmd_lock); cmd->cmd_sent_to_fw = 1; - spin_unlock(&cmd->cmd_lock); cmd->ctio_flags = le16_to_cpu(pkt->u.status0.flags); /* Memory Barrier */ @@ -3646,33 +3627,11 @@ static int __qlt_send_term_imm_notif(struct scsi_qla_host *vha, static void qlt_send_term_imm_notif(struct scsi_qla_host *vha, struct imm_ntfy_from_isp *imm, int ha_locked) { - unsigned long flags = 0; int rc; - if (ha_locked) { - rc = __qlt_send_term_imm_notif(vha, imm); - -#if 0 /* Todo */ - if (rc == -ENOMEM) - qlt_alloc_qfull_cmd(vha, imm, 0, 0); -#else - if (rc) { - } -#endif - goto done; - } - - spin_lock_irqsave(&vha->hw->hardware_lock, flags); + WARN_ON_ONCE(!ha_locked); rc = __qlt_send_term_imm_notif(vha, imm); - -#if 0 /* Todo */ - if (rc == -ENOMEM) - qlt_alloc_qfull_cmd(vha, imm, 0, 0); -#endif - -done: - if (!ha_locked) - spin_unlock_irqrestore(&vha->hw->hardware_lock, flags); + pr_debug("rc = %d\n", rc); } /* @@ -3913,6 +3872,7 @@ static int qlt_term_ctio_exchange(struct qla_qpair *qpair, void *ctio, if (ctio != NULL) { struct ctio7_from_24xx *c = (struct ctio7_from_24xx *)ctio; + term = !(c->flags & cpu_to_le16(OF_TERM_EXCH)); } else @@ -3977,39 +3937,6 @@ static void *qlt_ctio_to_cmd(struct scsi_qla_host *vha, return cmd; } -/* hardware_lock should be held by caller. */ -void -qlt_abort_cmd_on_host_reset(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd) -{ - struct qla_hw_data *ha = vha->hw; - - if (cmd->sg_mapped) - qlt_unmap_sg(vha, cmd); - - /* TODO: fix debug message type and ids. */ - if (cmd->state == QLA_TGT_STATE_PROCESSED) { - ql_dbg(ql_dbg_io, vha, 0xff00, - "HOST-ABORT: state=PROCESSED.\n"); - } else if (cmd->state == QLA_TGT_STATE_NEED_DATA) { - cmd->write_data_transferred = 0; - cmd->state = QLA_TGT_STATE_DATA_IN; - - ql_dbg(ql_dbg_io, vha, 0xff01, - "HOST-ABORT: state=DATA_IN.\n"); - - ha->tgt.tgt_ops->handle_data(cmd); - return; - } else { - ql_dbg(ql_dbg_io, vha, 0xff03, - "HOST-ABORT: state=BAD(%d).\n", - cmd->state); - dump_stack(); - } - - cmd->trc_flags |= TRC_FLUSH; - ha->tgt.tgt_ops->free_cmd(cmd); -} - /* * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire */ @@ -4031,7 +3958,7 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha, return; } - cmd = (struct qla_tgt_cmd *)qlt_ctio_to_cmd(vha, rsp, handle, ctio); + cmd = qlt_ctio_to_cmd(vha, rsp, handle, ctio); if (cmd == NULL) return; @@ -4240,11 +4167,9 @@ static void __qlt_do_work(struct qla_tgt_cmd *cmd) if (ret != 0) goto out_term; /* - * Drop extra session reference from qla_tgt_handle_cmd_for_atio*( + * Drop extra session reference from qlt_handle_cmd_for_atio(). */ - spin_lock_irqsave(&ha->tgt.sess_lock, flags); ha->tgt.tgt_ops->put_sess(sess); - spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); return; out_term: @@ -4261,9 +4186,7 @@ out_term: target_free_tag(sess->se_sess, &cmd->se_cmd); spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); - spin_lock_irqsave(&ha->tgt.sess_lock, flags); ha->tgt.tgt_ops->put_sess(sess); - spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); } static void qlt_do_work(struct work_struct *work) @@ -4472,9 +4395,7 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha, if (!cmd) { ql_dbg(ql_dbg_io, vha, 0x3062, "qla_target(%d): Allocation of cmd failed\n", vha->vp_idx); - spin_lock_irqsave(&ha->tgt.sess_lock, flags); ha->tgt.tgt_ops->put_sess(sess); - spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); return -EBUSY; } @@ -4773,6 +4694,7 @@ static int abort_cmds_for_s_id(struct scsi_qla_host *vha, port_id_t *s_id) list_for_each_entry(op, &vha->unknown_atio_list, cmd_list) { uint32_t op_key = sid_to_key(op->atio.u.isp24.fcp_hdr.s_id); + if (op_key == key) { op->aborted = true; count++; @@ -4781,6 +4703,7 @@ static int abort_cmds_for_s_id(struct scsi_qla_host *vha, port_id_t *s_id) list_for_each_entry(cmd, &vha->qla_cmd_list, cmd_list) { uint32_t cmd_key = sid_to_key(cmd->atio.u.isp24.fcp_hdr.s_id); + if (cmd_key == key) { cmd->aborted = 1; count++; @@ -5051,6 +4974,7 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha, if (sess != NULL) { bool delete = false; int sec; + spin_lock_irqsave(&tgt->ha->tgt.sess_lock, flags); switch (sess->fw_login_state) { case DSC_LS_PLOGI_PEND: @@ -5203,6 +5127,7 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha, case ELS_ADISC: { struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; + if (tgt->link_reinit_iocb_pending) { qlt_send_notify_ack(ha->base_qpair, &tgt->link_reinit_iocb, 0, 0, 0, 0, 0, 0); @@ -5266,6 +5191,7 @@ static void qlt_handle_imm_notify(struct scsi_qla_host *vha, case IMM_NTFY_LIP_LINK_REINIT: { struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf033, "qla_target(%d): LINK REINIT (loop %#x, " "subcode %x)\n", vha->vp_idx, @@ -5492,11 +5418,7 @@ qlt_alloc_qfull_cmd(struct scsi_qla_host *vha, se_sess = sess->se_sess; tag = sbitmap_queue_get(&se_sess->sess_tag_pool, &cpu); - if (tag < 0) - return; - - cmd = &((struct qla_tgt_cmd *)se_sess->sess_cmd_map)[tag]; - if (!cmd) { + if (tag < 0) { ql_dbg(ql_dbg_io, vha, 0x3009, "qla_target(%d): %s: Allocation of cmd failed\n", vha->vp_idx, __func__); @@ -5511,6 +5433,7 @@ qlt_alloc_qfull_cmd(struct scsi_qla_host *vha, return; } + cmd = &((struct qla_tgt_cmd *)se_sess->sess_cmd_map)[tag]; memset(cmd, 0, sizeof(struct qla_tgt_cmd)); qlt_incr_num_pend_cmds(vha); @@ -5820,8 +5743,7 @@ static void qlt_handle_abts_completion(struct scsi_qla_host *vha, struct qla_tgt_mgmt_cmd *mcmd; struct qla_hw_data *ha = vha->hw; - mcmd = (struct qla_tgt_mgmt_cmd *)qlt_ctio_to_cmd(vha, rsp, - pkt->handle, pkt); + mcmd = qlt_ctio_to_cmd(vha, rsp, pkt->handle, pkt); if (mcmd == NULL && h != QLA_TGT_SKIP_HANDLE) { ql_dbg(ql_dbg_async, vha, 0xe064, "qla_target(%d): ABTS Comp without mcmd\n", @@ -5883,6 +5805,7 @@ static void qlt_response_pkt(struct scsi_qla_host *vha, case CTIO_TYPE7: { struct ctio7_from_24xx *entry = (struct ctio7_from_24xx *)pkt; + qlt_do_ctio_completion(vha, rsp, entry->handle, le16_to_cpu(entry->status)|(pkt->entry_status << 16), entry); @@ -5893,6 +5816,7 @@ static void qlt_response_pkt(struct scsi_qla_host *vha, { struct atio_from_isp *atio = (struct atio_from_isp *)pkt; int rc; + if (atio->u.isp2x.status != cpu_to_le16(ATIO_CDB_VALID)) { ql_dbg(ql_dbg_tgt, vha, 0xe05e, @@ -5941,6 +5865,7 @@ static void qlt_response_pkt(struct scsi_qla_host *vha, case CONTINUE_TGT_IO_TYPE: { struct ctio_to_2xxx *entry = (struct ctio_to_2xxx *)pkt; + qlt_do_ctio_completion(vha, rsp, entry->handle, le16_to_cpu(entry->status)|(pkt->entry_status << 16), entry); @@ -5950,6 +5875,7 @@ static void qlt_response_pkt(struct scsi_qla_host *vha, case CTIO_A64_TYPE: { struct ctio_to_2xxx *entry = (struct ctio_to_2xxx *)pkt; + qlt_do_ctio_completion(vha, rsp, entry->handle, le16_to_cpu(entry->status)|(pkt->entry_status << 16), entry); @@ -5964,6 +5890,7 @@ static void qlt_response_pkt(struct scsi_qla_host *vha, case NOTIFY_ACK_TYPE: if (tgt->notify_ack_expected > 0) { struct nack_to_isp *entry = (struct nack_to_isp *)pkt; + ql_dbg(ql_dbg_tgt, vha, 0xe036, "NOTIFY_ACK seq %08x status %x\n", le16_to_cpu(entry->u.isp2x.seq_id), @@ -6239,6 +6166,7 @@ retry: if (rc == -ENOENT) { qlt_port_logo_t logo; + sid_to_portid(s_id, &logo.id); logo.cmd_count = 1; qlt_send_first_logo(vha, &logo); @@ -6318,17 +6246,19 @@ static void qlt_abort_work(struct qla_tgt *tgt, } rc = __qlt_24xx_handle_abts(vha, &prm->abts, sess); - ha->tgt.tgt_ops->put_sess(sess); spin_unlock_irqrestore(&ha->tgt.sess_lock, flags2); + ha->tgt.tgt_ops->put_sess(sess); + if (rc != 0) goto out_term; return; out_term2: + spin_unlock_irqrestore(&ha->tgt.sess_lock, flags2); + if (sess) ha->tgt.tgt_ops->put_sess(sess); - spin_unlock_irqrestore(&ha->tgt.sess_lock, flags2); out_term: spin_lock_irqsave(&ha->hardware_lock, flags); @@ -6386,9 +6316,10 @@ static void qlt_tmr_work(struct qla_tgt *tgt, scsilun_to_int((struct scsi_lun *)&a->u.isp24.fcp_cmnd.lun); rc = qlt_issue_task_mgmt(sess, unpacked_lun, fn, iocb, 0); - ha->tgt.tgt_ops->put_sess(sess); spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); + ha->tgt.tgt_ops->put_sess(sess); + if (rc != 0) goto out_term; return; @@ -6499,6 +6430,7 @@ int qlt_add_target(struct qla_hw_data *ha, struct scsi_qla_host *base_vha) unsigned long flags; struct qla_qpair *qpair = ha->queue_pair_map[i]; + h = &tgt->qphints[i + 1]; INIT_LIST_HEAD(&h->hint_elem); if (qpair) { @@ -6937,7 +6869,7 @@ qlt_24xx_config_rings(struct scsi_qla_host *vha) RD_REG_DWORD(ISP_ATIO_Q_OUT(vha)); if (ha->flags.msix_enabled) { - if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) { + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { if (IS_QLA2071(ha)) { /* 4 ports Baker: Enable Interrupt Handshake */ icb->msix_atio = 0; @@ -6952,7 +6884,7 @@ qlt_24xx_config_rings(struct scsi_qla_host *vha) } } else { /* INTx|MSI */ - if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) { + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { icb->msix_atio = 0; icb->firmware_options_2 |= BIT_26; ql_dbg(ql_dbg_init, vha, 0xf072, @@ -7201,7 +7133,8 @@ qlt_probe_one_stage1(struct scsi_qla_host *base_vha, struct qla_hw_data *ha) if (!QLA_TGT_MODE_ENABLED()) return; - if ((ql2xenablemsix == 0) || IS_QLA83XX(ha) || IS_QLA27XX(ha)) { + if ((ql2xenablemsix == 0) || IS_QLA83XX(ha) || IS_QLA27XX(ha) || + IS_QLA28XX(ha)) { ISP_ATIO_Q_IN(base_vha) = &ha->mqiobase->isp25mq.atio_q_in; ISP_ATIO_Q_OUT(base_vha) = &ha->mqiobase->isp25mq.atio_q_out; } else { @@ -7329,7 +7262,10 @@ qlt_mem_free(struct qla_hw_data *ha) sizeof(struct atio_from_isp), ha->tgt.atio_ring, ha->tgt.atio_dma); } + ha->tgt.atio_ring = NULL; + ha->tgt.atio_dma = 0; kfree(ha->tgt.tgt_vp_map); + ha->tgt.tgt_vp_map = NULL; } /* vport_slock to be held by the caller */ @@ -7413,6 +7349,9 @@ int __init qlt_init(void) { int ret; + BUILD_BUG_ON(sizeof(struct ctio7_to_24xx) != 64); + BUILD_BUG_ON(sizeof(struct ctio_to_2xxx) != 64); + if (!qlt_parse_ini_mode()) { ql_log(ql_log_fatal, NULL, 0xe06b, "qlt_parse_ini_mode() failed\n"); diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h index f3de75000a08..89ceffa7d4fd 100644 --- a/drivers/scsi/qla2xxx/qla_target.h +++ b/drivers/scsi/qla2xxx/qla_target.h @@ -29,6 +29,7 @@ #define __QLA_TARGET_H #include "qla_def.h" +#include "qla_dsd.h" /* * Must be changed on any change in any initiator visible interfaces or @@ -224,12 +225,7 @@ struct ctio_to_2xxx { uint16_t reserved_1[3]; uint16_t scsi_status; uint32_t transfer_length; - uint32_t dseg_0_address; /* Data segment 0 address. */ - uint32_t dseg_0_length; /* Data segment 0 length. */ - uint32_t dseg_1_address; /* Data segment 1 address. */ - uint32_t dseg_1_length; /* Data segment 1 length. */ - uint32_t dseg_2_address; /* Data segment 2 address. */ - uint32_t dseg_2_length; /* Data segment 2 length. */ + struct dsd32 dsd[3]; } __packed; #define ATIO_PATH_INVALID 0x07 #define ATIO_CANT_PROV_CAP 0x16 @@ -429,10 +425,7 @@ struct ctio7_to_24xx { uint32_t reserved2; uint32_t transfer_length; uint32_t reserved3; - /* Data segment 0 address. */ - uint32_t dseg_0_address[2]; - /* Data segment 0 length. */ - uint32_t dseg_0_length; + struct dsd64 dsd; } status0; struct { uint16_t sense_length; @@ -526,10 +519,10 @@ struct ctio_crc2_to_fw { uint32_t reserved5; __le32 transfer_length; /* total fc transfer length */ uint32_t reserved6; - __le32 crc_context_address[2];/* Data segment address. */ + __le64 crc_context_address __packed; /* Data segment address. */ uint16_t crc_context_len; /* Data segment length. */ uint16_t reserved_1; /* MUST be set to 0. */ -} __packed; +}; /* CTIO Type CRC_x Status IOCB */ struct ctio_crc_from_fw { @@ -855,7 +848,7 @@ enum trace_flags { TRC_CTIO_ERR = BIT_11, TRC_CTIO_DONE = BIT_12, TRC_CTIO_ABORTED = BIT_13, - TRC_CTIO_STRANGE= BIT_14, + TRC_CTIO_STRANGE = BIT_14, TRC_CMD_DONE = BIT_15, TRC_CMD_CHK_STOP = BIT_16, TRC_CMD_FREE = BIT_17, @@ -889,10 +882,14 @@ struct qla_tgt_cmd { unsigned int term_exchg:1; unsigned int cmd_sent_to_fw:1; unsigned int cmd_in_wq:1; - unsigned int aborted:1; - unsigned int data_work:1; - unsigned int data_work_free:1; - unsigned int released:1; + + /* + * This variable may be set from outside the LIO and I/O completion + * callback functions. Do not declare this member variable as a + * bitfield to avoid a read-modify-write operation when this variable + * is set. + */ + unsigned int aborted; struct scatterlist *sg; /* cmd data buffer SG vector */ int sg_cnt; /* SG segments count */ @@ -1103,7 +1100,5 @@ extern void qlt_do_generation_tick(struct scsi_qla_host *, int *); void qlt_send_resp_ctio(struct qla_qpair *, struct qla_tgt_cmd *, uint8_t, uint8_t, uint8_t, uint8_t); -extern void qlt_abort_cmd_on_host_reset(struct scsi_qla_host *, - struct qla_tgt_cmd *); #endif /* __QLA_TARGET_H */ diff --git a/drivers/scsi/qla2xxx/qla_tmpl.c b/drivers/scsi/qla2xxx/qla_tmpl.c index 9e52500caff0..de696a07532e 100644 --- a/drivers/scsi/qla2xxx/qla_tmpl.c +++ b/drivers/scsi/qla2xxx/qla_tmpl.c @@ -7,103 +7,9 @@ #include "qla_def.h" #include "qla_tmpl.h" -/* note default template is in big endian */ -static const uint32_t ql27xx_fwdt_default_template[] = { - 0x63000000, 0xa4000000, 0x7c050000, 0x00000000, - 0x30000000, 0x01000000, 0x00000000, 0xc0406eb4, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x04010000, 0x14000000, 0x00000000, - 0x02000000, 0x44000000, 0x09010000, 0x10000000, - 0x00000000, 0x02000000, 0x01010000, 0x1c000000, - 0x00000000, 0x02000000, 0x00600000, 0x00000000, - 0xc0000000, 0x01010000, 0x1c000000, 0x00000000, - 0x02000000, 0x00600000, 0x00000000, 0xcc000000, - 0x01010000, 0x1c000000, 0x00000000, 0x02000000, - 0x10600000, 0x00000000, 0xd4000000, 0x01010000, - 0x1c000000, 0x00000000, 0x02000000, 0x700f0000, - 0x00000060, 0xf0000000, 0x00010000, 0x18000000, - 0x00000000, 0x02000000, 0x00700000, 0x041000c0, - 0x00010000, 0x18000000, 0x00000000, 0x02000000, - 0x10700000, 0x041000c0, 0x00010000, 0x18000000, - 0x00000000, 0x02000000, 0x40700000, 0x041000c0, - 0x01010000, 0x1c000000, 0x00000000, 0x02000000, - 0x007c0000, 0x01000000, 0xc0000000, 0x00010000, - 0x18000000, 0x00000000, 0x02000000, 0x007c0000, - 0x040300c4, 0x00010000, 0x18000000, 0x00000000, - 0x02000000, 0x007c0000, 0x040100c0, 0x01010000, - 0x1c000000, 0x00000000, 0x02000000, 0x007c0000, - 0x00000000, 0xc0000000, 0x00010000, 0x18000000, - 0x00000000, 0x02000000, 0x007c0000, 0x04200000, - 0x0b010000, 0x18000000, 0x00000000, 0x02000000, - 0x0c000000, 0x00000000, 0x02010000, 0x20000000, - 0x00000000, 0x02000000, 0x700f0000, 0x040100fc, - 0xf0000000, 0x000000b0, 0x02010000, 0x20000000, - 0x00000000, 0x02000000, 0x700f0000, 0x040100fc, - 0xf0000000, 0x000010b0, 0x02010000, 0x20000000, - 0x00000000, 0x02000000, 0x700f0000, 0x040100fc, - 0xf0000000, 0x000020b0, 0x02010000, 0x20000000, - 0x00000000, 0x02000000, 0x700f0000, 0x040100fc, - 0xf0000000, 0x000030b0, 0x02010000, 0x20000000, - 0x00000000, 0x02000000, 0x700f0000, 0x040100fc, - 0xf0000000, 0x000040b0, 0x02010000, 0x20000000, - 0x00000000, 0x02000000, 0x700f0000, 0x040100fc, - 0xf0000000, 0x000050b0, 0x02010000, 0x20000000, - 0x00000000, 0x02000000, 0x700f0000, 0x040100fc, - 0xf0000000, 0x000060b0, 0x02010000, 0x20000000, - 0x00000000, 0x02000000, 0x700f0000, 0x040100fc, - 0xf0000000, 0x000070b0, 0x02010000, 0x20000000, - 0x00000000, 0x02000000, 0x700f0000, 0x040100fc, - 0xf0000000, 0x000080b0, 0x02010000, 0x20000000, - 0x00000000, 0x02000000, 0x700f0000, 0x040100fc, - 0xf0000000, 0x000090b0, 0x02010000, 0x20000000, - 0x00000000, 0x02000000, 0x700f0000, 0x040100fc, - 0xf0000000, 0x0000a0b0, 0x00010000, 0x18000000, - 0x00000000, 0x02000000, 0x0a000000, 0x040100c0, - 0x00010000, 0x18000000, 0x00000000, 0x02000000, - 0x0a000000, 0x04200080, 0x00010000, 0x18000000, - 0x00000000, 0x02000000, 0x00be0000, 0x041000c0, - 0x00010000, 0x18000000, 0x00000000, 0x02000000, - 0x10be0000, 0x041000c0, 0x00010000, 0x18000000, - 0x00000000, 0x02000000, 0x20be0000, 0x041000c0, - 0x00010000, 0x18000000, 0x00000000, 0x02000000, - 0x30be0000, 0x041000c0, 0x00010000, 0x18000000, - 0x00000000, 0x02000000, 0x00b00000, 0x041000c0, - 0x00010000, 0x18000000, 0x00000000, 0x02000000, - 0x10b00000, 0x041000c0, 0x00010000, 0x18000000, - 0x00000000, 0x02000000, 0x20b00000, 0x041000c0, - 0x00010000, 0x18000000, 0x00000000, 0x02000000, - 0x30b00000, 0x041000c0, 0x00010000, 0x18000000, - 0x00000000, 0x02000000, 0x00300000, 0x041000c0, - 0x00010000, 0x18000000, 0x00000000, 0x02000000, - 0x10300000, 0x041000c0, 0x00010000, 0x18000000, - 0x00000000, 0x02000000, 0x20300000, 0x041000c0, - 0x00010000, 0x18000000, 0x00000000, 0x02000000, - 0x30300000, 0x041000c0, 0x0a010000, 0x10000000, - 0x00000000, 0x02000000, 0x06010000, 0x1c000000, - 0x00000000, 0x02000000, 0x01000000, 0x00000200, - 0xff230200, 0x06010000, 0x1c000000, 0x00000000, - 0x02000000, 0x02000000, 0x00001000, 0x00000000, - 0x07010000, 0x18000000, 0x00000000, 0x02000000, - 0x00000000, 0x01000000, 0x07010000, 0x18000000, - 0x00000000, 0x02000000, 0x00000000, 0x02000000, - 0x07010000, 0x18000000, 0x00000000, 0x02000000, - 0x00000000, 0x03000000, 0x0d010000, 0x14000000, - 0x00000000, 0x02000000, 0x00000000, 0xff000000, - 0x10000000, 0x00000000, 0x00000080, -}; - -static inline void __iomem * -qla27xx_isp_reg(struct scsi_qla_host *vha) -{ - return &vha->hw->iobase->isp24; -} +#define ISPREG(vha) (&(vha)->hw->iobase->isp24) +#define IOBAR(reg) offsetof(typeof(*(reg)), iobase_addr) +#define IOBASE(vha) IOBAR(ISPREG(vha)) static inline void qla27xx_insert16(uint16_t value, void *buf, ulong *len) @@ -128,7 +34,6 @@ qla27xx_insert32(uint32_t value, void *buf, ulong *len) static inline void qla27xx_insertbuf(void *mem, ulong size, void *buf, ulong *len) { - if (buf && mem && size) { buf += *len; memcpy(buf, mem, size); @@ -190,9 +95,9 @@ static inline void qla27xx_write_reg(__iomem struct device_reg_24xx *reg, uint offset, uint32_t data, void *buf) { - __iomem void *window = (void __iomem *)reg + offset; - if (buf) { + void __iomem *window = (void __iomem *)reg + offset; + WRT_REG_DWORD(window, data); } } @@ -205,7 +110,7 @@ qla27xx_read_window(__iomem struct device_reg_24xx *reg, void __iomem *window = (void __iomem *)reg + offset; void (*readn)(void __iomem*, void *, ulong *) = qla27xx_read_vector(width); - qla27xx_write_reg(reg, IOBASE_ADDR, addr, buf); + qla27xx_write_reg(reg, IOBAR(reg), addr, buf); while (count--) { qla27xx_insert32(addr, buf, len); readn(window, buf, len); @@ -224,7 +129,7 @@ qla27xx_skip_entry(struct qla27xx_fwdt_entry *ent, void *buf) static inline struct qla27xx_fwdt_entry * qla27xx_next_entry(struct qla27xx_fwdt_entry *ent) { - return (void *)ent + ent->hdr.size; + return (void *)ent + le32_to_cpu(ent->hdr.size); } static struct qla27xx_fwdt_entry * @@ -254,12 +159,14 @@ static struct qla27xx_fwdt_entry * qla27xx_fwdt_entry_t256(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { - struct device_reg_24xx __iomem *reg = qla27xx_isp_reg(vha); + ulong addr = le32_to_cpu(ent->t256.base_addr); + uint offset = ent->t256.pci_offset; + ulong count = le16_to_cpu(ent->t256.reg_count); + uint width = ent->t256.reg_width; ql_dbg(ql_dbg_misc, vha, 0xd200, "%s: rdio t1 [%lx]\n", __func__, *len); - qla27xx_read_window(reg, ent->t256.base_addr, ent->t256.pci_offset, - ent->t256.reg_count, ent->t256.reg_width, buf, len); + qla27xx_read_window(ISPREG(vha), addr, offset, count, width, buf, len); return qla27xx_next_entry(ent); } @@ -268,12 +175,14 @@ static struct qla27xx_fwdt_entry * qla27xx_fwdt_entry_t257(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { - struct device_reg_24xx __iomem *reg = qla27xx_isp_reg(vha); + ulong addr = le32_to_cpu(ent->t257.base_addr); + uint offset = ent->t257.pci_offset; + ulong data = le32_to_cpu(ent->t257.write_data); ql_dbg(ql_dbg_misc, vha, 0xd201, "%s: wrio t1 [%lx]\n", __func__, *len); - qla27xx_write_reg(reg, IOBASE_ADDR, ent->t257.base_addr, buf); - qla27xx_write_reg(reg, ent->t257.pci_offset, ent->t257.write_data, buf); + qla27xx_write_reg(ISPREG(vha), IOBASE(vha), addr, buf); + qla27xx_write_reg(ISPREG(vha), offset, data, buf); return qla27xx_next_entry(ent); } @@ -282,13 +191,17 @@ static struct qla27xx_fwdt_entry * qla27xx_fwdt_entry_t258(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { - struct device_reg_24xx __iomem *reg = qla27xx_isp_reg(vha); + uint banksel = ent->t258.banksel_offset; + ulong bank = le32_to_cpu(ent->t258.bank); + ulong addr = le32_to_cpu(ent->t258.base_addr); + uint offset = ent->t258.pci_offset; + uint count = le16_to_cpu(ent->t258.reg_count); + uint width = ent->t258.reg_width; ql_dbg(ql_dbg_misc, vha, 0xd202, "%s: rdio t2 [%lx]\n", __func__, *len); - qla27xx_write_reg(reg, ent->t258.banksel_offset, ent->t258.bank, buf); - qla27xx_read_window(reg, ent->t258.base_addr, ent->t258.pci_offset, - ent->t258.reg_count, ent->t258.reg_width, buf, len); + qla27xx_write_reg(ISPREG(vha), banksel, bank, buf); + qla27xx_read_window(ISPREG(vha), addr, offset, count, width, buf, len); return qla27xx_next_entry(ent); } @@ -297,13 +210,17 @@ static struct qla27xx_fwdt_entry * qla27xx_fwdt_entry_t259(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { - struct device_reg_24xx __iomem *reg = qla27xx_isp_reg(vha); + ulong addr = le32_to_cpu(ent->t259.base_addr); + uint banksel = ent->t259.banksel_offset; + ulong bank = le32_to_cpu(ent->t259.bank); + uint offset = ent->t259.pci_offset; + ulong data = le32_to_cpu(ent->t259.write_data); ql_dbg(ql_dbg_misc, vha, 0xd203, "%s: wrio t2 [%lx]\n", __func__, *len); - qla27xx_write_reg(reg, IOBASE_ADDR, ent->t259.base_addr, buf); - qla27xx_write_reg(reg, ent->t259.banksel_offset, ent->t259.bank, buf); - qla27xx_write_reg(reg, ent->t259.pci_offset, ent->t259.write_data, buf); + qla27xx_write_reg(ISPREG(vha), IOBASE(vha), addr, buf); + qla27xx_write_reg(ISPREG(vha), banksel, bank, buf); + qla27xx_write_reg(ISPREG(vha), offset, data, buf); return qla27xx_next_entry(ent); } @@ -312,12 +229,12 @@ static struct qla27xx_fwdt_entry * qla27xx_fwdt_entry_t260(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { - struct device_reg_24xx __iomem *reg = qla27xx_isp_reg(vha); + uint offset = ent->t260.pci_offset; ql_dbg(ql_dbg_misc, vha, 0xd204, "%s: rdpci [%lx]\n", __func__, *len); - qla27xx_insert32(ent->t260.pci_offset, buf, len); - qla27xx_read_reg(reg, ent->t260.pci_offset, buf, len); + qla27xx_insert32(offset, buf, len); + qla27xx_read_reg(ISPREG(vha), offset, buf, len); return qla27xx_next_entry(ent); } @@ -326,11 +243,12 @@ static struct qla27xx_fwdt_entry * qla27xx_fwdt_entry_t261(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { - struct device_reg_24xx __iomem *reg = qla27xx_isp_reg(vha); + uint offset = ent->t261.pci_offset; + ulong data = le32_to_cpu(ent->t261.write_data); ql_dbg(ql_dbg_misc, vha, 0xd205, "%s: wrpci [%lx]\n", __func__, *len); - qla27xx_write_reg(reg, ent->t261.pci_offset, ent->t261.write_data, buf); + qla27xx_write_reg(ISPREG(vha), offset, data, buf); return qla27xx_next_entry(ent); } @@ -339,51 +257,50 @@ static struct qla27xx_fwdt_entry * qla27xx_fwdt_entry_t262(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { + uint area = ent->t262.ram_area; + ulong start = le32_to_cpu(ent->t262.start_addr); + ulong end = le32_to_cpu(ent->t262.end_addr); ulong dwords; - ulong start; - ulong end; ql_dbg(ql_dbg_misc, vha, 0xd206, "%s: rdram(%x) [%lx]\n", __func__, ent->t262.ram_area, *len); - start = ent->t262.start_addr; - end = ent->t262.end_addr; - if (ent->t262.ram_area == T262_RAM_AREA_CRITICAL_RAM) { + if (area == T262_RAM_AREA_CRITICAL_RAM) { ; - } else if (ent->t262.ram_area == T262_RAM_AREA_EXTERNAL_RAM) { + } else if (area == T262_RAM_AREA_EXTERNAL_RAM) { end = vha->hw->fw_memory_size; if (buf) - ent->t262.end_addr = end; - } else if (ent->t262.ram_area == T262_RAM_AREA_SHARED_RAM) { + ent->t262.end_addr = cpu_to_le32(end); + } else if (area == T262_RAM_AREA_SHARED_RAM) { start = vha->hw->fw_shared_ram_start; end = vha->hw->fw_shared_ram_end; if (buf) { - ent->t262.start_addr = start; - ent->t262.end_addr = end; + ent->t262.start_addr = cpu_to_le32(start); + ent->t262.end_addr = cpu_to_le32(end); } - } else if (ent->t262.ram_area == T262_RAM_AREA_DDR_RAM) { + } else if (area == T262_RAM_AREA_DDR_RAM) { start = vha->hw->fw_ddr_ram_start; end = vha->hw->fw_ddr_ram_end; if (buf) { - ent->t262.start_addr = start; - ent->t262.end_addr = end; + ent->t262.start_addr = cpu_to_le32(start); + ent->t262.end_addr = cpu_to_le32(end); } - } else if (ent->t262.ram_area == T262_RAM_AREA_MISC) { + } else if (area == T262_RAM_AREA_MISC) { if (buf) { - ent->t262.start_addr = start; - ent->t262.end_addr = end; + ent->t262.start_addr = cpu_to_le32(start); + ent->t262.end_addr = cpu_to_le32(end); } } else { ql_dbg(ql_dbg_misc, vha, 0xd022, - "%s: unknown area %x\n", __func__, ent->t262.ram_area); + "%s: unknown area %x\n", __func__, area); qla27xx_skip_entry(ent, buf); goto done; } if (end < start || start == 0 || end == 0) { ql_dbg(ql_dbg_misc, vha, 0xd023, - "%s: unusable range (start=%x end=%x)\n", __func__, - ent->t262.end_addr, ent->t262.start_addr); + "%s: unusable range (start=%lx end=%lx)\n", + __func__, start, end); qla27xx_skip_entry(ent, buf); goto done; } @@ -402,13 +319,14 @@ static struct qla27xx_fwdt_entry * qla27xx_fwdt_entry_t263(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { + uint type = ent->t263.queue_type; uint count = 0; uint i; uint length; - ql_dbg(ql_dbg_misc, vha, 0xd207, - "%s: getq(%x) [%lx]\n", __func__, ent->t263.queue_type, *len); - if (ent->t263.queue_type == T263_QUEUE_TYPE_REQ) { + ql_dbg(ql_dbg_misc + ql_dbg_verbose, vha, 0xd207, + "%s: getq(%x) [%lx]\n", __func__, type, *len); + if (type == T263_QUEUE_TYPE_REQ) { for (i = 0; i < vha->hw->max_req_queues; i++) { struct req_que *req = vha->hw->req_q_map[i]; @@ -422,7 +340,7 @@ qla27xx_fwdt_entry_t263(struct scsi_qla_host *vha, count++; } } - } else if (ent->t263.queue_type == T263_QUEUE_TYPE_RSP) { + } else if (type == T263_QUEUE_TYPE_RSP) { for (i = 0; i < vha->hw->max_rsp_queues; i++) { struct rsp_que *rsp = vha->hw->rsp_q_map[i]; @@ -450,7 +368,7 @@ qla27xx_fwdt_entry_t263(struct scsi_qla_host *vha, } } else { ql_dbg(ql_dbg_misc, vha, 0xd026, - "%s: unknown queue %x\n", __func__, ent->t263.queue_type); + "%s: unknown queue %x\n", __func__, type); qla27xx_skip_entry(ent, buf); } @@ -496,12 +414,10 @@ static struct qla27xx_fwdt_entry * qla27xx_fwdt_entry_t265(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { - struct device_reg_24xx __iomem *reg = qla27xx_isp_reg(vha); - - ql_dbg(ql_dbg_misc, vha, 0xd209, + ql_dbg(ql_dbg_misc + ql_dbg_verbose, vha, 0xd209, "%s: pause risc [%lx]\n", __func__, *len); if (buf) - qla24xx_pause_risc(reg, vha->hw); + qla24xx_pause_risc(ISPREG(vha), vha->hw); return qla27xx_next_entry(ent); } @@ -522,11 +438,12 @@ static struct qla27xx_fwdt_entry * qla27xx_fwdt_entry_t267(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { - struct device_reg_24xx __iomem *reg = qla27xx_isp_reg(vha); + uint offset = ent->t267.pci_offset; + ulong data = le32_to_cpu(ent->t267.data); ql_dbg(ql_dbg_misc, vha, 0xd20b, "%s: dis intr [%lx]\n", __func__, *len); - qla27xx_write_reg(reg, ent->t267.pci_offset, ent->t267.data, buf); + qla27xx_write_reg(ISPREG(vha), offset, data, buf); return qla27xx_next_entry(ent); } @@ -622,17 +539,16 @@ static struct qla27xx_fwdt_entry * qla27xx_fwdt_entry_t270(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { - struct device_reg_24xx __iomem *reg = qla27xx_isp_reg(vha); - ulong dwords = ent->t270.count; - ulong addr = ent->t270.addr; + ulong addr = le32_to_cpu(ent->t270.addr); + ulong dwords = le32_to_cpu(ent->t270.count); ql_dbg(ql_dbg_misc, vha, 0xd20e, "%s: rdremreg [%lx]\n", __func__, *len); - qla27xx_write_reg(reg, IOBASE_ADDR, 0x40, buf); + qla27xx_write_reg(ISPREG(vha), IOBASE_ADDR, 0x40, buf); while (dwords--) { - qla27xx_write_reg(reg, 0xc0, addr|0x80000000, buf); + qla27xx_write_reg(ISPREG(vha), 0xc0, addr|0x80000000, buf); qla27xx_insert32(addr, buf, len); - qla27xx_read_reg(reg, 0xc4, buf, len); + qla27xx_read_reg(ISPREG(vha), 0xc4, buf, len); addr += sizeof(uint32_t); } @@ -643,15 +559,14 @@ static struct qla27xx_fwdt_entry * qla27xx_fwdt_entry_t271(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { - struct device_reg_24xx __iomem *reg = qla27xx_isp_reg(vha); - ulong addr = ent->t271.addr; - ulong data = ent->t271.data; + ulong addr = le32_to_cpu(ent->t271.addr); + ulong data = le32_to_cpu(ent->t271.data); ql_dbg(ql_dbg_misc, vha, 0xd20f, "%s: wrremreg [%lx]\n", __func__, *len); - qla27xx_write_reg(reg, IOBASE_ADDR, 0x40, buf); - qla27xx_write_reg(reg, 0xc4, data, buf); - qla27xx_write_reg(reg, 0xc0, addr, buf); + qla27xx_write_reg(ISPREG(vha), IOBASE(vha), 0x40, buf); + qla27xx_write_reg(ISPREG(vha), 0xc4, data, buf); + qla27xx_write_reg(ISPREG(vha), 0xc0, addr, buf); return qla27xx_next_entry(ent); } @@ -660,8 +575,8 @@ static struct qla27xx_fwdt_entry * qla27xx_fwdt_entry_t272(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { - ulong dwords = ent->t272.count; - ulong start = ent->t272.addr; + ulong dwords = le32_to_cpu(ent->t272.count); + ulong start = le32_to_cpu(ent->t272.addr); ql_dbg(ql_dbg_misc, vha, 0xd210, "%s: rdremram [%lx]\n", __func__, *len); @@ -680,8 +595,8 @@ static struct qla27xx_fwdt_entry * qla27xx_fwdt_entry_t273(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { - ulong dwords = ent->t273.count; - ulong addr = ent->t273.addr; + ulong dwords = le32_to_cpu(ent->t273.count); + ulong addr = le32_to_cpu(ent->t273.addr); uint32_t value; ql_dbg(ql_dbg_misc, vha, 0xd211, @@ -703,12 +618,13 @@ static struct qla27xx_fwdt_entry * qla27xx_fwdt_entry_t274(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { + ulong type = ent->t274.queue_type; uint count = 0; uint i; - ql_dbg(ql_dbg_misc, vha, 0xd212, - "%s: getqsh(%x) [%lx]\n", __func__, ent->t274.queue_type, *len); - if (ent->t274.queue_type == T274_QUEUE_TYPE_REQ_SHAD) { + ql_dbg(ql_dbg_misc + ql_dbg_verbose, vha, 0xd212, + "%s: getqsh(%lx) [%lx]\n", __func__, type, *len); + if (type == T274_QUEUE_TYPE_REQ_SHAD) { for (i = 0; i < vha->hw->max_req_queues; i++) { struct req_que *req = vha->hw->req_q_map[i]; @@ -720,7 +636,7 @@ qla27xx_fwdt_entry_t274(struct scsi_qla_host *vha, count++; } } - } else if (ent->t274.queue_type == T274_QUEUE_TYPE_RSP_SHAD) { + } else if (type == T274_QUEUE_TYPE_RSP_SHAD) { for (i = 0; i < vha->hw->max_rsp_queues; i++) { struct rsp_que *rsp = vha->hw->rsp_q_map[i]; @@ -746,7 +662,7 @@ qla27xx_fwdt_entry_t274(struct scsi_qla_host *vha, } } else { ql_dbg(ql_dbg_misc, vha, 0xd02f, - "%s: unknown queue %x\n", __func__, ent->t274.queue_type); + "%s: unknown queue %lx\n", __func__, type); qla27xx_skip_entry(ent, buf); } @@ -765,23 +681,26 @@ qla27xx_fwdt_entry_t275(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { ulong offset = offsetof(typeof(*ent), t275.buffer); + ulong length = le32_to_cpu(ent->t275.length); + ulong size = le32_to_cpu(ent->hdr.size); + void *buffer = ent->t275.buffer; - ql_dbg(ql_dbg_misc, vha, 0xd213, - "%s: buffer(%x) [%lx]\n", __func__, ent->t275.length, *len); - if (!ent->t275.length) { + ql_dbg(ql_dbg_misc + ql_dbg_verbose, vha, 0xd213, + "%s: buffer(%lx) [%lx]\n", __func__, length, *len); + if (!length) { ql_dbg(ql_dbg_misc, vha, 0xd020, "%s: buffer zero length\n", __func__); qla27xx_skip_entry(ent, buf); goto done; } - if (offset + ent->t275.length > ent->hdr.size) { + if (offset + length > size) { + length = size - offset; ql_dbg(ql_dbg_misc, vha, 0xd030, - "%s: buffer overflow\n", __func__); - qla27xx_skip_entry(ent, buf); - goto done; + "%s: buffer overflow, truncate [%lx]\n", __func__, length); + ent->t275.length = cpu_to_le32(length); } - qla27xx_insertbuf(ent->t275.buffer, ent->t275.length, buf, len); + qla27xx_insertbuf(buffer, length, buf, len); done: return qla27xx_next_entry(ent); } @@ -790,15 +709,22 @@ static struct qla27xx_fwdt_entry * qla27xx_fwdt_entry_t276(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { - uint type = vha->hw->pdev->device >> 4 & 0xf; - uint func = vha->hw->port_no & 0x3; - ql_dbg(ql_dbg_misc + ql_dbg_verbose, vha, 0xd214, "%s: cond [%lx]\n", __func__, *len); - if (type != ent->t276.cond1 || func != ent->t276.cond2) { - ent = qla27xx_next_entry(ent); - qla27xx_skip_entry(ent, buf); + if (buf) { + ulong cond1 = le32_to_cpu(ent->t276.cond1); + ulong cond2 = le32_to_cpu(ent->t276.cond2); + uint type = vha->hw->pdev->device >> 4 & 0xf; + uint func = vha->hw->port_no & 0x3; + + if (type != cond1 || func != cond2) { + struct qla27xx_fwdt_template *tmp = buf; + + tmp->count--; + ent = qla27xx_next_entry(ent); + qla27xx_skip_entry(ent, buf); + } } return qla27xx_next_entry(ent); @@ -808,13 +734,15 @@ static struct qla27xx_fwdt_entry * qla27xx_fwdt_entry_t277(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { - struct device_reg_24xx __iomem *reg = qla27xx_isp_reg(vha); + ulong cmd_addr = le32_to_cpu(ent->t277.cmd_addr); + ulong wr_cmd_data = le32_to_cpu(ent->t277.wr_cmd_data); + ulong data_addr = le32_to_cpu(ent->t277.data_addr); ql_dbg(ql_dbg_misc + ql_dbg_verbose, vha, 0xd215, "%s: rdpep [%lx]\n", __func__, *len); - qla27xx_insert32(ent->t277.wr_cmd_data, buf, len); - qla27xx_write_reg(reg, ent->t277.cmd_addr, ent->t277.wr_cmd_data, buf); - qla27xx_read_reg(reg, ent->t277.data_addr, buf, len); + qla27xx_insert32(wr_cmd_data, buf, len); + qla27xx_write_reg(ISPREG(vha), cmd_addr, wr_cmd_data, buf); + qla27xx_read_reg(ISPREG(vha), data_addr, buf, len); return qla27xx_next_entry(ent); } @@ -823,12 +751,15 @@ static struct qla27xx_fwdt_entry * qla27xx_fwdt_entry_t278(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { - struct device_reg_24xx __iomem *reg = qla27xx_isp_reg(vha); + ulong cmd_addr = le32_to_cpu(ent->t278.cmd_addr); + ulong wr_cmd_data = le32_to_cpu(ent->t278.wr_cmd_data); + ulong data_addr = le32_to_cpu(ent->t278.data_addr); + ulong wr_data = le32_to_cpu(ent->t278.wr_data); ql_dbg(ql_dbg_misc + ql_dbg_verbose, vha, 0xd216, "%s: wrpep [%lx]\n", __func__, *len); - qla27xx_write_reg(reg, ent->t278.data_addr, ent->t278.wr_data, buf); - qla27xx_write_reg(reg, ent->t278.cmd_addr, ent->t278.wr_cmd_data, buf); + qla27xx_write_reg(ISPREG(vha), data_addr, wr_data, buf); + qla27xx_write_reg(ISPREG(vha), cmd_addr, wr_cmd_data, buf); return qla27xx_next_entry(ent); } @@ -837,8 +768,10 @@ static struct qla27xx_fwdt_entry * qla27xx_fwdt_entry_other(struct scsi_qla_host *vha, struct qla27xx_fwdt_entry *ent, void *buf, ulong *len) { + ulong type = le32_to_cpu(ent->hdr.type); + ql_dbg(ql_dbg_misc, vha, 0xd2ff, - "%s: type %x [%lx]\n", __func__, ent->hdr.type, *len); + "%s: other %lx [%lx]\n", __func__, type, *len); qla27xx_skip_entry(ent, buf); return qla27xx_next_entry(ent); @@ -893,36 +826,27 @@ static void qla27xx_walk_template(struct scsi_qla_host *vha, struct qla27xx_fwdt_template *tmp, void *buf, ulong *len) { - struct qla27xx_fwdt_entry *ent = (void *)tmp + tmp->entry_offset; - ulong count = tmp->entry_count; + struct qla27xx_fwdt_entry *ent = (void *)tmp + + le32_to_cpu(tmp->entry_offset); + ulong type; + tmp->count = le32_to_cpu(tmp->entry_count); ql_dbg(ql_dbg_misc, vha, 0xd01a, - "%s: entry count %lx\n", __func__, count); - while (count--) { - ent = qla27xx_find_entry(ent->hdr.type)(vha, ent, buf, len); + "%s: entry count %u\n", __func__, tmp->count); + while (ent && tmp->count--) { + type = le32_to_cpu(ent->hdr.type); + ent = qla27xx_find_entry(type)(vha, ent, buf, len); if (!ent) break; } - if (count) + if (tmp->count) ql_dbg(ql_dbg_misc, vha, 0xd018, - "%s: entry residual count (%lx)\n", __func__, count); + "%s: entry count residual=+%u\n", __func__, tmp->count); if (ent) ql_dbg(ql_dbg_misc, vha, 0xd019, - "%s: missing end entry (%lx)\n", __func__, count); - - if (buf && *len != vha->hw->fw_dump_len) - ql_dbg(ql_dbg_misc, vha, 0xd01b, - "%s: length=%#lx residual=%+ld\n", - __func__, *len, vha->hw->fw_dump_len - *len); - - if (buf) { - ql_log(ql_log_warn, vha, 0xd015, - "Firmware dump saved to temp buffer (%lu/%p)\n", - vha->host_no, vha->hw->fw_dump); - qla2x00_post_uevent_work(vha, QLA_UEVENT_CODE_FW_DUMP); - } + "%s: missing end entry\n", __func__); } static void @@ -945,8 +869,8 @@ qla27xx_driver_info(struct qla27xx_fwdt_template *tmp) } static void -qla27xx_firmware_info(struct qla27xx_fwdt_template *tmp, - struct scsi_qla_host *vha) +qla27xx_firmware_info(struct scsi_qla_host *vha, + struct qla27xx_fwdt_template *tmp) { tmp->firmware_version[0] = vha->hw->fw_major_version; tmp->firmware_version[1] = vha->hw->fw_minor_version; @@ -963,19 +887,19 @@ ql27xx_edit_template(struct scsi_qla_host *vha, { qla27xx_time_stamp(tmp); qla27xx_driver_info(tmp); - qla27xx_firmware_info(tmp, vha); + qla27xx_firmware_info(vha, tmp); } static inline uint32_t qla27xx_template_checksum(void *p, ulong size) { - uint32_t *buf = p; + __le32 *buf = p; uint64_t sum = 0; size /= sizeof(*buf); - while (size--) - sum += *buf++; + for ( ; size--; buf++) + sum += le32_to_cpu(*buf); sum = (sum & 0xffffffff) + (sum >> 32); @@ -991,29 +915,29 @@ qla27xx_verify_template_checksum(struct qla27xx_fwdt_template *tmp) static inline int qla27xx_verify_template_header(struct qla27xx_fwdt_template *tmp) { - return tmp->template_type == TEMPLATE_TYPE_FWDUMP; + return le32_to_cpu(tmp->template_type) == TEMPLATE_TYPE_FWDUMP; } -static void -qla27xx_execute_fwdt_template(struct scsi_qla_host *vha) +static ulong +qla27xx_execute_fwdt_template(struct scsi_qla_host *vha, + struct qla27xx_fwdt_template *tmp, void *buf) { - struct qla27xx_fwdt_template *tmp = vha->hw->fw_dump_template; - ulong len; + ulong len = 0; if (qla27xx_fwdt_template_valid(tmp)) { len = tmp->template_size; - tmp = memcpy(vha->hw->fw_dump, tmp, len); + tmp = memcpy(buf, tmp, len); ql27xx_edit_template(vha, tmp); - qla27xx_walk_template(vha, tmp, tmp, &len); - vha->hw->fw_dump_len = len; - vha->hw->fw_dumped = 1; + qla27xx_walk_template(vha, tmp, buf, &len); } + + return len; } ulong -qla27xx_fwdt_calculate_dump_size(struct scsi_qla_host *vha) +qla27xx_fwdt_calculate_dump_size(struct scsi_qla_host *vha, void *p) { - struct qla27xx_fwdt_template *tmp = vha->hw->fw_dump_template; + struct qla27xx_fwdt_template *tmp = p; ulong len = 0; if (qla27xx_fwdt_template_valid(tmp)) { @@ -1032,18 +956,6 @@ qla27xx_fwdt_template_size(void *p) return tmp->template_size; } -ulong -qla27xx_fwdt_template_default_size(void) -{ - return sizeof(ql27xx_fwdt_default_template); -} - -const void * -qla27xx_fwdt_template_default(void) -{ - return ql27xx_fwdt_default_template; -} - int qla27xx_fwdt_template_valid(void *p) { @@ -1051,7 +963,8 @@ qla27xx_fwdt_template_valid(void *p) if (!qla27xx_verify_template_header(tmp)) { ql_log(ql_log_warn, NULL, 0xd01c, - "%s: template type %x\n", __func__, tmp->template_type); + "%s: template type %x\n", __func__, + le32_to_cpu(tmp->template_type)); return false; } @@ -1074,17 +987,41 @@ qla27xx_fwdump(scsi_qla_host_t *vha, int hardware_locked) spin_lock_irqsave(&vha->hw->hardware_lock, flags); #endif - if (!vha->hw->fw_dump) - ql_log(ql_log_warn, vha, 0xd01e, "fwdump buffer missing.\n"); - else if (!vha->hw->fw_dump_template) - ql_log(ql_log_warn, vha, 0xd01f, "fwdump template missing.\n"); - else if (vha->hw->fw_dumped) - ql_log(ql_log_warn, vha, 0xd300, - "Firmware has been previously dumped (%p)," - " -- ignoring request\n", vha->hw->fw_dump); - else { - QLA_FW_STOPPED(vha->hw); - qla27xx_execute_fwdt_template(vha); + if (!vha->hw->fw_dump) { + ql_log(ql_log_warn, vha, 0xd01e, "-> fwdump no buffer\n"); + } else if (vha->hw->fw_dumped) { + ql_log(ql_log_warn, vha, 0xd01f, + "-> Firmware already dumped (%p) -- ignoring request\n", + vha->hw->fw_dump); + } else { + struct fwdt *fwdt = vha->hw->fwdt; + uint j; + ulong len; + void *buf = vha->hw->fw_dump; + + for (j = 0; j < 2; j++, fwdt++, buf += len) { + ql_log(ql_log_warn, vha, 0xd011, + "-> fwdt%u running...\n", j); + if (!fwdt->template) { + ql_log(ql_log_warn, vha, 0xd012, + "-> fwdt%u no template\n", j); + break; + } + len = qla27xx_execute_fwdt_template(vha, + fwdt->template, buf); + if (len != fwdt->dump_size) { + ql_log(ql_log_warn, vha, 0xd013, + "-> fwdt%u fwdump residual=%+ld\n", + j, fwdt->dump_size - len); + } + } + vha->hw->fw_dump_len = buf - (void *)vha->hw->fw_dump; + vha->hw->fw_dumped = 1; + + ql_log(ql_log_warn, vha, 0xd015, + "-> Firmware dump saved to buffer (%lu/%p) <%lx>\n", + vha->host_no, vha->hw->fw_dump, vha->hw->fw_dump_cap_flags); + qla2x00_post_uevent_work(vha, QLA_UEVENT_CODE_FW_DUMP); } #ifndef __CHECKER__ diff --git a/drivers/scsi/qla2xxx/qla_tmpl.h b/drivers/scsi/qla2xxx/qla_tmpl.h index 5c2c2a8a19c4..d2a0014e8b21 100644 --- a/drivers/scsi/qla2xxx/qla_tmpl.h +++ b/drivers/scsi/qla2xxx/qla_tmpl.h @@ -11,12 +11,12 @@ #define IOBASE_ADDR offsetof(struct device_reg_24xx, iobase_addr) struct __packed qla27xx_fwdt_template { - uint32_t template_type; - uint32_t entry_offset; + __le32 template_type; + __le32 entry_offset; uint32_t template_size; - uint32_t reserved_1; + uint32_t count; /* borrow field for running/residual count */ - uint32_t entry_count; + __le32 entry_count; uint32_t template_version; uint32_t capture_timestamp; uint32_t template_checksum; @@ -65,8 +65,8 @@ struct __packed qla27xx_fwdt_template { struct __packed qla27xx_fwdt_entry { struct __packed { - uint32_t type; - uint32_t size; + __le32 type; + __le32 size; uint32_t reserved_1; uint8_t capture_flags; @@ -81,36 +81,36 @@ struct __packed qla27xx_fwdt_entry { } t255; struct __packed { - uint32_t base_addr; + __le32 base_addr; uint8_t reg_width; - uint16_t reg_count; + __le16 reg_count; uint8_t pci_offset; } t256; struct __packed { - uint32_t base_addr; - uint32_t write_data; + __le32 base_addr; + __le32 write_data; uint8_t pci_offset; uint8_t reserved[3]; } t257; struct __packed { - uint32_t base_addr; + __le32 base_addr; uint8_t reg_width; - uint16_t reg_count; + __le16 reg_count; uint8_t pci_offset; uint8_t banksel_offset; uint8_t reserved[3]; - uint32_t bank; + __le32 bank; } t258; struct __packed { - uint32_t base_addr; - uint32_t write_data; + __le32 base_addr; + __le32 write_data; uint8_t reserved[2]; uint8_t pci_offset; uint8_t banksel_offset; - uint32_t bank; + __le32 bank; } t259; struct __packed { @@ -121,14 +121,14 @@ struct __packed qla27xx_fwdt_entry { struct __packed { uint8_t pci_offset; uint8_t reserved[3]; - uint32_t write_data; + __le32 write_data; } t261; struct __packed { uint8_t ram_area; uint8_t reserved[3]; - uint32_t start_addr; - uint32_t end_addr; + __le32 start_addr; + __le32 end_addr; } t262; struct __packed { @@ -158,7 +158,7 @@ struct __packed qla27xx_fwdt_entry { struct __packed { uint8_t pci_offset; uint8_t reserved[3]; - uint32_t data; + __le32 data; } t267; struct __packed { @@ -173,23 +173,23 @@ struct __packed qla27xx_fwdt_entry { } t269; struct __packed { - uint32_t addr; - uint32_t count; + __le32 addr; + __le32 count; } t270; struct __packed { - uint32_t addr; - uint32_t data; + __le32 addr; + __le32 data; } t271; struct __packed { - uint32_t addr; - uint32_t count; + __le32 addr; + __le32 count; } t272; struct __packed { - uint32_t addr; - uint32_t count; + __le32 addr; + __le32 count; } t273; struct __packed { @@ -199,26 +199,26 @@ struct __packed qla27xx_fwdt_entry { } t274; struct __packed { - uint32_t length; + __le32 length; uint8_t buffer[]; } t275; struct __packed { - uint32_t cond1; - uint32_t cond2; + __le32 cond1; + __le32 cond2; } t276; struct __packed { - uint32_t cmd_addr; - uint32_t wr_cmd_data; - uint32_t data_addr; + __le32 cmd_addr; + __le32 wr_cmd_data; + __le32 data_addr; } t277; struct __packed { - uint32_t cmd_addr; - uint32_t wr_cmd_data; - uint32_t data_addr; - uint32_t wr_data; + __le32 cmd_addr; + __le32 wr_cmd_data; + __le32 data_addr; + __le32 wr_data; } t278; }; }; diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index 0690dac24081..cd6bdf71e533 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -7,9 +7,9 @@ /* * Driver version */ -#define QLA2XXX_VERSION "10.00.00.14-k" +#define QLA2XXX_VERSION "10.01.00.16-k" #define QLA_DRIVER_MAJOR_VER 10 -#define QLA_DRIVER_MINOR_VER 0 +#define QLA_DRIVER_MINOR_VER 1 #define QLA_DRIVER_PATCH_VER 0 #define QLA_DRIVER_BETA_VER 0 diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index 8a3075d17c63..ec9f1996b417 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c @@ -24,22 +24,16 @@ #include <linux/module.h> -#include <linux/moduleparam.h> #include <linux/utsname.h> #include <linux/vmalloc.h> -#include <linux/init.h> #include <linux/list.h> #include <linux/slab.h> -#include <linux/kthread.h> #include <linux/types.h> #include <linux/string.h> #include <linux/configfs.h> #include <linux/ctype.h> #include <asm/unaligned.h> -#include <scsi/scsi.h> #include <scsi/scsi_host.h> -#include <scsi/scsi_device.h> -#include <scsi/scsi_cmnd.h> #include <target/target_core_base.h> #include <target/target_core_fabric.h> @@ -267,25 +261,17 @@ static void tcm_qla2xxx_free_mcmd(struct qla_tgt_mgmt_cmd *mcmd) static void tcm_qla2xxx_complete_free(struct work_struct *work) { struct qla_tgt_cmd *cmd = container_of(work, struct qla_tgt_cmd, work); - bool released = false; - unsigned long flags; cmd->cmd_in_wq = 0; WARN_ON(cmd->trc_flags & TRC_CMD_FREE); - spin_lock_irqsave(&cmd->cmd_lock, flags); + /* To do: protect all tgt_counters manipulations with proper locking. */ cmd->qpair->tgt_counters.qla_core_ret_sta_ctio++; cmd->trc_flags |= TRC_CMD_FREE; cmd->cmd_sent_to_fw = 0; - if (cmd->released) - released = true; - spin_unlock_irqrestore(&cmd->cmd_lock, flags); - if (released) - qlt_free_cmd(cmd); - else - transport_generic_free_cmd(&cmd->se_cmd, 0); + transport_generic_free_cmd(&cmd->se_cmd, 0); } /* @@ -326,7 +312,6 @@ static int tcm_qla2xxx_check_stop_free(struct se_cmd *se_cmd) static void tcm_qla2xxx_release_cmd(struct se_cmd *se_cmd) { struct qla_tgt_cmd *cmd; - unsigned long flags; if (se_cmd->se_cmd_flags & SCF_SCSI_TMR_CDB) { struct qla_tgt_mgmt_cmd *mcmd = container_of(se_cmd, @@ -336,14 +321,10 @@ static void tcm_qla2xxx_release_cmd(struct se_cmd *se_cmd) } cmd = container_of(se_cmd, struct qla_tgt_cmd, se_cmd); - spin_lock_irqsave(&cmd->cmd_lock, flags); - if (cmd->cmd_sent_to_fw) { - cmd->released = 1; - spin_unlock_irqrestore(&cmd->cmd_lock, flags); - } else { - spin_unlock_irqrestore(&cmd->cmd_lock, flags); - qlt_free_cmd(cmd); - } + if (WARN_ON(cmd->cmd_sent_to_fw)) + return; + + qlt_free_cmd(cmd); } static void tcm_qla2xxx_release_session(struct kref *kref) @@ -359,7 +340,6 @@ static void tcm_qla2xxx_put_sess(struct fc_port *sess) if (!sess) return; - assert_spin_locked(&sess->vha->hw->tgt.sess_lock); kref_put(&sess->sess_kref, tcm_qla2xxx_release_session); } @@ -374,8 +354,9 @@ static void tcm_qla2xxx_close_session(struct se_session *se_sess) spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); target_sess_cmd_list_set_waiting(se_sess); - tcm_qla2xxx_put_sess(sess); spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); + + tcm_qla2xxx_put_sess(sess); } static u32 tcm_qla2xxx_sess_get_index(struct se_session *se_sess) @@ -399,6 +380,8 @@ static int tcm_qla2xxx_write_pending(struct se_cmd *se_cmd) cmd->se_cmd.transport_state, cmd->se_cmd.t_state, cmd->se_cmd.se_cmd_flags); + transport_generic_request_failure(&cmd->se_cmd, + TCM_CHECK_CONDITION_ABORT_CMD); return 0; } cmd->trc_flags |= TRC_XFR_RDY; @@ -488,32 +471,18 @@ static int tcm_qla2xxx_handle_cmd(scsi_qla_host_t *vha, struct qla_tgt_cmd *cmd, static void tcm_qla2xxx_handle_data_work(struct work_struct *work) { struct qla_tgt_cmd *cmd = container_of(work, struct qla_tgt_cmd, work); - unsigned long flags; /* * Ensure that the complete FCP WRITE payload has been received. * Otherwise return an exception via CHECK_CONDITION status. */ cmd->cmd_in_wq = 0; - - spin_lock_irqsave(&cmd->cmd_lock, flags); cmd->cmd_sent_to_fw = 0; - - if (cmd->released) { - spin_unlock_irqrestore(&cmd->cmd_lock, flags); - qlt_free_cmd(cmd); - return; - } - - cmd->data_work = 1; if (cmd->aborted) { - cmd->data_work_free = 1; - spin_unlock_irqrestore(&cmd->cmd_lock, flags); - - tcm_qla2xxx_free_cmd(cmd); + transport_generic_request_failure(&cmd->se_cmd, + TCM_CHECK_CONDITION_ABORT_CMD); return; } - spin_unlock_irqrestore(&cmd->cmd_lock, flags); cmd->qpair->tgt_counters.qla_core_ret_ctio++; if (!cmd->write_data_transferred) { @@ -829,7 +798,6 @@ static void tcm_qla2xxx_clear_nacl_from_fcport_map(struct fc_port *sess) static void tcm_qla2xxx_shutdown_sess(struct fc_port *sess) { - assert_spin_locked(&sess->vha->hw->tgt.sess_lock); target_sess_cmd_list_set_waiting(sess->se_sess); } @@ -1489,7 +1457,7 @@ static int tcm_qla2xxx_check_initiator_node_acl( */ tpg = lport->tpg_1; if (!tpg) { - pr_err("Unable to lcoate struct tcm_qla2xxx_lport->tpg_1\n"); + pr_err("Unable to locate struct tcm_qla2xxx_lport->tpg_1\n"); return -EINVAL; } /* |