aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx/qla_attr.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_attr.c')
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c120
1 files changed, 76 insertions, 44 deletions
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index e96d58ded57c..87f90c4f08e9 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -16,15 +16,16 @@ qla2x00_sysfs_read_fw_dump(struct kobject *kobj, char *buf, loff_t off,
16{ 16{
17 struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, 17 struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
18 struct device, kobj))); 18 struct device, kobj)));
19 char *rbuf = (char *)ha->fw_dump;
19 20
20 if (ha->fw_dump_reading == 0) 21 if (ha->fw_dump_reading == 0)
21 return 0; 22 return 0;
22 if (off > ha->fw_dump_buffer_len) 23 if (off > ha->fw_dump_len)
23 return 0; 24 return 0;
24 if (off + count > ha->fw_dump_buffer_len) 25 if (off + count > ha->fw_dump_len)
25 count = ha->fw_dump_buffer_len - off; 26 count = ha->fw_dump_len - off;
26 27
27 memcpy(buf, &ha->fw_dump_buffer[off], count); 28 memcpy(buf, &rbuf[off], count);
28 29
29 return (count); 30 return (count);
30} 31}
@@ -36,7 +37,6 @@ qla2x00_sysfs_write_fw_dump(struct kobject *kobj, char *buf, loff_t off,
36 struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, 37 struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
37 struct device, kobj))); 38 struct device, kobj)));
38 int reading; 39 int reading;
39 uint32_t dump_size;
40 40
41 if (off != 0) 41 if (off != 0)
42 return (0); 42 return (0);
@@ -44,46 +44,27 @@ qla2x00_sysfs_write_fw_dump(struct kobject *kobj, char *buf, loff_t off,
44 reading = simple_strtol(buf, NULL, 10); 44 reading = simple_strtol(buf, NULL, 10);
45 switch (reading) { 45 switch (reading) {
46 case 0: 46 case 0:
47 if (ha->fw_dump_reading == 1) { 47 if (!ha->fw_dump_reading)
48 qla_printk(KERN_INFO, ha, 48 break;
49 "Firmware dump cleared on (%ld).\n", ha->host_no);
50 49
51 vfree(ha->fw_dump_buffer); 50 qla_printk(KERN_INFO, ha,
52 ha->fw_dump_buffer = NULL; 51 "Firmware dump cleared on (%ld).\n", ha->host_no);
53 ha->fw_dump_reading = 0; 52
54 ha->fw_dumped = 0; 53 ha->fw_dump_reading = 0;
55 } 54 ha->fw_dumped = 0;
56 break; 55 break;
57 case 1: 56 case 1:
58 if (ha->fw_dumped && !ha->fw_dump_reading) { 57 if (ha->fw_dumped && !ha->fw_dump_reading) {
59 ha->fw_dump_reading = 1; 58 ha->fw_dump_reading = 1;
60 59
61 if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
62 dump_size = FW_DUMP_SIZE_24XX;
63 else {
64 dump_size = FW_DUMP_SIZE_1M;
65 if (ha->fw_memory_size < 0x20000)
66 dump_size = FW_DUMP_SIZE_128K;
67 else if (ha->fw_memory_size < 0x80000)
68 dump_size = FW_DUMP_SIZE_512K;
69 }
70 ha->fw_dump_buffer = (char *)vmalloc(dump_size);
71 if (ha->fw_dump_buffer == NULL) {
72 qla_printk(KERN_WARNING, ha,
73 "Unable to allocate memory for firmware "
74 "dump buffer (%d).\n", dump_size);
75
76 ha->fw_dump_reading = 0;
77 return (count);
78 }
79 qla_printk(KERN_INFO, ha, 60 qla_printk(KERN_INFO, ha,
80 "Firmware dump ready for read on (%ld).\n", 61 "Raw firmware dump ready for read on (%ld).\n",
81 ha->host_no); 62 ha->host_no);
82 memset(ha->fw_dump_buffer, 0, dump_size);
83 ha->isp_ops.ascii_fw_dump(ha);
84 ha->fw_dump_buffer_len = strlen(ha->fw_dump_buffer);
85 } 63 }
86 break; 64 break;
65 case 2:
66 qla2x00_alloc_fw_dump(ha);
67 break;
87 } 68 }
88 return (count); 69 return (count);
89} 70}
@@ -313,9 +294,6 @@ qla2x00_sysfs_read_vpd(struct kobject *kobj, char *buf, loff_t off,
313 if (!capable(CAP_SYS_ADMIN) || off != 0) 294 if (!capable(CAP_SYS_ADMIN) || off != 0)
314 return 0; 295 return 0;
315 296
316 if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha))
317 return -ENOTSUPP;
318
319 /* Read NVRAM. */ 297 /* Read NVRAM. */
320 spin_lock_irqsave(&ha->hardware_lock, flags); 298 spin_lock_irqsave(&ha->hardware_lock, flags);
321 ha->isp_ops.read_nvram(ha, (uint8_t *)buf, ha->vpd_base, ha->vpd_size); 299 ha->isp_ops.read_nvram(ha, (uint8_t *)buf, ha->vpd_base, ha->vpd_size);
@@ -335,9 +313,6 @@ qla2x00_sysfs_write_vpd(struct kobject *kobj, char *buf, loff_t off,
335 if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->vpd_size) 313 if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->vpd_size)
336 return 0; 314 return 0;
337 315
338 if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha))
339 return -ENOTSUPP;
340
341 /* Write NVRAM. */ 316 /* Write NVRAM. */
342 spin_lock_irqsave(&ha->hardware_lock, flags); 317 spin_lock_irqsave(&ha->hardware_lock, flags);
343 ha->isp_ops.write_nvram(ha, (uint8_t *)buf, ha->vpd_base, count); 318 ha->isp_ops.write_nvram(ha, (uint8_t *)buf, ha->vpd_base, count);
@@ -357,6 +332,53 @@ static struct bin_attribute sysfs_vpd_attr = {
357 .write = qla2x00_sysfs_write_vpd, 332 .write = qla2x00_sysfs_write_vpd,
358}; 333};
359 334
335static ssize_t
336qla2x00_sysfs_read_sfp(struct kobject *kobj, char *buf, loff_t off,
337 size_t count)
338{
339 struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
340 struct device, kobj)));
341 uint16_t iter, addr, offset;
342 int rval;
343
344 if (!capable(CAP_SYS_ADMIN) || off != 0 || count != SFP_DEV_SIZE * 2)
345 return 0;
346
347 addr = 0xa0;
348 for (iter = 0, offset = 0; iter < (SFP_DEV_SIZE * 2) / SFP_BLOCK_SIZE;
349 iter++, offset += SFP_BLOCK_SIZE) {
350 if (iter == 4) {
351 /* Skip to next device address. */
352 addr = 0xa2;
353 offset = 0;
354 }
355
356 rval = qla2x00_read_sfp(ha, ha->sfp_data_dma, addr, offset,
357 SFP_BLOCK_SIZE);
358 if (rval != QLA_SUCCESS) {
359 qla_printk(KERN_WARNING, ha,
360 "Unable to read SFP data (%x/%x/%x).\n", rval,
361 addr, offset);
362 count = 0;
363 break;
364 }
365 memcpy(buf, ha->sfp_data, SFP_BLOCK_SIZE);
366 buf += SFP_BLOCK_SIZE;
367 }
368
369 return count;
370}
371
372static struct bin_attribute sysfs_sfp_attr = {
373 .attr = {
374 .name = "sfp",
375 .mode = S_IRUSR | S_IWUSR,
376 .owner = THIS_MODULE,
377 },
378 .size = SFP_DEV_SIZE * 2,
379 .read = qla2x00_sysfs_read_sfp,
380};
381
360void 382void
361qla2x00_alloc_sysfs_attr(scsi_qla_host_t *ha) 383qla2x00_alloc_sysfs_attr(scsi_qla_host_t *ha)
362{ 384{
@@ -367,7 +389,12 @@ qla2x00_alloc_sysfs_attr(scsi_qla_host_t *ha)
367 sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_optrom_attr); 389 sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_optrom_attr);
368 sysfs_create_bin_file(&host->shost_gendev.kobj, 390 sysfs_create_bin_file(&host->shost_gendev.kobj,
369 &sysfs_optrom_ctl_attr); 391 &sysfs_optrom_ctl_attr);
370 sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_vpd_attr); 392 if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
393 sysfs_create_bin_file(&host->shost_gendev.kobj,
394 &sysfs_vpd_attr);
395 sysfs_create_bin_file(&host->shost_gendev.kobj,
396 &sysfs_sfp_attr);
397 }
371} 398}
372 399
373void 400void
@@ -380,7 +407,12 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *ha)
380 sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_optrom_attr); 407 sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_optrom_attr);
381 sysfs_remove_bin_file(&host->shost_gendev.kobj, 408 sysfs_remove_bin_file(&host->shost_gendev.kobj,
382 &sysfs_optrom_ctl_attr); 409 &sysfs_optrom_ctl_attr);
383 sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_vpd_attr); 410 if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
411 sysfs_remove_bin_file(&host->shost_gendev.kobj,
412 &sysfs_vpd_attr);
413 sysfs_remove_bin_file(&host->shost_gendev.kobj,
414 &sysfs_sfp_attr);
415 }
384 416
385 if (ha->beacon_blink_led == 1) 417 if (ha->beacon_blink_led == 1)
386 ha->isp_ops.beacon_off(ha); 418 ha->isp_ops.beacon_off(ha);