diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_attr.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_attr.c | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 2b9e329a240c..488b3d16427b 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c | |||
@@ -308,6 +308,61 @@ static struct bin_attribute sysfs_optrom_ctl_attr = { | |||
308 | .write = qla2x00_sysfs_write_optrom_ctl, | 308 | .write = qla2x00_sysfs_write_optrom_ctl, |
309 | }; | 309 | }; |
310 | 310 | ||
311 | static ssize_t | ||
312 | qla2x00_sysfs_read_vpd(struct kobject *kobj, char *buf, loff_t off, | ||
313 | size_t count) | ||
314 | { | ||
315 | struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, | ||
316 | struct device, kobj))); | ||
317 | unsigned long flags; | ||
318 | |||
319 | if (!capable(CAP_SYS_ADMIN) || off != 0) | ||
320 | return 0; | ||
321 | |||
322 | if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) | ||
323 | return -ENOTSUPP; | ||
324 | |||
325 | /* Read NVRAM. */ | ||
326 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
327 | ha->isp_ops.read_nvram(ha, (uint8_t *)buf, ha->vpd_base, ha->vpd_size); | ||
328 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
329 | |||
330 | return ha->vpd_size; | ||
331 | } | ||
332 | |||
333 | static ssize_t | ||
334 | qla2x00_sysfs_write_vpd(struct kobject *kobj, char *buf, loff_t off, | ||
335 | size_t count) | ||
336 | { | ||
337 | struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, | ||
338 | struct device, kobj))); | ||
339 | unsigned long flags; | ||
340 | |||
341 | if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->vpd_size) | ||
342 | return 0; | ||
343 | |||
344 | if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) | ||
345 | return -ENOTSUPP; | ||
346 | |||
347 | /* Write NVRAM. */ | ||
348 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
349 | ha->isp_ops.write_nvram(ha, (uint8_t *)buf, ha->vpd_base, count); | ||
350 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
351 | |||
352 | return count; | ||
353 | } | ||
354 | |||
355 | static struct bin_attribute sysfs_vpd_attr = { | ||
356 | .attr = { | ||
357 | .name = "vpd", | ||
358 | .mode = S_IRUSR | S_IWUSR, | ||
359 | .owner = THIS_MODULE, | ||
360 | }, | ||
361 | .size = 0, | ||
362 | .read = qla2x00_sysfs_read_vpd, | ||
363 | .write = qla2x00_sysfs_write_vpd, | ||
364 | }; | ||
365 | |||
311 | void | 366 | void |
312 | qla2x00_alloc_sysfs_attr(scsi_qla_host_t *ha) | 367 | qla2x00_alloc_sysfs_attr(scsi_qla_host_t *ha) |
313 | { | 368 | { |
@@ -318,6 +373,7 @@ qla2x00_alloc_sysfs_attr(scsi_qla_host_t *ha) | |||
318 | sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_optrom_attr); | 373 | sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_optrom_attr); |
319 | sysfs_create_bin_file(&host->shost_gendev.kobj, | 374 | sysfs_create_bin_file(&host->shost_gendev.kobj, |
320 | &sysfs_optrom_ctl_attr); | 375 | &sysfs_optrom_ctl_attr); |
376 | sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_vpd_attr); | ||
321 | } | 377 | } |
322 | 378 | ||
323 | void | 379 | void |
@@ -330,6 +386,7 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *ha) | |||
330 | sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_optrom_attr); | 386 | sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_optrom_attr); |
331 | sysfs_remove_bin_file(&host->shost_gendev.kobj, | 387 | sysfs_remove_bin_file(&host->shost_gendev.kobj, |
332 | &sysfs_optrom_ctl_attr); | 388 | &sysfs_optrom_ctl_attr); |
389 | sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_vpd_attr); | ||
333 | 390 | ||
334 | if (ha->beacon_blink_led == 1) | 391 | if (ha->beacon_blink_led == 1) |
335 | ha->isp_ops.beacon_off(ha); | 392 | ha->isp_ops.beacon_off(ha); |