[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:
Родитель
38e83bff14
Коммит
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 scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
|
||||||
struct device, kobj)));
|
struct device, kobj)));
|
||||||
struct qla_hw_data *ha = vha->hw;
|
struct qla_hw_data *ha = vha->hw;
|
||||||
|
ssize_t rval = 0;
|
||||||
|
|
||||||
if (ha->optrom_state != QLA_SREADING)
|
if (ha->optrom_state != QLA_SREADING)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return memory_read_from_buffer(buf, count, &off, ha->optrom_buffer,
|
mutex_lock(&ha->optrom_mutex);
|
||||||
ha->optrom_region_size);
|
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
|
static ssize_t
|
||||||
|
@ -265,7 +270,9 @@ qla2x00_sysfs_write_optrom(struct file *filp, struct kobject *kobj,
|
||||||
if (off + count > ha->optrom_region_size)
|
if (off + count > ha->optrom_region_size)
|
||||||
count = ha->optrom_region_size - off;
|
count = ha->optrom_region_size - off;
|
||||||
|
|
||||||
|
mutex_lock(&ha->optrom_mutex);
|
||||||
memcpy(&ha->optrom_buffer[off], buf, count);
|
memcpy(&ha->optrom_buffer[off], buf, count);
|
||||||
|
mutex_unlock(&ha->optrom_mutex);
|
||||||
|
|
||||||
return count;
|
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 scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
|
||||||
struct device, kobj)));
|
struct device, kobj)));
|
||||||
struct qla_hw_data *ha = vha->hw;
|
struct qla_hw_data *ha = vha->hw;
|
||||||
|
|
||||||
uint32_t start = 0;
|
uint32_t start = 0;
|
||||||
uint32_t size = ha->optrom_size;
|
uint32_t size = ha->optrom_size;
|
||||||
int val, valid;
|
int val, valid;
|
||||||
|
ssize_t rval = count;
|
||||||
|
|
||||||
if (off)
|
if (off)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -304,12 +311,14 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
|
||||||
if (start > ha->optrom_size)
|
if (start > ha->optrom_size)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
mutex_lock(&ha->optrom_mutex);
|
||||||
switch (val) {
|
switch (val) {
|
||||||
case 0:
|
case 0:
|
||||||
if (ha->optrom_state != QLA_SREADING &&
|
if (ha->optrom_state != QLA_SREADING &&
|
||||||
ha->optrom_state != QLA_SWRITING)
|
ha->optrom_state != QLA_SWRITING) {
|
||||||
return -EINVAL;
|
rval = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
ha->optrom_state = QLA_SWAITING;
|
ha->optrom_state = QLA_SWAITING;
|
||||||
|
|
||||||
ql_dbg(ql_dbg_user, vha, 0x7061,
|
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;
|
ha->optrom_buffer = NULL;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
if (ha->optrom_state != QLA_SWAITING)
|
if (ha->optrom_state != QLA_SWAITING) {
|
||||||
return -EINVAL;
|
rval = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
ha->optrom_region_start = start;
|
ha->optrom_region_start = start;
|
||||||
ha->optrom_region_size = start + size > ha->optrom_size ?
|
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);
|
"(%x).\n", ha->optrom_region_size);
|
||||||
|
|
||||||
ha->optrom_state = QLA_SWAITING;
|
ha->optrom_state = QLA_SWAITING;
|
||||||
return -ENOMEM;
|
rval = -ENOMEM;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
|
if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
|
||||||
ql_log(ql_log_warn, vha, 0x7063,
|
ql_log(ql_log_warn, vha, 0x7063,
|
||||||
"HBA not online, failing NVRAM update.\n");
|
"HBA not online, failing NVRAM update.\n");
|
||||||
return -EAGAIN;
|
rval = -EAGAIN;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ql_dbg(ql_dbg_user, vha, 0x7064,
|
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);
|
ha->optrom_region_start, ha->optrom_region_size);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
if (ha->optrom_state != QLA_SWAITING)
|
if (ha->optrom_state != QLA_SWAITING) {
|
||||||
return -EINVAL;
|
rval = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We need to be more restrictive on which FLASH regions are
|
* 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) {
|
if (!valid) {
|
||||||
ql_log(ql_log_warn, vha, 0x7065,
|
ql_log(ql_log_warn, vha, 0x7065,
|
||||||
"Invalid start region 0x%x/0x%x.\n", start, size);
|
"Invalid start region 0x%x/0x%x.\n", start, size);
|
||||||
return -EINVAL;
|
rval = -EINVAL;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ha->optrom_region_start = start;
|
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);
|
"(%x)\n", ha->optrom_region_size);
|
||||||
|
|
||||||
ha->optrom_state = QLA_SWAITING;
|
ha->optrom_state = QLA_SWAITING;
|
||||||
return -ENOMEM;
|
rval = -ENOMEM;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ql_dbg(ql_dbg_user, vha, 0x7067,
|
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);
|
memset(ha->optrom_buffer, 0, ha->optrom_region_size);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
if (ha->optrom_state != QLA_SWRITING)
|
if (ha->optrom_state != QLA_SWRITING) {
|
||||||
return -EINVAL;
|
rval = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
|
if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
|
||||||
ql_log(ql_log_warn, vha, 0x7068,
|
ql_log(ql_log_warn, vha, 0x7068,
|
||||||
"HBA not online, failing flash update.\n");
|
"HBA not online, failing flash update.\n");
|
||||||
return -EAGAIN;
|
rval = -EAGAIN;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ql_dbg(ql_dbg_user, vha, 0x7069,
|
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);
|
ha->optrom_region_start, ha->optrom_region_size);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
rval = -EINVAL;
|
||||||
}
|
}
|
||||||
return count;
|
|
||||||
|
out:
|
||||||
|
mutex_unlock(&ha->optrom_mutex);
|
||||||
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct bin_attribute sysfs_optrom_ctl_attr = {
|
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)
|
if (ha->flags.nic_core_reset_hdlr_active)
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
|
mutex_lock(&ha->optrom_mutex);
|
||||||
rval = qla2x00_optrom_setup(bsg_job, vha, 0);
|
rval = qla2x00_optrom_setup(bsg_job, vha, 0);
|
||||||
if (rval)
|
if (rval) {
|
||||||
|
mutex_unlock(&ha->optrom_mutex);
|
||||||
return rval;
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
ha->isp_ops->read_optrom(vha, ha->optrom_buffer,
|
ha->isp_ops->read_optrom(vha, ha->optrom_buffer,
|
||||||
ha->optrom_region_start, ha->optrom_region_size);
|
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);
|
vfree(ha->optrom_buffer);
|
||||||
ha->optrom_buffer = NULL;
|
ha->optrom_buffer = NULL;
|
||||||
ha->optrom_state = QLA_SWAITING;
|
ha->optrom_state = QLA_SWAITING;
|
||||||
|
mutex_unlock(&ha->optrom_mutex);
|
||||||
bsg_job->job_done(bsg_job);
|
bsg_job->job_done(bsg_job);
|
||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
@ -1465,9 +1469,12 @@ qla2x00_update_optrom(struct fc_bsg_job *bsg_job)
|
||||||
struct qla_hw_data *ha = vha->hw;
|
struct qla_hw_data *ha = vha->hw;
|
||||||
int rval = 0;
|
int rval = 0;
|
||||||
|
|
||||||
|
mutex_lock(&ha->optrom_mutex);
|
||||||
rval = qla2x00_optrom_setup(bsg_job, vha, 1);
|
rval = qla2x00_optrom_setup(bsg_job, vha, 1);
|
||||||
if (rval)
|
if (rval) {
|
||||||
|
mutex_unlock(&ha->optrom_mutex);
|
||||||
return rval;
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
/* Set the isp82xx_no_md_cap not to capture minidump */
|
/* Set the isp82xx_no_md_cap not to capture minidump */
|
||||||
ha->flags.isp82xx_no_md_cap = 1;
|
ha->flags.isp82xx_no_md_cap = 1;
|
||||||
|
@ -1483,6 +1490,7 @@ qla2x00_update_optrom(struct fc_bsg_job *bsg_job)
|
||||||
vfree(ha->optrom_buffer);
|
vfree(ha->optrom_buffer);
|
||||||
ha->optrom_buffer = NULL;
|
ha->optrom_buffer = NULL;
|
||||||
ha->optrom_state = QLA_SWAITING;
|
ha->optrom_state = QLA_SWAITING;
|
||||||
|
mutex_unlock(&ha->optrom_mutex);
|
||||||
bsg_job->job_done(bsg_job);
|
bsg_job->job_done(bsg_job);
|
||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3183,6 +3183,7 @@ struct qla_hw_data {
|
||||||
#define QLA_SWRITING 2
|
#define QLA_SWRITING 2
|
||||||
uint32_t optrom_region_start;
|
uint32_t optrom_region_start;
|
||||||
uint32_t optrom_region_size;
|
uint32_t optrom_region_size;
|
||||||
|
struct mutex optrom_mutex;
|
||||||
|
|
||||||
/* PCI expansion ROM image information. */
|
/* PCI expansion ROM image information. */
|
||||||
#define ROM_CODE_TYPE_BIOS 0
|
#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->hardware_lock);
|
||||||
spin_lock_init(&ha->vport_slock);
|
spin_lock_init(&ha->vport_slock);
|
||||||
mutex_init(&ha->selflogin_lock);
|
mutex_init(&ha->selflogin_lock);
|
||||||
|
mutex_init(&ha->optrom_mutex);
|
||||||
|
|
||||||
/* Set ISP-type information. */
|
/* Set ISP-type information. */
|
||||||
qla2x00_set_isp_flags(ha);
|
qla2x00_set_isp_flags(ha);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче