3.2.96-rc1 review patch. If anyone has any objections, please let me know. ------------------ From: Chad Dupuis <chad.dupuis@xxxxxxxxxx> commit 7a8ab9c840b5dff9bb70328338a86444ed1c2415 upstream. Signed-off-by: Chad Dupuis <chad.dupuis@xxxxxxxxxx> Signed-off-by: Saurav Kashyap <saurav.kashyap@xxxxxxxxxx> Signed-off-by: James Bottomley <JBottomley@xxxxxxxxxxxxx> [bwh: Backported to 3.2: adjust context] Signed-off-by: Ben Hutchings <ben@xxxxxxxxxxxxxxx> --- drivers/scsi/qla2xxx/qla_attr.c | 61 ++++++++++++++++++++++++++++------------- drivers/scsi/qla2xxx/qla_bsg.c | 12 ++++++-- drivers/scsi/qla2xxx/qla_def.h | 1 + drivers/scsi/qla2xxx/qla_os.c | 1 + 4 files changed, 54 insertions(+), 21 deletions(-) --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -215,12 +215,17 @@ qla2x00_sysfs_read_optrom(struct file *f struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj, struct device, kobj))); struct qla_hw_data *ha = vha->hw; + ssize_t rval = 0; if (ha->optrom_state != QLA_SREADING) return 0; - return memory_read_from_buffer(buf, count, &off, ha->optrom_buffer, - ha->optrom_region_size); + mutex_lock(&ha->optrom_mutex); + rval = memory_read_from_buffer(buf, count, &off, ha->optrom_buffer, + ha->optrom_region_size); + mutex_unlock(&ha->optrom_mutex); + + return rval; } static ssize_t @@ -239,7 +244,9 @@ qla2x00_sysfs_write_optrom(struct file * if (off + count > ha->optrom_region_size) count = ha->optrom_region_size - off; + mutex_lock(&ha->optrom_mutex); memcpy(&ha->optrom_buffer[off], buf, count); + mutex_unlock(&ha->optrom_mutex); return count; } @@ -262,10 +269,10 @@ qla2x00_sysfs_write_optrom_ctl(struct fi 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 start = 0; uint32_t size = ha->optrom_size; int val, valid; + ssize_t rval = count; if (off) return -EINVAL; @@ -278,12 +285,14 @@ qla2x00_sysfs_write_optrom_ctl(struct fi if (start > ha->optrom_size) return -EINVAL; + mutex_lock(&ha->optrom_mutex); switch (val) { case 0: if (ha->optrom_state != QLA_SREADING && - ha->optrom_state != QLA_SWRITING) - return -EINVAL; - + ha->optrom_state != QLA_SWRITING) { + rval = -EINVAL; + goto out; + } ha->optrom_state = QLA_SWAITING; ql_dbg(ql_dbg_user, vha, 0x7061, @@ -294,8 +303,10 @@ qla2x00_sysfs_write_optrom_ctl(struct fi ha->optrom_buffer = NULL; break; case 1: - if (ha->optrom_state != QLA_SWAITING) - return -EINVAL; + if (ha->optrom_state != QLA_SWAITING) { + rval = -EINVAL; + goto out; + } ha->optrom_region_start = start; ha->optrom_region_size = start + size > ha->optrom_size ? @@ -309,13 +320,15 @@ qla2x00_sysfs_write_optrom_ctl(struct fi "(%x).\n", ha->optrom_region_size); ha->optrom_state = QLA_SWAITING; - return -ENOMEM; + rval = -ENOMEM; + goto out; } if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) { ql_log(ql_log_warn, vha, 0x7063, "HBA not online, failing NVRAM update.\n"); - return -EAGAIN; + rval = -EAGAIN; + goto out; } ql_dbg(ql_dbg_user, vha, 0x7064, @@ -327,8 +340,10 @@ qla2x00_sysfs_write_optrom_ctl(struct fi ha->optrom_region_start, ha->optrom_region_size); break; case 2: - if (ha->optrom_state != QLA_SWAITING) - return -EINVAL; + if (ha->optrom_state != QLA_SWAITING) { + rval = -EINVAL; + goto out; + } /* * We need to be more restrictive on which FLASH regions are @@ -361,7 +376,8 @@ qla2x00_sysfs_write_optrom_ctl(struct fi if (!valid) { ql_log(ql_log_warn, vha, 0x7065, "Invalid start region 0x%x/0x%x.\n", start, size); - return -EINVAL; + rval = -EINVAL; + goto out; } ha->optrom_region_start = start; @@ -376,7 +392,8 @@ qla2x00_sysfs_write_optrom_ctl(struct fi "(%x)\n", ha->optrom_region_size); ha->optrom_state = QLA_SWAITING; - return -ENOMEM; + rval = -ENOMEM; + goto out; } ql_dbg(ql_dbg_user, vha, 0x7067, @@ -386,13 +403,16 @@ qla2x00_sysfs_write_optrom_ctl(struct fi memset(ha->optrom_buffer, 0, ha->optrom_region_size); break; case 3: - if (ha->optrom_state != QLA_SWRITING) - return -EINVAL; + if (ha->optrom_state != QLA_SWRITING) { + rval = -EINVAL; + goto out; + } if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) { ql_log(ql_log_warn, vha, 0x7068, "HBA not online, failing flash update.\n"); - return -EAGAIN; + rval = -EAGAIN; + goto out; } ql_dbg(ql_dbg_user, vha, 0x7069, @@ -403,9 +423,12 @@ qla2x00_sysfs_write_optrom_ctl(struct fi ha->optrom_region_start, ha->optrom_region_size); break; default: - return -EINVAL; + rval = -EINVAL; } - return count; + +out: + mutex_unlock(&ha->optrom_mutex); + return rval; } static struct bin_attribute sysfs_optrom_ctl_attr = { --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -1400,9 +1400,12 @@ qla2x00_read_optrom(struct fc_bsg_job *b struct qla_hw_data *ha = vha->hw; int rval = 0; + mutex_lock(&ha->optrom_mutex); rval = qla2x00_optrom_setup(bsg_job, vha, 0); - if (rval) + if (rval) { + mutex_unlock(&ha->optrom_mutex); return rval; + } ha->isp_ops->read_optrom(vha, ha->optrom_buffer, ha->optrom_region_start, ha->optrom_region_size); @@ -1416,6 +1419,7 @@ qla2x00_read_optrom(struct fc_bsg_job *b vfree(ha->optrom_buffer); ha->optrom_buffer = NULL; ha->optrom_state = QLA_SWAITING; + mutex_unlock(&ha->optrom_mutex); bsg_job->job_done(bsg_job); return rval; } @@ -1428,9 +1432,12 @@ qla2x00_update_optrom(struct fc_bsg_job struct qla_hw_data *ha = vha->hw; int rval = 0; + mutex_lock(&ha->optrom_mutex); rval = qla2x00_optrom_setup(bsg_job, vha, 1); - if (rval) + if (rval) { + mutex_unlock(&ha->optrom_mutex); return rval; + } sg_copy_to_buffer(bsg_job->request_payload.sg_list, bsg_job->request_payload.sg_cnt, ha->optrom_buffer, @@ -1443,6 +1450,7 @@ qla2x00_update_optrom(struct fc_bsg_job vfree(ha->optrom_buffer); ha->optrom_buffer = NULL; ha->optrom_state = QLA_SWAITING; + mutex_unlock(&ha->optrom_mutex); bsg_job->job_done(bsg_job); return rval; } --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2723,6 +2723,7 @@ struct qla_hw_data { #define QLA_SWRITING 2 uint32_t optrom_region_start; uint32_t optrom_region_size; + struct mutex optrom_mutex; /* PCI expansion ROM image information. */ #define ROM_CODE_TYPE_BIOS 0 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -2023,6 +2023,7 @@ qla2x00_probe_one(struct pci_dev *pdev, ha->mem_only = mem_only; spin_lock_init(&ha->hardware_lock); spin_lock_init(&ha->vport_slock); + mutex_init(&ha->optrom_mutex); /* Set ISP-type information. */ qla2x00_set_isp_flags(ha);