18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * QLogic Fibre Channel HBA Driver 48c2ecf20Sopenharmony_ci * Copyright (c) 2003-2014 QLogic Corporation 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci#include "qla_def.h" 78c2ecf20Sopenharmony_ci#include "qla_target.h" 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/kthread.h> 108c2ecf20Sopenharmony_ci#include <linux/vmalloc.h> 118c2ecf20Sopenharmony_ci#include <linux/slab.h> 128c2ecf20Sopenharmony_ci#include <linux/delay.h> 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_cistatic int qla24xx_vport_disable(struct fc_vport *, bool); 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci/* SYSFS attributes --------------------------------------------------------- */ 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_cistatic ssize_t 198c2ecf20Sopenharmony_ciqla2x00_sysfs_read_fw_dump(struct file *filp, struct kobject *kobj, 208c2ecf20Sopenharmony_ci struct bin_attribute *bin_attr, 218c2ecf20Sopenharmony_ci char *buf, loff_t off, size_t count) 228c2ecf20Sopenharmony_ci{ 238c2ecf20Sopenharmony_ci struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj, 248c2ecf20Sopenharmony_ci struct device, kobj))); 258c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 268c2ecf20Sopenharmony_ci int rval = 0; 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci if (!(ha->fw_dump_reading || ha->mctp_dump_reading || 298c2ecf20Sopenharmony_ci ha->mpi_fw_dump_reading)) 308c2ecf20Sopenharmony_ci return 0; 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci mutex_lock(&ha->optrom_mutex); 338c2ecf20Sopenharmony_ci if (IS_P3P_TYPE(ha)) { 348c2ecf20Sopenharmony_ci if (off < ha->md_template_size) { 358c2ecf20Sopenharmony_ci rval = memory_read_from_buffer(buf, count, 368c2ecf20Sopenharmony_ci &off, ha->md_tmplt_hdr, ha->md_template_size); 378c2ecf20Sopenharmony_ci } else { 388c2ecf20Sopenharmony_ci off -= ha->md_template_size; 398c2ecf20Sopenharmony_ci rval = memory_read_from_buffer(buf, count, 408c2ecf20Sopenharmony_ci &off, ha->md_dump, ha->md_dump_size); 418c2ecf20Sopenharmony_ci } 428c2ecf20Sopenharmony_ci } else if (ha->mctp_dumped && ha->mctp_dump_reading) { 438c2ecf20Sopenharmony_ci rval = memory_read_from_buffer(buf, count, &off, ha->mctp_dump, 448c2ecf20Sopenharmony_ci MCTP_DUMP_SIZE); 458c2ecf20Sopenharmony_ci } else if (ha->mpi_fw_dumped && ha->mpi_fw_dump_reading) { 468c2ecf20Sopenharmony_ci rval = memory_read_from_buffer(buf, count, &off, 478c2ecf20Sopenharmony_ci ha->mpi_fw_dump, 488c2ecf20Sopenharmony_ci ha->mpi_fw_dump_len); 498c2ecf20Sopenharmony_ci } else if (ha->fw_dump_reading) { 508c2ecf20Sopenharmony_ci rval = memory_read_from_buffer(buf, count, &off, ha->fw_dump, 518c2ecf20Sopenharmony_ci ha->fw_dump_len); 528c2ecf20Sopenharmony_ci } else { 538c2ecf20Sopenharmony_ci rval = 0; 548c2ecf20Sopenharmony_ci } 558c2ecf20Sopenharmony_ci mutex_unlock(&ha->optrom_mutex); 568c2ecf20Sopenharmony_ci return rval; 578c2ecf20Sopenharmony_ci} 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_cistatic ssize_t 608c2ecf20Sopenharmony_ciqla2x00_sysfs_write_fw_dump(struct file *filp, struct kobject *kobj, 618c2ecf20Sopenharmony_ci struct bin_attribute *bin_attr, 628c2ecf20Sopenharmony_ci char *buf, loff_t off, size_t count) 638c2ecf20Sopenharmony_ci{ 648c2ecf20Sopenharmony_ci struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj, 658c2ecf20Sopenharmony_ci struct device, kobj))); 668c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 678c2ecf20Sopenharmony_ci int reading; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci if (off != 0) 708c2ecf20Sopenharmony_ci return (0); 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci reading = simple_strtol(buf, NULL, 10); 738c2ecf20Sopenharmony_ci switch (reading) { 748c2ecf20Sopenharmony_ci case 0: 758c2ecf20Sopenharmony_ci if (!ha->fw_dump_reading) 768c2ecf20Sopenharmony_ci break; 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x705d, 798c2ecf20Sopenharmony_ci "Firmware dump cleared on (%ld).\n", vha->host_no); 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci if (IS_P3P_TYPE(ha)) { 828c2ecf20Sopenharmony_ci qla82xx_md_free(vha); 838c2ecf20Sopenharmony_ci qla82xx_md_prep(vha); 848c2ecf20Sopenharmony_ci } 858c2ecf20Sopenharmony_ci ha->fw_dump_reading = 0; 868c2ecf20Sopenharmony_ci ha->fw_dumped = false; 878c2ecf20Sopenharmony_ci break; 888c2ecf20Sopenharmony_ci case 1: 898c2ecf20Sopenharmony_ci if (ha->fw_dumped && !ha->fw_dump_reading) { 908c2ecf20Sopenharmony_ci ha->fw_dump_reading = 1; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x705e, 938c2ecf20Sopenharmony_ci "Raw firmware dump ready for read on (%ld).\n", 948c2ecf20Sopenharmony_ci vha->host_no); 958c2ecf20Sopenharmony_ci } 968c2ecf20Sopenharmony_ci break; 978c2ecf20Sopenharmony_ci case 2: 988c2ecf20Sopenharmony_ci qla2x00_alloc_fw_dump(vha); 998c2ecf20Sopenharmony_ci break; 1008c2ecf20Sopenharmony_ci case 3: 1018c2ecf20Sopenharmony_ci if (IS_QLA82XX(ha)) { 1028c2ecf20Sopenharmony_ci qla82xx_idc_lock(ha); 1038c2ecf20Sopenharmony_ci qla82xx_set_reset_owner(vha); 1048c2ecf20Sopenharmony_ci qla82xx_idc_unlock(ha); 1058c2ecf20Sopenharmony_ci } else if (IS_QLA8044(ha)) { 1068c2ecf20Sopenharmony_ci qla8044_idc_lock(ha); 1078c2ecf20Sopenharmony_ci qla82xx_set_reset_owner(vha); 1088c2ecf20Sopenharmony_ci qla8044_idc_unlock(ha); 1098c2ecf20Sopenharmony_ci } else { 1108c2ecf20Sopenharmony_ci qla2x00_system_error(vha); 1118c2ecf20Sopenharmony_ci } 1128c2ecf20Sopenharmony_ci break; 1138c2ecf20Sopenharmony_ci case 4: 1148c2ecf20Sopenharmony_ci if (IS_P3P_TYPE(ha)) { 1158c2ecf20Sopenharmony_ci if (ha->md_tmplt_hdr) 1168c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_user, vha, 0x705b, 1178c2ecf20Sopenharmony_ci "MiniDump supported with this firmware.\n"); 1188c2ecf20Sopenharmony_ci else 1198c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_user, vha, 0x709d, 1208c2ecf20Sopenharmony_ci "MiniDump not supported with this firmware.\n"); 1218c2ecf20Sopenharmony_ci } 1228c2ecf20Sopenharmony_ci break; 1238c2ecf20Sopenharmony_ci case 5: 1248c2ecf20Sopenharmony_ci if (IS_P3P_TYPE(ha)) 1258c2ecf20Sopenharmony_ci set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); 1268c2ecf20Sopenharmony_ci break; 1278c2ecf20Sopenharmony_ci case 6: 1288c2ecf20Sopenharmony_ci if (!ha->mctp_dump_reading) 1298c2ecf20Sopenharmony_ci break; 1308c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x70c1, 1318c2ecf20Sopenharmony_ci "MCTP dump cleared on (%ld).\n", vha->host_no); 1328c2ecf20Sopenharmony_ci ha->mctp_dump_reading = 0; 1338c2ecf20Sopenharmony_ci ha->mctp_dumped = 0; 1348c2ecf20Sopenharmony_ci break; 1358c2ecf20Sopenharmony_ci case 7: 1368c2ecf20Sopenharmony_ci if (ha->mctp_dumped && !ha->mctp_dump_reading) { 1378c2ecf20Sopenharmony_ci ha->mctp_dump_reading = 1; 1388c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x70c2, 1398c2ecf20Sopenharmony_ci "Raw mctp dump ready for read on (%ld).\n", 1408c2ecf20Sopenharmony_ci vha->host_no); 1418c2ecf20Sopenharmony_ci } 1428c2ecf20Sopenharmony_ci break; 1438c2ecf20Sopenharmony_ci case 8: 1448c2ecf20Sopenharmony_ci if (!ha->mpi_fw_dump_reading) 1458c2ecf20Sopenharmony_ci break; 1468c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x70e7, 1478c2ecf20Sopenharmony_ci "MPI firmware dump cleared on (%ld).\n", vha->host_no); 1488c2ecf20Sopenharmony_ci ha->mpi_fw_dump_reading = 0; 1498c2ecf20Sopenharmony_ci ha->mpi_fw_dumped = 0; 1508c2ecf20Sopenharmony_ci break; 1518c2ecf20Sopenharmony_ci case 9: 1528c2ecf20Sopenharmony_ci if (ha->mpi_fw_dumped && !ha->mpi_fw_dump_reading) { 1538c2ecf20Sopenharmony_ci ha->mpi_fw_dump_reading = 1; 1548c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x70e8, 1558c2ecf20Sopenharmony_ci "Raw MPI firmware dump ready for read on (%ld).\n", 1568c2ecf20Sopenharmony_ci vha->host_no); 1578c2ecf20Sopenharmony_ci } 1588c2ecf20Sopenharmony_ci break; 1598c2ecf20Sopenharmony_ci case 10: 1608c2ecf20Sopenharmony_ci if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { 1618c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x70e9, 1628c2ecf20Sopenharmony_ci "Issuing MPI firmware dump on host#%ld.\n", 1638c2ecf20Sopenharmony_ci vha->host_no); 1648c2ecf20Sopenharmony_ci ha->isp_ops->mpi_fw_dump(vha, 0); 1658c2ecf20Sopenharmony_ci } 1668c2ecf20Sopenharmony_ci break; 1678c2ecf20Sopenharmony_ci } 1688c2ecf20Sopenharmony_ci return count; 1698c2ecf20Sopenharmony_ci} 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_cistatic struct bin_attribute sysfs_fw_dump_attr = { 1728c2ecf20Sopenharmony_ci .attr = { 1738c2ecf20Sopenharmony_ci .name = "fw_dump", 1748c2ecf20Sopenharmony_ci .mode = S_IRUSR | S_IWUSR, 1758c2ecf20Sopenharmony_ci }, 1768c2ecf20Sopenharmony_ci .size = 0, 1778c2ecf20Sopenharmony_ci .read = qla2x00_sysfs_read_fw_dump, 1788c2ecf20Sopenharmony_ci .write = qla2x00_sysfs_write_fw_dump, 1798c2ecf20Sopenharmony_ci}; 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_cistatic ssize_t 1828c2ecf20Sopenharmony_ciqla2x00_sysfs_read_nvram(struct file *filp, struct kobject *kobj, 1838c2ecf20Sopenharmony_ci struct bin_attribute *bin_attr, 1848c2ecf20Sopenharmony_ci char *buf, loff_t off, size_t count) 1858c2ecf20Sopenharmony_ci{ 1868c2ecf20Sopenharmony_ci struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj, 1878c2ecf20Sopenharmony_ci struct device, kobj))); 1888c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 1898c2ecf20Sopenharmony_ci uint32_t faddr; 1908c2ecf20Sopenharmony_ci struct active_regions active_regions = { }; 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci if (!capable(CAP_SYS_ADMIN)) 1938c2ecf20Sopenharmony_ci return 0; 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci mutex_lock(&ha->optrom_mutex); 1968c2ecf20Sopenharmony_ci if (qla2x00_chip_is_down(vha)) { 1978c2ecf20Sopenharmony_ci mutex_unlock(&ha->optrom_mutex); 1988c2ecf20Sopenharmony_ci return -EAGAIN; 1998c2ecf20Sopenharmony_ci } 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci if (!IS_NOCACHE_VPD_TYPE(ha)) { 2028c2ecf20Sopenharmony_ci mutex_unlock(&ha->optrom_mutex); 2038c2ecf20Sopenharmony_ci goto skip; 2048c2ecf20Sopenharmony_ci } 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci faddr = ha->flt_region_nvram; 2078c2ecf20Sopenharmony_ci if (IS_QLA28XX(ha)) { 2088c2ecf20Sopenharmony_ci qla28xx_get_aux_images(vha, &active_regions); 2098c2ecf20Sopenharmony_ci if (active_regions.aux.vpd_nvram == QLA27XX_SECONDARY_IMAGE) 2108c2ecf20Sopenharmony_ci faddr = ha->flt_region_nvram_sec; 2118c2ecf20Sopenharmony_ci } 2128c2ecf20Sopenharmony_ci ha->isp_ops->read_optrom(vha, ha->nvram, faddr << 2, ha->nvram_size); 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci mutex_unlock(&ha->optrom_mutex); 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ciskip: 2178c2ecf20Sopenharmony_ci return memory_read_from_buffer(buf, count, &off, ha->nvram, 2188c2ecf20Sopenharmony_ci ha->nvram_size); 2198c2ecf20Sopenharmony_ci} 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_cistatic ssize_t 2228c2ecf20Sopenharmony_ciqla2x00_sysfs_write_nvram(struct file *filp, struct kobject *kobj, 2238c2ecf20Sopenharmony_ci struct bin_attribute *bin_attr, 2248c2ecf20Sopenharmony_ci char *buf, loff_t off, size_t count) 2258c2ecf20Sopenharmony_ci{ 2268c2ecf20Sopenharmony_ci struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj, 2278c2ecf20Sopenharmony_ci struct device, kobj))); 2288c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 2298c2ecf20Sopenharmony_ci uint16_t cnt; 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->nvram_size || 2328c2ecf20Sopenharmony_ci !ha->isp_ops->write_nvram) 2338c2ecf20Sopenharmony_ci return -EINVAL; 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci /* Checksum NVRAM. */ 2368c2ecf20Sopenharmony_ci if (IS_FWI2_CAPABLE(ha)) { 2378c2ecf20Sopenharmony_ci __le32 *iter = (__force __le32 *)buf; 2388c2ecf20Sopenharmony_ci uint32_t chksum; 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci chksum = 0; 2418c2ecf20Sopenharmony_ci for (cnt = 0; cnt < ((count >> 2) - 1); cnt++, iter++) 2428c2ecf20Sopenharmony_ci chksum += le32_to_cpu(*iter); 2438c2ecf20Sopenharmony_ci chksum = ~chksum + 1; 2448c2ecf20Sopenharmony_ci *iter = cpu_to_le32(chksum); 2458c2ecf20Sopenharmony_ci } else { 2468c2ecf20Sopenharmony_ci uint8_t *iter; 2478c2ecf20Sopenharmony_ci uint8_t chksum; 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci iter = (uint8_t *)buf; 2508c2ecf20Sopenharmony_ci chksum = 0; 2518c2ecf20Sopenharmony_ci for (cnt = 0; cnt < count - 1; cnt++) 2528c2ecf20Sopenharmony_ci chksum += *iter++; 2538c2ecf20Sopenharmony_ci chksum = ~chksum + 1; 2548c2ecf20Sopenharmony_ci *iter = chksum; 2558c2ecf20Sopenharmony_ci } 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) { 2588c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x705f, 2598c2ecf20Sopenharmony_ci "HBA not online, failing NVRAM update.\n"); 2608c2ecf20Sopenharmony_ci return -EAGAIN; 2618c2ecf20Sopenharmony_ci } 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci mutex_lock(&ha->optrom_mutex); 2648c2ecf20Sopenharmony_ci if (qla2x00_chip_is_down(vha)) { 2658c2ecf20Sopenharmony_ci mutex_unlock(&ha->optrom_mutex); 2668c2ecf20Sopenharmony_ci return -EAGAIN; 2678c2ecf20Sopenharmony_ci } 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci /* Write NVRAM. */ 2708c2ecf20Sopenharmony_ci ha->isp_ops->write_nvram(vha, buf, ha->nvram_base, count); 2718c2ecf20Sopenharmony_ci ha->isp_ops->read_nvram(vha, ha->nvram, ha->nvram_base, 2728c2ecf20Sopenharmony_ci count); 2738c2ecf20Sopenharmony_ci mutex_unlock(&ha->optrom_mutex); 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_user, vha, 0x7060, 2768c2ecf20Sopenharmony_ci "Setting ISP_ABORT_NEEDED\n"); 2778c2ecf20Sopenharmony_ci /* NVRAM settings take effect immediately. */ 2788c2ecf20Sopenharmony_ci set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); 2798c2ecf20Sopenharmony_ci qla2xxx_wake_dpc(vha); 2808c2ecf20Sopenharmony_ci qla2x00_wait_for_chip_reset(vha); 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci return count; 2838c2ecf20Sopenharmony_ci} 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_cistatic struct bin_attribute sysfs_nvram_attr = { 2868c2ecf20Sopenharmony_ci .attr = { 2878c2ecf20Sopenharmony_ci .name = "nvram", 2888c2ecf20Sopenharmony_ci .mode = S_IRUSR | S_IWUSR, 2898c2ecf20Sopenharmony_ci }, 2908c2ecf20Sopenharmony_ci .size = 512, 2918c2ecf20Sopenharmony_ci .read = qla2x00_sysfs_read_nvram, 2928c2ecf20Sopenharmony_ci .write = qla2x00_sysfs_write_nvram, 2938c2ecf20Sopenharmony_ci}; 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_cistatic ssize_t 2968c2ecf20Sopenharmony_ciqla2x00_sysfs_read_optrom(struct file *filp, struct kobject *kobj, 2978c2ecf20Sopenharmony_ci struct bin_attribute *bin_attr, 2988c2ecf20Sopenharmony_ci char *buf, loff_t off, size_t count) 2998c2ecf20Sopenharmony_ci{ 3008c2ecf20Sopenharmony_ci struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj, 3018c2ecf20Sopenharmony_ci struct device, kobj))); 3028c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 3038c2ecf20Sopenharmony_ci ssize_t rval = 0; 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci mutex_lock(&ha->optrom_mutex); 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci if (ha->optrom_state != QLA_SREADING) 3088c2ecf20Sopenharmony_ci goto out; 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci rval = memory_read_from_buffer(buf, count, &off, ha->optrom_buffer, 3118c2ecf20Sopenharmony_ci ha->optrom_region_size); 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ciout: 3148c2ecf20Sopenharmony_ci mutex_unlock(&ha->optrom_mutex); 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci return rval; 3178c2ecf20Sopenharmony_ci} 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_cistatic ssize_t 3208c2ecf20Sopenharmony_ciqla2x00_sysfs_write_optrom(struct file *filp, struct kobject *kobj, 3218c2ecf20Sopenharmony_ci struct bin_attribute *bin_attr, 3228c2ecf20Sopenharmony_ci char *buf, loff_t off, size_t count) 3238c2ecf20Sopenharmony_ci{ 3248c2ecf20Sopenharmony_ci struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj, 3258c2ecf20Sopenharmony_ci struct device, kobj))); 3268c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci mutex_lock(&ha->optrom_mutex); 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci if (ha->optrom_state != QLA_SWRITING) { 3318c2ecf20Sopenharmony_ci mutex_unlock(&ha->optrom_mutex); 3328c2ecf20Sopenharmony_ci return -EINVAL; 3338c2ecf20Sopenharmony_ci } 3348c2ecf20Sopenharmony_ci if (off > ha->optrom_region_size) { 3358c2ecf20Sopenharmony_ci mutex_unlock(&ha->optrom_mutex); 3368c2ecf20Sopenharmony_ci return -ERANGE; 3378c2ecf20Sopenharmony_ci } 3388c2ecf20Sopenharmony_ci if (off + count > ha->optrom_region_size) 3398c2ecf20Sopenharmony_ci count = ha->optrom_region_size - off; 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci memcpy(&ha->optrom_buffer[off], buf, count); 3428c2ecf20Sopenharmony_ci mutex_unlock(&ha->optrom_mutex); 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci return count; 3458c2ecf20Sopenharmony_ci} 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_cistatic struct bin_attribute sysfs_optrom_attr = { 3488c2ecf20Sopenharmony_ci .attr = { 3498c2ecf20Sopenharmony_ci .name = "optrom", 3508c2ecf20Sopenharmony_ci .mode = S_IRUSR | S_IWUSR, 3518c2ecf20Sopenharmony_ci }, 3528c2ecf20Sopenharmony_ci .size = 0, 3538c2ecf20Sopenharmony_ci .read = qla2x00_sysfs_read_optrom, 3548c2ecf20Sopenharmony_ci .write = qla2x00_sysfs_write_optrom, 3558c2ecf20Sopenharmony_ci}; 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_cistatic ssize_t 3588c2ecf20Sopenharmony_ciqla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj, 3598c2ecf20Sopenharmony_ci struct bin_attribute *bin_attr, 3608c2ecf20Sopenharmony_ci char *buf, loff_t off, size_t count) 3618c2ecf20Sopenharmony_ci{ 3628c2ecf20Sopenharmony_ci struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj, 3638c2ecf20Sopenharmony_ci struct device, kobj))); 3648c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 3658c2ecf20Sopenharmony_ci uint32_t start = 0; 3668c2ecf20Sopenharmony_ci uint32_t size = ha->optrom_size; 3678c2ecf20Sopenharmony_ci int val, valid; 3688c2ecf20Sopenharmony_ci ssize_t rval = count; 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci if (off) 3718c2ecf20Sopenharmony_ci return -EINVAL; 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci if (unlikely(pci_channel_offline(ha->pdev))) 3748c2ecf20Sopenharmony_ci return -EAGAIN; 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci if (sscanf(buf, "%d:%x:%x", &val, &start, &size) < 1) 3778c2ecf20Sopenharmony_ci return -EINVAL; 3788c2ecf20Sopenharmony_ci if (start > ha->optrom_size) 3798c2ecf20Sopenharmony_ci return -EINVAL; 3808c2ecf20Sopenharmony_ci if (size > ha->optrom_size - start) 3818c2ecf20Sopenharmony_ci size = ha->optrom_size - start; 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci mutex_lock(&ha->optrom_mutex); 3848c2ecf20Sopenharmony_ci if (qla2x00_chip_is_down(vha)) { 3858c2ecf20Sopenharmony_ci mutex_unlock(&ha->optrom_mutex); 3868c2ecf20Sopenharmony_ci return -EAGAIN; 3878c2ecf20Sopenharmony_ci } 3888c2ecf20Sopenharmony_ci switch (val) { 3898c2ecf20Sopenharmony_ci case 0: 3908c2ecf20Sopenharmony_ci if (ha->optrom_state != QLA_SREADING && 3918c2ecf20Sopenharmony_ci ha->optrom_state != QLA_SWRITING) { 3928c2ecf20Sopenharmony_ci rval = -EINVAL; 3938c2ecf20Sopenharmony_ci goto out; 3948c2ecf20Sopenharmony_ci } 3958c2ecf20Sopenharmony_ci ha->optrom_state = QLA_SWAITING; 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_user, vha, 0x7061, 3988c2ecf20Sopenharmony_ci "Freeing flash region allocation -- 0x%x bytes.\n", 3998c2ecf20Sopenharmony_ci ha->optrom_region_size); 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci vfree(ha->optrom_buffer); 4028c2ecf20Sopenharmony_ci ha->optrom_buffer = NULL; 4038c2ecf20Sopenharmony_ci break; 4048c2ecf20Sopenharmony_ci case 1: 4058c2ecf20Sopenharmony_ci if (ha->optrom_state != QLA_SWAITING) { 4068c2ecf20Sopenharmony_ci rval = -EINVAL; 4078c2ecf20Sopenharmony_ci goto out; 4088c2ecf20Sopenharmony_ci } 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci ha->optrom_region_start = start; 4118c2ecf20Sopenharmony_ci ha->optrom_region_size = size; 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ci ha->optrom_state = QLA_SREADING; 4148c2ecf20Sopenharmony_ci ha->optrom_buffer = vzalloc(ha->optrom_region_size); 4158c2ecf20Sopenharmony_ci if (ha->optrom_buffer == NULL) { 4168c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x7062, 4178c2ecf20Sopenharmony_ci "Unable to allocate memory for optrom retrieval " 4188c2ecf20Sopenharmony_ci "(%x).\n", ha->optrom_region_size); 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_ci ha->optrom_state = QLA_SWAITING; 4218c2ecf20Sopenharmony_ci rval = -ENOMEM; 4228c2ecf20Sopenharmony_ci goto out; 4238c2ecf20Sopenharmony_ci } 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) { 4268c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x7063, 4278c2ecf20Sopenharmony_ci "HBA not online, failing NVRAM update.\n"); 4288c2ecf20Sopenharmony_ci rval = -EAGAIN; 4298c2ecf20Sopenharmony_ci goto out; 4308c2ecf20Sopenharmony_ci } 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_user, vha, 0x7064, 4338c2ecf20Sopenharmony_ci "Reading flash region -- 0x%x/0x%x.\n", 4348c2ecf20Sopenharmony_ci ha->optrom_region_start, ha->optrom_region_size); 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci ha->isp_ops->read_optrom(vha, ha->optrom_buffer, 4378c2ecf20Sopenharmony_ci ha->optrom_region_start, ha->optrom_region_size); 4388c2ecf20Sopenharmony_ci break; 4398c2ecf20Sopenharmony_ci case 2: 4408c2ecf20Sopenharmony_ci if (ha->optrom_state != QLA_SWAITING) { 4418c2ecf20Sopenharmony_ci rval = -EINVAL; 4428c2ecf20Sopenharmony_ci goto out; 4438c2ecf20Sopenharmony_ci } 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci /* 4468c2ecf20Sopenharmony_ci * We need to be more restrictive on which FLASH regions are 4478c2ecf20Sopenharmony_ci * allowed to be updated via user-space. Regions accessible 4488c2ecf20Sopenharmony_ci * via this method include: 4498c2ecf20Sopenharmony_ci * 4508c2ecf20Sopenharmony_ci * ISP21xx/ISP22xx/ISP23xx type boards: 4518c2ecf20Sopenharmony_ci * 4528c2ecf20Sopenharmony_ci * 0x000000 -> 0x020000 -- Boot code. 4538c2ecf20Sopenharmony_ci * 4548c2ecf20Sopenharmony_ci * ISP2322/ISP24xx type boards: 4558c2ecf20Sopenharmony_ci * 4568c2ecf20Sopenharmony_ci * 0x000000 -> 0x07ffff -- Boot code. 4578c2ecf20Sopenharmony_ci * 0x080000 -> 0x0fffff -- Firmware. 4588c2ecf20Sopenharmony_ci * 4598c2ecf20Sopenharmony_ci * ISP25xx type boards: 4608c2ecf20Sopenharmony_ci * 4618c2ecf20Sopenharmony_ci * 0x000000 -> 0x07ffff -- Boot code. 4628c2ecf20Sopenharmony_ci * 0x080000 -> 0x0fffff -- Firmware. 4638c2ecf20Sopenharmony_ci * 0x120000 -> 0x12ffff -- VPD and HBA parameters. 4648c2ecf20Sopenharmony_ci * 4658c2ecf20Sopenharmony_ci * > ISP25xx type boards: 4668c2ecf20Sopenharmony_ci * 4678c2ecf20Sopenharmony_ci * None -- should go through BSG. 4688c2ecf20Sopenharmony_ci */ 4698c2ecf20Sopenharmony_ci valid = 0; 4708c2ecf20Sopenharmony_ci if (ha->optrom_size == OPTROM_SIZE_2300 && start == 0) 4718c2ecf20Sopenharmony_ci valid = 1; 4728c2ecf20Sopenharmony_ci else if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha)) 4738c2ecf20Sopenharmony_ci valid = 1; 4748c2ecf20Sopenharmony_ci if (!valid) { 4758c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x7065, 4768c2ecf20Sopenharmony_ci "Invalid start region 0x%x/0x%x.\n", start, size); 4778c2ecf20Sopenharmony_ci rval = -EINVAL; 4788c2ecf20Sopenharmony_ci goto out; 4798c2ecf20Sopenharmony_ci } 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ci ha->optrom_region_start = start; 4828c2ecf20Sopenharmony_ci ha->optrom_region_size = size; 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_ci ha->optrom_state = QLA_SWRITING; 4858c2ecf20Sopenharmony_ci ha->optrom_buffer = vzalloc(ha->optrom_region_size); 4868c2ecf20Sopenharmony_ci if (ha->optrom_buffer == NULL) { 4878c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x7066, 4888c2ecf20Sopenharmony_ci "Unable to allocate memory for optrom update " 4898c2ecf20Sopenharmony_ci "(%x)\n", ha->optrom_region_size); 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_ci ha->optrom_state = QLA_SWAITING; 4928c2ecf20Sopenharmony_ci rval = -ENOMEM; 4938c2ecf20Sopenharmony_ci goto out; 4948c2ecf20Sopenharmony_ci } 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_user, vha, 0x7067, 4978c2ecf20Sopenharmony_ci "Staging flash region write -- 0x%x/0x%x.\n", 4988c2ecf20Sopenharmony_ci ha->optrom_region_start, ha->optrom_region_size); 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_ci break; 5018c2ecf20Sopenharmony_ci case 3: 5028c2ecf20Sopenharmony_ci if (ha->optrom_state != QLA_SWRITING) { 5038c2ecf20Sopenharmony_ci rval = -EINVAL; 5048c2ecf20Sopenharmony_ci goto out; 5058c2ecf20Sopenharmony_ci } 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) { 5088c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x7068, 5098c2ecf20Sopenharmony_ci "HBA not online, failing flash update.\n"); 5108c2ecf20Sopenharmony_ci rval = -EAGAIN; 5118c2ecf20Sopenharmony_ci goto out; 5128c2ecf20Sopenharmony_ci } 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_user, vha, 0x7069, 5158c2ecf20Sopenharmony_ci "Writing flash region -- 0x%x/0x%x.\n", 5168c2ecf20Sopenharmony_ci ha->optrom_region_start, ha->optrom_region_size); 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_ci rval = ha->isp_ops->write_optrom(vha, ha->optrom_buffer, 5198c2ecf20Sopenharmony_ci ha->optrom_region_start, ha->optrom_region_size); 5208c2ecf20Sopenharmony_ci if (rval) 5218c2ecf20Sopenharmony_ci rval = -EIO; 5228c2ecf20Sopenharmony_ci break; 5238c2ecf20Sopenharmony_ci default: 5248c2ecf20Sopenharmony_ci rval = -EINVAL; 5258c2ecf20Sopenharmony_ci } 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ciout: 5288c2ecf20Sopenharmony_ci mutex_unlock(&ha->optrom_mutex); 5298c2ecf20Sopenharmony_ci return rval; 5308c2ecf20Sopenharmony_ci} 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_cistatic struct bin_attribute sysfs_optrom_ctl_attr = { 5338c2ecf20Sopenharmony_ci .attr = { 5348c2ecf20Sopenharmony_ci .name = "optrom_ctl", 5358c2ecf20Sopenharmony_ci .mode = S_IWUSR, 5368c2ecf20Sopenharmony_ci }, 5378c2ecf20Sopenharmony_ci .size = 0, 5388c2ecf20Sopenharmony_ci .write = qla2x00_sysfs_write_optrom_ctl, 5398c2ecf20Sopenharmony_ci}; 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_cistatic ssize_t 5428c2ecf20Sopenharmony_ciqla2x00_sysfs_read_vpd(struct file *filp, struct kobject *kobj, 5438c2ecf20Sopenharmony_ci struct bin_attribute *bin_attr, 5448c2ecf20Sopenharmony_ci char *buf, loff_t off, size_t count) 5458c2ecf20Sopenharmony_ci{ 5468c2ecf20Sopenharmony_ci struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj, 5478c2ecf20Sopenharmony_ci struct device, kobj))); 5488c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 5498c2ecf20Sopenharmony_ci uint32_t faddr; 5508c2ecf20Sopenharmony_ci struct active_regions active_regions = { }; 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_ci if (unlikely(pci_channel_offline(ha->pdev))) 5538c2ecf20Sopenharmony_ci return -EAGAIN; 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_ci if (!capable(CAP_SYS_ADMIN)) 5568c2ecf20Sopenharmony_ci return -EINVAL; 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci if (!IS_NOCACHE_VPD_TYPE(ha)) 5598c2ecf20Sopenharmony_ci goto skip; 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_ci faddr = ha->flt_region_vpd << 2; 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_ci if (IS_QLA28XX(ha)) { 5648c2ecf20Sopenharmony_ci qla28xx_get_aux_images(vha, &active_regions); 5658c2ecf20Sopenharmony_ci if (active_regions.aux.vpd_nvram == QLA27XX_SECONDARY_IMAGE) 5668c2ecf20Sopenharmony_ci faddr = ha->flt_region_vpd_sec << 2; 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, vha, 0x7070, 5698c2ecf20Sopenharmony_ci "Loading %s nvram image.\n", 5708c2ecf20Sopenharmony_ci active_regions.aux.vpd_nvram == QLA27XX_PRIMARY_IMAGE ? 5718c2ecf20Sopenharmony_ci "primary" : "secondary"); 5728c2ecf20Sopenharmony_ci } 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ci mutex_lock(&ha->optrom_mutex); 5758c2ecf20Sopenharmony_ci if (qla2x00_chip_is_down(vha)) { 5768c2ecf20Sopenharmony_ci mutex_unlock(&ha->optrom_mutex); 5778c2ecf20Sopenharmony_ci return -EAGAIN; 5788c2ecf20Sopenharmony_ci } 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_ci ha->isp_ops->read_optrom(vha, ha->vpd, faddr, ha->vpd_size); 5818c2ecf20Sopenharmony_ci mutex_unlock(&ha->optrom_mutex); 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci ha->isp_ops->read_optrom(vha, ha->vpd, faddr, ha->vpd_size); 5848c2ecf20Sopenharmony_ciskip: 5858c2ecf20Sopenharmony_ci return memory_read_from_buffer(buf, count, &off, ha->vpd, ha->vpd_size); 5868c2ecf20Sopenharmony_ci} 5878c2ecf20Sopenharmony_ci 5888c2ecf20Sopenharmony_cistatic ssize_t 5898c2ecf20Sopenharmony_ciqla2x00_sysfs_write_vpd(struct file *filp, struct kobject *kobj, 5908c2ecf20Sopenharmony_ci struct bin_attribute *bin_attr, 5918c2ecf20Sopenharmony_ci char *buf, loff_t off, size_t count) 5928c2ecf20Sopenharmony_ci{ 5938c2ecf20Sopenharmony_ci struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj, 5948c2ecf20Sopenharmony_ci struct device, kobj))); 5958c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 5968c2ecf20Sopenharmony_ci uint8_t *tmp_data; 5978c2ecf20Sopenharmony_ci 5988c2ecf20Sopenharmony_ci if (unlikely(pci_channel_offline(ha->pdev))) 5998c2ecf20Sopenharmony_ci return 0; 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ci if (qla2x00_chip_is_down(vha)) 6028c2ecf20Sopenharmony_ci return 0; 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_ci if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->vpd_size || 6058c2ecf20Sopenharmony_ci !ha->isp_ops->write_nvram) 6068c2ecf20Sopenharmony_ci return 0; 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_ci if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) { 6098c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x706a, 6108c2ecf20Sopenharmony_ci "HBA not online, failing VPD update.\n"); 6118c2ecf20Sopenharmony_ci return -EAGAIN; 6128c2ecf20Sopenharmony_ci } 6138c2ecf20Sopenharmony_ci 6148c2ecf20Sopenharmony_ci mutex_lock(&ha->optrom_mutex); 6158c2ecf20Sopenharmony_ci if (qla2x00_chip_is_down(vha)) { 6168c2ecf20Sopenharmony_ci mutex_unlock(&ha->optrom_mutex); 6178c2ecf20Sopenharmony_ci return -EAGAIN; 6188c2ecf20Sopenharmony_ci } 6198c2ecf20Sopenharmony_ci 6208c2ecf20Sopenharmony_ci /* Write NVRAM. */ 6218c2ecf20Sopenharmony_ci ha->isp_ops->write_nvram(vha, buf, ha->vpd_base, count); 6228c2ecf20Sopenharmony_ci ha->isp_ops->read_nvram(vha, ha->vpd, ha->vpd_base, count); 6238c2ecf20Sopenharmony_ci 6248c2ecf20Sopenharmony_ci /* Update flash version information for 4Gb & above. */ 6258c2ecf20Sopenharmony_ci if (!IS_FWI2_CAPABLE(ha)) { 6268c2ecf20Sopenharmony_ci mutex_unlock(&ha->optrom_mutex); 6278c2ecf20Sopenharmony_ci return -EINVAL; 6288c2ecf20Sopenharmony_ci } 6298c2ecf20Sopenharmony_ci 6308c2ecf20Sopenharmony_ci tmp_data = vmalloc(256); 6318c2ecf20Sopenharmony_ci if (!tmp_data) { 6328c2ecf20Sopenharmony_ci mutex_unlock(&ha->optrom_mutex); 6338c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x706b, 6348c2ecf20Sopenharmony_ci "Unable to allocate memory for VPD information update.\n"); 6358c2ecf20Sopenharmony_ci return -ENOMEM; 6368c2ecf20Sopenharmony_ci } 6378c2ecf20Sopenharmony_ci ha->isp_ops->get_flash_version(vha, tmp_data); 6388c2ecf20Sopenharmony_ci vfree(tmp_data); 6398c2ecf20Sopenharmony_ci 6408c2ecf20Sopenharmony_ci mutex_unlock(&ha->optrom_mutex); 6418c2ecf20Sopenharmony_ci 6428c2ecf20Sopenharmony_ci return count; 6438c2ecf20Sopenharmony_ci} 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_cistatic struct bin_attribute sysfs_vpd_attr = { 6468c2ecf20Sopenharmony_ci .attr = { 6478c2ecf20Sopenharmony_ci .name = "vpd", 6488c2ecf20Sopenharmony_ci .mode = S_IRUSR | S_IWUSR, 6498c2ecf20Sopenharmony_ci }, 6508c2ecf20Sopenharmony_ci .size = 0, 6518c2ecf20Sopenharmony_ci .read = qla2x00_sysfs_read_vpd, 6528c2ecf20Sopenharmony_ci .write = qla2x00_sysfs_write_vpd, 6538c2ecf20Sopenharmony_ci}; 6548c2ecf20Sopenharmony_ci 6558c2ecf20Sopenharmony_cistatic ssize_t 6568c2ecf20Sopenharmony_ciqla2x00_sysfs_read_sfp(struct file *filp, struct kobject *kobj, 6578c2ecf20Sopenharmony_ci struct bin_attribute *bin_attr, 6588c2ecf20Sopenharmony_ci char *buf, loff_t off, size_t count) 6598c2ecf20Sopenharmony_ci{ 6608c2ecf20Sopenharmony_ci struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj, 6618c2ecf20Sopenharmony_ci struct device, kobj))); 6628c2ecf20Sopenharmony_ci int rval; 6638c2ecf20Sopenharmony_ci 6648c2ecf20Sopenharmony_ci if (!capable(CAP_SYS_ADMIN) || off != 0 || count < SFP_DEV_SIZE) 6658c2ecf20Sopenharmony_ci return 0; 6668c2ecf20Sopenharmony_ci 6678c2ecf20Sopenharmony_ci mutex_lock(&vha->hw->optrom_mutex); 6688c2ecf20Sopenharmony_ci if (qla2x00_chip_is_down(vha)) { 6698c2ecf20Sopenharmony_ci mutex_unlock(&vha->hw->optrom_mutex); 6708c2ecf20Sopenharmony_ci return 0; 6718c2ecf20Sopenharmony_ci } 6728c2ecf20Sopenharmony_ci 6738c2ecf20Sopenharmony_ci rval = qla2x00_read_sfp_dev(vha, buf, count); 6748c2ecf20Sopenharmony_ci mutex_unlock(&vha->hw->optrom_mutex); 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_ci if (rval) 6778c2ecf20Sopenharmony_ci return -EIO; 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_ci return count; 6808c2ecf20Sopenharmony_ci} 6818c2ecf20Sopenharmony_ci 6828c2ecf20Sopenharmony_cistatic struct bin_attribute sysfs_sfp_attr = { 6838c2ecf20Sopenharmony_ci .attr = { 6848c2ecf20Sopenharmony_ci .name = "sfp", 6858c2ecf20Sopenharmony_ci .mode = S_IRUSR | S_IWUSR, 6868c2ecf20Sopenharmony_ci }, 6878c2ecf20Sopenharmony_ci .size = SFP_DEV_SIZE, 6888c2ecf20Sopenharmony_ci .read = qla2x00_sysfs_read_sfp, 6898c2ecf20Sopenharmony_ci}; 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_cistatic ssize_t 6928c2ecf20Sopenharmony_ciqla2x00_sysfs_write_reset(struct file *filp, struct kobject *kobj, 6938c2ecf20Sopenharmony_ci struct bin_attribute *bin_attr, 6948c2ecf20Sopenharmony_ci char *buf, loff_t off, size_t count) 6958c2ecf20Sopenharmony_ci{ 6968c2ecf20Sopenharmony_ci struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj, 6978c2ecf20Sopenharmony_ci struct device, kobj))); 6988c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 6998c2ecf20Sopenharmony_ci struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); 7008c2ecf20Sopenharmony_ci int type; 7018c2ecf20Sopenharmony_ci uint32_t idc_control; 7028c2ecf20Sopenharmony_ci uint8_t *tmp_data = NULL; 7038c2ecf20Sopenharmony_ci 7048c2ecf20Sopenharmony_ci if (off != 0) 7058c2ecf20Sopenharmony_ci return -EINVAL; 7068c2ecf20Sopenharmony_ci 7078c2ecf20Sopenharmony_ci type = simple_strtol(buf, NULL, 10); 7088c2ecf20Sopenharmony_ci switch (type) { 7098c2ecf20Sopenharmony_ci case 0x2025c: 7108c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x706e, 7118c2ecf20Sopenharmony_ci "Issuing ISP reset.\n"); 7128c2ecf20Sopenharmony_ci 7138c2ecf20Sopenharmony_ci scsi_block_requests(vha->host); 7148c2ecf20Sopenharmony_ci if (IS_QLA82XX(ha)) { 7158c2ecf20Sopenharmony_ci ha->flags.isp82xx_no_md_cap = 1; 7168c2ecf20Sopenharmony_ci qla82xx_idc_lock(ha); 7178c2ecf20Sopenharmony_ci qla82xx_set_reset_owner(vha); 7188c2ecf20Sopenharmony_ci qla82xx_idc_unlock(ha); 7198c2ecf20Sopenharmony_ci } else if (IS_QLA8044(ha)) { 7208c2ecf20Sopenharmony_ci qla8044_idc_lock(ha); 7218c2ecf20Sopenharmony_ci idc_control = qla8044_rd_reg(ha, 7228c2ecf20Sopenharmony_ci QLA8044_IDC_DRV_CTRL); 7238c2ecf20Sopenharmony_ci qla8044_wr_reg(ha, QLA8044_IDC_DRV_CTRL, 7248c2ecf20Sopenharmony_ci (idc_control | GRACEFUL_RESET_BIT1)); 7258c2ecf20Sopenharmony_ci qla82xx_set_reset_owner(vha); 7268c2ecf20Sopenharmony_ci qla8044_idc_unlock(ha); 7278c2ecf20Sopenharmony_ci } else { 7288c2ecf20Sopenharmony_ci set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); 7298c2ecf20Sopenharmony_ci qla2xxx_wake_dpc(vha); 7308c2ecf20Sopenharmony_ci } 7318c2ecf20Sopenharmony_ci qla2x00_wait_for_chip_reset(vha); 7328c2ecf20Sopenharmony_ci scsi_unblock_requests(vha->host); 7338c2ecf20Sopenharmony_ci break; 7348c2ecf20Sopenharmony_ci case 0x2025d: 7358c2ecf20Sopenharmony_ci if (!IS_QLA81XX(ha) && !IS_QLA83XX(ha) && 7368c2ecf20Sopenharmony_ci !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) 7378c2ecf20Sopenharmony_ci return -EPERM; 7388c2ecf20Sopenharmony_ci 7398c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x706f, 7408c2ecf20Sopenharmony_ci "Issuing MPI reset.\n"); 7418c2ecf20Sopenharmony_ci 7428c2ecf20Sopenharmony_ci if (IS_QLA83XX(ha)) { 7438c2ecf20Sopenharmony_ci uint32_t idc_control; 7448c2ecf20Sopenharmony_ci 7458c2ecf20Sopenharmony_ci qla83xx_idc_lock(vha, 0); 7468c2ecf20Sopenharmony_ci __qla83xx_get_idc_control(vha, &idc_control); 7478c2ecf20Sopenharmony_ci idc_control |= QLA83XX_IDC_GRACEFUL_RESET; 7488c2ecf20Sopenharmony_ci __qla83xx_set_idc_control(vha, idc_control); 7498c2ecf20Sopenharmony_ci qla83xx_wr_reg(vha, QLA83XX_IDC_DEV_STATE, 7508c2ecf20Sopenharmony_ci QLA8XXX_DEV_NEED_RESET); 7518c2ecf20Sopenharmony_ci qla83xx_idc_audit(vha, IDC_AUDIT_TIMESTAMP); 7528c2ecf20Sopenharmony_ci qla83xx_idc_unlock(vha, 0); 7538c2ecf20Sopenharmony_ci break; 7548c2ecf20Sopenharmony_ci } else { 7558c2ecf20Sopenharmony_ci /* Make sure FC side is not in reset */ 7568c2ecf20Sopenharmony_ci WARN_ON_ONCE(qla2x00_wait_for_hba_online(vha) != 7578c2ecf20Sopenharmony_ci QLA_SUCCESS); 7588c2ecf20Sopenharmony_ci 7598c2ecf20Sopenharmony_ci /* Issue MPI reset */ 7608c2ecf20Sopenharmony_ci scsi_block_requests(vha->host); 7618c2ecf20Sopenharmony_ci if (qla81xx_restart_mpi_firmware(vha) != QLA_SUCCESS) 7628c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x7070, 7638c2ecf20Sopenharmony_ci "MPI reset failed.\n"); 7648c2ecf20Sopenharmony_ci scsi_unblock_requests(vha->host); 7658c2ecf20Sopenharmony_ci break; 7668c2ecf20Sopenharmony_ci } 7678c2ecf20Sopenharmony_ci break; 7688c2ecf20Sopenharmony_ci case 0x2025e: 7698c2ecf20Sopenharmony_ci if (!IS_P3P_TYPE(ha) || vha != base_vha) { 7708c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x7071, 7718c2ecf20Sopenharmony_ci "FCoE ctx reset not supported.\n"); 7728c2ecf20Sopenharmony_ci return -EPERM; 7738c2ecf20Sopenharmony_ci } 7748c2ecf20Sopenharmony_ci 7758c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x7072, 7768c2ecf20Sopenharmony_ci "Issuing FCoE ctx reset.\n"); 7778c2ecf20Sopenharmony_ci set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags); 7788c2ecf20Sopenharmony_ci qla2xxx_wake_dpc(vha); 7798c2ecf20Sopenharmony_ci qla2x00_wait_for_fcoe_ctx_reset(vha); 7808c2ecf20Sopenharmony_ci break; 7818c2ecf20Sopenharmony_ci case 0x2025f: 7828c2ecf20Sopenharmony_ci if (!IS_QLA8031(ha)) 7838c2ecf20Sopenharmony_ci return -EPERM; 7848c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x70bc, 7858c2ecf20Sopenharmony_ci "Disabling Reset by IDC control\n"); 7868c2ecf20Sopenharmony_ci qla83xx_idc_lock(vha, 0); 7878c2ecf20Sopenharmony_ci __qla83xx_get_idc_control(vha, &idc_control); 7888c2ecf20Sopenharmony_ci idc_control |= QLA83XX_IDC_RESET_DISABLED; 7898c2ecf20Sopenharmony_ci __qla83xx_set_idc_control(vha, idc_control); 7908c2ecf20Sopenharmony_ci qla83xx_idc_unlock(vha, 0); 7918c2ecf20Sopenharmony_ci break; 7928c2ecf20Sopenharmony_ci case 0x20260: 7938c2ecf20Sopenharmony_ci if (!IS_QLA8031(ha)) 7948c2ecf20Sopenharmony_ci return -EPERM; 7958c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x70bd, 7968c2ecf20Sopenharmony_ci "Enabling Reset by IDC control\n"); 7978c2ecf20Sopenharmony_ci qla83xx_idc_lock(vha, 0); 7988c2ecf20Sopenharmony_ci __qla83xx_get_idc_control(vha, &idc_control); 7998c2ecf20Sopenharmony_ci idc_control &= ~QLA83XX_IDC_RESET_DISABLED; 8008c2ecf20Sopenharmony_ci __qla83xx_set_idc_control(vha, idc_control); 8018c2ecf20Sopenharmony_ci qla83xx_idc_unlock(vha, 0); 8028c2ecf20Sopenharmony_ci break; 8038c2ecf20Sopenharmony_ci case 0x20261: 8048c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_user, vha, 0x70e0, 8058c2ecf20Sopenharmony_ci "Updating cache versions without reset "); 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_ci tmp_data = vmalloc(256); 8088c2ecf20Sopenharmony_ci if (!tmp_data) { 8098c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x70e1, 8108c2ecf20Sopenharmony_ci "Unable to allocate memory for VPD information update.\n"); 8118c2ecf20Sopenharmony_ci return -ENOMEM; 8128c2ecf20Sopenharmony_ci } 8138c2ecf20Sopenharmony_ci ha->isp_ops->get_flash_version(vha, tmp_data); 8148c2ecf20Sopenharmony_ci vfree(tmp_data); 8158c2ecf20Sopenharmony_ci break; 8168c2ecf20Sopenharmony_ci } 8178c2ecf20Sopenharmony_ci return count; 8188c2ecf20Sopenharmony_ci} 8198c2ecf20Sopenharmony_ci 8208c2ecf20Sopenharmony_cistatic struct bin_attribute sysfs_reset_attr = { 8218c2ecf20Sopenharmony_ci .attr = { 8228c2ecf20Sopenharmony_ci .name = "reset", 8238c2ecf20Sopenharmony_ci .mode = S_IWUSR, 8248c2ecf20Sopenharmony_ci }, 8258c2ecf20Sopenharmony_ci .size = 0, 8268c2ecf20Sopenharmony_ci .write = qla2x00_sysfs_write_reset, 8278c2ecf20Sopenharmony_ci}; 8288c2ecf20Sopenharmony_ci 8298c2ecf20Sopenharmony_cistatic ssize_t 8308c2ecf20Sopenharmony_ciqla2x00_issue_logo(struct file *filp, struct kobject *kobj, 8318c2ecf20Sopenharmony_ci struct bin_attribute *bin_attr, 8328c2ecf20Sopenharmony_ci char *buf, loff_t off, size_t count) 8338c2ecf20Sopenharmony_ci{ 8348c2ecf20Sopenharmony_ci struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj, 8358c2ecf20Sopenharmony_ci struct device, kobj))); 8368c2ecf20Sopenharmony_ci int type; 8378c2ecf20Sopenharmony_ci port_id_t did; 8388c2ecf20Sopenharmony_ci 8398c2ecf20Sopenharmony_ci if (!capable(CAP_SYS_ADMIN)) 8408c2ecf20Sopenharmony_ci return 0; 8418c2ecf20Sopenharmony_ci 8428c2ecf20Sopenharmony_ci if (unlikely(pci_channel_offline(vha->hw->pdev))) 8438c2ecf20Sopenharmony_ci return 0; 8448c2ecf20Sopenharmony_ci 8458c2ecf20Sopenharmony_ci if (qla2x00_chip_is_down(vha)) 8468c2ecf20Sopenharmony_ci return 0; 8478c2ecf20Sopenharmony_ci 8488c2ecf20Sopenharmony_ci type = simple_strtol(buf, NULL, 10); 8498c2ecf20Sopenharmony_ci 8508c2ecf20Sopenharmony_ci did.b.domain = (type & 0x00ff0000) >> 16; 8518c2ecf20Sopenharmony_ci did.b.area = (type & 0x0000ff00) >> 8; 8528c2ecf20Sopenharmony_ci did.b.al_pa = (type & 0x000000ff); 8538c2ecf20Sopenharmony_ci 8548c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0xd04d, "portid=%02x%02x%02x done\n", 8558c2ecf20Sopenharmony_ci did.b.domain, did.b.area, did.b.al_pa); 8568c2ecf20Sopenharmony_ci 8578c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x70e4, "%s: %d\n", __func__, type); 8588c2ecf20Sopenharmony_ci 8598c2ecf20Sopenharmony_ci qla24xx_els_dcmd_iocb(vha, ELS_DCMD_LOGO, did); 8608c2ecf20Sopenharmony_ci return count; 8618c2ecf20Sopenharmony_ci} 8628c2ecf20Sopenharmony_ci 8638c2ecf20Sopenharmony_cistatic struct bin_attribute sysfs_issue_logo_attr = { 8648c2ecf20Sopenharmony_ci .attr = { 8658c2ecf20Sopenharmony_ci .name = "issue_logo", 8668c2ecf20Sopenharmony_ci .mode = S_IWUSR, 8678c2ecf20Sopenharmony_ci }, 8688c2ecf20Sopenharmony_ci .size = 0, 8698c2ecf20Sopenharmony_ci .write = qla2x00_issue_logo, 8708c2ecf20Sopenharmony_ci}; 8718c2ecf20Sopenharmony_ci 8728c2ecf20Sopenharmony_cistatic ssize_t 8738c2ecf20Sopenharmony_ciqla2x00_sysfs_read_xgmac_stats(struct file *filp, struct kobject *kobj, 8748c2ecf20Sopenharmony_ci struct bin_attribute *bin_attr, 8758c2ecf20Sopenharmony_ci char *buf, loff_t off, size_t count) 8768c2ecf20Sopenharmony_ci{ 8778c2ecf20Sopenharmony_ci struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj, 8788c2ecf20Sopenharmony_ci struct device, kobj))); 8798c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 8808c2ecf20Sopenharmony_ci int rval; 8818c2ecf20Sopenharmony_ci uint16_t actual_size; 8828c2ecf20Sopenharmony_ci 8838c2ecf20Sopenharmony_ci if (!capable(CAP_SYS_ADMIN) || off != 0 || count > XGMAC_DATA_SIZE) 8848c2ecf20Sopenharmony_ci return 0; 8858c2ecf20Sopenharmony_ci 8868c2ecf20Sopenharmony_ci if (unlikely(pci_channel_offline(ha->pdev))) 8878c2ecf20Sopenharmony_ci return 0; 8888c2ecf20Sopenharmony_ci mutex_lock(&vha->hw->optrom_mutex); 8898c2ecf20Sopenharmony_ci if (qla2x00_chip_is_down(vha)) { 8908c2ecf20Sopenharmony_ci mutex_unlock(&vha->hw->optrom_mutex); 8918c2ecf20Sopenharmony_ci return 0; 8928c2ecf20Sopenharmony_ci } 8938c2ecf20Sopenharmony_ci 8948c2ecf20Sopenharmony_ci if (ha->xgmac_data) 8958c2ecf20Sopenharmony_ci goto do_read; 8968c2ecf20Sopenharmony_ci 8978c2ecf20Sopenharmony_ci ha->xgmac_data = dma_alloc_coherent(&ha->pdev->dev, XGMAC_DATA_SIZE, 8988c2ecf20Sopenharmony_ci &ha->xgmac_data_dma, GFP_KERNEL); 8998c2ecf20Sopenharmony_ci if (!ha->xgmac_data) { 9008c2ecf20Sopenharmony_ci mutex_unlock(&vha->hw->optrom_mutex); 9018c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x7076, 9028c2ecf20Sopenharmony_ci "Unable to allocate memory for XGMAC read-data.\n"); 9038c2ecf20Sopenharmony_ci return 0; 9048c2ecf20Sopenharmony_ci } 9058c2ecf20Sopenharmony_ci 9068c2ecf20Sopenharmony_cido_read: 9078c2ecf20Sopenharmony_ci actual_size = 0; 9088c2ecf20Sopenharmony_ci memset(ha->xgmac_data, 0, XGMAC_DATA_SIZE); 9098c2ecf20Sopenharmony_ci 9108c2ecf20Sopenharmony_ci rval = qla2x00_get_xgmac_stats(vha, ha->xgmac_data_dma, 9118c2ecf20Sopenharmony_ci XGMAC_DATA_SIZE, &actual_size); 9128c2ecf20Sopenharmony_ci 9138c2ecf20Sopenharmony_ci mutex_unlock(&vha->hw->optrom_mutex); 9148c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) { 9158c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x7077, 9168c2ecf20Sopenharmony_ci "Unable to read XGMAC data (%x).\n", rval); 9178c2ecf20Sopenharmony_ci count = 0; 9188c2ecf20Sopenharmony_ci } 9198c2ecf20Sopenharmony_ci 9208c2ecf20Sopenharmony_ci count = actual_size > count ? count : actual_size; 9218c2ecf20Sopenharmony_ci memcpy(buf, ha->xgmac_data, count); 9228c2ecf20Sopenharmony_ci 9238c2ecf20Sopenharmony_ci return count; 9248c2ecf20Sopenharmony_ci} 9258c2ecf20Sopenharmony_ci 9268c2ecf20Sopenharmony_cistatic struct bin_attribute sysfs_xgmac_stats_attr = { 9278c2ecf20Sopenharmony_ci .attr = { 9288c2ecf20Sopenharmony_ci .name = "xgmac_stats", 9298c2ecf20Sopenharmony_ci .mode = S_IRUSR, 9308c2ecf20Sopenharmony_ci }, 9318c2ecf20Sopenharmony_ci .size = 0, 9328c2ecf20Sopenharmony_ci .read = qla2x00_sysfs_read_xgmac_stats, 9338c2ecf20Sopenharmony_ci}; 9348c2ecf20Sopenharmony_ci 9358c2ecf20Sopenharmony_cistatic ssize_t 9368c2ecf20Sopenharmony_ciqla2x00_sysfs_read_dcbx_tlv(struct file *filp, struct kobject *kobj, 9378c2ecf20Sopenharmony_ci struct bin_attribute *bin_attr, 9388c2ecf20Sopenharmony_ci char *buf, loff_t off, size_t count) 9398c2ecf20Sopenharmony_ci{ 9408c2ecf20Sopenharmony_ci struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj, 9418c2ecf20Sopenharmony_ci struct device, kobj))); 9428c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 9438c2ecf20Sopenharmony_ci int rval; 9448c2ecf20Sopenharmony_ci 9458c2ecf20Sopenharmony_ci if (!capable(CAP_SYS_ADMIN) || off != 0 || count > DCBX_TLV_DATA_SIZE) 9468c2ecf20Sopenharmony_ci return 0; 9478c2ecf20Sopenharmony_ci 9488c2ecf20Sopenharmony_ci if (ha->dcbx_tlv) 9498c2ecf20Sopenharmony_ci goto do_read; 9508c2ecf20Sopenharmony_ci mutex_lock(&vha->hw->optrom_mutex); 9518c2ecf20Sopenharmony_ci if (qla2x00_chip_is_down(vha)) { 9528c2ecf20Sopenharmony_ci mutex_unlock(&vha->hw->optrom_mutex); 9538c2ecf20Sopenharmony_ci return 0; 9548c2ecf20Sopenharmony_ci } 9558c2ecf20Sopenharmony_ci 9568c2ecf20Sopenharmony_ci ha->dcbx_tlv = dma_alloc_coherent(&ha->pdev->dev, DCBX_TLV_DATA_SIZE, 9578c2ecf20Sopenharmony_ci &ha->dcbx_tlv_dma, GFP_KERNEL); 9588c2ecf20Sopenharmony_ci if (!ha->dcbx_tlv) { 9598c2ecf20Sopenharmony_ci mutex_unlock(&vha->hw->optrom_mutex); 9608c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x7078, 9618c2ecf20Sopenharmony_ci "Unable to allocate memory for DCBX TLV read-data.\n"); 9628c2ecf20Sopenharmony_ci return -ENOMEM; 9638c2ecf20Sopenharmony_ci } 9648c2ecf20Sopenharmony_ci 9658c2ecf20Sopenharmony_cido_read: 9668c2ecf20Sopenharmony_ci memset(ha->dcbx_tlv, 0, DCBX_TLV_DATA_SIZE); 9678c2ecf20Sopenharmony_ci 9688c2ecf20Sopenharmony_ci rval = qla2x00_get_dcbx_params(vha, ha->dcbx_tlv_dma, 9698c2ecf20Sopenharmony_ci DCBX_TLV_DATA_SIZE); 9708c2ecf20Sopenharmony_ci 9718c2ecf20Sopenharmony_ci mutex_unlock(&vha->hw->optrom_mutex); 9728c2ecf20Sopenharmony_ci 9738c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) { 9748c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x7079, 9758c2ecf20Sopenharmony_ci "Unable to read DCBX TLV (%x).\n", rval); 9768c2ecf20Sopenharmony_ci return -EIO; 9778c2ecf20Sopenharmony_ci } 9788c2ecf20Sopenharmony_ci 9798c2ecf20Sopenharmony_ci memcpy(buf, ha->dcbx_tlv, count); 9808c2ecf20Sopenharmony_ci 9818c2ecf20Sopenharmony_ci return count; 9828c2ecf20Sopenharmony_ci} 9838c2ecf20Sopenharmony_ci 9848c2ecf20Sopenharmony_cistatic struct bin_attribute sysfs_dcbx_tlv_attr = { 9858c2ecf20Sopenharmony_ci .attr = { 9868c2ecf20Sopenharmony_ci .name = "dcbx_tlv", 9878c2ecf20Sopenharmony_ci .mode = S_IRUSR, 9888c2ecf20Sopenharmony_ci }, 9898c2ecf20Sopenharmony_ci .size = 0, 9908c2ecf20Sopenharmony_ci .read = qla2x00_sysfs_read_dcbx_tlv, 9918c2ecf20Sopenharmony_ci}; 9928c2ecf20Sopenharmony_ci 9938c2ecf20Sopenharmony_cistatic struct sysfs_entry { 9948c2ecf20Sopenharmony_ci char *name; 9958c2ecf20Sopenharmony_ci struct bin_attribute *attr; 9968c2ecf20Sopenharmony_ci int type; 9978c2ecf20Sopenharmony_ci} bin_file_entries[] = { 9988c2ecf20Sopenharmony_ci { "fw_dump", &sysfs_fw_dump_attr, }, 9998c2ecf20Sopenharmony_ci { "nvram", &sysfs_nvram_attr, }, 10008c2ecf20Sopenharmony_ci { "optrom", &sysfs_optrom_attr, }, 10018c2ecf20Sopenharmony_ci { "optrom_ctl", &sysfs_optrom_ctl_attr, }, 10028c2ecf20Sopenharmony_ci { "vpd", &sysfs_vpd_attr, 1 }, 10038c2ecf20Sopenharmony_ci { "sfp", &sysfs_sfp_attr, 1 }, 10048c2ecf20Sopenharmony_ci { "reset", &sysfs_reset_attr, }, 10058c2ecf20Sopenharmony_ci { "issue_logo", &sysfs_issue_logo_attr, }, 10068c2ecf20Sopenharmony_ci { "xgmac_stats", &sysfs_xgmac_stats_attr, 3 }, 10078c2ecf20Sopenharmony_ci { "dcbx_tlv", &sysfs_dcbx_tlv_attr, 3 }, 10088c2ecf20Sopenharmony_ci { NULL }, 10098c2ecf20Sopenharmony_ci}; 10108c2ecf20Sopenharmony_ci 10118c2ecf20Sopenharmony_civoid 10128c2ecf20Sopenharmony_ciqla2x00_alloc_sysfs_attr(scsi_qla_host_t *vha) 10138c2ecf20Sopenharmony_ci{ 10148c2ecf20Sopenharmony_ci struct Scsi_Host *host = vha->host; 10158c2ecf20Sopenharmony_ci struct sysfs_entry *iter; 10168c2ecf20Sopenharmony_ci int ret; 10178c2ecf20Sopenharmony_ci 10188c2ecf20Sopenharmony_ci for (iter = bin_file_entries; iter->name; iter++) { 10198c2ecf20Sopenharmony_ci if (iter->type && !IS_FWI2_CAPABLE(vha->hw)) 10208c2ecf20Sopenharmony_ci continue; 10218c2ecf20Sopenharmony_ci if (iter->type == 2 && !IS_QLA25XX(vha->hw)) 10228c2ecf20Sopenharmony_ci continue; 10238c2ecf20Sopenharmony_ci if (iter->type == 3 && !(IS_CNA_CAPABLE(vha->hw))) 10248c2ecf20Sopenharmony_ci continue; 10258c2ecf20Sopenharmony_ci 10268c2ecf20Sopenharmony_ci ret = sysfs_create_bin_file(&host->shost_gendev.kobj, 10278c2ecf20Sopenharmony_ci iter->attr); 10288c2ecf20Sopenharmony_ci if (ret) 10298c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x00f3, 10308c2ecf20Sopenharmony_ci "Unable to create sysfs %s binary attribute (%d).\n", 10318c2ecf20Sopenharmony_ci iter->name, ret); 10328c2ecf20Sopenharmony_ci else 10338c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, vha, 0x00f4, 10348c2ecf20Sopenharmony_ci "Successfully created sysfs %s binary attribute.\n", 10358c2ecf20Sopenharmony_ci iter->name); 10368c2ecf20Sopenharmony_ci } 10378c2ecf20Sopenharmony_ci} 10388c2ecf20Sopenharmony_ci 10398c2ecf20Sopenharmony_civoid 10408c2ecf20Sopenharmony_ciqla2x00_free_sysfs_attr(scsi_qla_host_t *vha, bool stop_beacon) 10418c2ecf20Sopenharmony_ci{ 10428c2ecf20Sopenharmony_ci struct Scsi_Host *host = vha->host; 10438c2ecf20Sopenharmony_ci struct sysfs_entry *iter; 10448c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 10458c2ecf20Sopenharmony_ci 10468c2ecf20Sopenharmony_ci for (iter = bin_file_entries; iter->name; iter++) { 10478c2ecf20Sopenharmony_ci if (iter->type && !IS_FWI2_CAPABLE(ha)) 10488c2ecf20Sopenharmony_ci continue; 10498c2ecf20Sopenharmony_ci if (iter->type == 2 && !IS_QLA25XX(ha)) 10508c2ecf20Sopenharmony_ci continue; 10518c2ecf20Sopenharmony_ci if (iter->type == 3 && !(IS_CNA_CAPABLE(ha))) 10528c2ecf20Sopenharmony_ci continue; 10538c2ecf20Sopenharmony_ci 10548c2ecf20Sopenharmony_ci sysfs_remove_bin_file(&host->shost_gendev.kobj, 10558c2ecf20Sopenharmony_ci iter->attr); 10568c2ecf20Sopenharmony_ci } 10578c2ecf20Sopenharmony_ci 10588c2ecf20Sopenharmony_ci if (stop_beacon && ha->beacon_blink_led == 1) 10598c2ecf20Sopenharmony_ci ha->isp_ops->beacon_off(vha); 10608c2ecf20Sopenharmony_ci} 10618c2ecf20Sopenharmony_ci 10628c2ecf20Sopenharmony_ci/* Scsi_Host attributes. */ 10638c2ecf20Sopenharmony_ci 10648c2ecf20Sopenharmony_cistatic ssize_t 10658c2ecf20Sopenharmony_ciqla2x00_driver_version_show(struct device *dev, 10668c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 10678c2ecf20Sopenharmony_ci{ 10688c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%s\n", qla2x00_version_str); 10698c2ecf20Sopenharmony_ci} 10708c2ecf20Sopenharmony_ci 10718c2ecf20Sopenharmony_cistatic ssize_t 10728c2ecf20Sopenharmony_ciqla2x00_fw_version_show(struct device *dev, 10738c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 10748c2ecf20Sopenharmony_ci{ 10758c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 10768c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 10778c2ecf20Sopenharmony_ci char fw_str[128]; 10788c2ecf20Sopenharmony_ci 10798c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%s\n", 10808c2ecf20Sopenharmony_ci ha->isp_ops->fw_version_str(vha, fw_str, sizeof(fw_str))); 10818c2ecf20Sopenharmony_ci} 10828c2ecf20Sopenharmony_ci 10838c2ecf20Sopenharmony_cistatic ssize_t 10848c2ecf20Sopenharmony_ciqla2x00_serial_num_show(struct device *dev, struct device_attribute *attr, 10858c2ecf20Sopenharmony_ci char *buf) 10868c2ecf20Sopenharmony_ci{ 10878c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 10888c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 10898c2ecf20Sopenharmony_ci uint32_t sn; 10908c2ecf20Sopenharmony_ci 10918c2ecf20Sopenharmony_ci if (IS_QLAFX00(vha->hw)) { 10928c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%s\n", 10938c2ecf20Sopenharmony_ci vha->hw->mr.serial_num); 10948c2ecf20Sopenharmony_ci } else if (IS_FWI2_CAPABLE(ha)) { 10958c2ecf20Sopenharmony_ci qla2xxx_get_vpd_field(vha, "SN", buf, PAGE_SIZE - 1); 10968c2ecf20Sopenharmony_ci return strlen(strcat(buf, "\n")); 10978c2ecf20Sopenharmony_ci } 10988c2ecf20Sopenharmony_ci 10998c2ecf20Sopenharmony_ci sn = ((ha->serial0 & 0x1f) << 16) | (ha->serial2 << 8) | ha->serial1; 11008c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%c%05d\n", 'A' + sn / 100000, 11018c2ecf20Sopenharmony_ci sn % 100000); 11028c2ecf20Sopenharmony_ci} 11038c2ecf20Sopenharmony_ci 11048c2ecf20Sopenharmony_cistatic ssize_t 11058c2ecf20Sopenharmony_ciqla2x00_isp_name_show(struct device *dev, struct device_attribute *attr, 11068c2ecf20Sopenharmony_ci char *buf) 11078c2ecf20Sopenharmony_ci{ 11088c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 11098c2ecf20Sopenharmony_ci 11108c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "ISP%04X\n", vha->hw->pdev->device); 11118c2ecf20Sopenharmony_ci} 11128c2ecf20Sopenharmony_ci 11138c2ecf20Sopenharmony_cistatic ssize_t 11148c2ecf20Sopenharmony_ciqla2x00_isp_id_show(struct device *dev, struct device_attribute *attr, 11158c2ecf20Sopenharmony_ci char *buf) 11168c2ecf20Sopenharmony_ci{ 11178c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 11188c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 11198c2ecf20Sopenharmony_ci 11208c2ecf20Sopenharmony_ci if (IS_QLAFX00(vha->hw)) 11218c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%s\n", 11228c2ecf20Sopenharmony_ci vha->hw->mr.hw_version); 11238c2ecf20Sopenharmony_ci 11248c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%04x %04x %04x %04x\n", 11258c2ecf20Sopenharmony_ci ha->product_id[0], ha->product_id[1], ha->product_id[2], 11268c2ecf20Sopenharmony_ci ha->product_id[3]); 11278c2ecf20Sopenharmony_ci} 11288c2ecf20Sopenharmony_ci 11298c2ecf20Sopenharmony_cistatic ssize_t 11308c2ecf20Sopenharmony_ciqla2x00_model_name_show(struct device *dev, struct device_attribute *attr, 11318c2ecf20Sopenharmony_ci char *buf) 11328c2ecf20Sopenharmony_ci{ 11338c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 11348c2ecf20Sopenharmony_ci 11358c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%s\n", vha->hw->model_number); 11368c2ecf20Sopenharmony_ci} 11378c2ecf20Sopenharmony_ci 11388c2ecf20Sopenharmony_cistatic ssize_t 11398c2ecf20Sopenharmony_ciqla2x00_model_desc_show(struct device *dev, struct device_attribute *attr, 11408c2ecf20Sopenharmony_ci char *buf) 11418c2ecf20Sopenharmony_ci{ 11428c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 11438c2ecf20Sopenharmony_ci 11448c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%s\n", vha->hw->model_desc); 11458c2ecf20Sopenharmony_ci} 11468c2ecf20Sopenharmony_ci 11478c2ecf20Sopenharmony_cistatic ssize_t 11488c2ecf20Sopenharmony_ciqla2x00_pci_info_show(struct device *dev, struct device_attribute *attr, 11498c2ecf20Sopenharmony_ci char *buf) 11508c2ecf20Sopenharmony_ci{ 11518c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 11528c2ecf20Sopenharmony_ci char pci_info[30]; 11538c2ecf20Sopenharmony_ci 11548c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%s\n", 11558c2ecf20Sopenharmony_ci vha->hw->isp_ops->pci_info_str(vha, pci_info, 11568c2ecf20Sopenharmony_ci sizeof(pci_info))); 11578c2ecf20Sopenharmony_ci} 11588c2ecf20Sopenharmony_ci 11598c2ecf20Sopenharmony_cistatic ssize_t 11608c2ecf20Sopenharmony_ciqla2x00_link_state_show(struct device *dev, struct device_attribute *attr, 11618c2ecf20Sopenharmony_ci char *buf) 11628c2ecf20Sopenharmony_ci{ 11638c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 11648c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 11658c2ecf20Sopenharmony_ci int len = 0; 11668c2ecf20Sopenharmony_ci 11678c2ecf20Sopenharmony_ci if (atomic_read(&vha->loop_state) == LOOP_DOWN || 11688c2ecf20Sopenharmony_ci atomic_read(&vha->loop_state) == LOOP_DEAD || 11698c2ecf20Sopenharmony_ci vha->device_flags & DFLG_NO_CABLE) 11708c2ecf20Sopenharmony_ci len = scnprintf(buf, PAGE_SIZE, "Link Down\n"); 11718c2ecf20Sopenharmony_ci else if (atomic_read(&vha->loop_state) != LOOP_READY || 11728c2ecf20Sopenharmony_ci qla2x00_chip_is_down(vha)) 11738c2ecf20Sopenharmony_ci len = scnprintf(buf, PAGE_SIZE, "Unknown Link State\n"); 11748c2ecf20Sopenharmony_ci else { 11758c2ecf20Sopenharmony_ci len = scnprintf(buf, PAGE_SIZE, "Link Up - "); 11768c2ecf20Sopenharmony_ci 11778c2ecf20Sopenharmony_ci switch (ha->current_topology) { 11788c2ecf20Sopenharmony_ci case ISP_CFG_NL: 11798c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, "Loop\n"); 11808c2ecf20Sopenharmony_ci break; 11818c2ecf20Sopenharmony_ci case ISP_CFG_FL: 11828c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, "FL_Port\n"); 11838c2ecf20Sopenharmony_ci break; 11848c2ecf20Sopenharmony_ci case ISP_CFG_N: 11858c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, 11868c2ecf20Sopenharmony_ci "N_Port to N_Port\n"); 11878c2ecf20Sopenharmony_ci break; 11888c2ecf20Sopenharmony_ci case ISP_CFG_F: 11898c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, "F_Port\n"); 11908c2ecf20Sopenharmony_ci break; 11918c2ecf20Sopenharmony_ci default: 11928c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, "Loop\n"); 11938c2ecf20Sopenharmony_ci break; 11948c2ecf20Sopenharmony_ci } 11958c2ecf20Sopenharmony_ci } 11968c2ecf20Sopenharmony_ci return len; 11978c2ecf20Sopenharmony_ci} 11988c2ecf20Sopenharmony_ci 11998c2ecf20Sopenharmony_cistatic ssize_t 12008c2ecf20Sopenharmony_ciqla2x00_zio_show(struct device *dev, struct device_attribute *attr, 12018c2ecf20Sopenharmony_ci char *buf) 12028c2ecf20Sopenharmony_ci{ 12038c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 12048c2ecf20Sopenharmony_ci int len = 0; 12058c2ecf20Sopenharmony_ci 12068c2ecf20Sopenharmony_ci switch (vha->hw->zio_mode) { 12078c2ecf20Sopenharmony_ci case QLA_ZIO_MODE_6: 12088c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, "Mode 6\n"); 12098c2ecf20Sopenharmony_ci break; 12108c2ecf20Sopenharmony_ci case QLA_ZIO_DISABLED: 12118c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, "Disabled\n"); 12128c2ecf20Sopenharmony_ci break; 12138c2ecf20Sopenharmony_ci } 12148c2ecf20Sopenharmony_ci return len; 12158c2ecf20Sopenharmony_ci} 12168c2ecf20Sopenharmony_ci 12178c2ecf20Sopenharmony_cistatic ssize_t 12188c2ecf20Sopenharmony_ciqla2x00_zio_store(struct device *dev, struct device_attribute *attr, 12198c2ecf20Sopenharmony_ci const char *buf, size_t count) 12208c2ecf20Sopenharmony_ci{ 12218c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 12228c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 12238c2ecf20Sopenharmony_ci int val = 0; 12248c2ecf20Sopenharmony_ci uint16_t zio_mode; 12258c2ecf20Sopenharmony_ci 12268c2ecf20Sopenharmony_ci if (!IS_ZIO_SUPPORTED(ha)) 12278c2ecf20Sopenharmony_ci return -ENOTSUPP; 12288c2ecf20Sopenharmony_ci 12298c2ecf20Sopenharmony_ci if (sscanf(buf, "%d", &val) != 1) 12308c2ecf20Sopenharmony_ci return -EINVAL; 12318c2ecf20Sopenharmony_ci 12328c2ecf20Sopenharmony_ci if (val) 12338c2ecf20Sopenharmony_ci zio_mode = QLA_ZIO_MODE_6; 12348c2ecf20Sopenharmony_ci else 12358c2ecf20Sopenharmony_ci zio_mode = QLA_ZIO_DISABLED; 12368c2ecf20Sopenharmony_ci 12378c2ecf20Sopenharmony_ci /* Update per-hba values and queue a reset. */ 12388c2ecf20Sopenharmony_ci if (zio_mode != QLA_ZIO_DISABLED || ha->zio_mode != QLA_ZIO_DISABLED) { 12398c2ecf20Sopenharmony_ci ha->zio_mode = zio_mode; 12408c2ecf20Sopenharmony_ci set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); 12418c2ecf20Sopenharmony_ci } 12428c2ecf20Sopenharmony_ci return strlen(buf); 12438c2ecf20Sopenharmony_ci} 12448c2ecf20Sopenharmony_ci 12458c2ecf20Sopenharmony_cistatic ssize_t 12468c2ecf20Sopenharmony_ciqla2x00_zio_timer_show(struct device *dev, struct device_attribute *attr, 12478c2ecf20Sopenharmony_ci char *buf) 12488c2ecf20Sopenharmony_ci{ 12498c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 12508c2ecf20Sopenharmony_ci 12518c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d us\n", vha->hw->zio_timer * 100); 12528c2ecf20Sopenharmony_ci} 12538c2ecf20Sopenharmony_ci 12548c2ecf20Sopenharmony_cistatic ssize_t 12558c2ecf20Sopenharmony_ciqla2x00_zio_timer_store(struct device *dev, struct device_attribute *attr, 12568c2ecf20Sopenharmony_ci const char *buf, size_t count) 12578c2ecf20Sopenharmony_ci{ 12588c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 12598c2ecf20Sopenharmony_ci int val = 0; 12608c2ecf20Sopenharmony_ci uint16_t zio_timer; 12618c2ecf20Sopenharmony_ci 12628c2ecf20Sopenharmony_ci if (sscanf(buf, "%d", &val) != 1) 12638c2ecf20Sopenharmony_ci return -EINVAL; 12648c2ecf20Sopenharmony_ci if (val > 25500 || val < 100) 12658c2ecf20Sopenharmony_ci return -ERANGE; 12668c2ecf20Sopenharmony_ci 12678c2ecf20Sopenharmony_ci zio_timer = (uint16_t)(val / 100); 12688c2ecf20Sopenharmony_ci vha->hw->zio_timer = zio_timer; 12698c2ecf20Sopenharmony_ci 12708c2ecf20Sopenharmony_ci return strlen(buf); 12718c2ecf20Sopenharmony_ci} 12728c2ecf20Sopenharmony_ci 12738c2ecf20Sopenharmony_cistatic ssize_t 12748c2ecf20Sopenharmony_ciqla_zio_threshold_show(struct device *dev, struct device_attribute *attr, 12758c2ecf20Sopenharmony_ci char *buf) 12768c2ecf20Sopenharmony_ci{ 12778c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 12788c2ecf20Sopenharmony_ci 12798c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d exchanges\n", 12808c2ecf20Sopenharmony_ci vha->hw->last_zio_threshold); 12818c2ecf20Sopenharmony_ci} 12828c2ecf20Sopenharmony_ci 12838c2ecf20Sopenharmony_cistatic ssize_t 12848c2ecf20Sopenharmony_ciqla_zio_threshold_store(struct device *dev, struct device_attribute *attr, 12858c2ecf20Sopenharmony_ci const char *buf, size_t count) 12868c2ecf20Sopenharmony_ci{ 12878c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 12888c2ecf20Sopenharmony_ci int val = 0; 12898c2ecf20Sopenharmony_ci 12908c2ecf20Sopenharmony_ci if (vha->hw->zio_mode != QLA_ZIO_MODE_6) 12918c2ecf20Sopenharmony_ci return -EINVAL; 12928c2ecf20Sopenharmony_ci if (sscanf(buf, "%d", &val) != 1) 12938c2ecf20Sopenharmony_ci return -EINVAL; 12948c2ecf20Sopenharmony_ci if (val < 0 || val > 256) 12958c2ecf20Sopenharmony_ci return -ERANGE; 12968c2ecf20Sopenharmony_ci 12978c2ecf20Sopenharmony_ci atomic_set(&vha->hw->zio_threshold, val); 12988c2ecf20Sopenharmony_ci return strlen(buf); 12998c2ecf20Sopenharmony_ci} 13008c2ecf20Sopenharmony_ci 13018c2ecf20Sopenharmony_cistatic ssize_t 13028c2ecf20Sopenharmony_ciqla2x00_beacon_show(struct device *dev, struct device_attribute *attr, 13038c2ecf20Sopenharmony_ci char *buf) 13048c2ecf20Sopenharmony_ci{ 13058c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 13068c2ecf20Sopenharmony_ci int len = 0; 13078c2ecf20Sopenharmony_ci 13088c2ecf20Sopenharmony_ci if (vha->hw->beacon_blink_led) 13098c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, "Enabled\n"); 13108c2ecf20Sopenharmony_ci else 13118c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, "Disabled\n"); 13128c2ecf20Sopenharmony_ci return len; 13138c2ecf20Sopenharmony_ci} 13148c2ecf20Sopenharmony_ci 13158c2ecf20Sopenharmony_cistatic ssize_t 13168c2ecf20Sopenharmony_ciqla2x00_beacon_store(struct device *dev, struct device_attribute *attr, 13178c2ecf20Sopenharmony_ci const char *buf, size_t count) 13188c2ecf20Sopenharmony_ci{ 13198c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 13208c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 13218c2ecf20Sopenharmony_ci int val = 0; 13228c2ecf20Sopenharmony_ci int rval; 13238c2ecf20Sopenharmony_ci 13248c2ecf20Sopenharmony_ci if (IS_QLA2100(ha) || IS_QLA2200(ha)) 13258c2ecf20Sopenharmony_ci return -EPERM; 13268c2ecf20Sopenharmony_ci 13278c2ecf20Sopenharmony_ci if (sscanf(buf, "%d", &val) != 1) 13288c2ecf20Sopenharmony_ci return -EINVAL; 13298c2ecf20Sopenharmony_ci 13308c2ecf20Sopenharmony_ci mutex_lock(&vha->hw->optrom_mutex); 13318c2ecf20Sopenharmony_ci if (qla2x00_chip_is_down(vha)) { 13328c2ecf20Sopenharmony_ci mutex_unlock(&vha->hw->optrom_mutex); 13338c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x707a, 13348c2ecf20Sopenharmony_ci "Abort ISP active -- ignoring beacon request.\n"); 13358c2ecf20Sopenharmony_ci return -EBUSY; 13368c2ecf20Sopenharmony_ci } 13378c2ecf20Sopenharmony_ci 13388c2ecf20Sopenharmony_ci if (val) 13398c2ecf20Sopenharmony_ci rval = ha->isp_ops->beacon_on(vha); 13408c2ecf20Sopenharmony_ci else 13418c2ecf20Sopenharmony_ci rval = ha->isp_ops->beacon_off(vha); 13428c2ecf20Sopenharmony_ci 13438c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) 13448c2ecf20Sopenharmony_ci count = 0; 13458c2ecf20Sopenharmony_ci 13468c2ecf20Sopenharmony_ci mutex_unlock(&vha->hw->optrom_mutex); 13478c2ecf20Sopenharmony_ci 13488c2ecf20Sopenharmony_ci return count; 13498c2ecf20Sopenharmony_ci} 13508c2ecf20Sopenharmony_ci 13518c2ecf20Sopenharmony_cistatic ssize_t 13528c2ecf20Sopenharmony_ciqla2x00_beacon_config_show(struct device *dev, struct device_attribute *attr, 13538c2ecf20Sopenharmony_ci char *buf) 13548c2ecf20Sopenharmony_ci{ 13558c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 13568c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 13578c2ecf20Sopenharmony_ci uint16_t led[3] = { 0 }; 13588c2ecf20Sopenharmony_ci 13598c2ecf20Sopenharmony_ci if (!IS_QLA2031(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) 13608c2ecf20Sopenharmony_ci return -EPERM; 13618c2ecf20Sopenharmony_ci 13628c2ecf20Sopenharmony_ci if (ql26xx_led_config(vha, 0, led)) 13638c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "\n"); 13648c2ecf20Sopenharmony_ci 13658c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%#04hx %#04hx %#04hx\n", 13668c2ecf20Sopenharmony_ci led[0], led[1], led[2]); 13678c2ecf20Sopenharmony_ci} 13688c2ecf20Sopenharmony_ci 13698c2ecf20Sopenharmony_cistatic ssize_t 13708c2ecf20Sopenharmony_ciqla2x00_beacon_config_store(struct device *dev, struct device_attribute *attr, 13718c2ecf20Sopenharmony_ci const char *buf, size_t count) 13728c2ecf20Sopenharmony_ci{ 13738c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 13748c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 13758c2ecf20Sopenharmony_ci uint16_t options = BIT_0; 13768c2ecf20Sopenharmony_ci uint16_t led[3] = { 0 }; 13778c2ecf20Sopenharmony_ci uint16_t word[4]; 13788c2ecf20Sopenharmony_ci int n; 13798c2ecf20Sopenharmony_ci 13808c2ecf20Sopenharmony_ci if (!IS_QLA2031(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) 13818c2ecf20Sopenharmony_ci return -EPERM; 13828c2ecf20Sopenharmony_ci 13838c2ecf20Sopenharmony_ci n = sscanf(buf, "%hx %hx %hx %hx", word+0, word+1, word+2, word+3); 13848c2ecf20Sopenharmony_ci if (n == 4) { 13858c2ecf20Sopenharmony_ci if (word[0] == 3) { 13868c2ecf20Sopenharmony_ci options |= BIT_3|BIT_2|BIT_1; 13878c2ecf20Sopenharmony_ci led[0] = word[1]; 13888c2ecf20Sopenharmony_ci led[1] = word[2]; 13898c2ecf20Sopenharmony_ci led[2] = word[3]; 13908c2ecf20Sopenharmony_ci goto write; 13918c2ecf20Sopenharmony_ci } 13928c2ecf20Sopenharmony_ci return -EINVAL; 13938c2ecf20Sopenharmony_ci } 13948c2ecf20Sopenharmony_ci 13958c2ecf20Sopenharmony_ci if (n == 2) { 13968c2ecf20Sopenharmony_ci /* check led index */ 13978c2ecf20Sopenharmony_ci if (word[0] == 0) { 13988c2ecf20Sopenharmony_ci options |= BIT_2; 13998c2ecf20Sopenharmony_ci led[0] = word[1]; 14008c2ecf20Sopenharmony_ci goto write; 14018c2ecf20Sopenharmony_ci } 14028c2ecf20Sopenharmony_ci if (word[0] == 1) { 14038c2ecf20Sopenharmony_ci options |= BIT_3; 14048c2ecf20Sopenharmony_ci led[1] = word[1]; 14058c2ecf20Sopenharmony_ci goto write; 14068c2ecf20Sopenharmony_ci } 14078c2ecf20Sopenharmony_ci if (word[0] == 2) { 14088c2ecf20Sopenharmony_ci options |= BIT_1; 14098c2ecf20Sopenharmony_ci led[2] = word[1]; 14108c2ecf20Sopenharmony_ci goto write; 14118c2ecf20Sopenharmony_ci } 14128c2ecf20Sopenharmony_ci return -EINVAL; 14138c2ecf20Sopenharmony_ci } 14148c2ecf20Sopenharmony_ci 14158c2ecf20Sopenharmony_ci return -EINVAL; 14168c2ecf20Sopenharmony_ci 14178c2ecf20Sopenharmony_ciwrite: 14188c2ecf20Sopenharmony_ci if (ql26xx_led_config(vha, options, led)) 14198c2ecf20Sopenharmony_ci return -EFAULT; 14208c2ecf20Sopenharmony_ci 14218c2ecf20Sopenharmony_ci return count; 14228c2ecf20Sopenharmony_ci} 14238c2ecf20Sopenharmony_ci 14248c2ecf20Sopenharmony_cistatic ssize_t 14258c2ecf20Sopenharmony_ciqla2x00_optrom_bios_version_show(struct device *dev, 14268c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 14278c2ecf20Sopenharmony_ci{ 14288c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 14298c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 14308c2ecf20Sopenharmony_ci 14318c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->bios_revision[1], 14328c2ecf20Sopenharmony_ci ha->bios_revision[0]); 14338c2ecf20Sopenharmony_ci} 14348c2ecf20Sopenharmony_ci 14358c2ecf20Sopenharmony_cistatic ssize_t 14368c2ecf20Sopenharmony_ciqla2x00_optrom_efi_version_show(struct device *dev, 14378c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 14388c2ecf20Sopenharmony_ci{ 14398c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 14408c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 14418c2ecf20Sopenharmony_ci 14428c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->efi_revision[1], 14438c2ecf20Sopenharmony_ci ha->efi_revision[0]); 14448c2ecf20Sopenharmony_ci} 14458c2ecf20Sopenharmony_ci 14468c2ecf20Sopenharmony_cistatic ssize_t 14478c2ecf20Sopenharmony_ciqla2x00_optrom_fcode_version_show(struct device *dev, 14488c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 14498c2ecf20Sopenharmony_ci{ 14508c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 14518c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 14528c2ecf20Sopenharmony_ci 14538c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->fcode_revision[1], 14548c2ecf20Sopenharmony_ci ha->fcode_revision[0]); 14558c2ecf20Sopenharmony_ci} 14568c2ecf20Sopenharmony_ci 14578c2ecf20Sopenharmony_cistatic ssize_t 14588c2ecf20Sopenharmony_ciqla2x00_optrom_fw_version_show(struct device *dev, 14598c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 14608c2ecf20Sopenharmony_ci{ 14618c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 14628c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 14638c2ecf20Sopenharmony_ci 14648c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d.%02d.%02d %d\n", 14658c2ecf20Sopenharmony_ci ha->fw_revision[0], ha->fw_revision[1], ha->fw_revision[2], 14668c2ecf20Sopenharmony_ci ha->fw_revision[3]); 14678c2ecf20Sopenharmony_ci} 14688c2ecf20Sopenharmony_ci 14698c2ecf20Sopenharmony_cistatic ssize_t 14708c2ecf20Sopenharmony_ciqla2x00_optrom_gold_fw_version_show(struct device *dev, 14718c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 14728c2ecf20Sopenharmony_ci{ 14738c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 14748c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 14758c2ecf20Sopenharmony_ci 14768c2ecf20Sopenharmony_ci if (!IS_QLA81XX(ha) && !IS_QLA83XX(ha) && 14778c2ecf20Sopenharmony_ci !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) 14788c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "\n"); 14798c2ecf20Sopenharmony_ci 14808c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d.%02d.%02d (%d)\n", 14818c2ecf20Sopenharmony_ci ha->gold_fw_version[0], ha->gold_fw_version[1], 14828c2ecf20Sopenharmony_ci ha->gold_fw_version[2], ha->gold_fw_version[3]); 14838c2ecf20Sopenharmony_ci} 14848c2ecf20Sopenharmony_ci 14858c2ecf20Sopenharmony_cistatic ssize_t 14868c2ecf20Sopenharmony_ciqla2x00_total_isp_aborts_show(struct device *dev, 14878c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 14888c2ecf20Sopenharmony_ci{ 14898c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 14908c2ecf20Sopenharmony_ci 14918c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d\n", 14928c2ecf20Sopenharmony_ci vha->qla_stats.total_isp_aborts); 14938c2ecf20Sopenharmony_ci} 14948c2ecf20Sopenharmony_ci 14958c2ecf20Sopenharmony_cistatic ssize_t 14968c2ecf20Sopenharmony_ciqla24xx_84xx_fw_version_show(struct device *dev, 14978c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 14988c2ecf20Sopenharmony_ci{ 14998c2ecf20Sopenharmony_ci int rval = QLA_SUCCESS; 15008c2ecf20Sopenharmony_ci uint16_t status[2] = { 0 }; 15018c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 15028c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 15038c2ecf20Sopenharmony_ci 15048c2ecf20Sopenharmony_ci if (!IS_QLA84XX(ha)) 15058c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "\n"); 15068c2ecf20Sopenharmony_ci 15078c2ecf20Sopenharmony_ci if (!ha->cs84xx->op_fw_version) { 15088c2ecf20Sopenharmony_ci rval = qla84xx_verify_chip(vha, status); 15098c2ecf20Sopenharmony_ci 15108c2ecf20Sopenharmony_ci if (!rval && !status[0]) 15118c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%u\n", 15128c2ecf20Sopenharmony_ci (uint32_t)ha->cs84xx->op_fw_version); 15138c2ecf20Sopenharmony_ci } 15148c2ecf20Sopenharmony_ci 15158c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "\n"); 15168c2ecf20Sopenharmony_ci} 15178c2ecf20Sopenharmony_ci 15188c2ecf20Sopenharmony_cistatic ssize_t 15198c2ecf20Sopenharmony_ciqla2x00_serdes_version_show(struct device *dev, struct device_attribute *attr, 15208c2ecf20Sopenharmony_ci char *buf) 15218c2ecf20Sopenharmony_ci{ 15228c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 15238c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 15248c2ecf20Sopenharmony_ci 15258c2ecf20Sopenharmony_ci if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) 15268c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "\n"); 15278c2ecf20Sopenharmony_ci 15288c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d.%02d.%02d\n", 15298c2ecf20Sopenharmony_ci ha->serdes_version[0], ha->serdes_version[1], 15308c2ecf20Sopenharmony_ci ha->serdes_version[2]); 15318c2ecf20Sopenharmony_ci} 15328c2ecf20Sopenharmony_ci 15338c2ecf20Sopenharmony_cistatic ssize_t 15348c2ecf20Sopenharmony_ciqla2x00_mpi_version_show(struct device *dev, struct device_attribute *attr, 15358c2ecf20Sopenharmony_ci char *buf) 15368c2ecf20Sopenharmony_ci{ 15378c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 15388c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 15398c2ecf20Sopenharmony_ci 15408c2ecf20Sopenharmony_ci if (!IS_QLA81XX(ha) && !IS_QLA8031(ha) && !IS_QLA8044(ha) && 15418c2ecf20Sopenharmony_ci !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) 15428c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "\n"); 15438c2ecf20Sopenharmony_ci 15448c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d.%02d.%02d (%x)\n", 15458c2ecf20Sopenharmony_ci ha->mpi_version[0], ha->mpi_version[1], ha->mpi_version[2], 15468c2ecf20Sopenharmony_ci ha->mpi_capabilities); 15478c2ecf20Sopenharmony_ci} 15488c2ecf20Sopenharmony_ci 15498c2ecf20Sopenharmony_cistatic ssize_t 15508c2ecf20Sopenharmony_ciqla2x00_phy_version_show(struct device *dev, struct device_attribute *attr, 15518c2ecf20Sopenharmony_ci char *buf) 15528c2ecf20Sopenharmony_ci{ 15538c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 15548c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 15558c2ecf20Sopenharmony_ci 15568c2ecf20Sopenharmony_ci if (!IS_QLA81XX(ha) && !IS_QLA8031(ha)) 15578c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "\n"); 15588c2ecf20Sopenharmony_ci 15598c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d.%02d.%02d\n", 15608c2ecf20Sopenharmony_ci ha->phy_version[0], ha->phy_version[1], ha->phy_version[2]); 15618c2ecf20Sopenharmony_ci} 15628c2ecf20Sopenharmony_ci 15638c2ecf20Sopenharmony_cistatic ssize_t 15648c2ecf20Sopenharmony_ciqla2x00_flash_block_size_show(struct device *dev, 15658c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 15668c2ecf20Sopenharmony_ci{ 15678c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 15688c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 15698c2ecf20Sopenharmony_ci 15708c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "0x%x\n", ha->fdt_block_size); 15718c2ecf20Sopenharmony_ci} 15728c2ecf20Sopenharmony_ci 15738c2ecf20Sopenharmony_cistatic ssize_t 15748c2ecf20Sopenharmony_ciqla2x00_vlan_id_show(struct device *dev, struct device_attribute *attr, 15758c2ecf20Sopenharmony_ci char *buf) 15768c2ecf20Sopenharmony_ci{ 15778c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 15788c2ecf20Sopenharmony_ci 15798c2ecf20Sopenharmony_ci if (!IS_CNA_CAPABLE(vha->hw)) 15808c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "\n"); 15818c2ecf20Sopenharmony_ci 15828c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d\n", vha->fcoe_vlan_id); 15838c2ecf20Sopenharmony_ci} 15848c2ecf20Sopenharmony_ci 15858c2ecf20Sopenharmony_cistatic ssize_t 15868c2ecf20Sopenharmony_ciqla2x00_vn_port_mac_address_show(struct device *dev, 15878c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 15888c2ecf20Sopenharmony_ci{ 15898c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 15908c2ecf20Sopenharmony_ci 15918c2ecf20Sopenharmony_ci if (!IS_CNA_CAPABLE(vha->hw)) 15928c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "\n"); 15938c2ecf20Sopenharmony_ci 15948c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%pMR\n", vha->fcoe_vn_port_mac); 15958c2ecf20Sopenharmony_ci} 15968c2ecf20Sopenharmony_ci 15978c2ecf20Sopenharmony_cistatic ssize_t 15988c2ecf20Sopenharmony_ciqla2x00_fabric_param_show(struct device *dev, struct device_attribute *attr, 15998c2ecf20Sopenharmony_ci char *buf) 16008c2ecf20Sopenharmony_ci{ 16018c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 16028c2ecf20Sopenharmony_ci 16038c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d\n", vha->hw->switch_cap); 16048c2ecf20Sopenharmony_ci} 16058c2ecf20Sopenharmony_ci 16068c2ecf20Sopenharmony_cistatic ssize_t 16078c2ecf20Sopenharmony_ciqla2x00_thermal_temp_show(struct device *dev, 16088c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 16098c2ecf20Sopenharmony_ci{ 16108c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 16118c2ecf20Sopenharmony_ci uint16_t temp = 0; 16128c2ecf20Sopenharmony_ci int rc; 16138c2ecf20Sopenharmony_ci 16148c2ecf20Sopenharmony_ci mutex_lock(&vha->hw->optrom_mutex); 16158c2ecf20Sopenharmony_ci if (qla2x00_chip_is_down(vha)) { 16168c2ecf20Sopenharmony_ci mutex_unlock(&vha->hw->optrom_mutex); 16178c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x70dc, "ISP reset active.\n"); 16188c2ecf20Sopenharmony_ci goto done; 16198c2ecf20Sopenharmony_ci } 16208c2ecf20Sopenharmony_ci 16218c2ecf20Sopenharmony_ci if (vha->hw->flags.eeh_busy) { 16228c2ecf20Sopenharmony_ci mutex_unlock(&vha->hw->optrom_mutex); 16238c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x70dd, "PCI EEH busy.\n"); 16248c2ecf20Sopenharmony_ci goto done; 16258c2ecf20Sopenharmony_ci } 16268c2ecf20Sopenharmony_ci 16278c2ecf20Sopenharmony_ci rc = qla2x00_get_thermal_temp(vha, &temp); 16288c2ecf20Sopenharmony_ci mutex_unlock(&vha->hw->optrom_mutex); 16298c2ecf20Sopenharmony_ci if (rc == QLA_SUCCESS) 16308c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d\n", temp); 16318c2ecf20Sopenharmony_ci 16328c2ecf20Sopenharmony_cidone: 16338c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "\n"); 16348c2ecf20Sopenharmony_ci} 16358c2ecf20Sopenharmony_ci 16368c2ecf20Sopenharmony_cistatic ssize_t 16378c2ecf20Sopenharmony_ciqla2x00_fw_state_show(struct device *dev, struct device_attribute *attr, 16388c2ecf20Sopenharmony_ci char *buf) 16398c2ecf20Sopenharmony_ci{ 16408c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 16418c2ecf20Sopenharmony_ci int rval = QLA_FUNCTION_FAILED; 16428c2ecf20Sopenharmony_ci uint16_t state[6]; 16438c2ecf20Sopenharmony_ci uint32_t pstate; 16448c2ecf20Sopenharmony_ci 16458c2ecf20Sopenharmony_ci if (IS_QLAFX00(vha->hw)) { 16468c2ecf20Sopenharmony_ci pstate = qlafx00_fw_state_show(dev, attr, buf); 16478c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "0x%x\n", pstate); 16488c2ecf20Sopenharmony_ci } 16498c2ecf20Sopenharmony_ci 16508c2ecf20Sopenharmony_ci mutex_lock(&vha->hw->optrom_mutex); 16518c2ecf20Sopenharmony_ci if (qla2x00_chip_is_down(vha)) { 16528c2ecf20Sopenharmony_ci mutex_unlock(&vha->hw->optrom_mutex); 16538c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x707c, 16548c2ecf20Sopenharmony_ci "ISP reset active.\n"); 16558c2ecf20Sopenharmony_ci goto out; 16568c2ecf20Sopenharmony_ci } else if (vha->hw->flags.eeh_busy) { 16578c2ecf20Sopenharmony_ci mutex_unlock(&vha->hw->optrom_mutex); 16588c2ecf20Sopenharmony_ci goto out; 16598c2ecf20Sopenharmony_ci } 16608c2ecf20Sopenharmony_ci 16618c2ecf20Sopenharmony_ci rval = qla2x00_get_firmware_state(vha, state); 16628c2ecf20Sopenharmony_ci mutex_unlock(&vha->hw->optrom_mutex); 16638c2ecf20Sopenharmony_ciout: 16648c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) { 16658c2ecf20Sopenharmony_ci memset(state, -1, sizeof(state)); 16668c2ecf20Sopenharmony_ci rval = qla2x00_get_firmware_state(vha, state); 16678c2ecf20Sopenharmony_ci } 16688c2ecf20Sopenharmony_ci 16698c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", 16708c2ecf20Sopenharmony_ci state[0], state[1], state[2], state[3], state[4], state[5]); 16718c2ecf20Sopenharmony_ci} 16728c2ecf20Sopenharmony_ci 16738c2ecf20Sopenharmony_cistatic ssize_t 16748c2ecf20Sopenharmony_ciqla2x00_diag_requests_show(struct device *dev, 16758c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 16768c2ecf20Sopenharmony_ci{ 16778c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 16788c2ecf20Sopenharmony_ci 16798c2ecf20Sopenharmony_ci if (!IS_BIDI_CAPABLE(vha->hw)) 16808c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "\n"); 16818c2ecf20Sopenharmony_ci 16828c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%llu\n", vha->bidi_stats.io_count); 16838c2ecf20Sopenharmony_ci} 16848c2ecf20Sopenharmony_ci 16858c2ecf20Sopenharmony_cistatic ssize_t 16868c2ecf20Sopenharmony_ciqla2x00_diag_megabytes_show(struct device *dev, 16878c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 16888c2ecf20Sopenharmony_ci{ 16898c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 16908c2ecf20Sopenharmony_ci 16918c2ecf20Sopenharmony_ci if (!IS_BIDI_CAPABLE(vha->hw)) 16928c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "\n"); 16938c2ecf20Sopenharmony_ci 16948c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%llu\n", 16958c2ecf20Sopenharmony_ci vha->bidi_stats.transfer_bytes >> 20); 16968c2ecf20Sopenharmony_ci} 16978c2ecf20Sopenharmony_ci 16988c2ecf20Sopenharmony_cistatic ssize_t 16998c2ecf20Sopenharmony_ciqla2x00_fw_dump_size_show(struct device *dev, struct device_attribute *attr, 17008c2ecf20Sopenharmony_ci char *buf) 17018c2ecf20Sopenharmony_ci{ 17028c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 17038c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 17048c2ecf20Sopenharmony_ci uint32_t size; 17058c2ecf20Sopenharmony_ci 17068c2ecf20Sopenharmony_ci if (!ha->fw_dumped) 17078c2ecf20Sopenharmony_ci size = 0; 17088c2ecf20Sopenharmony_ci else if (IS_P3P_TYPE(ha)) 17098c2ecf20Sopenharmony_ci size = ha->md_template_size + ha->md_dump_size; 17108c2ecf20Sopenharmony_ci else 17118c2ecf20Sopenharmony_ci size = ha->fw_dump_len; 17128c2ecf20Sopenharmony_ci 17138c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d\n", size); 17148c2ecf20Sopenharmony_ci} 17158c2ecf20Sopenharmony_ci 17168c2ecf20Sopenharmony_cistatic ssize_t 17178c2ecf20Sopenharmony_ciqla2x00_allow_cna_fw_dump_show(struct device *dev, 17188c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 17198c2ecf20Sopenharmony_ci{ 17208c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 17218c2ecf20Sopenharmony_ci 17228c2ecf20Sopenharmony_ci if (!IS_P3P_TYPE(vha->hw)) 17238c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "\n"); 17248c2ecf20Sopenharmony_ci else 17258c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%s\n", 17268c2ecf20Sopenharmony_ci vha->hw->allow_cna_fw_dump ? "true" : "false"); 17278c2ecf20Sopenharmony_ci} 17288c2ecf20Sopenharmony_ci 17298c2ecf20Sopenharmony_cistatic ssize_t 17308c2ecf20Sopenharmony_ciqla2x00_allow_cna_fw_dump_store(struct device *dev, 17318c2ecf20Sopenharmony_ci struct device_attribute *attr, const char *buf, size_t count) 17328c2ecf20Sopenharmony_ci{ 17338c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 17348c2ecf20Sopenharmony_ci int val = 0; 17358c2ecf20Sopenharmony_ci 17368c2ecf20Sopenharmony_ci if (!IS_P3P_TYPE(vha->hw)) 17378c2ecf20Sopenharmony_ci return -EINVAL; 17388c2ecf20Sopenharmony_ci 17398c2ecf20Sopenharmony_ci if (sscanf(buf, "%d", &val) != 1) 17408c2ecf20Sopenharmony_ci return -EINVAL; 17418c2ecf20Sopenharmony_ci 17428c2ecf20Sopenharmony_ci vha->hw->allow_cna_fw_dump = val != 0; 17438c2ecf20Sopenharmony_ci 17448c2ecf20Sopenharmony_ci return strlen(buf); 17458c2ecf20Sopenharmony_ci} 17468c2ecf20Sopenharmony_ci 17478c2ecf20Sopenharmony_cistatic ssize_t 17488c2ecf20Sopenharmony_ciqla2x00_pep_version_show(struct device *dev, struct device_attribute *attr, 17498c2ecf20Sopenharmony_ci char *buf) 17508c2ecf20Sopenharmony_ci{ 17518c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 17528c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 17538c2ecf20Sopenharmony_ci 17548c2ecf20Sopenharmony_ci if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) 17558c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "\n"); 17568c2ecf20Sopenharmony_ci 17578c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d.%02d.%02d\n", 17588c2ecf20Sopenharmony_ci ha->pep_version[0], ha->pep_version[1], ha->pep_version[2]); 17598c2ecf20Sopenharmony_ci} 17608c2ecf20Sopenharmony_ci 17618c2ecf20Sopenharmony_cistatic ssize_t 17628c2ecf20Sopenharmony_ciqla2x00_min_supported_speed_show(struct device *dev, 17638c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 17648c2ecf20Sopenharmony_ci{ 17658c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 17668c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 17678c2ecf20Sopenharmony_ci 17688c2ecf20Sopenharmony_ci if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) 17698c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "\n"); 17708c2ecf20Sopenharmony_ci 17718c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%s\n", 17728c2ecf20Sopenharmony_ci ha->min_supported_speed == 6 ? "64Gps" : 17738c2ecf20Sopenharmony_ci ha->min_supported_speed == 5 ? "32Gps" : 17748c2ecf20Sopenharmony_ci ha->min_supported_speed == 4 ? "16Gps" : 17758c2ecf20Sopenharmony_ci ha->min_supported_speed == 3 ? "8Gps" : 17768c2ecf20Sopenharmony_ci ha->min_supported_speed == 2 ? "4Gps" : 17778c2ecf20Sopenharmony_ci ha->min_supported_speed != 0 ? "unknown" : ""); 17788c2ecf20Sopenharmony_ci} 17798c2ecf20Sopenharmony_ci 17808c2ecf20Sopenharmony_cistatic ssize_t 17818c2ecf20Sopenharmony_ciqla2x00_max_supported_speed_show(struct device *dev, 17828c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 17838c2ecf20Sopenharmony_ci{ 17848c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 17858c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 17868c2ecf20Sopenharmony_ci 17878c2ecf20Sopenharmony_ci if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) 17888c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "\n"); 17898c2ecf20Sopenharmony_ci 17908c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%s\n", 17918c2ecf20Sopenharmony_ci ha->max_supported_speed == 2 ? "64Gps" : 17928c2ecf20Sopenharmony_ci ha->max_supported_speed == 1 ? "32Gps" : 17938c2ecf20Sopenharmony_ci ha->max_supported_speed == 0 ? "16Gps" : "unknown"); 17948c2ecf20Sopenharmony_ci} 17958c2ecf20Sopenharmony_ci 17968c2ecf20Sopenharmony_cistatic ssize_t 17978c2ecf20Sopenharmony_ciqla2x00_port_speed_store(struct device *dev, struct device_attribute *attr, 17988c2ecf20Sopenharmony_ci const char *buf, size_t count) 17998c2ecf20Sopenharmony_ci{ 18008c2ecf20Sopenharmony_ci struct scsi_qla_host *vha = shost_priv(dev_to_shost(dev)); 18018c2ecf20Sopenharmony_ci ulong type, speed; 18028c2ecf20Sopenharmony_ci int oldspeed, rval; 18038c2ecf20Sopenharmony_ci int mode = QLA_SET_DATA_RATE_LR; 18048c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 18058c2ecf20Sopenharmony_ci 18068c2ecf20Sopenharmony_ci if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) { 18078c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x70d8, 18088c2ecf20Sopenharmony_ci "Speed setting not supported \n"); 18098c2ecf20Sopenharmony_ci return -EINVAL; 18108c2ecf20Sopenharmony_ci } 18118c2ecf20Sopenharmony_ci 18128c2ecf20Sopenharmony_ci rval = kstrtol(buf, 10, &type); 18138c2ecf20Sopenharmony_ci if (rval) 18148c2ecf20Sopenharmony_ci return rval; 18158c2ecf20Sopenharmony_ci speed = type; 18168c2ecf20Sopenharmony_ci if (type == 40 || type == 80 || type == 160 || 18178c2ecf20Sopenharmony_ci type == 320) { 18188c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_user, vha, 0x70d9, 18198c2ecf20Sopenharmony_ci "Setting will be affected after a loss of sync\n"); 18208c2ecf20Sopenharmony_ci type = type/10; 18218c2ecf20Sopenharmony_ci mode = QLA_SET_DATA_RATE_NOLR; 18228c2ecf20Sopenharmony_ci } 18238c2ecf20Sopenharmony_ci 18248c2ecf20Sopenharmony_ci oldspeed = ha->set_data_rate; 18258c2ecf20Sopenharmony_ci 18268c2ecf20Sopenharmony_ci switch (type) { 18278c2ecf20Sopenharmony_ci case 0: 18288c2ecf20Sopenharmony_ci ha->set_data_rate = PORT_SPEED_AUTO; 18298c2ecf20Sopenharmony_ci break; 18308c2ecf20Sopenharmony_ci case 4: 18318c2ecf20Sopenharmony_ci ha->set_data_rate = PORT_SPEED_4GB; 18328c2ecf20Sopenharmony_ci break; 18338c2ecf20Sopenharmony_ci case 8: 18348c2ecf20Sopenharmony_ci ha->set_data_rate = PORT_SPEED_8GB; 18358c2ecf20Sopenharmony_ci break; 18368c2ecf20Sopenharmony_ci case 16: 18378c2ecf20Sopenharmony_ci ha->set_data_rate = PORT_SPEED_16GB; 18388c2ecf20Sopenharmony_ci break; 18398c2ecf20Sopenharmony_ci case 32: 18408c2ecf20Sopenharmony_ci ha->set_data_rate = PORT_SPEED_32GB; 18418c2ecf20Sopenharmony_ci break; 18428c2ecf20Sopenharmony_ci default: 18438c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x1199, 18448c2ecf20Sopenharmony_ci "Unrecognized speed setting:%lx. Setting Autoneg\n", 18458c2ecf20Sopenharmony_ci speed); 18468c2ecf20Sopenharmony_ci ha->set_data_rate = PORT_SPEED_AUTO; 18478c2ecf20Sopenharmony_ci } 18488c2ecf20Sopenharmony_ci 18498c2ecf20Sopenharmony_ci if (qla2x00_chip_is_down(vha) || (oldspeed == ha->set_data_rate)) 18508c2ecf20Sopenharmony_ci return -EINVAL; 18518c2ecf20Sopenharmony_ci 18528c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x70da, 18538c2ecf20Sopenharmony_ci "Setting speed to %lx Gbps \n", type); 18548c2ecf20Sopenharmony_ci 18558c2ecf20Sopenharmony_ci rval = qla2x00_set_data_rate(vha, mode); 18568c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) 18578c2ecf20Sopenharmony_ci return -EIO; 18588c2ecf20Sopenharmony_ci 18598c2ecf20Sopenharmony_ci return strlen(buf); 18608c2ecf20Sopenharmony_ci} 18618c2ecf20Sopenharmony_ci 18628c2ecf20Sopenharmony_cistatic const struct { 18638c2ecf20Sopenharmony_ci u16 rate; 18648c2ecf20Sopenharmony_ci char *str; 18658c2ecf20Sopenharmony_ci} port_speed_str[] = { 18668c2ecf20Sopenharmony_ci { PORT_SPEED_4GB, "4" }, 18678c2ecf20Sopenharmony_ci { PORT_SPEED_8GB, "8" }, 18688c2ecf20Sopenharmony_ci { PORT_SPEED_16GB, "16" }, 18698c2ecf20Sopenharmony_ci { PORT_SPEED_32GB, "32" }, 18708c2ecf20Sopenharmony_ci { PORT_SPEED_64GB, "64" }, 18718c2ecf20Sopenharmony_ci { PORT_SPEED_10GB, "10" }, 18728c2ecf20Sopenharmony_ci}; 18738c2ecf20Sopenharmony_ci 18748c2ecf20Sopenharmony_cistatic ssize_t 18758c2ecf20Sopenharmony_ciqla2x00_port_speed_show(struct device *dev, struct device_attribute *attr, 18768c2ecf20Sopenharmony_ci char *buf) 18778c2ecf20Sopenharmony_ci{ 18788c2ecf20Sopenharmony_ci struct scsi_qla_host *vha = shost_priv(dev_to_shost(dev)); 18798c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 18808c2ecf20Sopenharmony_ci ssize_t rval; 18818c2ecf20Sopenharmony_ci u16 i; 18828c2ecf20Sopenharmony_ci char *speed = "Unknown"; 18838c2ecf20Sopenharmony_ci 18848c2ecf20Sopenharmony_ci rval = qla2x00_get_data_rate(vha); 18858c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) { 18868c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x70db, 18878c2ecf20Sopenharmony_ci "Unable to get port speed rval:%zd\n", rval); 18888c2ecf20Sopenharmony_ci return -EINVAL; 18898c2ecf20Sopenharmony_ci } 18908c2ecf20Sopenharmony_ci 18918c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(port_speed_str); i++) { 18928c2ecf20Sopenharmony_ci if (port_speed_str[i].rate != ha->link_data_rate) 18938c2ecf20Sopenharmony_ci continue; 18948c2ecf20Sopenharmony_ci speed = port_speed_str[i].str; 18958c2ecf20Sopenharmony_ci break; 18968c2ecf20Sopenharmony_ci } 18978c2ecf20Sopenharmony_ci 18988c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%s\n", speed); 18998c2ecf20Sopenharmony_ci} 19008c2ecf20Sopenharmony_ci 19018c2ecf20Sopenharmony_ci/* ----- */ 19028c2ecf20Sopenharmony_ci 19038c2ecf20Sopenharmony_cistatic ssize_t 19048c2ecf20Sopenharmony_ciqlini_mode_show(struct device *dev, struct device_attribute *attr, char *buf) 19058c2ecf20Sopenharmony_ci{ 19068c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 19078c2ecf20Sopenharmony_ci int len = 0; 19088c2ecf20Sopenharmony_ci 19098c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, 19108c2ecf20Sopenharmony_ci "Supported options: enabled | disabled | dual | exclusive\n"); 19118c2ecf20Sopenharmony_ci 19128c2ecf20Sopenharmony_ci /* --- */ 19138c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, "Current selection: "); 19148c2ecf20Sopenharmony_ci 19158c2ecf20Sopenharmony_ci switch (vha->qlini_mode) { 19168c2ecf20Sopenharmony_ci case QLA2XXX_INI_MODE_EXCLUSIVE: 19178c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, 19188c2ecf20Sopenharmony_ci QLA2XXX_INI_MODE_STR_EXCLUSIVE); 19198c2ecf20Sopenharmony_ci break; 19208c2ecf20Sopenharmony_ci case QLA2XXX_INI_MODE_DISABLED: 19218c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, 19228c2ecf20Sopenharmony_ci QLA2XXX_INI_MODE_STR_DISABLED); 19238c2ecf20Sopenharmony_ci break; 19248c2ecf20Sopenharmony_ci case QLA2XXX_INI_MODE_ENABLED: 19258c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, 19268c2ecf20Sopenharmony_ci QLA2XXX_INI_MODE_STR_ENABLED); 19278c2ecf20Sopenharmony_ci break; 19288c2ecf20Sopenharmony_ci case QLA2XXX_INI_MODE_DUAL: 19298c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, 19308c2ecf20Sopenharmony_ci QLA2XXX_INI_MODE_STR_DUAL); 19318c2ecf20Sopenharmony_ci break; 19328c2ecf20Sopenharmony_ci } 19338c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, "\n"); 19348c2ecf20Sopenharmony_ci 19358c2ecf20Sopenharmony_ci return len; 19368c2ecf20Sopenharmony_ci} 19378c2ecf20Sopenharmony_ci 19388c2ecf20Sopenharmony_cistatic char *mode_to_str[] = { 19398c2ecf20Sopenharmony_ci "exclusive", 19408c2ecf20Sopenharmony_ci "disabled", 19418c2ecf20Sopenharmony_ci "enabled", 19428c2ecf20Sopenharmony_ci "dual", 19438c2ecf20Sopenharmony_ci}; 19448c2ecf20Sopenharmony_ci 19458c2ecf20Sopenharmony_ci#define NEED_EXCH_OFFLOAD(_exchg) ((_exchg) > FW_DEF_EXCHANGES_CNT) 19468c2ecf20Sopenharmony_cistatic void qla_set_ini_mode(scsi_qla_host_t *vha, int op) 19478c2ecf20Sopenharmony_ci{ 19488c2ecf20Sopenharmony_ci enum { 19498c2ecf20Sopenharmony_ci NO_ACTION, 19508c2ecf20Sopenharmony_ci MODE_CHANGE_ACCEPT, 19518c2ecf20Sopenharmony_ci MODE_CHANGE_NO_ACTION, 19528c2ecf20Sopenharmony_ci TARGET_STILL_ACTIVE, 19538c2ecf20Sopenharmony_ci }; 19548c2ecf20Sopenharmony_ci int action = NO_ACTION; 19558c2ecf20Sopenharmony_ci int set_mode = 0; 19568c2ecf20Sopenharmony_ci u8 eo_toggle = 0; /* exchange offload flipped */ 19578c2ecf20Sopenharmony_ci 19588c2ecf20Sopenharmony_ci switch (vha->qlini_mode) { 19598c2ecf20Sopenharmony_ci case QLA2XXX_INI_MODE_DISABLED: 19608c2ecf20Sopenharmony_ci switch (op) { 19618c2ecf20Sopenharmony_ci case QLA2XXX_INI_MODE_DISABLED: 19628c2ecf20Sopenharmony_ci if (qla_tgt_mode_enabled(vha)) { 19638c2ecf20Sopenharmony_ci if (NEED_EXCH_OFFLOAD(vha->u_ql2xexchoffld) != 19648c2ecf20Sopenharmony_ci vha->hw->flags.exchoffld_enabled) 19658c2ecf20Sopenharmony_ci eo_toggle = 1; 19668c2ecf20Sopenharmony_ci if (((vha->ql2xexchoffld != 19678c2ecf20Sopenharmony_ci vha->u_ql2xexchoffld) && 19688c2ecf20Sopenharmony_ci NEED_EXCH_OFFLOAD(vha->u_ql2xexchoffld)) || 19698c2ecf20Sopenharmony_ci eo_toggle) { 19708c2ecf20Sopenharmony_ci /* 19718c2ecf20Sopenharmony_ci * The number of exchange to be offload 19728c2ecf20Sopenharmony_ci * was tweaked or offload option was 19738c2ecf20Sopenharmony_ci * flipped 19748c2ecf20Sopenharmony_ci */ 19758c2ecf20Sopenharmony_ci action = MODE_CHANGE_ACCEPT; 19768c2ecf20Sopenharmony_ci } else { 19778c2ecf20Sopenharmony_ci action = MODE_CHANGE_NO_ACTION; 19788c2ecf20Sopenharmony_ci } 19798c2ecf20Sopenharmony_ci } else { 19808c2ecf20Sopenharmony_ci action = MODE_CHANGE_NO_ACTION; 19818c2ecf20Sopenharmony_ci } 19828c2ecf20Sopenharmony_ci break; 19838c2ecf20Sopenharmony_ci case QLA2XXX_INI_MODE_EXCLUSIVE: 19848c2ecf20Sopenharmony_ci if (qla_tgt_mode_enabled(vha)) { 19858c2ecf20Sopenharmony_ci if (NEED_EXCH_OFFLOAD(vha->u_ql2xexchoffld) != 19868c2ecf20Sopenharmony_ci vha->hw->flags.exchoffld_enabled) 19878c2ecf20Sopenharmony_ci eo_toggle = 1; 19888c2ecf20Sopenharmony_ci if (((vha->ql2xexchoffld != 19898c2ecf20Sopenharmony_ci vha->u_ql2xexchoffld) && 19908c2ecf20Sopenharmony_ci NEED_EXCH_OFFLOAD(vha->u_ql2xexchoffld)) || 19918c2ecf20Sopenharmony_ci eo_toggle) { 19928c2ecf20Sopenharmony_ci /* 19938c2ecf20Sopenharmony_ci * The number of exchange to be offload 19948c2ecf20Sopenharmony_ci * was tweaked or offload option was 19958c2ecf20Sopenharmony_ci * flipped 19968c2ecf20Sopenharmony_ci */ 19978c2ecf20Sopenharmony_ci action = MODE_CHANGE_ACCEPT; 19988c2ecf20Sopenharmony_ci } else { 19998c2ecf20Sopenharmony_ci action = MODE_CHANGE_NO_ACTION; 20008c2ecf20Sopenharmony_ci } 20018c2ecf20Sopenharmony_ci } else { 20028c2ecf20Sopenharmony_ci action = MODE_CHANGE_ACCEPT; 20038c2ecf20Sopenharmony_ci } 20048c2ecf20Sopenharmony_ci break; 20058c2ecf20Sopenharmony_ci case QLA2XXX_INI_MODE_DUAL: 20068c2ecf20Sopenharmony_ci action = MODE_CHANGE_ACCEPT; 20078c2ecf20Sopenharmony_ci /* active_mode is target only, reset it to dual */ 20088c2ecf20Sopenharmony_ci if (qla_tgt_mode_enabled(vha)) { 20098c2ecf20Sopenharmony_ci set_mode = 1; 20108c2ecf20Sopenharmony_ci action = MODE_CHANGE_ACCEPT; 20118c2ecf20Sopenharmony_ci } else { 20128c2ecf20Sopenharmony_ci action = MODE_CHANGE_NO_ACTION; 20138c2ecf20Sopenharmony_ci } 20148c2ecf20Sopenharmony_ci break; 20158c2ecf20Sopenharmony_ci 20168c2ecf20Sopenharmony_ci case QLA2XXX_INI_MODE_ENABLED: 20178c2ecf20Sopenharmony_ci if (qla_tgt_mode_enabled(vha)) 20188c2ecf20Sopenharmony_ci action = TARGET_STILL_ACTIVE; 20198c2ecf20Sopenharmony_ci else { 20208c2ecf20Sopenharmony_ci action = MODE_CHANGE_ACCEPT; 20218c2ecf20Sopenharmony_ci set_mode = 1; 20228c2ecf20Sopenharmony_ci } 20238c2ecf20Sopenharmony_ci break; 20248c2ecf20Sopenharmony_ci } 20258c2ecf20Sopenharmony_ci break; 20268c2ecf20Sopenharmony_ci 20278c2ecf20Sopenharmony_ci case QLA2XXX_INI_MODE_EXCLUSIVE: 20288c2ecf20Sopenharmony_ci switch (op) { 20298c2ecf20Sopenharmony_ci case QLA2XXX_INI_MODE_EXCLUSIVE: 20308c2ecf20Sopenharmony_ci if (qla_tgt_mode_enabled(vha)) { 20318c2ecf20Sopenharmony_ci if (NEED_EXCH_OFFLOAD(vha->u_ql2xexchoffld) != 20328c2ecf20Sopenharmony_ci vha->hw->flags.exchoffld_enabled) 20338c2ecf20Sopenharmony_ci eo_toggle = 1; 20348c2ecf20Sopenharmony_ci if (((vha->ql2xexchoffld != 20358c2ecf20Sopenharmony_ci vha->u_ql2xexchoffld) && 20368c2ecf20Sopenharmony_ci NEED_EXCH_OFFLOAD(vha->u_ql2xexchoffld)) || 20378c2ecf20Sopenharmony_ci eo_toggle) 20388c2ecf20Sopenharmony_ci /* 20398c2ecf20Sopenharmony_ci * The number of exchange to be offload 20408c2ecf20Sopenharmony_ci * was tweaked or offload option was 20418c2ecf20Sopenharmony_ci * flipped 20428c2ecf20Sopenharmony_ci */ 20438c2ecf20Sopenharmony_ci action = MODE_CHANGE_ACCEPT; 20448c2ecf20Sopenharmony_ci else 20458c2ecf20Sopenharmony_ci action = NO_ACTION; 20468c2ecf20Sopenharmony_ci } else 20478c2ecf20Sopenharmony_ci action = NO_ACTION; 20488c2ecf20Sopenharmony_ci 20498c2ecf20Sopenharmony_ci break; 20508c2ecf20Sopenharmony_ci 20518c2ecf20Sopenharmony_ci case QLA2XXX_INI_MODE_DISABLED: 20528c2ecf20Sopenharmony_ci if (qla_tgt_mode_enabled(vha)) { 20538c2ecf20Sopenharmony_ci if (NEED_EXCH_OFFLOAD(vha->u_ql2xexchoffld) != 20548c2ecf20Sopenharmony_ci vha->hw->flags.exchoffld_enabled) 20558c2ecf20Sopenharmony_ci eo_toggle = 1; 20568c2ecf20Sopenharmony_ci if (((vha->ql2xexchoffld != 20578c2ecf20Sopenharmony_ci vha->u_ql2xexchoffld) && 20588c2ecf20Sopenharmony_ci NEED_EXCH_OFFLOAD(vha->u_ql2xexchoffld)) || 20598c2ecf20Sopenharmony_ci eo_toggle) 20608c2ecf20Sopenharmony_ci action = MODE_CHANGE_ACCEPT; 20618c2ecf20Sopenharmony_ci else 20628c2ecf20Sopenharmony_ci action = MODE_CHANGE_NO_ACTION; 20638c2ecf20Sopenharmony_ci } else 20648c2ecf20Sopenharmony_ci action = MODE_CHANGE_NO_ACTION; 20658c2ecf20Sopenharmony_ci break; 20668c2ecf20Sopenharmony_ci 20678c2ecf20Sopenharmony_ci case QLA2XXX_INI_MODE_DUAL: /* exclusive -> dual */ 20688c2ecf20Sopenharmony_ci if (qla_tgt_mode_enabled(vha)) { 20698c2ecf20Sopenharmony_ci action = MODE_CHANGE_ACCEPT; 20708c2ecf20Sopenharmony_ci set_mode = 1; 20718c2ecf20Sopenharmony_ci } else 20728c2ecf20Sopenharmony_ci action = MODE_CHANGE_ACCEPT; 20738c2ecf20Sopenharmony_ci break; 20748c2ecf20Sopenharmony_ci 20758c2ecf20Sopenharmony_ci case QLA2XXX_INI_MODE_ENABLED: 20768c2ecf20Sopenharmony_ci if (qla_tgt_mode_enabled(vha)) 20778c2ecf20Sopenharmony_ci action = TARGET_STILL_ACTIVE; 20788c2ecf20Sopenharmony_ci else { 20798c2ecf20Sopenharmony_ci if (vha->hw->flags.fw_started) 20808c2ecf20Sopenharmony_ci action = MODE_CHANGE_NO_ACTION; 20818c2ecf20Sopenharmony_ci else 20828c2ecf20Sopenharmony_ci action = MODE_CHANGE_ACCEPT; 20838c2ecf20Sopenharmony_ci } 20848c2ecf20Sopenharmony_ci break; 20858c2ecf20Sopenharmony_ci } 20868c2ecf20Sopenharmony_ci break; 20878c2ecf20Sopenharmony_ci 20888c2ecf20Sopenharmony_ci case QLA2XXX_INI_MODE_ENABLED: 20898c2ecf20Sopenharmony_ci switch (op) { 20908c2ecf20Sopenharmony_ci case QLA2XXX_INI_MODE_ENABLED: 20918c2ecf20Sopenharmony_ci if (NEED_EXCH_OFFLOAD(vha->u_ql2xiniexchg) != 20928c2ecf20Sopenharmony_ci vha->hw->flags.exchoffld_enabled) 20938c2ecf20Sopenharmony_ci eo_toggle = 1; 20948c2ecf20Sopenharmony_ci if (((vha->ql2xiniexchg != vha->u_ql2xiniexchg) && 20958c2ecf20Sopenharmony_ci NEED_EXCH_OFFLOAD(vha->u_ql2xiniexchg)) || 20968c2ecf20Sopenharmony_ci eo_toggle) 20978c2ecf20Sopenharmony_ci action = MODE_CHANGE_ACCEPT; 20988c2ecf20Sopenharmony_ci else 20998c2ecf20Sopenharmony_ci action = NO_ACTION; 21008c2ecf20Sopenharmony_ci break; 21018c2ecf20Sopenharmony_ci case QLA2XXX_INI_MODE_DUAL: 21028c2ecf20Sopenharmony_ci case QLA2XXX_INI_MODE_DISABLED: 21038c2ecf20Sopenharmony_ci action = MODE_CHANGE_ACCEPT; 21048c2ecf20Sopenharmony_ci break; 21058c2ecf20Sopenharmony_ci default: 21068c2ecf20Sopenharmony_ci action = MODE_CHANGE_NO_ACTION; 21078c2ecf20Sopenharmony_ci break; 21088c2ecf20Sopenharmony_ci } 21098c2ecf20Sopenharmony_ci break; 21108c2ecf20Sopenharmony_ci 21118c2ecf20Sopenharmony_ci case QLA2XXX_INI_MODE_DUAL: 21128c2ecf20Sopenharmony_ci switch (op) { 21138c2ecf20Sopenharmony_ci case QLA2XXX_INI_MODE_DUAL: 21148c2ecf20Sopenharmony_ci if (qla_tgt_mode_enabled(vha) || 21158c2ecf20Sopenharmony_ci qla_dual_mode_enabled(vha)) { 21168c2ecf20Sopenharmony_ci if (NEED_EXCH_OFFLOAD(vha->u_ql2xexchoffld + 21178c2ecf20Sopenharmony_ci vha->u_ql2xiniexchg) != 21188c2ecf20Sopenharmony_ci vha->hw->flags.exchoffld_enabled) 21198c2ecf20Sopenharmony_ci eo_toggle = 1; 21208c2ecf20Sopenharmony_ci 21218c2ecf20Sopenharmony_ci if ((((vha->ql2xexchoffld + 21228c2ecf20Sopenharmony_ci vha->ql2xiniexchg) != 21238c2ecf20Sopenharmony_ci (vha->u_ql2xiniexchg + 21248c2ecf20Sopenharmony_ci vha->u_ql2xexchoffld)) && 21258c2ecf20Sopenharmony_ci NEED_EXCH_OFFLOAD(vha->u_ql2xiniexchg + 21268c2ecf20Sopenharmony_ci vha->u_ql2xexchoffld)) || eo_toggle) 21278c2ecf20Sopenharmony_ci action = MODE_CHANGE_ACCEPT; 21288c2ecf20Sopenharmony_ci else 21298c2ecf20Sopenharmony_ci action = NO_ACTION; 21308c2ecf20Sopenharmony_ci } else { 21318c2ecf20Sopenharmony_ci if (NEED_EXCH_OFFLOAD(vha->u_ql2xexchoffld + 21328c2ecf20Sopenharmony_ci vha->u_ql2xiniexchg) != 21338c2ecf20Sopenharmony_ci vha->hw->flags.exchoffld_enabled) 21348c2ecf20Sopenharmony_ci eo_toggle = 1; 21358c2ecf20Sopenharmony_ci 21368c2ecf20Sopenharmony_ci if ((((vha->ql2xexchoffld + vha->ql2xiniexchg) 21378c2ecf20Sopenharmony_ci != (vha->u_ql2xiniexchg + 21388c2ecf20Sopenharmony_ci vha->u_ql2xexchoffld)) && 21398c2ecf20Sopenharmony_ci NEED_EXCH_OFFLOAD(vha->u_ql2xiniexchg + 21408c2ecf20Sopenharmony_ci vha->u_ql2xexchoffld)) || eo_toggle) 21418c2ecf20Sopenharmony_ci action = MODE_CHANGE_NO_ACTION; 21428c2ecf20Sopenharmony_ci else 21438c2ecf20Sopenharmony_ci action = NO_ACTION; 21448c2ecf20Sopenharmony_ci } 21458c2ecf20Sopenharmony_ci break; 21468c2ecf20Sopenharmony_ci 21478c2ecf20Sopenharmony_ci case QLA2XXX_INI_MODE_DISABLED: 21488c2ecf20Sopenharmony_ci if (qla_tgt_mode_enabled(vha) || 21498c2ecf20Sopenharmony_ci qla_dual_mode_enabled(vha)) { 21508c2ecf20Sopenharmony_ci /* turning off initiator mode */ 21518c2ecf20Sopenharmony_ci set_mode = 1; 21528c2ecf20Sopenharmony_ci action = MODE_CHANGE_ACCEPT; 21538c2ecf20Sopenharmony_ci } else { 21548c2ecf20Sopenharmony_ci action = MODE_CHANGE_NO_ACTION; 21558c2ecf20Sopenharmony_ci } 21568c2ecf20Sopenharmony_ci break; 21578c2ecf20Sopenharmony_ci 21588c2ecf20Sopenharmony_ci case QLA2XXX_INI_MODE_EXCLUSIVE: 21598c2ecf20Sopenharmony_ci if (qla_tgt_mode_enabled(vha) || 21608c2ecf20Sopenharmony_ci qla_dual_mode_enabled(vha)) { 21618c2ecf20Sopenharmony_ci set_mode = 1; 21628c2ecf20Sopenharmony_ci action = MODE_CHANGE_ACCEPT; 21638c2ecf20Sopenharmony_ci } else { 21648c2ecf20Sopenharmony_ci action = MODE_CHANGE_ACCEPT; 21658c2ecf20Sopenharmony_ci } 21668c2ecf20Sopenharmony_ci break; 21678c2ecf20Sopenharmony_ci 21688c2ecf20Sopenharmony_ci case QLA2XXX_INI_MODE_ENABLED: 21698c2ecf20Sopenharmony_ci if (qla_tgt_mode_enabled(vha) || 21708c2ecf20Sopenharmony_ci qla_dual_mode_enabled(vha)) { 21718c2ecf20Sopenharmony_ci action = TARGET_STILL_ACTIVE; 21728c2ecf20Sopenharmony_ci } else { 21738c2ecf20Sopenharmony_ci action = MODE_CHANGE_ACCEPT; 21748c2ecf20Sopenharmony_ci } 21758c2ecf20Sopenharmony_ci } 21768c2ecf20Sopenharmony_ci break; 21778c2ecf20Sopenharmony_ci } 21788c2ecf20Sopenharmony_ci 21798c2ecf20Sopenharmony_ci switch (action) { 21808c2ecf20Sopenharmony_ci case MODE_CHANGE_ACCEPT: 21818c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0xffff, 21828c2ecf20Sopenharmony_ci "Mode change accepted. From %s to %s, Tgt exchg %d|%d. ini exchg %d|%d\n", 21838c2ecf20Sopenharmony_ci mode_to_str[vha->qlini_mode], mode_to_str[op], 21848c2ecf20Sopenharmony_ci vha->ql2xexchoffld, vha->u_ql2xexchoffld, 21858c2ecf20Sopenharmony_ci vha->ql2xiniexchg, vha->u_ql2xiniexchg); 21868c2ecf20Sopenharmony_ci 21878c2ecf20Sopenharmony_ci vha->qlini_mode = op; 21888c2ecf20Sopenharmony_ci vha->ql2xexchoffld = vha->u_ql2xexchoffld; 21898c2ecf20Sopenharmony_ci vha->ql2xiniexchg = vha->u_ql2xiniexchg; 21908c2ecf20Sopenharmony_ci if (set_mode) 21918c2ecf20Sopenharmony_ci qlt_set_mode(vha); 21928c2ecf20Sopenharmony_ci vha->flags.online = 1; 21938c2ecf20Sopenharmony_ci set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); 21948c2ecf20Sopenharmony_ci break; 21958c2ecf20Sopenharmony_ci 21968c2ecf20Sopenharmony_ci case MODE_CHANGE_NO_ACTION: 21978c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0xffff, 21988c2ecf20Sopenharmony_ci "Mode is set. No action taken. From %s to %s, Tgt exchg %d|%d. ini exchg %d|%d\n", 21998c2ecf20Sopenharmony_ci mode_to_str[vha->qlini_mode], mode_to_str[op], 22008c2ecf20Sopenharmony_ci vha->ql2xexchoffld, vha->u_ql2xexchoffld, 22018c2ecf20Sopenharmony_ci vha->ql2xiniexchg, vha->u_ql2xiniexchg); 22028c2ecf20Sopenharmony_ci vha->qlini_mode = op; 22038c2ecf20Sopenharmony_ci vha->ql2xexchoffld = vha->u_ql2xexchoffld; 22048c2ecf20Sopenharmony_ci vha->ql2xiniexchg = vha->u_ql2xiniexchg; 22058c2ecf20Sopenharmony_ci break; 22068c2ecf20Sopenharmony_ci 22078c2ecf20Sopenharmony_ci case TARGET_STILL_ACTIVE: 22088c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0xffff, 22098c2ecf20Sopenharmony_ci "Target Mode is active. Unable to change Mode.\n"); 22108c2ecf20Sopenharmony_ci break; 22118c2ecf20Sopenharmony_ci 22128c2ecf20Sopenharmony_ci case NO_ACTION: 22138c2ecf20Sopenharmony_ci default: 22148c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0xffff, 22158c2ecf20Sopenharmony_ci "Mode unchange. No action taken. %d|%d pct %d|%d.\n", 22168c2ecf20Sopenharmony_ci vha->qlini_mode, op, 22178c2ecf20Sopenharmony_ci vha->ql2xexchoffld, vha->u_ql2xexchoffld); 22188c2ecf20Sopenharmony_ci break; 22198c2ecf20Sopenharmony_ci } 22208c2ecf20Sopenharmony_ci} 22218c2ecf20Sopenharmony_ci 22228c2ecf20Sopenharmony_cistatic ssize_t 22238c2ecf20Sopenharmony_ciqlini_mode_store(struct device *dev, struct device_attribute *attr, 22248c2ecf20Sopenharmony_ci const char *buf, size_t count) 22258c2ecf20Sopenharmony_ci{ 22268c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 22278c2ecf20Sopenharmony_ci int ini; 22288c2ecf20Sopenharmony_ci 22298c2ecf20Sopenharmony_ci if (!buf) 22308c2ecf20Sopenharmony_ci return -EINVAL; 22318c2ecf20Sopenharmony_ci 22328c2ecf20Sopenharmony_ci if (strncasecmp(QLA2XXX_INI_MODE_STR_EXCLUSIVE, buf, 22338c2ecf20Sopenharmony_ci strlen(QLA2XXX_INI_MODE_STR_EXCLUSIVE)) == 0) 22348c2ecf20Sopenharmony_ci ini = QLA2XXX_INI_MODE_EXCLUSIVE; 22358c2ecf20Sopenharmony_ci else if (strncasecmp(QLA2XXX_INI_MODE_STR_DISABLED, buf, 22368c2ecf20Sopenharmony_ci strlen(QLA2XXX_INI_MODE_STR_DISABLED)) == 0) 22378c2ecf20Sopenharmony_ci ini = QLA2XXX_INI_MODE_DISABLED; 22388c2ecf20Sopenharmony_ci else if (strncasecmp(QLA2XXX_INI_MODE_STR_ENABLED, buf, 22398c2ecf20Sopenharmony_ci strlen(QLA2XXX_INI_MODE_STR_ENABLED)) == 0) 22408c2ecf20Sopenharmony_ci ini = QLA2XXX_INI_MODE_ENABLED; 22418c2ecf20Sopenharmony_ci else if (strncasecmp(QLA2XXX_INI_MODE_STR_DUAL, buf, 22428c2ecf20Sopenharmony_ci strlen(QLA2XXX_INI_MODE_STR_DUAL)) == 0) 22438c2ecf20Sopenharmony_ci ini = QLA2XXX_INI_MODE_DUAL; 22448c2ecf20Sopenharmony_ci else 22458c2ecf20Sopenharmony_ci return -EINVAL; 22468c2ecf20Sopenharmony_ci 22478c2ecf20Sopenharmony_ci qla_set_ini_mode(vha, ini); 22488c2ecf20Sopenharmony_ci return strlen(buf); 22498c2ecf20Sopenharmony_ci} 22508c2ecf20Sopenharmony_ci 22518c2ecf20Sopenharmony_cistatic ssize_t 22528c2ecf20Sopenharmony_ciql2xexchoffld_show(struct device *dev, struct device_attribute *attr, 22538c2ecf20Sopenharmony_ci char *buf) 22548c2ecf20Sopenharmony_ci{ 22558c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 22568c2ecf20Sopenharmony_ci int len = 0; 22578c2ecf20Sopenharmony_ci 22588c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, 22598c2ecf20Sopenharmony_ci "target exchange: new %d : current: %d\n\n", 22608c2ecf20Sopenharmony_ci vha->u_ql2xexchoffld, vha->ql2xexchoffld); 22618c2ecf20Sopenharmony_ci 22628c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, 22638c2ecf20Sopenharmony_ci "Please (re)set operating mode via \"/sys/class/scsi_host/host%ld/qlini_mode\" to load new setting.\n", 22648c2ecf20Sopenharmony_ci vha->host_no); 22658c2ecf20Sopenharmony_ci 22668c2ecf20Sopenharmony_ci return len; 22678c2ecf20Sopenharmony_ci} 22688c2ecf20Sopenharmony_ci 22698c2ecf20Sopenharmony_cistatic ssize_t 22708c2ecf20Sopenharmony_ciql2xexchoffld_store(struct device *dev, struct device_attribute *attr, 22718c2ecf20Sopenharmony_ci const char *buf, size_t count) 22728c2ecf20Sopenharmony_ci{ 22738c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 22748c2ecf20Sopenharmony_ci int val = 0; 22758c2ecf20Sopenharmony_ci 22768c2ecf20Sopenharmony_ci if (sscanf(buf, "%d", &val) != 1) 22778c2ecf20Sopenharmony_ci return -EINVAL; 22788c2ecf20Sopenharmony_ci 22798c2ecf20Sopenharmony_ci if (val > FW_MAX_EXCHANGES_CNT) 22808c2ecf20Sopenharmony_ci val = FW_MAX_EXCHANGES_CNT; 22818c2ecf20Sopenharmony_ci else if (val < 0) 22828c2ecf20Sopenharmony_ci val = 0; 22838c2ecf20Sopenharmony_ci 22848c2ecf20Sopenharmony_ci vha->u_ql2xexchoffld = val; 22858c2ecf20Sopenharmony_ci return strlen(buf); 22868c2ecf20Sopenharmony_ci} 22878c2ecf20Sopenharmony_ci 22888c2ecf20Sopenharmony_cistatic ssize_t 22898c2ecf20Sopenharmony_ciql2xiniexchg_show(struct device *dev, struct device_attribute *attr, 22908c2ecf20Sopenharmony_ci char *buf) 22918c2ecf20Sopenharmony_ci{ 22928c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 22938c2ecf20Sopenharmony_ci int len = 0; 22948c2ecf20Sopenharmony_ci 22958c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, 22968c2ecf20Sopenharmony_ci "target exchange: new %d : current: %d\n\n", 22978c2ecf20Sopenharmony_ci vha->u_ql2xiniexchg, vha->ql2xiniexchg); 22988c2ecf20Sopenharmony_ci 22998c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, 23008c2ecf20Sopenharmony_ci "Please (re)set operating mode via \"/sys/class/scsi_host/host%ld/qlini_mode\" to load new setting.\n", 23018c2ecf20Sopenharmony_ci vha->host_no); 23028c2ecf20Sopenharmony_ci 23038c2ecf20Sopenharmony_ci return len; 23048c2ecf20Sopenharmony_ci} 23058c2ecf20Sopenharmony_ci 23068c2ecf20Sopenharmony_cistatic ssize_t 23078c2ecf20Sopenharmony_ciql2xiniexchg_store(struct device *dev, struct device_attribute *attr, 23088c2ecf20Sopenharmony_ci const char *buf, size_t count) 23098c2ecf20Sopenharmony_ci{ 23108c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 23118c2ecf20Sopenharmony_ci int val = 0; 23128c2ecf20Sopenharmony_ci 23138c2ecf20Sopenharmony_ci if (sscanf(buf, "%d", &val) != 1) 23148c2ecf20Sopenharmony_ci return -EINVAL; 23158c2ecf20Sopenharmony_ci 23168c2ecf20Sopenharmony_ci if (val > FW_MAX_EXCHANGES_CNT) 23178c2ecf20Sopenharmony_ci val = FW_MAX_EXCHANGES_CNT; 23188c2ecf20Sopenharmony_ci else if (val < 0) 23198c2ecf20Sopenharmony_ci val = 0; 23208c2ecf20Sopenharmony_ci 23218c2ecf20Sopenharmony_ci vha->u_ql2xiniexchg = val; 23228c2ecf20Sopenharmony_ci return strlen(buf); 23238c2ecf20Sopenharmony_ci} 23248c2ecf20Sopenharmony_ci 23258c2ecf20Sopenharmony_cistatic ssize_t 23268c2ecf20Sopenharmony_ciqla2x00_dif_bundle_statistics_show(struct device *dev, 23278c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 23288c2ecf20Sopenharmony_ci{ 23298c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 23308c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 23318c2ecf20Sopenharmony_ci 23328c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, 23338c2ecf20Sopenharmony_ci "cross=%llu read=%llu write=%llu kalloc=%llu dma_alloc=%llu unusable=%u\n", 23348c2ecf20Sopenharmony_ci ha->dif_bundle_crossed_pages, ha->dif_bundle_reads, 23358c2ecf20Sopenharmony_ci ha->dif_bundle_writes, ha->dif_bundle_kallocs, 23368c2ecf20Sopenharmony_ci ha->dif_bundle_dma_allocs, ha->pool.unusable.count); 23378c2ecf20Sopenharmony_ci} 23388c2ecf20Sopenharmony_ci 23398c2ecf20Sopenharmony_cistatic ssize_t 23408c2ecf20Sopenharmony_ciqla2x00_fw_attr_show(struct device *dev, 23418c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 23428c2ecf20Sopenharmony_ci{ 23438c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 23448c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 23458c2ecf20Sopenharmony_ci 23468c2ecf20Sopenharmony_ci if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) 23478c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "\n"); 23488c2ecf20Sopenharmony_ci 23498c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%llx\n", 23508c2ecf20Sopenharmony_ci (uint64_t)ha->fw_attributes_ext[1] << 48 | 23518c2ecf20Sopenharmony_ci (uint64_t)ha->fw_attributes_ext[0] << 32 | 23528c2ecf20Sopenharmony_ci (uint64_t)ha->fw_attributes_h << 16 | 23538c2ecf20Sopenharmony_ci (uint64_t)ha->fw_attributes); 23548c2ecf20Sopenharmony_ci} 23558c2ecf20Sopenharmony_ci 23568c2ecf20Sopenharmony_cistatic ssize_t 23578c2ecf20Sopenharmony_ciqla2x00_port_no_show(struct device *dev, struct device_attribute *attr, 23588c2ecf20Sopenharmony_ci char *buf) 23598c2ecf20Sopenharmony_ci{ 23608c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 23618c2ecf20Sopenharmony_ci 23628c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%u\n", vha->hw->port_no); 23638c2ecf20Sopenharmony_ci} 23648c2ecf20Sopenharmony_ci 23658c2ecf20Sopenharmony_cistatic ssize_t 23668c2ecf20Sopenharmony_ciqla2x00_dport_diagnostics_show(struct device *dev, 23678c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 23688c2ecf20Sopenharmony_ci{ 23698c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); 23708c2ecf20Sopenharmony_ci 23718c2ecf20Sopenharmony_ci if (!IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw) && 23728c2ecf20Sopenharmony_ci !IS_QLA28XX(vha->hw)) 23738c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "\n"); 23748c2ecf20Sopenharmony_ci 23758c2ecf20Sopenharmony_ci if (!*vha->dport_data) 23768c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "\n"); 23778c2ecf20Sopenharmony_ci 23788c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%04x %04x %04x %04x\n", 23798c2ecf20Sopenharmony_ci vha->dport_data[0], vha->dport_data[1], 23808c2ecf20Sopenharmony_ci vha->dport_data[2], vha->dport_data[3]); 23818c2ecf20Sopenharmony_ci} 23828c2ecf20Sopenharmony_cistatic DEVICE_ATTR(dport_diagnostics, 0444, 23838c2ecf20Sopenharmony_ci qla2x00_dport_diagnostics_show, NULL); 23848c2ecf20Sopenharmony_ci 23858c2ecf20Sopenharmony_cistatic DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_driver_version_show, NULL); 23868c2ecf20Sopenharmony_cistatic DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL); 23878c2ecf20Sopenharmony_cistatic DEVICE_ATTR(serial_num, S_IRUGO, qla2x00_serial_num_show, NULL); 23888c2ecf20Sopenharmony_cistatic DEVICE_ATTR(isp_name, S_IRUGO, qla2x00_isp_name_show, NULL); 23898c2ecf20Sopenharmony_cistatic DEVICE_ATTR(isp_id, S_IRUGO, qla2x00_isp_id_show, NULL); 23908c2ecf20Sopenharmony_cistatic DEVICE_ATTR(model_name, S_IRUGO, qla2x00_model_name_show, NULL); 23918c2ecf20Sopenharmony_cistatic DEVICE_ATTR(model_desc, S_IRUGO, qla2x00_model_desc_show, NULL); 23928c2ecf20Sopenharmony_cistatic DEVICE_ATTR(pci_info, S_IRUGO, qla2x00_pci_info_show, NULL); 23938c2ecf20Sopenharmony_cistatic DEVICE_ATTR(link_state, S_IRUGO, qla2x00_link_state_show, NULL); 23948c2ecf20Sopenharmony_cistatic DEVICE_ATTR(zio, S_IRUGO | S_IWUSR, qla2x00_zio_show, qla2x00_zio_store); 23958c2ecf20Sopenharmony_cistatic DEVICE_ATTR(zio_timer, S_IRUGO | S_IWUSR, qla2x00_zio_timer_show, 23968c2ecf20Sopenharmony_ci qla2x00_zio_timer_store); 23978c2ecf20Sopenharmony_cistatic DEVICE_ATTR(beacon, S_IRUGO | S_IWUSR, qla2x00_beacon_show, 23988c2ecf20Sopenharmony_ci qla2x00_beacon_store); 23998c2ecf20Sopenharmony_cistatic DEVICE_ATTR(beacon_config, 0644, qla2x00_beacon_config_show, 24008c2ecf20Sopenharmony_ci qla2x00_beacon_config_store); 24018c2ecf20Sopenharmony_cistatic DEVICE_ATTR(optrom_bios_version, S_IRUGO, 24028c2ecf20Sopenharmony_ci qla2x00_optrom_bios_version_show, NULL); 24038c2ecf20Sopenharmony_cistatic DEVICE_ATTR(optrom_efi_version, S_IRUGO, 24048c2ecf20Sopenharmony_ci qla2x00_optrom_efi_version_show, NULL); 24058c2ecf20Sopenharmony_cistatic DEVICE_ATTR(optrom_fcode_version, S_IRUGO, 24068c2ecf20Sopenharmony_ci qla2x00_optrom_fcode_version_show, NULL); 24078c2ecf20Sopenharmony_cistatic DEVICE_ATTR(optrom_fw_version, S_IRUGO, qla2x00_optrom_fw_version_show, 24088c2ecf20Sopenharmony_ci NULL); 24098c2ecf20Sopenharmony_cistatic DEVICE_ATTR(optrom_gold_fw_version, S_IRUGO, 24108c2ecf20Sopenharmony_ci qla2x00_optrom_gold_fw_version_show, NULL); 24118c2ecf20Sopenharmony_cistatic DEVICE_ATTR(84xx_fw_version, S_IRUGO, qla24xx_84xx_fw_version_show, 24128c2ecf20Sopenharmony_ci NULL); 24138c2ecf20Sopenharmony_cistatic DEVICE_ATTR(total_isp_aborts, S_IRUGO, qla2x00_total_isp_aborts_show, 24148c2ecf20Sopenharmony_ci NULL); 24158c2ecf20Sopenharmony_cistatic DEVICE_ATTR(serdes_version, 0444, qla2x00_serdes_version_show, NULL); 24168c2ecf20Sopenharmony_cistatic DEVICE_ATTR(mpi_version, S_IRUGO, qla2x00_mpi_version_show, NULL); 24178c2ecf20Sopenharmony_cistatic DEVICE_ATTR(phy_version, S_IRUGO, qla2x00_phy_version_show, NULL); 24188c2ecf20Sopenharmony_cistatic DEVICE_ATTR(flash_block_size, S_IRUGO, qla2x00_flash_block_size_show, 24198c2ecf20Sopenharmony_ci NULL); 24208c2ecf20Sopenharmony_cistatic DEVICE_ATTR(vlan_id, S_IRUGO, qla2x00_vlan_id_show, NULL); 24218c2ecf20Sopenharmony_cistatic DEVICE_ATTR(vn_port_mac_address, S_IRUGO, 24228c2ecf20Sopenharmony_ci qla2x00_vn_port_mac_address_show, NULL); 24238c2ecf20Sopenharmony_cistatic DEVICE_ATTR(fabric_param, S_IRUGO, qla2x00_fabric_param_show, NULL); 24248c2ecf20Sopenharmony_cistatic DEVICE_ATTR(fw_state, S_IRUGO, qla2x00_fw_state_show, NULL); 24258c2ecf20Sopenharmony_cistatic DEVICE_ATTR(thermal_temp, S_IRUGO, qla2x00_thermal_temp_show, NULL); 24268c2ecf20Sopenharmony_cistatic DEVICE_ATTR(diag_requests, S_IRUGO, qla2x00_diag_requests_show, NULL); 24278c2ecf20Sopenharmony_cistatic DEVICE_ATTR(diag_megabytes, S_IRUGO, qla2x00_diag_megabytes_show, NULL); 24288c2ecf20Sopenharmony_cistatic DEVICE_ATTR(fw_dump_size, S_IRUGO, qla2x00_fw_dump_size_show, NULL); 24298c2ecf20Sopenharmony_cistatic DEVICE_ATTR(allow_cna_fw_dump, S_IRUGO | S_IWUSR, 24308c2ecf20Sopenharmony_ci qla2x00_allow_cna_fw_dump_show, 24318c2ecf20Sopenharmony_ci qla2x00_allow_cna_fw_dump_store); 24328c2ecf20Sopenharmony_cistatic DEVICE_ATTR(pep_version, S_IRUGO, qla2x00_pep_version_show, NULL); 24338c2ecf20Sopenharmony_cistatic DEVICE_ATTR(min_supported_speed, 0444, 24348c2ecf20Sopenharmony_ci qla2x00_min_supported_speed_show, NULL); 24358c2ecf20Sopenharmony_cistatic DEVICE_ATTR(max_supported_speed, 0444, 24368c2ecf20Sopenharmony_ci qla2x00_max_supported_speed_show, NULL); 24378c2ecf20Sopenharmony_cistatic DEVICE_ATTR(zio_threshold, 0644, 24388c2ecf20Sopenharmony_ci qla_zio_threshold_show, 24398c2ecf20Sopenharmony_ci qla_zio_threshold_store); 24408c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(qlini_mode); 24418c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(ql2xexchoffld); 24428c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(ql2xiniexchg); 24438c2ecf20Sopenharmony_cistatic DEVICE_ATTR(dif_bundle_statistics, 0444, 24448c2ecf20Sopenharmony_ci qla2x00_dif_bundle_statistics_show, NULL); 24458c2ecf20Sopenharmony_cistatic DEVICE_ATTR(port_speed, 0644, qla2x00_port_speed_show, 24468c2ecf20Sopenharmony_ci qla2x00_port_speed_store); 24478c2ecf20Sopenharmony_cistatic DEVICE_ATTR(port_no, 0444, qla2x00_port_no_show, NULL); 24488c2ecf20Sopenharmony_cistatic DEVICE_ATTR(fw_attr, 0444, qla2x00_fw_attr_show, NULL); 24498c2ecf20Sopenharmony_ci 24508c2ecf20Sopenharmony_ci 24518c2ecf20Sopenharmony_cistruct device_attribute *qla2x00_host_attrs[] = { 24528c2ecf20Sopenharmony_ci &dev_attr_driver_version, 24538c2ecf20Sopenharmony_ci &dev_attr_fw_version, 24548c2ecf20Sopenharmony_ci &dev_attr_serial_num, 24558c2ecf20Sopenharmony_ci &dev_attr_isp_name, 24568c2ecf20Sopenharmony_ci &dev_attr_isp_id, 24578c2ecf20Sopenharmony_ci &dev_attr_model_name, 24588c2ecf20Sopenharmony_ci &dev_attr_model_desc, 24598c2ecf20Sopenharmony_ci &dev_attr_pci_info, 24608c2ecf20Sopenharmony_ci &dev_attr_link_state, 24618c2ecf20Sopenharmony_ci &dev_attr_zio, 24628c2ecf20Sopenharmony_ci &dev_attr_zio_timer, 24638c2ecf20Sopenharmony_ci &dev_attr_beacon, 24648c2ecf20Sopenharmony_ci &dev_attr_beacon_config, 24658c2ecf20Sopenharmony_ci &dev_attr_optrom_bios_version, 24668c2ecf20Sopenharmony_ci &dev_attr_optrom_efi_version, 24678c2ecf20Sopenharmony_ci &dev_attr_optrom_fcode_version, 24688c2ecf20Sopenharmony_ci &dev_attr_optrom_fw_version, 24698c2ecf20Sopenharmony_ci &dev_attr_84xx_fw_version, 24708c2ecf20Sopenharmony_ci &dev_attr_total_isp_aborts, 24718c2ecf20Sopenharmony_ci &dev_attr_serdes_version, 24728c2ecf20Sopenharmony_ci &dev_attr_mpi_version, 24738c2ecf20Sopenharmony_ci &dev_attr_phy_version, 24748c2ecf20Sopenharmony_ci &dev_attr_flash_block_size, 24758c2ecf20Sopenharmony_ci &dev_attr_vlan_id, 24768c2ecf20Sopenharmony_ci &dev_attr_vn_port_mac_address, 24778c2ecf20Sopenharmony_ci &dev_attr_fabric_param, 24788c2ecf20Sopenharmony_ci &dev_attr_fw_state, 24798c2ecf20Sopenharmony_ci &dev_attr_optrom_gold_fw_version, 24808c2ecf20Sopenharmony_ci &dev_attr_thermal_temp, 24818c2ecf20Sopenharmony_ci &dev_attr_diag_requests, 24828c2ecf20Sopenharmony_ci &dev_attr_diag_megabytes, 24838c2ecf20Sopenharmony_ci &dev_attr_fw_dump_size, 24848c2ecf20Sopenharmony_ci &dev_attr_allow_cna_fw_dump, 24858c2ecf20Sopenharmony_ci &dev_attr_pep_version, 24868c2ecf20Sopenharmony_ci &dev_attr_min_supported_speed, 24878c2ecf20Sopenharmony_ci &dev_attr_max_supported_speed, 24888c2ecf20Sopenharmony_ci &dev_attr_zio_threshold, 24898c2ecf20Sopenharmony_ci &dev_attr_dif_bundle_statistics, 24908c2ecf20Sopenharmony_ci &dev_attr_port_speed, 24918c2ecf20Sopenharmony_ci &dev_attr_port_no, 24928c2ecf20Sopenharmony_ci &dev_attr_fw_attr, 24938c2ecf20Sopenharmony_ci &dev_attr_dport_diagnostics, 24948c2ecf20Sopenharmony_ci NULL, /* reserve for qlini_mode */ 24958c2ecf20Sopenharmony_ci NULL, /* reserve for ql2xiniexchg */ 24968c2ecf20Sopenharmony_ci NULL, /* reserve for ql2xexchoffld */ 24978c2ecf20Sopenharmony_ci NULL, 24988c2ecf20Sopenharmony_ci}; 24998c2ecf20Sopenharmony_ci 25008c2ecf20Sopenharmony_civoid qla_insert_tgt_attrs(void) 25018c2ecf20Sopenharmony_ci{ 25028c2ecf20Sopenharmony_ci struct device_attribute **attr; 25038c2ecf20Sopenharmony_ci 25048c2ecf20Sopenharmony_ci /* advance to empty slot */ 25058c2ecf20Sopenharmony_ci for (attr = &qla2x00_host_attrs[0]; *attr; ++attr) 25068c2ecf20Sopenharmony_ci continue; 25078c2ecf20Sopenharmony_ci 25088c2ecf20Sopenharmony_ci *attr = &dev_attr_qlini_mode; 25098c2ecf20Sopenharmony_ci attr++; 25108c2ecf20Sopenharmony_ci *attr = &dev_attr_ql2xiniexchg; 25118c2ecf20Sopenharmony_ci attr++; 25128c2ecf20Sopenharmony_ci *attr = &dev_attr_ql2xexchoffld; 25138c2ecf20Sopenharmony_ci} 25148c2ecf20Sopenharmony_ci 25158c2ecf20Sopenharmony_ci/* Host attributes. */ 25168c2ecf20Sopenharmony_ci 25178c2ecf20Sopenharmony_cistatic void 25188c2ecf20Sopenharmony_ciqla2x00_get_host_port_id(struct Scsi_Host *shost) 25198c2ecf20Sopenharmony_ci{ 25208c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(shost); 25218c2ecf20Sopenharmony_ci 25228c2ecf20Sopenharmony_ci fc_host_port_id(shost) = vha->d_id.b.domain << 16 | 25238c2ecf20Sopenharmony_ci vha->d_id.b.area << 8 | vha->d_id.b.al_pa; 25248c2ecf20Sopenharmony_ci} 25258c2ecf20Sopenharmony_ci 25268c2ecf20Sopenharmony_cistatic void 25278c2ecf20Sopenharmony_ciqla2x00_get_host_speed(struct Scsi_Host *shost) 25288c2ecf20Sopenharmony_ci{ 25298c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(shost); 25308c2ecf20Sopenharmony_ci u32 speed; 25318c2ecf20Sopenharmony_ci 25328c2ecf20Sopenharmony_ci if (IS_QLAFX00(vha->hw)) { 25338c2ecf20Sopenharmony_ci qlafx00_get_host_speed(shost); 25348c2ecf20Sopenharmony_ci return; 25358c2ecf20Sopenharmony_ci } 25368c2ecf20Sopenharmony_ci 25378c2ecf20Sopenharmony_ci switch (vha->hw->link_data_rate) { 25388c2ecf20Sopenharmony_ci case PORT_SPEED_1GB: 25398c2ecf20Sopenharmony_ci speed = FC_PORTSPEED_1GBIT; 25408c2ecf20Sopenharmony_ci break; 25418c2ecf20Sopenharmony_ci case PORT_SPEED_2GB: 25428c2ecf20Sopenharmony_ci speed = FC_PORTSPEED_2GBIT; 25438c2ecf20Sopenharmony_ci break; 25448c2ecf20Sopenharmony_ci case PORT_SPEED_4GB: 25458c2ecf20Sopenharmony_ci speed = FC_PORTSPEED_4GBIT; 25468c2ecf20Sopenharmony_ci break; 25478c2ecf20Sopenharmony_ci case PORT_SPEED_8GB: 25488c2ecf20Sopenharmony_ci speed = FC_PORTSPEED_8GBIT; 25498c2ecf20Sopenharmony_ci break; 25508c2ecf20Sopenharmony_ci case PORT_SPEED_10GB: 25518c2ecf20Sopenharmony_ci speed = FC_PORTSPEED_10GBIT; 25528c2ecf20Sopenharmony_ci break; 25538c2ecf20Sopenharmony_ci case PORT_SPEED_16GB: 25548c2ecf20Sopenharmony_ci speed = FC_PORTSPEED_16GBIT; 25558c2ecf20Sopenharmony_ci break; 25568c2ecf20Sopenharmony_ci case PORT_SPEED_32GB: 25578c2ecf20Sopenharmony_ci speed = FC_PORTSPEED_32GBIT; 25588c2ecf20Sopenharmony_ci break; 25598c2ecf20Sopenharmony_ci case PORT_SPEED_64GB: 25608c2ecf20Sopenharmony_ci speed = FC_PORTSPEED_64GBIT; 25618c2ecf20Sopenharmony_ci break; 25628c2ecf20Sopenharmony_ci default: 25638c2ecf20Sopenharmony_ci speed = FC_PORTSPEED_UNKNOWN; 25648c2ecf20Sopenharmony_ci break; 25658c2ecf20Sopenharmony_ci } 25668c2ecf20Sopenharmony_ci 25678c2ecf20Sopenharmony_ci fc_host_speed(shost) = speed; 25688c2ecf20Sopenharmony_ci} 25698c2ecf20Sopenharmony_ci 25708c2ecf20Sopenharmony_cistatic void 25718c2ecf20Sopenharmony_ciqla2x00_get_host_port_type(struct Scsi_Host *shost) 25728c2ecf20Sopenharmony_ci{ 25738c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(shost); 25748c2ecf20Sopenharmony_ci uint32_t port_type; 25758c2ecf20Sopenharmony_ci 25768c2ecf20Sopenharmony_ci if (vha->vp_idx) { 25778c2ecf20Sopenharmony_ci fc_host_port_type(shost) = FC_PORTTYPE_NPIV; 25788c2ecf20Sopenharmony_ci return; 25798c2ecf20Sopenharmony_ci } 25808c2ecf20Sopenharmony_ci switch (vha->hw->current_topology) { 25818c2ecf20Sopenharmony_ci case ISP_CFG_NL: 25828c2ecf20Sopenharmony_ci port_type = FC_PORTTYPE_LPORT; 25838c2ecf20Sopenharmony_ci break; 25848c2ecf20Sopenharmony_ci case ISP_CFG_FL: 25858c2ecf20Sopenharmony_ci port_type = FC_PORTTYPE_NLPORT; 25868c2ecf20Sopenharmony_ci break; 25878c2ecf20Sopenharmony_ci case ISP_CFG_N: 25888c2ecf20Sopenharmony_ci port_type = FC_PORTTYPE_PTP; 25898c2ecf20Sopenharmony_ci break; 25908c2ecf20Sopenharmony_ci case ISP_CFG_F: 25918c2ecf20Sopenharmony_ci port_type = FC_PORTTYPE_NPORT; 25928c2ecf20Sopenharmony_ci break; 25938c2ecf20Sopenharmony_ci default: 25948c2ecf20Sopenharmony_ci port_type = FC_PORTTYPE_UNKNOWN; 25958c2ecf20Sopenharmony_ci break; 25968c2ecf20Sopenharmony_ci } 25978c2ecf20Sopenharmony_ci 25988c2ecf20Sopenharmony_ci fc_host_port_type(shost) = port_type; 25998c2ecf20Sopenharmony_ci} 26008c2ecf20Sopenharmony_ci 26018c2ecf20Sopenharmony_cistatic void 26028c2ecf20Sopenharmony_ciqla2x00_get_starget_node_name(struct scsi_target *starget) 26038c2ecf20Sopenharmony_ci{ 26048c2ecf20Sopenharmony_ci struct Scsi_Host *host = dev_to_shost(starget->dev.parent); 26058c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(host); 26068c2ecf20Sopenharmony_ci fc_port_t *fcport; 26078c2ecf20Sopenharmony_ci u64 node_name = 0; 26088c2ecf20Sopenharmony_ci 26098c2ecf20Sopenharmony_ci list_for_each_entry(fcport, &vha->vp_fcports, list) { 26108c2ecf20Sopenharmony_ci if (fcport->rport && 26118c2ecf20Sopenharmony_ci starget->id == fcport->rport->scsi_target_id) { 26128c2ecf20Sopenharmony_ci node_name = wwn_to_u64(fcport->node_name); 26138c2ecf20Sopenharmony_ci break; 26148c2ecf20Sopenharmony_ci } 26158c2ecf20Sopenharmony_ci } 26168c2ecf20Sopenharmony_ci 26178c2ecf20Sopenharmony_ci fc_starget_node_name(starget) = node_name; 26188c2ecf20Sopenharmony_ci} 26198c2ecf20Sopenharmony_ci 26208c2ecf20Sopenharmony_cistatic void 26218c2ecf20Sopenharmony_ciqla2x00_get_starget_port_name(struct scsi_target *starget) 26228c2ecf20Sopenharmony_ci{ 26238c2ecf20Sopenharmony_ci struct Scsi_Host *host = dev_to_shost(starget->dev.parent); 26248c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(host); 26258c2ecf20Sopenharmony_ci fc_port_t *fcport; 26268c2ecf20Sopenharmony_ci u64 port_name = 0; 26278c2ecf20Sopenharmony_ci 26288c2ecf20Sopenharmony_ci list_for_each_entry(fcport, &vha->vp_fcports, list) { 26298c2ecf20Sopenharmony_ci if (fcport->rport && 26308c2ecf20Sopenharmony_ci starget->id == fcport->rport->scsi_target_id) { 26318c2ecf20Sopenharmony_ci port_name = wwn_to_u64(fcport->port_name); 26328c2ecf20Sopenharmony_ci break; 26338c2ecf20Sopenharmony_ci } 26348c2ecf20Sopenharmony_ci } 26358c2ecf20Sopenharmony_ci 26368c2ecf20Sopenharmony_ci fc_starget_port_name(starget) = port_name; 26378c2ecf20Sopenharmony_ci} 26388c2ecf20Sopenharmony_ci 26398c2ecf20Sopenharmony_cistatic void 26408c2ecf20Sopenharmony_ciqla2x00_get_starget_port_id(struct scsi_target *starget) 26418c2ecf20Sopenharmony_ci{ 26428c2ecf20Sopenharmony_ci struct Scsi_Host *host = dev_to_shost(starget->dev.parent); 26438c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(host); 26448c2ecf20Sopenharmony_ci fc_port_t *fcport; 26458c2ecf20Sopenharmony_ci uint32_t port_id = ~0U; 26468c2ecf20Sopenharmony_ci 26478c2ecf20Sopenharmony_ci list_for_each_entry(fcport, &vha->vp_fcports, list) { 26488c2ecf20Sopenharmony_ci if (fcport->rport && 26498c2ecf20Sopenharmony_ci starget->id == fcport->rport->scsi_target_id) { 26508c2ecf20Sopenharmony_ci port_id = fcport->d_id.b.domain << 16 | 26518c2ecf20Sopenharmony_ci fcport->d_id.b.area << 8 | fcport->d_id.b.al_pa; 26528c2ecf20Sopenharmony_ci break; 26538c2ecf20Sopenharmony_ci } 26548c2ecf20Sopenharmony_ci } 26558c2ecf20Sopenharmony_ci 26568c2ecf20Sopenharmony_ci fc_starget_port_id(starget) = port_id; 26578c2ecf20Sopenharmony_ci} 26588c2ecf20Sopenharmony_ci 26598c2ecf20Sopenharmony_cistatic inline void 26608c2ecf20Sopenharmony_ciqla2x00_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout) 26618c2ecf20Sopenharmony_ci{ 26628c2ecf20Sopenharmony_ci rport->dev_loss_tmo = timeout ? timeout : 1; 26638c2ecf20Sopenharmony_ci} 26648c2ecf20Sopenharmony_ci 26658c2ecf20Sopenharmony_cistatic void 26668c2ecf20Sopenharmony_ciqla2x00_dev_loss_tmo_callbk(struct fc_rport *rport) 26678c2ecf20Sopenharmony_ci{ 26688c2ecf20Sopenharmony_ci struct Scsi_Host *host = rport_to_shost(rport); 26698c2ecf20Sopenharmony_ci fc_port_t *fcport = *(fc_port_t **)rport->dd_data; 26708c2ecf20Sopenharmony_ci unsigned long flags; 26718c2ecf20Sopenharmony_ci 26728c2ecf20Sopenharmony_ci if (!fcport) 26738c2ecf20Sopenharmony_ci return; 26748c2ecf20Sopenharmony_ci 26758c2ecf20Sopenharmony_ci /* Now that the rport has been deleted, set the fcport state to 26768c2ecf20Sopenharmony_ci FCS_DEVICE_DEAD */ 26778c2ecf20Sopenharmony_ci qla2x00_set_fcport_state(fcport, FCS_DEVICE_DEAD); 26788c2ecf20Sopenharmony_ci 26798c2ecf20Sopenharmony_ci /* 26808c2ecf20Sopenharmony_ci * Transport has effectively 'deleted' the rport, clear 26818c2ecf20Sopenharmony_ci * all local references. 26828c2ecf20Sopenharmony_ci */ 26838c2ecf20Sopenharmony_ci spin_lock_irqsave(host->host_lock, flags); 26848c2ecf20Sopenharmony_ci fcport->rport = fcport->drport = NULL; 26858c2ecf20Sopenharmony_ci *((fc_port_t **)rport->dd_data) = NULL; 26868c2ecf20Sopenharmony_ci spin_unlock_irqrestore(host->host_lock, flags); 26878c2ecf20Sopenharmony_ci 26888c2ecf20Sopenharmony_ci if (test_bit(ABORT_ISP_ACTIVE, &fcport->vha->dpc_flags)) 26898c2ecf20Sopenharmony_ci return; 26908c2ecf20Sopenharmony_ci 26918c2ecf20Sopenharmony_ci if (unlikely(pci_channel_offline(fcport->vha->hw->pdev))) { 26928c2ecf20Sopenharmony_ci qla2x00_abort_all_cmds(fcport->vha, DID_NO_CONNECT << 16); 26938c2ecf20Sopenharmony_ci return; 26948c2ecf20Sopenharmony_ci } 26958c2ecf20Sopenharmony_ci} 26968c2ecf20Sopenharmony_ci 26978c2ecf20Sopenharmony_cistatic void 26988c2ecf20Sopenharmony_ciqla2x00_terminate_rport_io(struct fc_rport *rport) 26998c2ecf20Sopenharmony_ci{ 27008c2ecf20Sopenharmony_ci fc_port_t *fcport = *(fc_port_t **)rport->dd_data; 27018c2ecf20Sopenharmony_ci scsi_qla_host_t *vha; 27028c2ecf20Sopenharmony_ci 27038c2ecf20Sopenharmony_ci if (!fcport) 27048c2ecf20Sopenharmony_ci return; 27058c2ecf20Sopenharmony_ci 27068c2ecf20Sopenharmony_ci if (test_bit(UNLOADING, &fcport->vha->dpc_flags)) 27078c2ecf20Sopenharmony_ci return; 27088c2ecf20Sopenharmony_ci 27098c2ecf20Sopenharmony_ci if (test_bit(ABORT_ISP_ACTIVE, &fcport->vha->dpc_flags)) 27108c2ecf20Sopenharmony_ci return; 27118c2ecf20Sopenharmony_ci vha = fcport->vha; 27128c2ecf20Sopenharmony_ci 27138c2ecf20Sopenharmony_ci if (unlikely(pci_channel_offline(fcport->vha->hw->pdev))) { 27148c2ecf20Sopenharmony_ci qla2x00_abort_all_cmds(fcport->vha, DID_NO_CONNECT << 16); 27158c2ecf20Sopenharmony_ci qla2x00_eh_wait_for_pending_commands(fcport->vha, fcport->d_id.b24, 27168c2ecf20Sopenharmony_ci 0, WAIT_TARGET); 27178c2ecf20Sopenharmony_ci return; 27188c2ecf20Sopenharmony_ci } 27198c2ecf20Sopenharmony_ci /* 27208c2ecf20Sopenharmony_ci * At this point all fcport's software-states are cleared. Perform any 27218c2ecf20Sopenharmony_ci * final cleanup of firmware resources (PCBs and XCBs). 27228c2ecf20Sopenharmony_ci */ 27238c2ecf20Sopenharmony_ci if (fcport->loop_id != FC_NO_LOOP_ID) { 27248c2ecf20Sopenharmony_ci if (IS_FWI2_CAPABLE(fcport->vha->hw)) 27258c2ecf20Sopenharmony_ci fcport->vha->hw->isp_ops->fabric_logout(fcport->vha, 27268c2ecf20Sopenharmony_ci fcport->loop_id, fcport->d_id.b.domain, 27278c2ecf20Sopenharmony_ci fcport->d_id.b.area, fcport->d_id.b.al_pa); 27288c2ecf20Sopenharmony_ci else 27298c2ecf20Sopenharmony_ci qla2x00_port_logout(fcport->vha, fcport); 27308c2ecf20Sopenharmony_ci } 27318c2ecf20Sopenharmony_ci 27328c2ecf20Sopenharmony_ci /* check for any straggling io left behind */ 27338c2ecf20Sopenharmony_ci if (qla2x00_eh_wait_for_pending_commands(fcport->vha, fcport->d_id.b24, 0, WAIT_TARGET)) { 27348c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x300b, 27358c2ecf20Sopenharmony_ci "IO not return. Resetting. \n"); 27368c2ecf20Sopenharmony_ci set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); 27378c2ecf20Sopenharmony_ci qla2xxx_wake_dpc(vha); 27388c2ecf20Sopenharmony_ci qla2x00_wait_for_chip_reset(vha); 27398c2ecf20Sopenharmony_ci } 27408c2ecf20Sopenharmony_ci} 27418c2ecf20Sopenharmony_ci 27428c2ecf20Sopenharmony_cistatic int 27438c2ecf20Sopenharmony_ciqla2x00_issue_lip(struct Scsi_Host *shost) 27448c2ecf20Sopenharmony_ci{ 27458c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(shost); 27468c2ecf20Sopenharmony_ci 27478c2ecf20Sopenharmony_ci if (IS_QLAFX00(vha->hw)) 27488c2ecf20Sopenharmony_ci return 0; 27498c2ecf20Sopenharmony_ci 27508c2ecf20Sopenharmony_ci qla2x00_loop_reset(vha); 27518c2ecf20Sopenharmony_ci return 0; 27528c2ecf20Sopenharmony_ci} 27538c2ecf20Sopenharmony_ci 27548c2ecf20Sopenharmony_cistatic struct fc_host_statistics * 27558c2ecf20Sopenharmony_ciqla2x00_get_fc_host_stats(struct Scsi_Host *shost) 27568c2ecf20Sopenharmony_ci{ 27578c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(shost); 27588c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 27598c2ecf20Sopenharmony_ci struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); 27608c2ecf20Sopenharmony_ci int rval; 27618c2ecf20Sopenharmony_ci struct link_statistics *stats; 27628c2ecf20Sopenharmony_ci dma_addr_t stats_dma; 27638c2ecf20Sopenharmony_ci struct fc_host_statistics *p = &vha->fc_host_stat; 27648c2ecf20Sopenharmony_ci struct qla_qpair *qpair; 27658c2ecf20Sopenharmony_ci int i; 27668c2ecf20Sopenharmony_ci u64 ib = 0, ob = 0, ir = 0, or = 0; 27678c2ecf20Sopenharmony_ci 27688c2ecf20Sopenharmony_ci memset(p, -1, sizeof(*p)); 27698c2ecf20Sopenharmony_ci 27708c2ecf20Sopenharmony_ci if (IS_QLAFX00(vha->hw)) 27718c2ecf20Sopenharmony_ci goto done; 27728c2ecf20Sopenharmony_ci 27738c2ecf20Sopenharmony_ci if (test_bit(UNLOADING, &vha->dpc_flags)) 27748c2ecf20Sopenharmony_ci goto done; 27758c2ecf20Sopenharmony_ci 27768c2ecf20Sopenharmony_ci if (unlikely(pci_channel_offline(ha->pdev))) 27778c2ecf20Sopenharmony_ci goto done; 27788c2ecf20Sopenharmony_ci 27798c2ecf20Sopenharmony_ci if (qla2x00_chip_is_down(vha)) 27808c2ecf20Sopenharmony_ci goto done; 27818c2ecf20Sopenharmony_ci 27828c2ecf20Sopenharmony_ci stats = dma_alloc_coherent(&ha->pdev->dev, sizeof(*stats), &stats_dma, 27838c2ecf20Sopenharmony_ci GFP_KERNEL); 27848c2ecf20Sopenharmony_ci if (!stats) { 27858c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x707d, 27868c2ecf20Sopenharmony_ci "Failed to allocate memory for stats.\n"); 27878c2ecf20Sopenharmony_ci goto done; 27888c2ecf20Sopenharmony_ci } 27898c2ecf20Sopenharmony_ci 27908c2ecf20Sopenharmony_ci rval = QLA_FUNCTION_FAILED; 27918c2ecf20Sopenharmony_ci if (IS_FWI2_CAPABLE(ha)) { 27928c2ecf20Sopenharmony_ci rval = qla24xx_get_isp_stats(base_vha, stats, stats_dma, 0); 27938c2ecf20Sopenharmony_ci } else if (atomic_read(&base_vha->loop_state) == LOOP_READY && 27948c2ecf20Sopenharmony_ci !ha->dpc_active) { 27958c2ecf20Sopenharmony_ci /* Must be in a 'READY' state for statistics retrieval. */ 27968c2ecf20Sopenharmony_ci rval = qla2x00_get_link_status(base_vha, base_vha->loop_id, 27978c2ecf20Sopenharmony_ci stats, stats_dma); 27988c2ecf20Sopenharmony_ci } 27998c2ecf20Sopenharmony_ci 28008c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) 28018c2ecf20Sopenharmony_ci goto done_free; 28028c2ecf20Sopenharmony_ci 28038c2ecf20Sopenharmony_ci /* --- */ 28048c2ecf20Sopenharmony_ci for (i = 0; i < vha->hw->max_qpairs; i++) { 28058c2ecf20Sopenharmony_ci qpair = vha->hw->queue_pair_map[i]; 28068c2ecf20Sopenharmony_ci if (!qpair) 28078c2ecf20Sopenharmony_ci continue; 28088c2ecf20Sopenharmony_ci ir += qpair->counters.input_requests; 28098c2ecf20Sopenharmony_ci or += qpair->counters.output_requests; 28108c2ecf20Sopenharmony_ci ib += qpair->counters.input_bytes; 28118c2ecf20Sopenharmony_ci ob += qpair->counters.output_bytes; 28128c2ecf20Sopenharmony_ci } 28138c2ecf20Sopenharmony_ci ir += ha->base_qpair->counters.input_requests; 28148c2ecf20Sopenharmony_ci or += ha->base_qpair->counters.output_requests; 28158c2ecf20Sopenharmony_ci ib += ha->base_qpair->counters.input_bytes; 28168c2ecf20Sopenharmony_ci ob += ha->base_qpair->counters.output_bytes; 28178c2ecf20Sopenharmony_ci 28188c2ecf20Sopenharmony_ci ir += vha->qla_stats.input_requests; 28198c2ecf20Sopenharmony_ci or += vha->qla_stats.output_requests; 28208c2ecf20Sopenharmony_ci ib += vha->qla_stats.input_bytes; 28218c2ecf20Sopenharmony_ci ob += vha->qla_stats.output_bytes; 28228c2ecf20Sopenharmony_ci /* --- */ 28238c2ecf20Sopenharmony_ci 28248c2ecf20Sopenharmony_ci p->link_failure_count = le32_to_cpu(stats->link_fail_cnt); 28258c2ecf20Sopenharmony_ci p->loss_of_sync_count = le32_to_cpu(stats->loss_sync_cnt); 28268c2ecf20Sopenharmony_ci p->loss_of_signal_count = le32_to_cpu(stats->loss_sig_cnt); 28278c2ecf20Sopenharmony_ci p->prim_seq_protocol_err_count = le32_to_cpu(stats->prim_seq_err_cnt); 28288c2ecf20Sopenharmony_ci p->invalid_tx_word_count = le32_to_cpu(stats->inval_xmit_word_cnt); 28298c2ecf20Sopenharmony_ci p->invalid_crc_count = le32_to_cpu(stats->inval_crc_cnt); 28308c2ecf20Sopenharmony_ci if (IS_FWI2_CAPABLE(ha)) { 28318c2ecf20Sopenharmony_ci p->lip_count = le32_to_cpu(stats->lip_cnt); 28328c2ecf20Sopenharmony_ci p->tx_frames = le32_to_cpu(stats->tx_frames); 28338c2ecf20Sopenharmony_ci p->rx_frames = le32_to_cpu(stats->rx_frames); 28348c2ecf20Sopenharmony_ci p->dumped_frames = le32_to_cpu(stats->discarded_frames); 28358c2ecf20Sopenharmony_ci p->nos_count = le32_to_cpu(stats->nos_rcvd); 28368c2ecf20Sopenharmony_ci p->error_frames = 28378c2ecf20Sopenharmony_ci le32_to_cpu(stats->dropped_frames) + 28388c2ecf20Sopenharmony_ci le32_to_cpu(stats->discarded_frames); 28398c2ecf20Sopenharmony_ci if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { 28408c2ecf20Sopenharmony_ci p->rx_words = le64_to_cpu(stats->fpm_recv_word_cnt); 28418c2ecf20Sopenharmony_ci p->tx_words = le64_to_cpu(stats->fpm_xmit_word_cnt); 28428c2ecf20Sopenharmony_ci } else { 28438c2ecf20Sopenharmony_ci p->rx_words = ib >> 2; 28448c2ecf20Sopenharmony_ci p->tx_words = ob >> 2; 28458c2ecf20Sopenharmony_ci } 28468c2ecf20Sopenharmony_ci } 28478c2ecf20Sopenharmony_ci 28488c2ecf20Sopenharmony_ci p->fcp_control_requests = vha->qla_stats.control_requests; 28498c2ecf20Sopenharmony_ci p->fcp_input_requests = ir; 28508c2ecf20Sopenharmony_ci p->fcp_output_requests = or; 28518c2ecf20Sopenharmony_ci p->fcp_input_megabytes = ib >> 20; 28528c2ecf20Sopenharmony_ci p->fcp_output_megabytes = ob >> 20; 28538c2ecf20Sopenharmony_ci p->seconds_since_last_reset = 28548c2ecf20Sopenharmony_ci get_jiffies_64() - vha->qla_stats.jiffies_at_last_reset; 28558c2ecf20Sopenharmony_ci do_div(p->seconds_since_last_reset, HZ); 28568c2ecf20Sopenharmony_ci 28578c2ecf20Sopenharmony_cidone_free: 28588c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, sizeof(struct link_statistics), 28598c2ecf20Sopenharmony_ci stats, stats_dma); 28608c2ecf20Sopenharmony_cidone: 28618c2ecf20Sopenharmony_ci return p; 28628c2ecf20Sopenharmony_ci} 28638c2ecf20Sopenharmony_ci 28648c2ecf20Sopenharmony_cistatic void 28658c2ecf20Sopenharmony_ciqla2x00_reset_host_stats(struct Scsi_Host *shost) 28668c2ecf20Sopenharmony_ci{ 28678c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(shost); 28688c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 28698c2ecf20Sopenharmony_ci struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); 28708c2ecf20Sopenharmony_ci struct link_statistics *stats; 28718c2ecf20Sopenharmony_ci dma_addr_t stats_dma; 28728c2ecf20Sopenharmony_ci int i; 28738c2ecf20Sopenharmony_ci struct qla_qpair *qpair; 28748c2ecf20Sopenharmony_ci 28758c2ecf20Sopenharmony_ci memset(&vha->qla_stats, 0, sizeof(vha->qla_stats)); 28768c2ecf20Sopenharmony_ci memset(&vha->fc_host_stat, 0, sizeof(vha->fc_host_stat)); 28778c2ecf20Sopenharmony_ci for (i = 0; i < vha->hw->max_qpairs; i++) { 28788c2ecf20Sopenharmony_ci qpair = vha->hw->queue_pair_map[i]; 28798c2ecf20Sopenharmony_ci if (!qpair) 28808c2ecf20Sopenharmony_ci continue; 28818c2ecf20Sopenharmony_ci memset(&qpair->counters, 0, sizeof(qpair->counters)); 28828c2ecf20Sopenharmony_ci } 28838c2ecf20Sopenharmony_ci memset(&ha->base_qpair->counters, 0, sizeof(qpair->counters)); 28848c2ecf20Sopenharmony_ci 28858c2ecf20Sopenharmony_ci vha->qla_stats.jiffies_at_last_reset = get_jiffies_64(); 28868c2ecf20Sopenharmony_ci 28878c2ecf20Sopenharmony_ci if (IS_FWI2_CAPABLE(ha)) { 28888c2ecf20Sopenharmony_ci int rval; 28898c2ecf20Sopenharmony_ci 28908c2ecf20Sopenharmony_ci stats = dma_alloc_coherent(&ha->pdev->dev, 28918c2ecf20Sopenharmony_ci sizeof(*stats), &stats_dma, GFP_KERNEL); 28928c2ecf20Sopenharmony_ci if (!stats) { 28938c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x70d7, 28948c2ecf20Sopenharmony_ci "Failed to allocate memory for stats.\n"); 28958c2ecf20Sopenharmony_ci return; 28968c2ecf20Sopenharmony_ci } 28978c2ecf20Sopenharmony_ci 28988c2ecf20Sopenharmony_ci /* reset firmware statistics */ 28998c2ecf20Sopenharmony_ci rval = qla24xx_get_isp_stats(base_vha, stats, stats_dma, BIT_0); 29008c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) 29018c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x70de, 29028c2ecf20Sopenharmony_ci "Resetting ISP statistics failed: rval = %d\n", 29038c2ecf20Sopenharmony_ci rval); 29048c2ecf20Sopenharmony_ci 29058c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, sizeof(*stats), 29068c2ecf20Sopenharmony_ci stats, stats_dma); 29078c2ecf20Sopenharmony_ci } 29088c2ecf20Sopenharmony_ci} 29098c2ecf20Sopenharmony_ci 29108c2ecf20Sopenharmony_cistatic void 29118c2ecf20Sopenharmony_ciqla2x00_get_host_symbolic_name(struct Scsi_Host *shost) 29128c2ecf20Sopenharmony_ci{ 29138c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(shost); 29148c2ecf20Sopenharmony_ci 29158c2ecf20Sopenharmony_ci qla2x00_get_sym_node_name(vha, fc_host_symbolic_name(shost), 29168c2ecf20Sopenharmony_ci sizeof(fc_host_symbolic_name(shost))); 29178c2ecf20Sopenharmony_ci} 29188c2ecf20Sopenharmony_ci 29198c2ecf20Sopenharmony_cistatic void 29208c2ecf20Sopenharmony_ciqla2x00_set_host_system_hostname(struct Scsi_Host *shost) 29218c2ecf20Sopenharmony_ci{ 29228c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(shost); 29238c2ecf20Sopenharmony_ci 29248c2ecf20Sopenharmony_ci set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags); 29258c2ecf20Sopenharmony_ci} 29268c2ecf20Sopenharmony_ci 29278c2ecf20Sopenharmony_cistatic void 29288c2ecf20Sopenharmony_ciqla2x00_get_host_fabric_name(struct Scsi_Host *shost) 29298c2ecf20Sopenharmony_ci{ 29308c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(shost); 29318c2ecf20Sopenharmony_ci static const uint8_t node_name[WWN_SIZE] = { 29328c2ecf20Sopenharmony_ci 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF 29338c2ecf20Sopenharmony_ci }; 29348c2ecf20Sopenharmony_ci u64 fabric_name = wwn_to_u64(node_name); 29358c2ecf20Sopenharmony_ci 29368c2ecf20Sopenharmony_ci if (vha->device_flags & SWITCH_FOUND) 29378c2ecf20Sopenharmony_ci fabric_name = wwn_to_u64(vha->fabric_node_name); 29388c2ecf20Sopenharmony_ci 29398c2ecf20Sopenharmony_ci fc_host_fabric_name(shost) = fabric_name; 29408c2ecf20Sopenharmony_ci} 29418c2ecf20Sopenharmony_ci 29428c2ecf20Sopenharmony_cistatic void 29438c2ecf20Sopenharmony_ciqla2x00_get_host_port_state(struct Scsi_Host *shost) 29448c2ecf20Sopenharmony_ci{ 29458c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(shost); 29468c2ecf20Sopenharmony_ci struct scsi_qla_host *base_vha = pci_get_drvdata(vha->hw->pdev); 29478c2ecf20Sopenharmony_ci 29488c2ecf20Sopenharmony_ci if (!base_vha->flags.online) { 29498c2ecf20Sopenharmony_ci fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE; 29508c2ecf20Sopenharmony_ci return; 29518c2ecf20Sopenharmony_ci } 29528c2ecf20Sopenharmony_ci 29538c2ecf20Sopenharmony_ci switch (atomic_read(&base_vha->loop_state)) { 29548c2ecf20Sopenharmony_ci case LOOP_UPDATE: 29558c2ecf20Sopenharmony_ci fc_host_port_state(shost) = FC_PORTSTATE_DIAGNOSTICS; 29568c2ecf20Sopenharmony_ci break; 29578c2ecf20Sopenharmony_ci case LOOP_DOWN: 29588c2ecf20Sopenharmony_ci if (test_bit(LOOP_RESYNC_NEEDED, &base_vha->dpc_flags)) 29598c2ecf20Sopenharmony_ci fc_host_port_state(shost) = FC_PORTSTATE_DIAGNOSTICS; 29608c2ecf20Sopenharmony_ci else 29618c2ecf20Sopenharmony_ci fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN; 29628c2ecf20Sopenharmony_ci break; 29638c2ecf20Sopenharmony_ci case LOOP_DEAD: 29648c2ecf20Sopenharmony_ci fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN; 29658c2ecf20Sopenharmony_ci break; 29668c2ecf20Sopenharmony_ci case LOOP_READY: 29678c2ecf20Sopenharmony_ci fc_host_port_state(shost) = FC_PORTSTATE_ONLINE; 29688c2ecf20Sopenharmony_ci break; 29698c2ecf20Sopenharmony_ci default: 29708c2ecf20Sopenharmony_ci fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN; 29718c2ecf20Sopenharmony_ci break; 29728c2ecf20Sopenharmony_ci } 29738c2ecf20Sopenharmony_ci} 29748c2ecf20Sopenharmony_ci 29758c2ecf20Sopenharmony_cistatic int 29768c2ecf20Sopenharmony_ciqla24xx_vport_create(struct fc_vport *fc_vport, bool disable) 29778c2ecf20Sopenharmony_ci{ 29788c2ecf20Sopenharmony_ci int ret = 0; 29798c2ecf20Sopenharmony_ci uint8_t qos = 0; 29808c2ecf20Sopenharmony_ci scsi_qla_host_t *base_vha = shost_priv(fc_vport->shost); 29818c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = NULL; 29828c2ecf20Sopenharmony_ci struct qla_hw_data *ha = base_vha->hw; 29838c2ecf20Sopenharmony_ci int cnt; 29848c2ecf20Sopenharmony_ci struct req_que *req = ha->req_q_map[0]; 29858c2ecf20Sopenharmony_ci struct qla_qpair *qpair; 29868c2ecf20Sopenharmony_ci 29878c2ecf20Sopenharmony_ci ret = qla24xx_vport_create_req_sanity_check(fc_vport); 29888c2ecf20Sopenharmony_ci if (ret) { 29898c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x707e, 29908c2ecf20Sopenharmony_ci "Vport sanity check failed, status %x\n", ret); 29918c2ecf20Sopenharmony_ci return (ret); 29928c2ecf20Sopenharmony_ci } 29938c2ecf20Sopenharmony_ci 29948c2ecf20Sopenharmony_ci vha = qla24xx_create_vhost(fc_vport); 29958c2ecf20Sopenharmony_ci if (vha == NULL) { 29968c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x707f, "Vport create host failed.\n"); 29978c2ecf20Sopenharmony_ci return FC_VPORT_FAILED; 29988c2ecf20Sopenharmony_ci } 29998c2ecf20Sopenharmony_ci if (disable) { 30008c2ecf20Sopenharmony_ci atomic_set(&vha->vp_state, VP_OFFLINE); 30018c2ecf20Sopenharmony_ci fc_vport_set_state(fc_vport, FC_VPORT_DISABLED); 30028c2ecf20Sopenharmony_ci } else 30038c2ecf20Sopenharmony_ci atomic_set(&vha->vp_state, VP_FAILED); 30048c2ecf20Sopenharmony_ci 30058c2ecf20Sopenharmony_ci /* ready to create vport */ 30068c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x7080, 30078c2ecf20Sopenharmony_ci "VP entry id %d assigned.\n", vha->vp_idx); 30088c2ecf20Sopenharmony_ci 30098c2ecf20Sopenharmony_ci /* initialized vport states */ 30108c2ecf20Sopenharmony_ci atomic_set(&vha->loop_state, LOOP_DOWN); 30118c2ecf20Sopenharmony_ci vha->vp_err_state = VP_ERR_PORTDWN; 30128c2ecf20Sopenharmony_ci vha->vp_prev_err_state = VP_ERR_UNKWN; 30138c2ecf20Sopenharmony_ci /* Check if physical ha port is Up */ 30148c2ecf20Sopenharmony_ci if (atomic_read(&base_vha->loop_state) == LOOP_DOWN || 30158c2ecf20Sopenharmony_ci atomic_read(&base_vha->loop_state) == LOOP_DEAD) { 30168c2ecf20Sopenharmony_ci /* Don't retry or attempt login of this virtual port */ 30178c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_user, vha, 0x7081, 30188c2ecf20Sopenharmony_ci "Vport loop state is not UP.\n"); 30198c2ecf20Sopenharmony_ci atomic_set(&vha->loop_state, LOOP_DEAD); 30208c2ecf20Sopenharmony_ci if (!disable) 30218c2ecf20Sopenharmony_ci fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN); 30228c2ecf20Sopenharmony_ci } 30238c2ecf20Sopenharmony_ci 30248c2ecf20Sopenharmony_ci if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif) { 30258c2ecf20Sopenharmony_ci if (ha->fw_attributes & BIT_4) { 30268c2ecf20Sopenharmony_ci int prot = 0, guard; 30278c2ecf20Sopenharmony_ci 30288c2ecf20Sopenharmony_ci vha->flags.difdix_supported = 1; 30298c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_user, vha, 0x7082, 30308c2ecf20Sopenharmony_ci "Registered for DIF/DIX type 1 and 3 protection.\n"); 30318c2ecf20Sopenharmony_ci scsi_host_set_prot(vha->host, 30328c2ecf20Sopenharmony_ci prot | SHOST_DIF_TYPE1_PROTECTION 30338c2ecf20Sopenharmony_ci | SHOST_DIF_TYPE2_PROTECTION 30348c2ecf20Sopenharmony_ci | SHOST_DIF_TYPE3_PROTECTION 30358c2ecf20Sopenharmony_ci | SHOST_DIX_TYPE1_PROTECTION 30368c2ecf20Sopenharmony_ci | SHOST_DIX_TYPE2_PROTECTION 30378c2ecf20Sopenharmony_ci | SHOST_DIX_TYPE3_PROTECTION); 30388c2ecf20Sopenharmony_ci 30398c2ecf20Sopenharmony_ci guard = SHOST_DIX_GUARD_CRC; 30408c2ecf20Sopenharmony_ci 30418c2ecf20Sopenharmony_ci if (IS_PI_IPGUARD_CAPABLE(ha) && 30428c2ecf20Sopenharmony_ci (ql2xenabledif > 1 || IS_PI_DIFB_DIX0_CAPABLE(ha))) 30438c2ecf20Sopenharmony_ci guard |= SHOST_DIX_GUARD_IP; 30448c2ecf20Sopenharmony_ci 30458c2ecf20Sopenharmony_ci scsi_host_set_guard(vha->host, guard); 30468c2ecf20Sopenharmony_ci } else 30478c2ecf20Sopenharmony_ci vha->flags.difdix_supported = 0; 30488c2ecf20Sopenharmony_ci } 30498c2ecf20Sopenharmony_ci 30508c2ecf20Sopenharmony_ci if (scsi_add_host_with_dma(vha->host, &fc_vport->dev, 30518c2ecf20Sopenharmony_ci &ha->pdev->dev)) { 30528c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_user, vha, 0x7083, 30538c2ecf20Sopenharmony_ci "scsi_add_host failure for VP[%d].\n", vha->vp_idx); 30548c2ecf20Sopenharmony_ci goto vport_create_failed_2; 30558c2ecf20Sopenharmony_ci } 30568c2ecf20Sopenharmony_ci 30578c2ecf20Sopenharmony_ci /* initialize attributes */ 30588c2ecf20Sopenharmony_ci fc_host_dev_loss_tmo(vha->host) = ha->port_down_retry_count; 30598c2ecf20Sopenharmony_ci fc_host_node_name(vha->host) = wwn_to_u64(vha->node_name); 30608c2ecf20Sopenharmony_ci fc_host_port_name(vha->host) = wwn_to_u64(vha->port_name); 30618c2ecf20Sopenharmony_ci fc_host_supported_classes(vha->host) = 30628c2ecf20Sopenharmony_ci fc_host_supported_classes(base_vha->host); 30638c2ecf20Sopenharmony_ci fc_host_supported_speeds(vha->host) = 30648c2ecf20Sopenharmony_ci fc_host_supported_speeds(base_vha->host); 30658c2ecf20Sopenharmony_ci 30668c2ecf20Sopenharmony_ci qlt_vport_create(vha, ha); 30678c2ecf20Sopenharmony_ci qla24xx_vport_disable(fc_vport, disable); 30688c2ecf20Sopenharmony_ci 30698c2ecf20Sopenharmony_ci if (!ql2xmqsupport || !ha->npiv_info) 30708c2ecf20Sopenharmony_ci goto vport_queue; 30718c2ecf20Sopenharmony_ci 30728c2ecf20Sopenharmony_ci /* Create a request queue in QoS mode for the vport */ 30738c2ecf20Sopenharmony_ci for (cnt = 0; cnt < ha->nvram_npiv_size; cnt++) { 30748c2ecf20Sopenharmony_ci if (memcmp(ha->npiv_info[cnt].port_name, vha->port_name, 8) == 0 30758c2ecf20Sopenharmony_ci && memcmp(ha->npiv_info[cnt].node_name, vha->node_name, 30768c2ecf20Sopenharmony_ci 8) == 0) { 30778c2ecf20Sopenharmony_ci qos = ha->npiv_info[cnt].q_qos; 30788c2ecf20Sopenharmony_ci break; 30798c2ecf20Sopenharmony_ci } 30808c2ecf20Sopenharmony_ci } 30818c2ecf20Sopenharmony_ci 30828c2ecf20Sopenharmony_ci if (qos) { 30838c2ecf20Sopenharmony_ci qpair = qla2xxx_create_qpair(vha, qos, vha->vp_idx, true); 30848c2ecf20Sopenharmony_ci if (!qpair) 30858c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x7084, 30868c2ecf20Sopenharmony_ci "Can't create qpair for VP[%d]\n", 30878c2ecf20Sopenharmony_ci vha->vp_idx); 30888c2ecf20Sopenharmony_ci else { 30898c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_multiq, vha, 0xc001, 30908c2ecf20Sopenharmony_ci "Queue pair: %d Qos: %d) created for VP[%d]\n", 30918c2ecf20Sopenharmony_ci qpair->id, qos, vha->vp_idx); 30928c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_user, vha, 0x7085, 30938c2ecf20Sopenharmony_ci "Queue Pair: %d Qos: %d) created for VP[%d]\n", 30948c2ecf20Sopenharmony_ci qpair->id, qos, vha->vp_idx); 30958c2ecf20Sopenharmony_ci req = qpair->req; 30968c2ecf20Sopenharmony_ci vha->qpair = qpair; 30978c2ecf20Sopenharmony_ci } 30988c2ecf20Sopenharmony_ci } 30998c2ecf20Sopenharmony_ci 31008c2ecf20Sopenharmony_civport_queue: 31018c2ecf20Sopenharmony_ci vha->req = req; 31028c2ecf20Sopenharmony_ci return 0; 31038c2ecf20Sopenharmony_ci 31048c2ecf20Sopenharmony_civport_create_failed_2: 31058c2ecf20Sopenharmony_ci qla24xx_disable_vp(vha); 31068c2ecf20Sopenharmony_ci qla24xx_deallocate_vp_id(vha); 31078c2ecf20Sopenharmony_ci scsi_host_put(vha->host); 31088c2ecf20Sopenharmony_ci return FC_VPORT_FAILED; 31098c2ecf20Sopenharmony_ci} 31108c2ecf20Sopenharmony_ci 31118c2ecf20Sopenharmony_cistatic int 31128c2ecf20Sopenharmony_ciqla24xx_vport_delete(struct fc_vport *fc_vport) 31138c2ecf20Sopenharmony_ci{ 31148c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = fc_vport->dd_data; 31158c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 31168c2ecf20Sopenharmony_ci uint16_t id = vha->vp_idx; 31178c2ecf20Sopenharmony_ci 31188c2ecf20Sopenharmony_ci set_bit(VPORT_DELETE, &vha->dpc_flags); 31198c2ecf20Sopenharmony_ci 31208c2ecf20Sopenharmony_ci while (test_bit(LOOP_RESYNC_ACTIVE, &vha->dpc_flags) || 31218c2ecf20Sopenharmony_ci test_bit(FCPORT_UPDATE_NEEDED, &vha->dpc_flags)) 31228c2ecf20Sopenharmony_ci msleep(1000); 31238c2ecf20Sopenharmony_ci 31248c2ecf20Sopenharmony_ci 31258c2ecf20Sopenharmony_ci qla24xx_disable_vp(vha); 31268c2ecf20Sopenharmony_ci qla2x00_wait_for_sess_deletion(vha); 31278c2ecf20Sopenharmony_ci 31288c2ecf20Sopenharmony_ci qla_nvme_delete(vha); 31298c2ecf20Sopenharmony_ci vha->flags.delete_progress = 1; 31308c2ecf20Sopenharmony_ci 31318c2ecf20Sopenharmony_ci qlt_remove_target(ha, vha); 31328c2ecf20Sopenharmony_ci 31338c2ecf20Sopenharmony_ci fc_remove_host(vha->host); 31348c2ecf20Sopenharmony_ci 31358c2ecf20Sopenharmony_ci scsi_remove_host(vha->host); 31368c2ecf20Sopenharmony_ci 31378c2ecf20Sopenharmony_ci /* Allow timer to run to drain queued items, when removing vp */ 31388c2ecf20Sopenharmony_ci qla24xx_deallocate_vp_id(vha); 31398c2ecf20Sopenharmony_ci 31408c2ecf20Sopenharmony_ci if (vha->timer_active) { 31418c2ecf20Sopenharmony_ci qla2x00_vp_stop_timer(vha); 31428c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_user, vha, 0x7086, 31438c2ecf20Sopenharmony_ci "Timer for the VP[%d] has stopped\n", vha->vp_idx); 31448c2ecf20Sopenharmony_ci } 31458c2ecf20Sopenharmony_ci 31468c2ecf20Sopenharmony_ci qla2x00_free_fcports(vha); 31478c2ecf20Sopenharmony_ci 31488c2ecf20Sopenharmony_ci mutex_lock(&ha->vport_lock); 31498c2ecf20Sopenharmony_ci ha->cur_vport_count--; 31508c2ecf20Sopenharmony_ci clear_bit(vha->vp_idx, ha->vp_idx_map); 31518c2ecf20Sopenharmony_ci mutex_unlock(&ha->vport_lock); 31528c2ecf20Sopenharmony_ci 31538c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, vha->gnl.size, vha->gnl.l, 31548c2ecf20Sopenharmony_ci vha->gnl.ldma); 31558c2ecf20Sopenharmony_ci 31568c2ecf20Sopenharmony_ci vha->gnl.l = NULL; 31578c2ecf20Sopenharmony_ci 31588c2ecf20Sopenharmony_ci vfree(vha->scan.l); 31598c2ecf20Sopenharmony_ci 31608c2ecf20Sopenharmony_ci if (vha->qpair && vha->qpair->vp_idx == vha->vp_idx) { 31618c2ecf20Sopenharmony_ci if (qla2xxx_delete_qpair(vha, vha->qpair) != QLA_SUCCESS) 31628c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x7087, 31638c2ecf20Sopenharmony_ci "Queue Pair delete failed.\n"); 31648c2ecf20Sopenharmony_ci } 31658c2ecf20Sopenharmony_ci 31668c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x7088, "VP[%d] deleted.\n", id); 31678c2ecf20Sopenharmony_ci scsi_host_put(vha->host); 31688c2ecf20Sopenharmony_ci return 0; 31698c2ecf20Sopenharmony_ci} 31708c2ecf20Sopenharmony_ci 31718c2ecf20Sopenharmony_cistatic int 31728c2ecf20Sopenharmony_ciqla24xx_vport_disable(struct fc_vport *fc_vport, bool disable) 31738c2ecf20Sopenharmony_ci{ 31748c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = fc_vport->dd_data; 31758c2ecf20Sopenharmony_ci 31768c2ecf20Sopenharmony_ci if (disable) 31778c2ecf20Sopenharmony_ci qla24xx_disable_vp(vha); 31788c2ecf20Sopenharmony_ci else 31798c2ecf20Sopenharmony_ci qla24xx_enable_vp(vha); 31808c2ecf20Sopenharmony_ci 31818c2ecf20Sopenharmony_ci return 0; 31828c2ecf20Sopenharmony_ci} 31838c2ecf20Sopenharmony_ci 31848c2ecf20Sopenharmony_cistruct fc_function_template qla2xxx_transport_functions = { 31858c2ecf20Sopenharmony_ci 31868c2ecf20Sopenharmony_ci .show_host_node_name = 1, 31878c2ecf20Sopenharmony_ci .show_host_port_name = 1, 31888c2ecf20Sopenharmony_ci .show_host_supported_classes = 1, 31898c2ecf20Sopenharmony_ci .show_host_supported_speeds = 1, 31908c2ecf20Sopenharmony_ci 31918c2ecf20Sopenharmony_ci .get_host_port_id = qla2x00_get_host_port_id, 31928c2ecf20Sopenharmony_ci .show_host_port_id = 1, 31938c2ecf20Sopenharmony_ci .get_host_speed = qla2x00_get_host_speed, 31948c2ecf20Sopenharmony_ci .show_host_speed = 1, 31958c2ecf20Sopenharmony_ci .get_host_port_type = qla2x00_get_host_port_type, 31968c2ecf20Sopenharmony_ci .show_host_port_type = 1, 31978c2ecf20Sopenharmony_ci .get_host_symbolic_name = qla2x00_get_host_symbolic_name, 31988c2ecf20Sopenharmony_ci .show_host_symbolic_name = 1, 31998c2ecf20Sopenharmony_ci .set_host_system_hostname = qla2x00_set_host_system_hostname, 32008c2ecf20Sopenharmony_ci .show_host_system_hostname = 1, 32018c2ecf20Sopenharmony_ci .get_host_fabric_name = qla2x00_get_host_fabric_name, 32028c2ecf20Sopenharmony_ci .show_host_fabric_name = 1, 32038c2ecf20Sopenharmony_ci .get_host_port_state = qla2x00_get_host_port_state, 32048c2ecf20Sopenharmony_ci .show_host_port_state = 1, 32058c2ecf20Sopenharmony_ci 32068c2ecf20Sopenharmony_ci .dd_fcrport_size = sizeof(struct fc_port *), 32078c2ecf20Sopenharmony_ci .show_rport_supported_classes = 1, 32088c2ecf20Sopenharmony_ci 32098c2ecf20Sopenharmony_ci .get_starget_node_name = qla2x00_get_starget_node_name, 32108c2ecf20Sopenharmony_ci .show_starget_node_name = 1, 32118c2ecf20Sopenharmony_ci .get_starget_port_name = qla2x00_get_starget_port_name, 32128c2ecf20Sopenharmony_ci .show_starget_port_name = 1, 32138c2ecf20Sopenharmony_ci .get_starget_port_id = qla2x00_get_starget_port_id, 32148c2ecf20Sopenharmony_ci .show_starget_port_id = 1, 32158c2ecf20Sopenharmony_ci 32168c2ecf20Sopenharmony_ci .set_rport_dev_loss_tmo = qla2x00_set_rport_loss_tmo, 32178c2ecf20Sopenharmony_ci .show_rport_dev_loss_tmo = 1, 32188c2ecf20Sopenharmony_ci 32198c2ecf20Sopenharmony_ci .issue_fc_host_lip = qla2x00_issue_lip, 32208c2ecf20Sopenharmony_ci .dev_loss_tmo_callbk = qla2x00_dev_loss_tmo_callbk, 32218c2ecf20Sopenharmony_ci .terminate_rport_io = qla2x00_terminate_rport_io, 32228c2ecf20Sopenharmony_ci .get_fc_host_stats = qla2x00_get_fc_host_stats, 32238c2ecf20Sopenharmony_ci .reset_fc_host_stats = qla2x00_reset_host_stats, 32248c2ecf20Sopenharmony_ci 32258c2ecf20Sopenharmony_ci .vport_create = qla24xx_vport_create, 32268c2ecf20Sopenharmony_ci .vport_disable = qla24xx_vport_disable, 32278c2ecf20Sopenharmony_ci .vport_delete = qla24xx_vport_delete, 32288c2ecf20Sopenharmony_ci .bsg_request = qla24xx_bsg_request, 32298c2ecf20Sopenharmony_ci .bsg_timeout = qla24xx_bsg_timeout, 32308c2ecf20Sopenharmony_ci}; 32318c2ecf20Sopenharmony_ci 32328c2ecf20Sopenharmony_cistruct fc_function_template qla2xxx_transport_vport_functions = { 32338c2ecf20Sopenharmony_ci 32348c2ecf20Sopenharmony_ci .show_host_node_name = 1, 32358c2ecf20Sopenharmony_ci .show_host_port_name = 1, 32368c2ecf20Sopenharmony_ci .show_host_supported_classes = 1, 32378c2ecf20Sopenharmony_ci 32388c2ecf20Sopenharmony_ci .get_host_port_id = qla2x00_get_host_port_id, 32398c2ecf20Sopenharmony_ci .show_host_port_id = 1, 32408c2ecf20Sopenharmony_ci .get_host_speed = qla2x00_get_host_speed, 32418c2ecf20Sopenharmony_ci .show_host_speed = 1, 32428c2ecf20Sopenharmony_ci .get_host_port_type = qla2x00_get_host_port_type, 32438c2ecf20Sopenharmony_ci .show_host_port_type = 1, 32448c2ecf20Sopenharmony_ci .get_host_symbolic_name = qla2x00_get_host_symbolic_name, 32458c2ecf20Sopenharmony_ci .show_host_symbolic_name = 1, 32468c2ecf20Sopenharmony_ci .set_host_system_hostname = qla2x00_set_host_system_hostname, 32478c2ecf20Sopenharmony_ci .show_host_system_hostname = 1, 32488c2ecf20Sopenharmony_ci .get_host_fabric_name = qla2x00_get_host_fabric_name, 32498c2ecf20Sopenharmony_ci .show_host_fabric_name = 1, 32508c2ecf20Sopenharmony_ci .get_host_port_state = qla2x00_get_host_port_state, 32518c2ecf20Sopenharmony_ci .show_host_port_state = 1, 32528c2ecf20Sopenharmony_ci 32538c2ecf20Sopenharmony_ci .dd_fcrport_size = sizeof(struct fc_port *), 32548c2ecf20Sopenharmony_ci .show_rport_supported_classes = 1, 32558c2ecf20Sopenharmony_ci 32568c2ecf20Sopenharmony_ci .get_starget_node_name = qla2x00_get_starget_node_name, 32578c2ecf20Sopenharmony_ci .show_starget_node_name = 1, 32588c2ecf20Sopenharmony_ci .get_starget_port_name = qla2x00_get_starget_port_name, 32598c2ecf20Sopenharmony_ci .show_starget_port_name = 1, 32608c2ecf20Sopenharmony_ci .get_starget_port_id = qla2x00_get_starget_port_id, 32618c2ecf20Sopenharmony_ci .show_starget_port_id = 1, 32628c2ecf20Sopenharmony_ci 32638c2ecf20Sopenharmony_ci .set_rport_dev_loss_tmo = qla2x00_set_rport_loss_tmo, 32648c2ecf20Sopenharmony_ci .show_rport_dev_loss_tmo = 1, 32658c2ecf20Sopenharmony_ci 32668c2ecf20Sopenharmony_ci .issue_fc_host_lip = qla2x00_issue_lip, 32678c2ecf20Sopenharmony_ci .dev_loss_tmo_callbk = qla2x00_dev_loss_tmo_callbk, 32688c2ecf20Sopenharmony_ci .terminate_rport_io = qla2x00_terminate_rport_io, 32698c2ecf20Sopenharmony_ci .get_fc_host_stats = qla2x00_get_fc_host_stats, 32708c2ecf20Sopenharmony_ci .reset_fc_host_stats = qla2x00_reset_host_stats, 32718c2ecf20Sopenharmony_ci 32728c2ecf20Sopenharmony_ci .bsg_request = qla24xx_bsg_request, 32738c2ecf20Sopenharmony_ci .bsg_timeout = qla24xx_bsg_timeout, 32748c2ecf20Sopenharmony_ci}; 32758c2ecf20Sopenharmony_ci 32768c2ecf20Sopenharmony_cistatic uint 32778c2ecf20Sopenharmony_ciqla2x00_get_host_supported_speeds(scsi_qla_host_t *vha, uint speeds) 32788c2ecf20Sopenharmony_ci{ 32798c2ecf20Sopenharmony_ci uint supported_speeds = FC_PORTSPEED_UNKNOWN; 32808c2ecf20Sopenharmony_ci 32818c2ecf20Sopenharmony_ci if (speeds & FDMI_PORT_SPEED_64GB) 32828c2ecf20Sopenharmony_ci supported_speeds |= FC_PORTSPEED_64GBIT; 32838c2ecf20Sopenharmony_ci if (speeds & FDMI_PORT_SPEED_32GB) 32848c2ecf20Sopenharmony_ci supported_speeds |= FC_PORTSPEED_32GBIT; 32858c2ecf20Sopenharmony_ci if (speeds & FDMI_PORT_SPEED_16GB) 32868c2ecf20Sopenharmony_ci supported_speeds |= FC_PORTSPEED_16GBIT; 32878c2ecf20Sopenharmony_ci if (speeds & FDMI_PORT_SPEED_8GB) 32888c2ecf20Sopenharmony_ci supported_speeds |= FC_PORTSPEED_8GBIT; 32898c2ecf20Sopenharmony_ci if (speeds & FDMI_PORT_SPEED_4GB) 32908c2ecf20Sopenharmony_ci supported_speeds |= FC_PORTSPEED_4GBIT; 32918c2ecf20Sopenharmony_ci if (speeds & FDMI_PORT_SPEED_2GB) 32928c2ecf20Sopenharmony_ci supported_speeds |= FC_PORTSPEED_2GBIT; 32938c2ecf20Sopenharmony_ci if (speeds & FDMI_PORT_SPEED_1GB) 32948c2ecf20Sopenharmony_ci supported_speeds |= FC_PORTSPEED_1GBIT; 32958c2ecf20Sopenharmony_ci 32968c2ecf20Sopenharmony_ci return supported_speeds; 32978c2ecf20Sopenharmony_ci} 32988c2ecf20Sopenharmony_ci 32998c2ecf20Sopenharmony_civoid 33008c2ecf20Sopenharmony_ciqla2x00_init_host_attr(scsi_qla_host_t *vha) 33018c2ecf20Sopenharmony_ci{ 33028c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 33038c2ecf20Sopenharmony_ci u32 speeds = 0, fdmi_speed = 0; 33048c2ecf20Sopenharmony_ci 33058c2ecf20Sopenharmony_ci fc_host_dev_loss_tmo(vha->host) = ha->port_down_retry_count; 33068c2ecf20Sopenharmony_ci fc_host_node_name(vha->host) = wwn_to_u64(vha->node_name); 33078c2ecf20Sopenharmony_ci fc_host_port_name(vha->host) = wwn_to_u64(vha->port_name); 33088c2ecf20Sopenharmony_ci fc_host_supported_classes(vha->host) = ha->base_qpair->enable_class_2 ? 33098c2ecf20Sopenharmony_ci (FC_COS_CLASS2|FC_COS_CLASS3) : FC_COS_CLASS3; 33108c2ecf20Sopenharmony_ci fc_host_max_npiv_vports(vha->host) = ha->max_npiv_vports; 33118c2ecf20Sopenharmony_ci fc_host_npiv_vports_inuse(vha->host) = ha->cur_vport_count; 33128c2ecf20Sopenharmony_ci 33138c2ecf20Sopenharmony_ci fdmi_speed = qla25xx_fdmi_port_speed_capability(ha); 33148c2ecf20Sopenharmony_ci speeds = qla2x00_get_host_supported_speeds(vha, fdmi_speed); 33158c2ecf20Sopenharmony_ci 33168c2ecf20Sopenharmony_ci fc_host_supported_speeds(vha->host) = speeds; 33178c2ecf20Sopenharmony_ci} 3318