|
@@ -308,6 +308,61 @@ static struct bin_attribute sysfs_optrom_ctl_attr = {
|
|
|
.write = qla2x00_sysfs_write_optrom_ctl,
|
|
|
};
|
|
|
|
|
|
+static ssize_t
|
|
|
+qla2x00_sysfs_read_vpd(struct kobject *kobj, char *buf, loff_t off,
|
|
|
+ size_t count)
|
|
|
+{
|
|
|
+ struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
|
|
|
+ struct device, kobj)));
|
|
|
+ unsigned long flags;
|
|
|
+
|
|
|
+ if (!capable(CAP_SYS_ADMIN) || off != 0)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha))
|
|
|
+ return -ENOTSUPP;
|
|
|
+
|
|
|
+ /* Read NVRAM. */
|
|
|
+ spin_lock_irqsave(&ha->hardware_lock, flags);
|
|
|
+ ha->isp_ops.read_nvram(ha, (uint8_t *)buf, ha->vpd_base, ha->vpd_size);
|
|
|
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
|
|
+
|
|
|
+ return ha->vpd_size;
|
|
|
+}
|
|
|
+
|
|
|
+static ssize_t
|
|
|
+qla2x00_sysfs_write_vpd(struct kobject *kobj, char *buf, loff_t off,
|
|
|
+ size_t count)
|
|
|
+{
|
|
|
+ struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
|
|
|
+ struct device, kobj)));
|
|
|
+ unsigned long flags;
|
|
|
+
|
|
|
+ if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->vpd_size)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha))
|
|
|
+ return -ENOTSUPP;
|
|
|
+
|
|
|
+ /* Write NVRAM. */
|
|
|
+ spin_lock_irqsave(&ha->hardware_lock, flags);
|
|
|
+ ha->isp_ops.write_nvram(ha, (uint8_t *)buf, ha->vpd_base, count);
|
|
|
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
|
|
+
|
|
|
+ return count;
|
|
|
+}
|
|
|
+
|
|
|
+static struct bin_attribute sysfs_vpd_attr = {
|
|
|
+ .attr = {
|
|
|
+ .name = "vpd",
|
|
|
+ .mode = S_IRUSR | S_IWUSR,
|
|
|
+ .owner = THIS_MODULE,
|
|
|
+ },
|
|
|
+ .size = 0,
|
|
|
+ .read = qla2x00_sysfs_read_vpd,
|
|
|
+ .write = qla2x00_sysfs_write_vpd,
|
|
|
+};
|
|
|
+
|
|
|
void
|
|
|
qla2x00_alloc_sysfs_attr(scsi_qla_host_t *ha)
|
|
|
{
|
|
@@ -318,6 +373,7 @@ qla2x00_alloc_sysfs_attr(scsi_qla_host_t *ha)
|
|
|
sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_optrom_attr);
|
|
|
sysfs_create_bin_file(&host->shost_gendev.kobj,
|
|
|
&sysfs_optrom_ctl_attr);
|
|
|
+ sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_vpd_attr);
|
|
|
}
|
|
|
|
|
|
void
|
|
@@ -330,6 +386,7 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *ha)
|
|
|
sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_optrom_attr);
|
|
|
sysfs_remove_bin_file(&host->shost_gendev.kobj,
|
|
|
&sysfs_optrom_ctl_attr);
|
|
|
+ sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_vpd_attr);
|
|
|
|
|
|
if (ha->beacon_blink_led == 1)
|
|
|
ha->isp_ops.beacon_off(ha);
|