diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_attr.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_attr.c | 147 |
1 files changed, 131 insertions, 16 deletions
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 5ab953029f8..1c28215f8be 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * QLogic Fibre Channel HBA Driver | 2 | * QLogic Fibre Channel HBA Driver |
3 | * Copyright (c) 2003-2011 QLogic Corporation | 3 | * Copyright (c) 2003-2012 QLogic Corporation |
4 | * | 4 | * |
5 | * See LICENSE.qla2xxx for copyright and licensing details. | 5 | * See LICENSE.qla2xxx for copyright and licensing details. |
6 | */ | 6 | */ |
@@ -26,7 +26,7 @@ qla2x00_sysfs_read_fw_dump(struct file *filp, struct kobject *kobj, | |||
26 | struct qla_hw_data *ha = vha->hw; | 26 | struct qla_hw_data *ha = vha->hw; |
27 | int rval = 0; | 27 | int rval = 0; |
28 | 28 | ||
29 | if (ha->fw_dump_reading == 0) | 29 | if (!(ha->fw_dump_reading || ha->mctp_dump_reading)) |
30 | return 0; | 30 | return 0; |
31 | 31 | ||
32 | if (IS_QLA82XX(ha)) { | 32 | if (IS_QLA82XX(ha)) { |
@@ -39,9 +39,14 @@ qla2x00_sysfs_read_fw_dump(struct file *filp, struct kobject *kobj, | |||
39 | rval = memory_read_from_buffer(buf, count, | 39 | rval = memory_read_from_buffer(buf, count, |
40 | &off, ha->md_dump, ha->md_dump_size); | 40 | &off, ha->md_dump, ha->md_dump_size); |
41 | return rval; | 41 | return rval; |
42 | } else | 42 | } else if (ha->mctp_dumped && ha->mctp_dump_reading) |
43 | return memory_read_from_buffer(buf, count, &off, ha->mctp_dump, | ||
44 | MCTP_DUMP_SIZE); | ||
45 | else if (ha->fw_dump_reading) | ||
43 | return memory_read_from_buffer(buf, count, &off, ha->fw_dump, | 46 | return memory_read_from_buffer(buf, count, &off, ha->fw_dump, |
44 | ha->fw_dump_len); | 47 | ha->fw_dump_len); |
48 | else | ||
49 | return 0; | ||
45 | } | 50 | } |
46 | 51 | ||
47 | static ssize_t | 52 | static ssize_t |
@@ -107,6 +112,22 @@ qla2x00_sysfs_write_fw_dump(struct file *filp, struct kobject *kobj, | |||
107 | if (IS_QLA82XX(ha)) | 112 | if (IS_QLA82XX(ha)) |
108 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); | 113 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); |
109 | break; | 114 | break; |
115 | case 6: | ||
116 | if (!ha->mctp_dump_reading) | ||
117 | break; | ||
118 | ql_log(ql_log_info, vha, 0x70c1, | ||
119 | "MCTP dump cleared on (%ld).\n", vha->host_no); | ||
120 | ha->mctp_dump_reading = 0; | ||
121 | ha->mctp_dumped = 0; | ||
122 | break; | ||
123 | case 7: | ||
124 | if (ha->mctp_dumped && !ha->mctp_dump_reading) { | ||
125 | ha->mctp_dump_reading = 1; | ||
126 | ql_log(ql_log_info, vha, 0x70c2, | ||
127 | "Raw mctp dump ready for read on (%ld).\n", | ||
128 | vha->host_no); | ||
129 | } | ||
130 | break; | ||
110 | } | 131 | } |
111 | return count; | 132 | return count; |
112 | } | 133 | } |
@@ -564,6 +585,7 @@ qla2x00_sysfs_write_reset(struct file *filp, struct kobject *kobj, | |||
564 | struct qla_hw_data *ha = vha->hw; | 585 | struct qla_hw_data *ha = vha->hw; |
565 | struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); | 586 | struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); |
566 | int type; | 587 | int type; |
588 | uint32_t idc_control; | ||
567 | 589 | ||
568 | if (off != 0) | 590 | if (off != 0) |
569 | return -EINVAL; | 591 | return -EINVAL; |
@@ -587,22 +609,36 @@ qla2x00_sysfs_write_reset(struct file *filp, struct kobject *kobj, | |||
587 | scsi_unblock_requests(vha->host); | 609 | scsi_unblock_requests(vha->host); |
588 | break; | 610 | break; |
589 | case 0x2025d: | 611 | case 0x2025d: |
590 | if (!IS_QLA81XX(ha) || !IS_QLA8031(ha)) | 612 | if (!IS_QLA81XX(ha) && !IS_QLA83XX(ha)) |
591 | return -EPERM; | 613 | return -EPERM; |
592 | 614 | ||
593 | ql_log(ql_log_info, vha, 0x706f, | 615 | ql_log(ql_log_info, vha, 0x706f, |
594 | "Issuing MPI reset.\n"); | 616 | "Issuing MPI reset.\n"); |
595 | 617 | ||
596 | /* Make sure FC side is not in reset */ | 618 | if (IS_QLA83XX(ha)) { |
597 | qla2x00_wait_for_hba_online(vha); | 619 | uint32_t idc_control; |
598 | 620 | ||
599 | /* Issue MPI reset */ | 621 | qla83xx_idc_lock(vha, 0); |
600 | scsi_block_requests(vha->host); | 622 | __qla83xx_get_idc_control(vha, &idc_control); |
601 | if (qla81xx_restart_mpi_firmware(vha) != QLA_SUCCESS) | 623 | idc_control |= QLA83XX_IDC_GRACEFUL_RESET; |
602 | ql_log(ql_log_warn, vha, 0x7070, | 624 | __qla83xx_set_idc_control(vha, idc_control); |
603 | "MPI reset failed.\n"); | 625 | qla83xx_wr_reg(vha, QLA83XX_IDC_DEV_STATE, |
604 | scsi_unblock_requests(vha->host); | 626 | QLA8XXX_DEV_NEED_RESET); |
605 | break; | 627 | qla83xx_idc_audit(vha, IDC_AUDIT_TIMESTAMP); |
628 | qla83xx_idc_unlock(vha, 0); | ||
629 | break; | ||
630 | } else { | ||
631 | /* Make sure FC side is not in reset */ | ||
632 | qla2x00_wait_for_hba_online(vha); | ||
633 | |||
634 | /* Issue MPI reset */ | ||
635 | scsi_block_requests(vha->host); | ||
636 | if (qla81xx_restart_mpi_firmware(vha) != QLA_SUCCESS) | ||
637 | ql_log(ql_log_warn, vha, 0x7070, | ||
638 | "MPI reset failed.\n"); | ||
639 | scsi_unblock_requests(vha->host); | ||
640 | break; | ||
641 | } | ||
606 | case 0x2025e: | 642 | case 0x2025e: |
607 | if (!IS_QLA82XX(ha) || vha != base_vha) { | 643 | if (!IS_QLA82XX(ha) || vha != base_vha) { |
608 | ql_log(ql_log_info, vha, 0x7071, | 644 | ql_log(ql_log_info, vha, 0x7071, |
@@ -616,6 +652,29 @@ qla2x00_sysfs_write_reset(struct file *filp, struct kobject *kobj, | |||
616 | qla2xxx_wake_dpc(vha); | 652 | qla2xxx_wake_dpc(vha); |
617 | qla2x00_wait_for_fcoe_ctx_reset(vha); | 653 | qla2x00_wait_for_fcoe_ctx_reset(vha); |
618 | break; | 654 | break; |
655 | case 0x2025f: | ||
656 | if (!IS_QLA8031(ha)) | ||
657 | return -EPERM; | ||
658 | ql_log(ql_log_info, vha, 0x70bc, | ||
659 | "Disabling Reset by IDC control\n"); | ||
660 | qla83xx_idc_lock(vha, 0); | ||
661 | __qla83xx_get_idc_control(vha, &idc_control); | ||
662 | idc_control |= QLA83XX_IDC_RESET_DISABLED; | ||
663 | __qla83xx_set_idc_control(vha, idc_control); | ||
664 | qla83xx_idc_unlock(vha, 0); | ||
665 | break; | ||
666 | case 0x20260: | ||
667 | if (!IS_QLA8031(ha)) | ||
668 | return -EPERM; | ||
669 | ql_log(ql_log_info, vha, 0x70bd, | ||
670 | "Enabling Reset by IDC control\n"); | ||
671 | qla83xx_idc_lock(vha, 0); | ||
672 | __qla83xx_get_idc_control(vha, &idc_control); | ||
673 | idc_control &= ~QLA83XX_IDC_RESET_DISABLED; | ||
674 | __qla83xx_set_idc_control(vha, idc_control); | ||
675 | qla83xx_idc_unlock(vha, 0); | ||
676 | break; | ||
677 | |||
619 | } | 678 | } |
620 | return count; | 679 | return count; |
621 | } | 680 | } |
@@ -1251,6 +1310,49 @@ qla2x00_fw_state_show(struct device *dev, struct device_attribute *attr, | |||
1251 | state[1], state[2], state[3], state[4]); | 1310 | state[1], state[2], state[3], state[4]); |
1252 | } | 1311 | } |
1253 | 1312 | ||
1313 | static ssize_t | ||
1314 | qla2x00_diag_requests_show(struct device *dev, | ||
1315 | struct device_attribute *attr, char *buf) | ||
1316 | { | ||
1317 | scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); | ||
1318 | |||
1319 | if (!IS_BIDI_CAPABLE(vha->hw)) | ||
1320 | return snprintf(buf, PAGE_SIZE, "\n"); | ||
1321 | |||
1322 | return snprintf(buf, PAGE_SIZE, "%llu\n", vha->bidi_stats.io_count); | ||
1323 | } | ||
1324 | |||
1325 | static ssize_t | ||
1326 | qla2x00_diag_megabytes_show(struct device *dev, | ||
1327 | struct device_attribute *attr, char *buf) | ||
1328 | { | ||
1329 | scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); | ||
1330 | |||
1331 | if (!IS_BIDI_CAPABLE(vha->hw)) | ||
1332 | return snprintf(buf, PAGE_SIZE, "\n"); | ||
1333 | |||
1334 | return snprintf(buf, PAGE_SIZE, "%llu\n", | ||
1335 | vha->bidi_stats.transfer_bytes >> 20); | ||
1336 | } | ||
1337 | |||
1338 | static ssize_t | ||
1339 | qla2x00_fw_dump_size_show(struct device *dev, struct device_attribute *attr, | ||
1340 | char *buf) | ||
1341 | { | ||
1342 | scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); | ||
1343 | struct qla_hw_data *ha = vha->hw; | ||
1344 | uint32_t size; | ||
1345 | |||
1346 | if (!ha->fw_dumped) | ||
1347 | size = 0; | ||
1348 | else if (IS_QLA82XX(ha)) | ||
1349 | size = ha->md_template_size + ha->md_dump_size; | ||
1350 | else | ||
1351 | size = ha->fw_dump_len; | ||
1352 | |||
1353 | return snprintf(buf, PAGE_SIZE, "%d\n", size); | ||
1354 | } | ||
1355 | |||
1254 | static DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show, NULL); | 1356 | static DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show, NULL); |
1255 | static DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL); | 1357 | static DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL); |
1256 | static DEVICE_ATTR(serial_num, S_IRUGO, qla2x00_serial_num_show, NULL); | 1358 | static DEVICE_ATTR(serial_num, S_IRUGO, qla2x00_serial_num_show, NULL); |
@@ -1289,6 +1391,9 @@ static DEVICE_ATTR(vn_port_mac_address, S_IRUGO, | |||
1289 | static DEVICE_ATTR(fabric_param, S_IRUGO, qla2x00_fabric_param_show, NULL); | 1391 | static DEVICE_ATTR(fabric_param, S_IRUGO, qla2x00_fabric_param_show, NULL); |
1290 | static DEVICE_ATTR(fw_state, S_IRUGO, qla2x00_fw_state_show, NULL); | 1392 | static DEVICE_ATTR(fw_state, S_IRUGO, qla2x00_fw_state_show, NULL); |
1291 | static DEVICE_ATTR(thermal_temp, S_IRUGO, qla2x00_thermal_temp_show, NULL); | 1393 | static DEVICE_ATTR(thermal_temp, S_IRUGO, qla2x00_thermal_temp_show, NULL); |
1394 | static DEVICE_ATTR(diag_requests, S_IRUGO, qla2x00_diag_requests_show, NULL); | ||
1395 | static DEVICE_ATTR(diag_megabytes, S_IRUGO, qla2x00_diag_megabytes_show, NULL); | ||
1396 | static DEVICE_ATTR(fw_dump_size, S_IRUGO, qla2x00_fw_dump_size_show, NULL); | ||
1292 | 1397 | ||
1293 | struct device_attribute *qla2x00_host_attrs[] = { | 1398 | struct device_attribute *qla2x00_host_attrs[] = { |
1294 | &dev_attr_driver_version, | 1399 | &dev_attr_driver_version, |
@@ -1318,6 +1423,9 @@ struct device_attribute *qla2x00_host_attrs[] = { | |||
1318 | &dev_attr_fw_state, | 1423 | &dev_attr_fw_state, |
1319 | &dev_attr_optrom_gold_fw_version, | 1424 | &dev_attr_optrom_gold_fw_version, |
1320 | &dev_attr_thermal_temp, | 1425 | &dev_attr_thermal_temp, |
1426 | &dev_attr_diag_requests, | ||
1427 | &dev_attr_diag_megabytes, | ||
1428 | &dev_attr_fw_dump_size, | ||
1321 | NULL, | 1429 | NULL, |
1322 | }; | 1430 | }; |
1323 | 1431 | ||
@@ -1704,7 +1812,7 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable) | |||
1704 | 1812 | ||
1705 | if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif) { | 1813 | if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif) { |
1706 | if (ha->fw_attributes & BIT_4) { | 1814 | if (ha->fw_attributes & BIT_4) { |
1707 | int prot = 0; | 1815 | int prot = 0, guard; |
1708 | vha->flags.difdix_supported = 1; | 1816 | vha->flags.difdix_supported = 1; |
1709 | ql_dbg(ql_dbg_user, vha, 0x7082, | 1817 | ql_dbg(ql_dbg_user, vha, 0x7082, |
1710 | "Registered for DIF/DIX type 1 and 3 protection.\n"); | 1818 | "Registered for DIF/DIX type 1 and 3 protection.\n"); |
@@ -1717,7 +1825,14 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable) | |||
1717 | | SHOST_DIX_TYPE1_PROTECTION | 1825 | | SHOST_DIX_TYPE1_PROTECTION |
1718 | | SHOST_DIX_TYPE2_PROTECTION | 1826 | | SHOST_DIX_TYPE2_PROTECTION |
1719 | | SHOST_DIX_TYPE3_PROTECTION); | 1827 | | SHOST_DIX_TYPE3_PROTECTION); |
1720 | scsi_host_set_guard(vha->host, SHOST_DIX_GUARD_CRC); | 1828 | |
1829 | guard = SHOST_DIX_GUARD_CRC; | ||
1830 | |||
1831 | if (IS_PI_IPGUARD_CAPABLE(ha) && | ||
1832 | (ql2xenabledif > 1 || IS_PI_DIFB_DIX0_CAPABLE(ha))) | ||
1833 | guard |= SHOST_DIX_GUARD_IP; | ||
1834 | |||
1835 | scsi_host_set_guard(vha->host, guard); | ||
1721 | } else | 1836 | } else |
1722 | vha->flags.difdix_supported = 0; | 1837 | vha->flags.difdix_supported = 0; |
1723 | } | 1838 | } |