[SCSI] qla2xxx: Add mutex around optrom calls to serialize accesses.
Signed-off-by: Chad Dupuis <chad.dupuis@qlogic.com> Signed-off-by: Saurav Kashyap <saurav.kashyap@qlogic.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
This commit is contained in:
parent
38e83bff14
commit
7a8ab9c840
|
@ -241,12 +241,17 @@ qla2x00_sysfs_read_optrom(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;
|
||||
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
|
||||
|
@ -265,7 +270,9 @@ qla2x00_sysfs_write_optrom(struct file *filp, struct kobject *kobj,
|
|||
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;
|
||||
}
|
||||
|
@ -288,10 +295,10 @@ qla2x00_sysfs_write_optrom_ctl(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 start = 0;
|
||||
uint32_t size = ha->optrom_size;
|
||||
int val, valid;
|
||||
ssize_t rval = count;
|
||||
|
||||
if (off)
|
||||
return -EINVAL;
|
||||
|
@ -304,12 +311,14 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
|
|||
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,
|
||||
|
@ -320,8 +329,10 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
|
|||
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 ?
|
||||
|
@ -335,13 +346,15 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
|
|||
"(%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,
|
||||
|
@ -353,8 +366,10 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
|
|||
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
|
||||
|
@ -388,7 +403,8 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
|
|||
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;
|
||||
|
@ -403,7 +419,8 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
|
|||
"(%x)\n", ha->optrom_region_size);
|
||||
|
||||
ha->optrom_state = QLA_SWAITING;
|
||||
return -ENOMEM;
|
||||
rval = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ql_dbg(ql_dbg_user, vha, 0x7067,
|
||||
|
@ -413,13 +430,16 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
|
|||
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,
|
||||
|
@ -430,9 +450,12 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
|
|||
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 = {
|
||||
|
|
|
@ -1437,9 +1437,12 @@ qla2x00_read_optrom(struct fc_bsg_job *bsg_job)
|
|||
if (ha->flags.nic_core_reset_hdlr_active)
|
||||
return -EBUSY;
|
||||
|
||||
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);
|
||||
|
@ -1453,6 +1456,7 @@ qla2x00_read_optrom(struct fc_bsg_job *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;
|
||||
}
|
||||
|
@ -1465,9 +1469,12 @@ qla2x00_update_optrom(struct fc_bsg_job *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;
|
||||
}
|
||||
|
||||
/* Set the isp82xx_no_md_cap not to capture minidump */
|
||||
ha->flags.isp82xx_no_md_cap = 1;
|
||||
|
@ -1483,6 +1490,7 @@ qla2x00_update_optrom(struct fc_bsg_job *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;
|
||||
}
|
||||
|
|
|
@ -3183,6 +3183,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
|
||||
|
|
|
@ -2334,6 +2334,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
spin_lock_init(&ha->hardware_lock);
|
||||
spin_lock_init(&ha->vport_slock);
|
||||
mutex_init(&ha->selflogin_lock);
|
||||
mutex_init(&ha->optrom_mutex);
|
||||
|
||||
/* Set ISP-type information. */
|
||||
qla2x00_set_isp_flags(ha);
|
||||
|
|
Loading…
Reference in a new issue