diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_attr.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_attr.c | 227 |
1 files changed, 208 insertions, 19 deletions
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index b09993a06576..0f8796201504 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c | |||
@@ -97,7 +97,7 @@ qla2x00_sysfs_read_nvram(struct kobject *kobj, | |||
97 | return 0; | 97 | return 0; |
98 | 98 | ||
99 | if (IS_NOCACHE_VPD_TYPE(ha)) | 99 | if (IS_NOCACHE_VPD_TYPE(ha)) |
100 | ha->isp_ops->read_optrom(vha, ha->vpd, ha->flt_region_nvram << 2, | 100 | ha->isp_ops->read_optrom(vha, ha->nvram, ha->flt_region_nvram << 2, |
101 | ha->nvram_size); | 101 | ha->nvram_size); |
102 | return memory_read_from_buffer(buf, count, &off, ha->nvram, | 102 | return memory_read_from_buffer(buf, count, &off, ha->nvram, |
103 | ha->nvram_size); | 103 | ha->nvram_size); |
@@ -692,6 +692,109 @@ static struct bin_attribute sysfs_edc_status_attr = { | |||
692 | .read = qla2x00_sysfs_read_edc_status, | 692 | .read = qla2x00_sysfs_read_edc_status, |
693 | }; | 693 | }; |
694 | 694 | ||
695 | static ssize_t | ||
696 | qla2x00_sysfs_read_xgmac_stats(struct kobject *kobj, | ||
697 | struct bin_attribute *bin_attr, | ||
698 | char *buf, loff_t off, size_t count) | ||
699 | { | ||
700 | struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj, | ||
701 | struct device, kobj))); | ||
702 | struct qla_hw_data *ha = vha->hw; | ||
703 | int rval; | ||
704 | uint16_t actual_size; | ||
705 | |||
706 | if (!capable(CAP_SYS_ADMIN) || off != 0 || count > XGMAC_DATA_SIZE) | ||
707 | return 0; | ||
708 | |||
709 | if (ha->xgmac_data) | ||
710 | goto do_read; | ||
711 | |||
712 | ha->xgmac_data = dma_alloc_coherent(&ha->pdev->dev, XGMAC_DATA_SIZE, | ||
713 | &ha->xgmac_data_dma, GFP_KERNEL); | ||
714 | if (!ha->xgmac_data) { | ||
715 | qla_printk(KERN_WARNING, ha, | ||
716 | "Unable to allocate memory for XGMAC read-data.\n"); | ||
717 | return 0; | ||
718 | } | ||
719 | |||
720 | do_read: | ||
721 | actual_size = 0; | ||
722 | memset(ha->xgmac_data, 0, XGMAC_DATA_SIZE); | ||
723 | |||
724 | rval = qla2x00_get_xgmac_stats(vha, ha->xgmac_data_dma, | ||
725 | XGMAC_DATA_SIZE, &actual_size); | ||
726 | if (rval != QLA_SUCCESS) { | ||
727 | qla_printk(KERN_WARNING, ha, | ||
728 | "Unable to read XGMAC data (%x).\n", rval); | ||
729 | count = 0; | ||
730 | } | ||
731 | |||
732 | count = actual_size > count ? count: actual_size; | ||
733 | memcpy(buf, ha->xgmac_data, count); | ||
734 | |||
735 | return count; | ||
736 | } | ||
737 | |||
738 | static struct bin_attribute sysfs_xgmac_stats_attr = { | ||
739 | .attr = { | ||
740 | .name = "xgmac_stats", | ||
741 | .mode = S_IRUSR, | ||
742 | }, | ||
743 | .size = 0, | ||
744 | .read = qla2x00_sysfs_read_xgmac_stats, | ||
745 | }; | ||
746 | |||
747 | static ssize_t | ||
748 | qla2x00_sysfs_read_dcbx_tlv(struct kobject *kobj, | ||
749 | struct bin_attribute *bin_attr, | ||
750 | char *buf, loff_t off, size_t count) | ||
751 | { | ||
752 | struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj, | ||
753 | struct device, kobj))); | ||
754 | struct qla_hw_data *ha = vha->hw; | ||
755 | int rval; | ||
756 | uint16_t actual_size; | ||
757 | |||
758 | if (!capable(CAP_SYS_ADMIN) || off != 0 || count > DCBX_TLV_DATA_SIZE) | ||
759 | return 0; | ||
760 | |||
761 | if (ha->dcbx_tlv) | ||
762 | goto do_read; | ||
763 | |||
764 | ha->dcbx_tlv = dma_alloc_coherent(&ha->pdev->dev, DCBX_TLV_DATA_SIZE, | ||
765 | &ha->dcbx_tlv_dma, GFP_KERNEL); | ||
766 | if (!ha->dcbx_tlv) { | ||
767 | qla_printk(KERN_WARNING, ha, | ||
768 | "Unable to allocate memory for DCBX TLV read-data.\n"); | ||
769 | return 0; | ||
770 | } | ||
771 | |||
772 | do_read: | ||
773 | actual_size = 0; | ||
774 | memset(ha->dcbx_tlv, 0, DCBX_TLV_DATA_SIZE); | ||
775 | |||
776 | rval = qla2x00_get_dcbx_params(vha, ha->dcbx_tlv_dma, | ||
777 | DCBX_TLV_DATA_SIZE); | ||
778 | if (rval != QLA_SUCCESS) { | ||
779 | qla_printk(KERN_WARNING, ha, | ||
780 | "Unable to read DCBX TLV data (%x).\n", rval); | ||
781 | count = 0; | ||
782 | } | ||
783 | |||
784 | memcpy(buf, ha->dcbx_tlv, count); | ||
785 | |||
786 | return count; | ||
787 | } | ||
788 | |||
789 | static struct bin_attribute sysfs_dcbx_tlv_attr = { | ||
790 | .attr = { | ||
791 | .name = "dcbx_tlv", | ||
792 | .mode = S_IRUSR, | ||
793 | }, | ||
794 | .size = 0, | ||
795 | .read = qla2x00_sysfs_read_dcbx_tlv, | ||
796 | }; | ||
797 | |||
695 | static struct sysfs_entry { | 798 | static struct sysfs_entry { |
696 | char *name; | 799 | char *name; |
697 | struct bin_attribute *attr; | 800 | struct bin_attribute *attr; |
@@ -706,6 +809,8 @@ static struct sysfs_entry { | |||
706 | { "reset", &sysfs_reset_attr, }, | 809 | { "reset", &sysfs_reset_attr, }, |
707 | { "edc", &sysfs_edc_attr, 2 }, | 810 | { "edc", &sysfs_edc_attr, 2 }, |
708 | { "edc_status", &sysfs_edc_status_attr, 2 }, | 811 | { "edc_status", &sysfs_edc_status_attr, 2 }, |
812 | { "xgmac_stats", &sysfs_xgmac_stats_attr, 3 }, | ||
813 | { "dcbx_tlv", &sysfs_dcbx_tlv_attr, 3 }, | ||
709 | { NULL }, | 814 | { NULL }, |
710 | }; | 815 | }; |
711 | 816 | ||
@@ -721,6 +826,8 @@ qla2x00_alloc_sysfs_attr(scsi_qla_host_t *vha) | |||
721 | continue; | 826 | continue; |
722 | if (iter->is4GBp_only == 2 && !IS_QLA25XX(vha->hw)) | 827 | if (iter->is4GBp_only == 2 && !IS_QLA25XX(vha->hw)) |
723 | continue; | 828 | continue; |
829 | if (iter->is4GBp_only == 3 && !IS_QLA81XX(vha->hw)) | ||
830 | continue; | ||
724 | 831 | ||
725 | ret = sysfs_create_bin_file(&host->shost_gendev.kobj, | 832 | ret = sysfs_create_bin_file(&host->shost_gendev.kobj, |
726 | iter->attr); | 833 | iter->attr); |
@@ -743,6 +850,8 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *vha) | |||
743 | continue; | 850 | continue; |
744 | if (iter->is4GBp_only == 2 && !IS_QLA25XX(ha)) | 851 | if (iter->is4GBp_only == 2 && !IS_QLA25XX(ha)) |
745 | continue; | 852 | continue; |
853 | if (iter->is4GBp_only == 3 && !IS_QLA81XX(ha)) | ||
854 | continue; | ||
746 | 855 | ||
747 | sysfs_remove_bin_file(&host->shost_gendev.kobj, | 856 | sysfs_remove_bin_file(&host->shost_gendev.kobj, |
748 | iter->attr); | 857 | iter->attr); |
@@ -1088,6 +1197,58 @@ qla2x00_flash_block_size_show(struct device *dev, | |||
1088 | return snprintf(buf, PAGE_SIZE, "0x%x\n", ha->fdt_block_size); | 1197 | return snprintf(buf, PAGE_SIZE, "0x%x\n", ha->fdt_block_size); |
1089 | } | 1198 | } |
1090 | 1199 | ||
1200 | static ssize_t | ||
1201 | qla2x00_vlan_id_show(struct device *dev, struct device_attribute *attr, | ||
1202 | char *buf) | ||
1203 | { | ||
1204 | scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); | ||
1205 | |||
1206 | if (!IS_QLA81XX(vha->hw)) | ||
1207 | return snprintf(buf, PAGE_SIZE, "\n"); | ||
1208 | |||
1209 | return snprintf(buf, PAGE_SIZE, "%d\n", vha->fcoe_vlan_id); | ||
1210 | } | ||
1211 | |||
1212 | static ssize_t | ||
1213 | qla2x00_vn_port_mac_address_show(struct device *dev, | ||
1214 | struct device_attribute *attr, char *buf) | ||
1215 | { | ||
1216 | scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); | ||
1217 | |||
1218 | if (!IS_QLA81XX(vha->hw)) | ||
1219 | return snprintf(buf, PAGE_SIZE, "\n"); | ||
1220 | |||
1221 | return snprintf(buf, PAGE_SIZE, "%02x:%02x:%02x:%02x:%02x:%02x\n", | ||
1222 | vha->fcoe_vn_port_mac[5], vha->fcoe_vn_port_mac[4], | ||
1223 | vha->fcoe_vn_port_mac[3], vha->fcoe_vn_port_mac[2], | ||
1224 | vha->fcoe_vn_port_mac[1], vha->fcoe_vn_port_mac[0]); | ||
1225 | } | ||
1226 | |||
1227 | static ssize_t | ||
1228 | qla2x00_fabric_param_show(struct device *dev, struct device_attribute *attr, | ||
1229 | char *buf) | ||
1230 | { | ||
1231 | scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); | ||
1232 | |||
1233 | return snprintf(buf, PAGE_SIZE, "%d\n", vha->hw->switch_cap); | ||
1234 | } | ||
1235 | |||
1236 | static ssize_t | ||
1237 | qla2x00_fw_state_show(struct device *dev, struct device_attribute *attr, | ||
1238 | char *buf) | ||
1239 | { | ||
1240 | scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); | ||
1241 | int rval; | ||
1242 | uint16_t state[5]; | ||
1243 | |||
1244 | rval = qla2x00_get_firmware_state(vha, state); | ||
1245 | if (rval != QLA_SUCCESS) | ||
1246 | memset(state, -1, sizeof(state)); | ||
1247 | |||
1248 | return snprintf(buf, PAGE_SIZE, "0x%x 0x%x 0x%x 0x%x 0x%x\n", state[0], | ||
1249 | state[1], state[2], state[3], state[4]); | ||
1250 | } | ||
1251 | |||
1091 | static DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show, NULL); | 1252 | static DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show, NULL); |
1092 | static DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL); | 1253 | static DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL); |
1093 | static DEVICE_ATTR(serial_num, S_IRUGO, qla2x00_serial_num_show, NULL); | 1254 | static DEVICE_ATTR(serial_num, S_IRUGO, qla2x00_serial_num_show, NULL); |
@@ -1116,6 +1277,11 @@ static DEVICE_ATTR(mpi_version, S_IRUGO, qla2x00_mpi_version_show, NULL); | |||
1116 | static DEVICE_ATTR(phy_version, S_IRUGO, qla2x00_phy_version_show, NULL); | 1277 | static DEVICE_ATTR(phy_version, S_IRUGO, qla2x00_phy_version_show, NULL); |
1117 | static DEVICE_ATTR(flash_block_size, S_IRUGO, qla2x00_flash_block_size_show, | 1278 | static DEVICE_ATTR(flash_block_size, S_IRUGO, qla2x00_flash_block_size_show, |
1118 | NULL); | 1279 | NULL); |
1280 | static DEVICE_ATTR(vlan_id, S_IRUGO, qla2x00_vlan_id_show, NULL); | ||
1281 | static DEVICE_ATTR(vn_port_mac_address, S_IRUGO, | ||
1282 | qla2x00_vn_port_mac_address_show, NULL); | ||
1283 | static DEVICE_ATTR(fabric_param, S_IRUGO, qla2x00_fabric_param_show, NULL); | ||
1284 | static DEVICE_ATTR(fw_state, S_IRUGO, qla2x00_fw_state_show, NULL); | ||
1119 | 1285 | ||
1120 | struct device_attribute *qla2x00_host_attrs[] = { | 1286 | struct device_attribute *qla2x00_host_attrs[] = { |
1121 | &dev_attr_driver_version, | 1287 | &dev_attr_driver_version, |
@@ -1138,6 +1304,10 @@ struct device_attribute *qla2x00_host_attrs[] = { | |||
1138 | &dev_attr_mpi_version, | 1304 | &dev_attr_mpi_version, |
1139 | &dev_attr_phy_version, | 1305 | &dev_attr_phy_version, |
1140 | &dev_attr_flash_block_size, | 1306 | &dev_attr_flash_block_size, |
1307 | &dev_attr_vlan_id, | ||
1308 | &dev_attr_vn_port_mac_address, | ||
1309 | &dev_attr_fabric_param, | ||
1310 | &dev_attr_fw_state, | ||
1141 | NULL, | 1311 | NULL, |
1142 | }; | 1312 | }; |
1143 | 1313 | ||
@@ -1313,7 +1483,8 @@ qla2x00_terminate_rport_io(struct fc_rport *rport) | |||
1313 | * At this point all fcport's software-states are cleared. Perform any | 1483 | * At this point all fcport's software-states are cleared. Perform any |
1314 | * final cleanup of firmware resources (PCBs and XCBs). | 1484 | * final cleanup of firmware resources (PCBs and XCBs). |
1315 | */ | 1485 | */ |
1316 | if (fcport->loop_id != FC_NO_LOOP_ID) | 1486 | if (fcport->loop_id != FC_NO_LOOP_ID && |
1487 | !test_bit(UNLOADING, &fcport->vha->dpc_flags)) | ||
1317 | fcport->vha->hw->isp_ops->fabric_logout(fcport->vha, | 1488 | fcport->vha->hw->isp_ops->fabric_logout(fcport->vha, |
1318 | fcport->loop_id, fcport->d_id.b.domain, | 1489 | fcport->loop_id, fcport->d_id.b.domain, |
1319 | fcport->d_id.b.area, fcport->d_id.b.al_pa); | 1490 | fcport->d_id.b.area, fcport->d_id.b.al_pa); |
@@ -1437,11 +1608,13 @@ static int | |||
1437 | qla24xx_vport_create(struct fc_vport *fc_vport, bool disable) | 1608 | qla24xx_vport_create(struct fc_vport *fc_vport, bool disable) |
1438 | { | 1609 | { |
1439 | int ret = 0; | 1610 | int ret = 0; |
1440 | int cnt = 0; | 1611 | uint8_t qos = 0; |
1441 | uint8_t qos = QLA_DEFAULT_QUE_QOS; | ||
1442 | scsi_qla_host_t *base_vha = shost_priv(fc_vport->shost); | 1612 | scsi_qla_host_t *base_vha = shost_priv(fc_vport->shost); |
1443 | scsi_qla_host_t *vha = NULL; | 1613 | scsi_qla_host_t *vha = NULL; |
1444 | struct qla_hw_data *ha = base_vha->hw; | 1614 | struct qla_hw_data *ha = base_vha->hw; |
1615 | uint16_t options = 0; | ||
1616 | int cnt; | ||
1617 | struct req_que *req = ha->req_q_map[0]; | ||
1445 | 1618 | ||
1446 | ret = qla24xx_vport_create_req_sanity_check(fc_vport); | 1619 | ret = qla24xx_vport_create_req_sanity_check(fc_vport); |
1447 | if (ret) { | 1620 | if (ret) { |
@@ -1497,23 +1670,39 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable) | |||
1497 | 1670 | ||
1498 | qla24xx_vport_disable(fc_vport, disable); | 1671 | qla24xx_vport_disable(fc_vport, disable); |
1499 | 1672 | ||
1500 | /* Create a queue pair for the vport */ | 1673 | if (ql2xmultique_tag) { |
1501 | if (ha->mqenable) { | 1674 | req = ha->req_q_map[1]; |
1502 | if (ha->npiv_info) { | 1675 | goto vport_queue; |
1503 | for (; cnt < ha->nvram_npiv_size; cnt++) { | 1676 | } else if (ql2xmaxqueues == 1 || !ha->npiv_info) |
1504 | if (ha->npiv_info[cnt].port_name == | 1677 | goto vport_queue; |
1505 | vha->port_name && | 1678 | /* Create a request queue in QoS mode for the vport */ |
1506 | ha->npiv_info[cnt].node_name == | 1679 | for (cnt = 0; cnt < ha->nvram_npiv_size; cnt++) { |
1507 | vha->node_name) { | 1680 | if (memcmp(ha->npiv_info[cnt].port_name, vha->port_name, 8) == 0 |
1508 | qos = ha->npiv_info[cnt].q_qos; | 1681 | && memcmp(ha->npiv_info[cnt].node_name, vha->node_name, |
1509 | break; | 1682 | 8) == 0) { |
1510 | } | 1683 | qos = ha->npiv_info[cnt].q_qos; |
1511 | } | 1684 | break; |
1685 | } | ||
1686 | } | ||
1687 | if (qos) { | ||
1688 | ret = qla25xx_create_req_que(ha, options, vha->vp_idx, 0, 0, | ||
1689 | qos); | ||
1690 | if (!ret) | ||
1691 | qla_printk(KERN_WARNING, ha, | ||
1692 | "Can't create request queue for vp_idx:%d\n", | ||
1693 | vha->vp_idx); | ||
1694 | else { | ||
1695 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
1696 | "Request Que:%d (QoS: %d) created for vp_idx:%d\n", | ||
1697 | ret, qos, vha->vp_idx)); | ||
1698 | req = ha->req_q_map[ret]; | ||
1512 | } | 1699 | } |
1513 | qla25xx_create_queues(vha, qos); | ||
1514 | } | 1700 | } |
1515 | 1701 | ||
1702 | vport_queue: | ||
1703 | vha->req = req; | ||
1516 | return 0; | 1704 | return 0; |
1705 | |||
1517 | vport_create_failed_2: | 1706 | vport_create_failed_2: |
1518 | qla24xx_disable_vp(vha); | 1707 | qla24xx_disable_vp(vha); |
1519 | qla24xx_deallocate_vp_id(vha); | 1708 | qla24xx_deallocate_vp_id(vha); |
@@ -1554,8 +1743,8 @@ qla24xx_vport_delete(struct fc_vport *fc_vport) | |||
1554 | vha->host_no, vha->vp_idx, vha)); | 1743 | vha->host_no, vha->vp_idx, vha)); |
1555 | } | 1744 | } |
1556 | 1745 | ||
1557 | if (ha->mqenable) { | 1746 | if (vha->req->id && !ql2xmultique_tag) { |
1558 | if (qla25xx_delete_queues(vha, 0) != QLA_SUCCESS) | 1747 | if (qla25xx_delete_req_que(vha, vha->req) != QLA_SUCCESS) |
1559 | qla_printk(KERN_WARNING, ha, | 1748 | qla_printk(KERN_WARNING, ha, |
1560 | "Queue delete failed.\n"); | 1749 | "Queue delete failed.\n"); |
1561 | } | 1750 | } |