162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * QLogic Fibre Channel HBA Driver 462306a36Sopenharmony_ci * Copyright (c) 2003-2014 QLogic Corporation 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci#include "qla_def.h" 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/debugfs.h> 962306a36Sopenharmony_ci#include <linux/seq_file.h> 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_cistatic struct dentry *qla2x00_dfs_root; 1262306a36Sopenharmony_cistatic atomic_t qla2x00_dfs_root_count; 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#define QLA_DFS_RPORT_DEVLOSS_TMO 1 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_cistatic int 1762306a36Sopenharmony_ciqla_dfs_rport_get(struct fc_port *fp, int attr_id, u64 *val) 1862306a36Sopenharmony_ci{ 1962306a36Sopenharmony_ci switch (attr_id) { 2062306a36Sopenharmony_ci case QLA_DFS_RPORT_DEVLOSS_TMO: 2162306a36Sopenharmony_ci /* Only supported for FC-NVMe devices that are registered. */ 2262306a36Sopenharmony_ci if (!(fp->nvme_flag & NVME_FLAG_REGISTERED)) 2362306a36Sopenharmony_ci return -EIO; 2462306a36Sopenharmony_ci *val = fp->nvme_remote_port->dev_loss_tmo; 2562306a36Sopenharmony_ci break; 2662306a36Sopenharmony_ci default: 2762306a36Sopenharmony_ci return -EINVAL; 2862306a36Sopenharmony_ci } 2962306a36Sopenharmony_ci return 0; 3062306a36Sopenharmony_ci} 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_cistatic int 3362306a36Sopenharmony_ciqla_dfs_rport_set(struct fc_port *fp, int attr_id, u64 val) 3462306a36Sopenharmony_ci{ 3562306a36Sopenharmony_ci switch (attr_id) { 3662306a36Sopenharmony_ci case QLA_DFS_RPORT_DEVLOSS_TMO: 3762306a36Sopenharmony_ci /* Only supported for FC-NVMe devices that are registered. */ 3862306a36Sopenharmony_ci if (!(fp->nvme_flag & NVME_FLAG_REGISTERED)) 3962306a36Sopenharmony_ci return -EIO; 4062306a36Sopenharmony_ci#if (IS_ENABLED(CONFIG_NVME_FC)) 4162306a36Sopenharmony_ci return nvme_fc_set_remoteport_devloss(fp->nvme_remote_port, 4262306a36Sopenharmony_ci val); 4362306a36Sopenharmony_ci#else /* CONFIG_NVME_FC */ 4462306a36Sopenharmony_ci return -EINVAL; 4562306a36Sopenharmony_ci#endif /* CONFIG_NVME_FC */ 4662306a36Sopenharmony_ci default: 4762306a36Sopenharmony_ci return -EINVAL; 4862306a36Sopenharmony_ci } 4962306a36Sopenharmony_ci return 0; 5062306a36Sopenharmony_ci} 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci#define DEFINE_QLA_DFS_RPORT_RW_ATTR(_attr_id, _attr) \ 5362306a36Sopenharmony_cistatic int qla_dfs_rport_##_attr##_get(void *data, u64 *val) \ 5462306a36Sopenharmony_ci{ \ 5562306a36Sopenharmony_ci struct fc_port *fp = data; \ 5662306a36Sopenharmony_ci return qla_dfs_rport_get(fp, _attr_id, val); \ 5762306a36Sopenharmony_ci} \ 5862306a36Sopenharmony_cistatic int qla_dfs_rport_##_attr##_set(void *data, u64 val) \ 5962306a36Sopenharmony_ci{ \ 6062306a36Sopenharmony_ci struct fc_port *fp = data; \ 6162306a36Sopenharmony_ci return qla_dfs_rport_set(fp, _attr_id, val); \ 6262306a36Sopenharmony_ci} \ 6362306a36Sopenharmony_ciDEFINE_DEBUGFS_ATTRIBUTE(qla_dfs_rport_##_attr##_fops, \ 6462306a36Sopenharmony_ci qla_dfs_rport_##_attr##_get, \ 6562306a36Sopenharmony_ci qla_dfs_rport_##_attr##_set, "%llu\n") 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci/* 6862306a36Sopenharmony_ci * Wrapper for getting fc_port fields. 6962306a36Sopenharmony_ci * 7062306a36Sopenharmony_ci * _attr : Attribute name. 7162306a36Sopenharmony_ci * _get_val : Accessor macro to retrieve the value. 7262306a36Sopenharmony_ci */ 7362306a36Sopenharmony_ci#define DEFINE_QLA_DFS_RPORT_FIELD_GET(_attr, _get_val) \ 7462306a36Sopenharmony_cistatic int qla_dfs_rport_field_##_attr##_get(void *data, u64 *val) \ 7562306a36Sopenharmony_ci{ \ 7662306a36Sopenharmony_ci struct fc_port *fp = data; \ 7762306a36Sopenharmony_ci *val = _get_val; \ 7862306a36Sopenharmony_ci return 0; \ 7962306a36Sopenharmony_ci} \ 8062306a36Sopenharmony_ciDEFINE_DEBUGFS_ATTRIBUTE(qla_dfs_rport_field_##_attr##_fops, \ 8162306a36Sopenharmony_ci qla_dfs_rport_field_##_attr##_get, \ 8262306a36Sopenharmony_ci NULL, "%llu\n") 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci#define DEFINE_QLA_DFS_RPORT_ACCESS(_attr, _get_val) \ 8562306a36Sopenharmony_ci DEFINE_QLA_DFS_RPORT_FIELD_GET(_attr, _get_val) 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci#define DEFINE_QLA_DFS_RPORT_FIELD(_attr) \ 8862306a36Sopenharmony_ci DEFINE_QLA_DFS_RPORT_FIELD_GET(_attr, fp->_attr) 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ciDEFINE_QLA_DFS_RPORT_RW_ATTR(QLA_DFS_RPORT_DEVLOSS_TMO, dev_loss_tmo); 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ciDEFINE_QLA_DFS_RPORT_FIELD(disc_state); 9362306a36Sopenharmony_ciDEFINE_QLA_DFS_RPORT_FIELD(scan_state); 9462306a36Sopenharmony_ciDEFINE_QLA_DFS_RPORT_FIELD(fw_login_state); 9562306a36Sopenharmony_ciDEFINE_QLA_DFS_RPORT_FIELD(login_pause); 9662306a36Sopenharmony_ciDEFINE_QLA_DFS_RPORT_FIELD(flags); 9762306a36Sopenharmony_ciDEFINE_QLA_DFS_RPORT_FIELD(nvme_flag); 9862306a36Sopenharmony_ciDEFINE_QLA_DFS_RPORT_FIELD(last_rscn_gen); 9962306a36Sopenharmony_ciDEFINE_QLA_DFS_RPORT_FIELD(rscn_gen); 10062306a36Sopenharmony_ciDEFINE_QLA_DFS_RPORT_FIELD(login_gen); 10162306a36Sopenharmony_ciDEFINE_QLA_DFS_RPORT_FIELD(loop_id); 10262306a36Sopenharmony_ciDEFINE_QLA_DFS_RPORT_FIELD_GET(port_id, fp->d_id.b24); 10362306a36Sopenharmony_ciDEFINE_QLA_DFS_RPORT_FIELD_GET(sess_kref, kref_read(&fp->sess_kref)); 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_civoid 10662306a36Sopenharmony_ciqla2x00_dfs_create_rport(scsi_qla_host_t *vha, struct fc_port *fp) 10762306a36Sopenharmony_ci{ 10862306a36Sopenharmony_ci char wwn[32]; 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci#define QLA_CREATE_RPORT_FIELD_ATTR(_attr) \ 11162306a36Sopenharmony_ci debugfs_create_file(#_attr, 0400, fp->dfs_rport_dir, \ 11262306a36Sopenharmony_ci fp, &qla_dfs_rport_field_##_attr##_fops) 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci if (!vha->dfs_rport_root || fp->dfs_rport_dir) 11562306a36Sopenharmony_ci return; 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci sprintf(wwn, "pn-%016llx", wwn_to_u64(fp->port_name)); 11862306a36Sopenharmony_ci fp->dfs_rport_dir = debugfs_create_dir(wwn, vha->dfs_rport_root); 11962306a36Sopenharmony_ci if (IS_ERR(fp->dfs_rport_dir)) 12062306a36Sopenharmony_ci return; 12162306a36Sopenharmony_ci if (NVME_TARGET(vha->hw, fp)) 12262306a36Sopenharmony_ci debugfs_create_file("dev_loss_tmo", 0600, fp->dfs_rport_dir, 12362306a36Sopenharmony_ci fp, &qla_dfs_rport_dev_loss_tmo_fops); 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci QLA_CREATE_RPORT_FIELD_ATTR(disc_state); 12662306a36Sopenharmony_ci QLA_CREATE_RPORT_FIELD_ATTR(scan_state); 12762306a36Sopenharmony_ci QLA_CREATE_RPORT_FIELD_ATTR(fw_login_state); 12862306a36Sopenharmony_ci QLA_CREATE_RPORT_FIELD_ATTR(login_pause); 12962306a36Sopenharmony_ci QLA_CREATE_RPORT_FIELD_ATTR(flags); 13062306a36Sopenharmony_ci QLA_CREATE_RPORT_FIELD_ATTR(nvme_flag); 13162306a36Sopenharmony_ci QLA_CREATE_RPORT_FIELD_ATTR(last_rscn_gen); 13262306a36Sopenharmony_ci QLA_CREATE_RPORT_FIELD_ATTR(rscn_gen); 13362306a36Sopenharmony_ci QLA_CREATE_RPORT_FIELD_ATTR(login_gen); 13462306a36Sopenharmony_ci QLA_CREATE_RPORT_FIELD_ATTR(loop_id); 13562306a36Sopenharmony_ci QLA_CREATE_RPORT_FIELD_ATTR(port_id); 13662306a36Sopenharmony_ci QLA_CREATE_RPORT_FIELD_ATTR(sess_kref); 13762306a36Sopenharmony_ci} 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_civoid 14062306a36Sopenharmony_ciqla2x00_dfs_remove_rport(scsi_qla_host_t *vha, struct fc_port *fp) 14162306a36Sopenharmony_ci{ 14262306a36Sopenharmony_ci if (!vha->dfs_rport_root || !fp->dfs_rport_dir) 14362306a36Sopenharmony_ci return; 14462306a36Sopenharmony_ci debugfs_remove_recursive(fp->dfs_rport_dir); 14562306a36Sopenharmony_ci fp->dfs_rport_dir = NULL; 14662306a36Sopenharmony_ci} 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_cistatic int 14962306a36Sopenharmony_ciqla2x00_dfs_tgt_sess_show(struct seq_file *s, void *unused) 15062306a36Sopenharmony_ci{ 15162306a36Sopenharmony_ci scsi_qla_host_t *vha = s->private; 15262306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 15362306a36Sopenharmony_ci unsigned long flags; 15462306a36Sopenharmony_ci struct fc_port *sess = NULL; 15562306a36Sopenharmony_ci struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci seq_printf(s, "%s\n", vha->host_str); 15862306a36Sopenharmony_ci if (tgt) { 15962306a36Sopenharmony_ci seq_puts(s, "Port ID Port Name Handle\n"); 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci spin_lock_irqsave(&ha->tgt.sess_lock, flags); 16262306a36Sopenharmony_ci list_for_each_entry(sess, &vha->vp_fcports, list) 16362306a36Sopenharmony_ci seq_printf(s, "%02x:%02x:%02x %8phC %d\n", 16462306a36Sopenharmony_ci sess->d_id.b.domain, sess->d_id.b.area, 16562306a36Sopenharmony_ci sess->d_id.b.al_pa, sess->port_name, 16662306a36Sopenharmony_ci sess->loop_id); 16762306a36Sopenharmony_ci spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); 16862306a36Sopenharmony_ci } 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci return 0; 17162306a36Sopenharmony_ci} 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(qla2x00_dfs_tgt_sess); 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_cistatic int 17662306a36Sopenharmony_ciqla2x00_dfs_tgt_port_database_show(struct seq_file *s, void *unused) 17762306a36Sopenharmony_ci{ 17862306a36Sopenharmony_ci scsi_qla_host_t *vha = s->private; 17962306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 18062306a36Sopenharmony_ci struct gid_list_info *gid_list; 18162306a36Sopenharmony_ci dma_addr_t gid_list_dma; 18262306a36Sopenharmony_ci fc_port_t fc_port; 18362306a36Sopenharmony_ci char *id_iter; 18462306a36Sopenharmony_ci int rc, i; 18562306a36Sopenharmony_ci uint16_t entries, loop_id; 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci seq_printf(s, "%s\n", vha->host_str); 18862306a36Sopenharmony_ci gid_list = dma_alloc_coherent(&ha->pdev->dev, 18962306a36Sopenharmony_ci qla2x00_gid_list_size(ha), 19062306a36Sopenharmony_ci &gid_list_dma, GFP_KERNEL); 19162306a36Sopenharmony_ci if (!gid_list) { 19262306a36Sopenharmony_ci ql_dbg(ql_dbg_user, vha, 0x7018, 19362306a36Sopenharmony_ci "DMA allocation failed for %u\n", 19462306a36Sopenharmony_ci qla2x00_gid_list_size(ha)); 19562306a36Sopenharmony_ci return 0; 19662306a36Sopenharmony_ci } 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci rc = qla24xx_gidlist_wait(vha, gid_list, gid_list_dma, 19962306a36Sopenharmony_ci &entries); 20062306a36Sopenharmony_ci if (rc != QLA_SUCCESS) 20162306a36Sopenharmony_ci goto out_free_id_list; 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci id_iter = (char *)gid_list; 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci seq_puts(s, "Port Name Port ID Loop ID\n"); 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci for (i = 0; i < entries; i++) { 20862306a36Sopenharmony_ci struct gid_list_info *gid = 20962306a36Sopenharmony_ci (struct gid_list_info *)id_iter; 21062306a36Sopenharmony_ci loop_id = le16_to_cpu(gid->loop_id); 21162306a36Sopenharmony_ci memset(&fc_port, 0, sizeof(fc_port_t)); 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci fc_port.loop_id = loop_id; 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci rc = qla24xx_gpdb_wait(vha, &fc_port, 0); 21662306a36Sopenharmony_ci seq_printf(s, "%8phC %02x%02x%02x %d\n", 21762306a36Sopenharmony_ci fc_port.port_name, fc_port.d_id.b.domain, 21862306a36Sopenharmony_ci fc_port.d_id.b.area, fc_port.d_id.b.al_pa, 21962306a36Sopenharmony_ci fc_port.loop_id); 22062306a36Sopenharmony_ci id_iter += ha->gid_list_info_size; 22162306a36Sopenharmony_ci } 22262306a36Sopenharmony_ciout_free_id_list: 22362306a36Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, qla2x00_gid_list_size(ha), 22462306a36Sopenharmony_ci gid_list, gid_list_dma); 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci return 0; 22762306a36Sopenharmony_ci} 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(qla2x00_dfs_tgt_port_database); 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_cistatic int 23262306a36Sopenharmony_ciqla_dfs_fw_resource_cnt_show(struct seq_file *s, void *unused) 23362306a36Sopenharmony_ci{ 23462306a36Sopenharmony_ci struct scsi_qla_host *vha = s->private; 23562306a36Sopenharmony_ci uint16_t mb[MAX_IOCB_MB_REG]; 23662306a36Sopenharmony_ci int rc; 23762306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 23862306a36Sopenharmony_ci u16 iocbs_used, i, exch_used; 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci rc = qla24xx_res_count_wait(vha, mb, SIZEOF_IOCB_MB_REG); 24162306a36Sopenharmony_ci if (rc != QLA_SUCCESS) { 24262306a36Sopenharmony_ci seq_printf(s, "Mailbox Command failed %d, mb %#x", rc, mb[0]); 24362306a36Sopenharmony_ci } else { 24462306a36Sopenharmony_ci seq_puts(s, "FW Resource count\n\n"); 24562306a36Sopenharmony_ci seq_printf(s, "Original TGT exchg count[%d]\n", mb[1]); 24662306a36Sopenharmony_ci seq_printf(s, "Current TGT exchg count[%d]\n", mb[2]); 24762306a36Sopenharmony_ci seq_printf(s, "Current Initiator Exchange count[%d]\n", mb[3]); 24862306a36Sopenharmony_ci seq_printf(s, "Original Initiator Exchange count[%d]\n", mb[6]); 24962306a36Sopenharmony_ci seq_printf(s, "Current IOCB count[%d]\n", mb[7]); 25062306a36Sopenharmony_ci seq_printf(s, "Original IOCB count[%d]\n", mb[10]); 25162306a36Sopenharmony_ci seq_printf(s, "MAX VP count[%d]\n", mb[11]); 25262306a36Sopenharmony_ci seq_printf(s, "MAX FCF count[%d]\n", mb[12]); 25362306a36Sopenharmony_ci seq_printf(s, "Current free pageable XCB buffer cnt[%d]\n", 25462306a36Sopenharmony_ci mb[20]); 25562306a36Sopenharmony_ci seq_printf(s, "Original Initiator fast XCB buffer cnt[%d]\n", 25662306a36Sopenharmony_ci mb[21]); 25762306a36Sopenharmony_ci seq_printf(s, "Current free Initiator fast XCB buffer cnt[%d]\n", 25862306a36Sopenharmony_ci mb[22]); 25962306a36Sopenharmony_ci seq_printf(s, "Original Target fast XCB buffer cnt[%d]\n", 26062306a36Sopenharmony_ci mb[23]); 26162306a36Sopenharmony_ci } 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci if (ql2xenforce_iocb_limit) { 26462306a36Sopenharmony_ci /* lock is not require. It's an estimate. */ 26562306a36Sopenharmony_ci iocbs_used = ha->base_qpair->fwres.iocbs_used; 26662306a36Sopenharmony_ci exch_used = ha->base_qpair->fwres.exch_used; 26762306a36Sopenharmony_ci for (i = 0; i < ha->max_qpairs; i++) { 26862306a36Sopenharmony_ci if (ha->queue_pair_map[i]) { 26962306a36Sopenharmony_ci iocbs_used += ha->queue_pair_map[i]->fwres.iocbs_used; 27062306a36Sopenharmony_ci exch_used += ha->queue_pair_map[i]->fwres.exch_used; 27162306a36Sopenharmony_ci } 27262306a36Sopenharmony_ci } 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci seq_printf(s, "Driver: estimate iocb used [%d] high water limit [%d]\n", 27562306a36Sopenharmony_ci iocbs_used, ha->base_qpair->fwres.iocbs_limit); 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci seq_printf(s, "estimate exchange used[%d] high water limit [%d] n", 27862306a36Sopenharmony_ci exch_used, ha->base_qpair->fwres.exch_limit); 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci if (ql2xenforce_iocb_limit == 2) { 28162306a36Sopenharmony_ci iocbs_used = atomic_read(&ha->fwres.iocb_used); 28262306a36Sopenharmony_ci exch_used = atomic_read(&ha->fwres.exch_used); 28362306a36Sopenharmony_ci seq_printf(s, " estimate iocb2 used [%d] high water limit [%d]\n", 28462306a36Sopenharmony_ci iocbs_used, ha->fwres.iocb_limit); 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci seq_printf(s, " estimate exchange2 used[%d] high water limit [%d] \n", 28762306a36Sopenharmony_ci exch_used, ha->fwres.exch_limit); 28862306a36Sopenharmony_ci } 28962306a36Sopenharmony_ci } 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci return 0; 29262306a36Sopenharmony_ci} 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(qla_dfs_fw_resource_cnt); 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_cistatic int 29762306a36Sopenharmony_ciqla_dfs_tgt_counters_show(struct seq_file *s, void *unused) 29862306a36Sopenharmony_ci{ 29962306a36Sopenharmony_ci struct scsi_qla_host *vha = s->private; 30062306a36Sopenharmony_ci struct qla_qpair *qpair = vha->hw->base_qpair; 30162306a36Sopenharmony_ci uint64_t qla_core_sbt_cmd, core_qla_que_buf, qla_core_ret_ctio, 30262306a36Sopenharmony_ci core_qla_snd_status, qla_core_ret_sta_ctio, core_qla_free_cmd, 30362306a36Sopenharmony_ci num_q_full_sent, num_alloc_iocb_failed, num_term_xchg_sent; 30462306a36Sopenharmony_ci u16 i; 30562306a36Sopenharmony_ci fc_port_t *fcport = NULL; 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci if (qla2x00_chip_is_down(vha)) 30862306a36Sopenharmony_ci return 0; 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci qla_core_sbt_cmd = qpair->tgt_counters.qla_core_sbt_cmd; 31162306a36Sopenharmony_ci core_qla_que_buf = qpair->tgt_counters.core_qla_que_buf; 31262306a36Sopenharmony_ci qla_core_ret_ctio = qpair->tgt_counters.qla_core_ret_ctio; 31362306a36Sopenharmony_ci core_qla_snd_status = qpair->tgt_counters.core_qla_snd_status; 31462306a36Sopenharmony_ci qla_core_ret_sta_ctio = qpair->tgt_counters.qla_core_ret_sta_ctio; 31562306a36Sopenharmony_ci core_qla_free_cmd = qpair->tgt_counters.core_qla_free_cmd; 31662306a36Sopenharmony_ci num_q_full_sent = qpair->tgt_counters.num_q_full_sent; 31762306a36Sopenharmony_ci num_alloc_iocb_failed = qpair->tgt_counters.num_alloc_iocb_failed; 31862306a36Sopenharmony_ci num_term_xchg_sent = qpair->tgt_counters.num_term_xchg_sent; 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci for (i = 0; i < vha->hw->max_qpairs; i++) { 32162306a36Sopenharmony_ci qpair = vha->hw->queue_pair_map[i]; 32262306a36Sopenharmony_ci if (!qpair) 32362306a36Sopenharmony_ci continue; 32462306a36Sopenharmony_ci qla_core_sbt_cmd += qpair->tgt_counters.qla_core_sbt_cmd; 32562306a36Sopenharmony_ci core_qla_que_buf += qpair->tgt_counters.core_qla_que_buf; 32662306a36Sopenharmony_ci qla_core_ret_ctio += qpair->tgt_counters.qla_core_ret_ctio; 32762306a36Sopenharmony_ci core_qla_snd_status += qpair->tgt_counters.core_qla_snd_status; 32862306a36Sopenharmony_ci qla_core_ret_sta_ctio += 32962306a36Sopenharmony_ci qpair->tgt_counters.qla_core_ret_sta_ctio; 33062306a36Sopenharmony_ci core_qla_free_cmd += qpair->tgt_counters.core_qla_free_cmd; 33162306a36Sopenharmony_ci num_q_full_sent += qpair->tgt_counters.num_q_full_sent; 33262306a36Sopenharmony_ci num_alloc_iocb_failed += 33362306a36Sopenharmony_ci qpair->tgt_counters.num_alloc_iocb_failed; 33462306a36Sopenharmony_ci num_term_xchg_sent += qpair->tgt_counters.num_term_xchg_sent; 33562306a36Sopenharmony_ci } 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci seq_puts(s, "Target Counters\n"); 33862306a36Sopenharmony_ci seq_printf(s, "qla_core_sbt_cmd = %lld\n", 33962306a36Sopenharmony_ci qla_core_sbt_cmd); 34062306a36Sopenharmony_ci seq_printf(s, "qla_core_ret_sta_ctio = %lld\n", 34162306a36Sopenharmony_ci qla_core_ret_sta_ctio); 34262306a36Sopenharmony_ci seq_printf(s, "qla_core_ret_ctio = %lld\n", 34362306a36Sopenharmony_ci qla_core_ret_ctio); 34462306a36Sopenharmony_ci seq_printf(s, "core_qla_que_buf = %lld\n", 34562306a36Sopenharmony_ci core_qla_que_buf); 34662306a36Sopenharmony_ci seq_printf(s, "core_qla_snd_status = %lld\n", 34762306a36Sopenharmony_ci core_qla_snd_status); 34862306a36Sopenharmony_ci seq_printf(s, "core_qla_free_cmd = %lld\n", 34962306a36Sopenharmony_ci core_qla_free_cmd); 35062306a36Sopenharmony_ci seq_printf(s, "num alloc iocb failed = %lld\n", 35162306a36Sopenharmony_ci num_alloc_iocb_failed); 35262306a36Sopenharmony_ci seq_printf(s, "num term exchange sent = %lld\n", 35362306a36Sopenharmony_ci num_term_xchg_sent); 35462306a36Sopenharmony_ci seq_printf(s, "num Q full sent = %lld\n", 35562306a36Sopenharmony_ci num_q_full_sent); 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci /* DIF stats */ 35862306a36Sopenharmony_ci seq_printf(s, "DIF Inp Bytes = %lld\n", 35962306a36Sopenharmony_ci vha->qla_stats.qla_dif_stats.dif_input_bytes); 36062306a36Sopenharmony_ci seq_printf(s, "DIF Outp Bytes = %lld\n", 36162306a36Sopenharmony_ci vha->qla_stats.qla_dif_stats.dif_output_bytes); 36262306a36Sopenharmony_ci seq_printf(s, "DIF Inp Req = %lld\n", 36362306a36Sopenharmony_ci vha->qla_stats.qla_dif_stats.dif_input_requests); 36462306a36Sopenharmony_ci seq_printf(s, "DIF Outp Req = %lld\n", 36562306a36Sopenharmony_ci vha->qla_stats.qla_dif_stats.dif_output_requests); 36662306a36Sopenharmony_ci seq_printf(s, "DIF Guard err = %d\n", 36762306a36Sopenharmony_ci vha->qla_stats.qla_dif_stats.dif_guard_err); 36862306a36Sopenharmony_ci seq_printf(s, "DIF Ref tag err = %d\n", 36962306a36Sopenharmony_ci vha->qla_stats.qla_dif_stats.dif_ref_tag_err); 37062306a36Sopenharmony_ci seq_printf(s, "DIF App tag err = %d\n", 37162306a36Sopenharmony_ci vha->qla_stats.qla_dif_stats.dif_app_tag_err); 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci seq_puts(s, "\n"); 37462306a36Sopenharmony_ci seq_puts(s, "Initiator Error Counters\n"); 37562306a36Sopenharmony_ci seq_printf(s, "HW Error Count = %14lld\n", 37662306a36Sopenharmony_ci vha->hw_err_cnt); 37762306a36Sopenharmony_ci seq_printf(s, "Link Down Count = %14lld\n", 37862306a36Sopenharmony_ci vha->short_link_down_cnt); 37962306a36Sopenharmony_ci seq_printf(s, "Interface Err Count = %14lld\n", 38062306a36Sopenharmony_ci vha->interface_err_cnt); 38162306a36Sopenharmony_ci seq_printf(s, "Cmd Timeout Count = %14lld\n", 38262306a36Sopenharmony_ci vha->cmd_timeout_cnt); 38362306a36Sopenharmony_ci seq_printf(s, "Reset Count = %14lld\n", 38462306a36Sopenharmony_ci vha->reset_cmd_err_cnt); 38562306a36Sopenharmony_ci seq_puts(s, "\n"); 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci list_for_each_entry(fcport, &vha->vp_fcports, list) { 38862306a36Sopenharmony_ci if (!fcport->rport) 38962306a36Sopenharmony_ci continue; 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci seq_printf(s, "Target Num = %7d Link Down Count = %14lld\n", 39262306a36Sopenharmony_ci fcport->rport->number, fcport->tgt_short_link_down_cnt); 39362306a36Sopenharmony_ci } 39462306a36Sopenharmony_ci seq_puts(s, "\n"); 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci return 0; 39762306a36Sopenharmony_ci} 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(qla_dfs_tgt_counters); 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_cistatic int 40262306a36Sopenharmony_ciqla2x00_dfs_fce_show(struct seq_file *s, void *unused) 40362306a36Sopenharmony_ci{ 40462306a36Sopenharmony_ci scsi_qla_host_t *vha = s->private; 40562306a36Sopenharmony_ci uint32_t cnt; 40662306a36Sopenharmony_ci uint32_t *fce; 40762306a36Sopenharmony_ci uint64_t fce_start; 40862306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci mutex_lock(&ha->fce_mutex); 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci seq_puts(s, "FCE Trace Buffer\n"); 41362306a36Sopenharmony_ci seq_printf(s, "In Pointer = %llx\n\n", (unsigned long long)ha->fce_wr); 41462306a36Sopenharmony_ci seq_printf(s, "Base = %llx\n\n", (unsigned long long) ha->fce_dma); 41562306a36Sopenharmony_ci seq_puts(s, "FCE Enable Registers\n"); 41662306a36Sopenharmony_ci seq_printf(s, "%08x %08x %08x %08x %08x %08x\n", 41762306a36Sopenharmony_ci ha->fce_mb[0], ha->fce_mb[2], ha->fce_mb[3], ha->fce_mb[4], 41862306a36Sopenharmony_ci ha->fce_mb[5], ha->fce_mb[6]); 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci fce = (uint32_t *) ha->fce; 42162306a36Sopenharmony_ci fce_start = (unsigned long long) ha->fce_dma; 42262306a36Sopenharmony_ci for (cnt = 0; cnt < fce_calc_size(ha->fce_bufs) / 4; cnt++) { 42362306a36Sopenharmony_ci if (cnt % 8 == 0) 42462306a36Sopenharmony_ci seq_printf(s, "\n%llx: ", 42562306a36Sopenharmony_ci (unsigned long long)((cnt * 4) + fce_start)); 42662306a36Sopenharmony_ci else 42762306a36Sopenharmony_ci seq_putc(s, ' '); 42862306a36Sopenharmony_ci seq_printf(s, "%08x", *fce++); 42962306a36Sopenharmony_ci } 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci seq_puts(s, "\nEnd\n"); 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci mutex_unlock(&ha->fce_mutex); 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci return 0; 43662306a36Sopenharmony_ci} 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_cistatic int 43962306a36Sopenharmony_ciqla2x00_dfs_fce_open(struct inode *inode, struct file *file) 44062306a36Sopenharmony_ci{ 44162306a36Sopenharmony_ci scsi_qla_host_t *vha = inode->i_private; 44262306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 44362306a36Sopenharmony_ci int rval; 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci if (!ha->flags.fce_enabled) 44662306a36Sopenharmony_ci goto out; 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci mutex_lock(&ha->fce_mutex); 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_ci /* Pause tracing to flush FCE buffers. */ 45162306a36Sopenharmony_ci rval = qla2x00_disable_fce_trace(vha, &ha->fce_wr, &ha->fce_rd); 45262306a36Sopenharmony_ci if (rval) 45362306a36Sopenharmony_ci ql_dbg(ql_dbg_user, vha, 0x705c, 45462306a36Sopenharmony_ci "DebugFS: Unable to disable FCE (%d).\n", rval); 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci ha->flags.fce_enabled = 0; 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci mutex_unlock(&ha->fce_mutex); 45962306a36Sopenharmony_ciout: 46062306a36Sopenharmony_ci return single_open(file, qla2x00_dfs_fce_show, vha); 46162306a36Sopenharmony_ci} 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_cistatic int 46462306a36Sopenharmony_ciqla2x00_dfs_fce_release(struct inode *inode, struct file *file) 46562306a36Sopenharmony_ci{ 46662306a36Sopenharmony_ci scsi_qla_host_t *vha = inode->i_private; 46762306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 46862306a36Sopenharmony_ci int rval; 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci if (ha->flags.fce_enabled) 47162306a36Sopenharmony_ci goto out; 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ci mutex_lock(&ha->fce_mutex); 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci /* Re-enable FCE tracing. */ 47662306a36Sopenharmony_ci ha->flags.fce_enabled = 1; 47762306a36Sopenharmony_ci memset(ha->fce, 0, fce_calc_size(ha->fce_bufs)); 47862306a36Sopenharmony_ci rval = qla2x00_enable_fce_trace(vha, ha->fce_dma, ha->fce_bufs, 47962306a36Sopenharmony_ci ha->fce_mb, &ha->fce_bufs); 48062306a36Sopenharmony_ci if (rval) { 48162306a36Sopenharmony_ci ql_dbg(ql_dbg_user, vha, 0x700d, 48262306a36Sopenharmony_ci "DebugFS: Unable to reinitialize FCE (%d).\n", rval); 48362306a36Sopenharmony_ci ha->flags.fce_enabled = 0; 48462306a36Sopenharmony_ci } 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci mutex_unlock(&ha->fce_mutex); 48762306a36Sopenharmony_ciout: 48862306a36Sopenharmony_ci return single_release(inode, file); 48962306a36Sopenharmony_ci} 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_cistatic const struct file_operations dfs_fce_ops = { 49262306a36Sopenharmony_ci .open = qla2x00_dfs_fce_open, 49362306a36Sopenharmony_ci .read = seq_read, 49462306a36Sopenharmony_ci .llseek = seq_lseek, 49562306a36Sopenharmony_ci .release = qla2x00_dfs_fce_release, 49662306a36Sopenharmony_ci}; 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_cistatic int 49962306a36Sopenharmony_ciqla_dfs_naqp_show(struct seq_file *s, void *unused) 50062306a36Sopenharmony_ci{ 50162306a36Sopenharmony_ci struct scsi_qla_host *vha = s->private; 50262306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci seq_printf(s, "%d\n", ha->tgt.num_act_qpairs); 50562306a36Sopenharmony_ci return 0; 50662306a36Sopenharmony_ci} 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci/* 50962306a36Sopenharmony_ci * Helper macros for setting up debugfs entries. 51062306a36Sopenharmony_ci * _name: The name of the debugfs entry 51162306a36Sopenharmony_ci * _ctx_struct: The context that was passed when creating the debugfs file 51262306a36Sopenharmony_ci * 51362306a36Sopenharmony_ci * QLA_DFS_SETUP_RD could be used when there is only a show function. 51462306a36Sopenharmony_ci * - show function take the name qla_dfs_<sysfs-name>_show 51562306a36Sopenharmony_ci * 51662306a36Sopenharmony_ci * QLA_DFS_SETUP_RW could be used when there are both show and write functions. 51762306a36Sopenharmony_ci * - show function take the name qla_dfs_<sysfs-name>_show 51862306a36Sopenharmony_ci * - write function take the name qla_dfs_<sysfs-name>_write 51962306a36Sopenharmony_ci * 52062306a36Sopenharmony_ci * To have a new debugfs entry, do: 52162306a36Sopenharmony_ci * 1. Create a "struct dentry *" in the appropriate structure in the format 52262306a36Sopenharmony_ci * dfs_<sysfs-name> 52362306a36Sopenharmony_ci * 2. Setup debugfs entries using QLA_DFS_SETUP_RD / QLA_DFS_SETUP_RW 52462306a36Sopenharmony_ci * 3. Create debugfs file in qla2x00_dfs_setup() using QLA_DFS_CREATE_FILE 52562306a36Sopenharmony_ci * or QLA_DFS_ROOT_CREATE_FILE 52662306a36Sopenharmony_ci * 4. Remove debugfs file in qla2x00_dfs_remove() using QLA_DFS_REMOVE_FILE 52762306a36Sopenharmony_ci * or QLA_DFS_ROOT_REMOVE_FILE 52862306a36Sopenharmony_ci * 52962306a36Sopenharmony_ci * Example for creating "TEST" sysfs file: 53062306a36Sopenharmony_ci * 1. struct qla_hw_data { ... struct dentry *dfs_TEST; } 53162306a36Sopenharmony_ci * 2. QLA_DFS_SETUP_RD(TEST, scsi_qla_host_t); 53262306a36Sopenharmony_ci * 3. In qla2x00_dfs_setup(): 53362306a36Sopenharmony_ci * QLA_DFS_CREATE_FILE(ha, TEST, 0600, ha->dfs_dir, vha); 53462306a36Sopenharmony_ci * 4. In qla2x00_dfs_remove(): 53562306a36Sopenharmony_ci * QLA_DFS_REMOVE_FILE(ha, TEST); 53662306a36Sopenharmony_ci */ 53762306a36Sopenharmony_ci#define QLA_DFS_SETUP_RD(_name, _ctx_struct) \ 53862306a36Sopenharmony_cistatic int \ 53962306a36Sopenharmony_ciqla_dfs_##_name##_open(struct inode *inode, struct file *file) \ 54062306a36Sopenharmony_ci{ \ 54162306a36Sopenharmony_ci _ctx_struct *__ctx = inode->i_private; \ 54262306a36Sopenharmony_ci \ 54362306a36Sopenharmony_ci return single_open(file, qla_dfs_##_name##_show, __ctx); \ 54462306a36Sopenharmony_ci} \ 54562306a36Sopenharmony_ci \ 54662306a36Sopenharmony_cistatic const struct file_operations qla_dfs_##_name##_ops = { \ 54762306a36Sopenharmony_ci .open = qla_dfs_##_name##_open, \ 54862306a36Sopenharmony_ci .read = seq_read, \ 54962306a36Sopenharmony_ci .llseek = seq_lseek, \ 55062306a36Sopenharmony_ci .release = single_release, \ 55162306a36Sopenharmony_ci}; 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci#define QLA_DFS_SETUP_RW(_name, _ctx_struct) \ 55462306a36Sopenharmony_cistatic int \ 55562306a36Sopenharmony_ciqla_dfs_##_name##_open(struct inode *inode, struct file *file) \ 55662306a36Sopenharmony_ci{ \ 55762306a36Sopenharmony_ci _ctx_struct *__ctx = inode->i_private; \ 55862306a36Sopenharmony_ci \ 55962306a36Sopenharmony_ci return single_open(file, qla_dfs_##_name##_show, __ctx); \ 56062306a36Sopenharmony_ci} \ 56162306a36Sopenharmony_ci \ 56262306a36Sopenharmony_cistatic const struct file_operations qla_dfs_##_name##_ops = { \ 56362306a36Sopenharmony_ci .open = qla_dfs_##_name##_open, \ 56462306a36Sopenharmony_ci .read = seq_read, \ 56562306a36Sopenharmony_ci .llseek = seq_lseek, \ 56662306a36Sopenharmony_ci .release = single_release, \ 56762306a36Sopenharmony_ci .write = qla_dfs_##_name##_write, \ 56862306a36Sopenharmony_ci}; 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ci#define QLA_DFS_ROOT_CREATE_FILE(_name, _perm, _ctx) \ 57162306a36Sopenharmony_ci do { \ 57262306a36Sopenharmony_ci if (!qla_dfs_##_name) \ 57362306a36Sopenharmony_ci qla_dfs_##_name = debugfs_create_file(#_name, \ 57462306a36Sopenharmony_ci _perm, qla2x00_dfs_root, _ctx, \ 57562306a36Sopenharmony_ci &qla_dfs_##_name##_ops); \ 57662306a36Sopenharmony_ci } while (0) 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_ci#define QLA_DFS_ROOT_REMOVE_FILE(_name) \ 57962306a36Sopenharmony_ci do { \ 58062306a36Sopenharmony_ci if (qla_dfs_##_name) { \ 58162306a36Sopenharmony_ci debugfs_remove(qla_dfs_##_name); \ 58262306a36Sopenharmony_ci qla_dfs_##_name = NULL; \ 58362306a36Sopenharmony_ci } \ 58462306a36Sopenharmony_ci } while (0) 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_ci#define QLA_DFS_CREATE_FILE(_struct, _name, _perm, _parent, _ctx) \ 58762306a36Sopenharmony_ci do { \ 58862306a36Sopenharmony_ci (_struct)->dfs_##_name = debugfs_create_file(#_name, \ 58962306a36Sopenharmony_ci _perm, _parent, _ctx, \ 59062306a36Sopenharmony_ci &qla_dfs_##_name##_ops) \ 59162306a36Sopenharmony_ci } while (0) 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ci#define QLA_DFS_REMOVE_FILE(_struct, _name) \ 59462306a36Sopenharmony_ci do { \ 59562306a36Sopenharmony_ci if ((_struct)->dfs_##_name) { \ 59662306a36Sopenharmony_ci debugfs_remove((_struct)->dfs_##_name); \ 59762306a36Sopenharmony_ci (_struct)->dfs_##_name = NULL; \ 59862306a36Sopenharmony_ci } \ 59962306a36Sopenharmony_ci } while (0) 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_cistatic int 60262306a36Sopenharmony_ciqla_dfs_naqp_open(struct inode *inode, struct file *file) 60362306a36Sopenharmony_ci{ 60462306a36Sopenharmony_ci struct scsi_qla_host *vha = inode->i_private; 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_ci return single_open(file, qla_dfs_naqp_show, vha); 60762306a36Sopenharmony_ci} 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_cistatic ssize_t 61062306a36Sopenharmony_ciqla_dfs_naqp_write(struct file *file, const char __user *buffer, 61162306a36Sopenharmony_ci size_t count, loff_t *pos) 61262306a36Sopenharmony_ci{ 61362306a36Sopenharmony_ci struct seq_file *s = file->private_data; 61462306a36Sopenharmony_ci struct scsi_qla_host *vha = s->private; 61562306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 61662306a36Sopenharmony_ci char *buf; 61762306a36Sopenharmony_ci int rc = 0; 61862306a36Sopenharmony_ci unsigned long num_act_qp; 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_ci if (!(IS_QLA27XX(ha) || IS_QLA83XX(ha) || IS_QLA28XX(ha))) { 62162306a36Sopenharmony_ci pr_err("host%ld: this adapter does not support Multi Q.", 62262306a36Sopenharmony_ci vha->host_no); 62362306a36Sopenharmony_ci return -EINVAL; 62462306a36Sopenharmony_ci } 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci if (!vha->flags.qpairs_available) { 62762306a36Sopenharmony_ci pr_err("host%ld: Driver is not setup with Multi Q.", 62862306a36Sopenharmony_ci vha->host_no); 62962306a36Sopenharmony_ci return -EINVAL; 63062306a36Sopenharmony_ci } 63162306a36Sopenharmony_ci buf = memdup_user_nul(buffer, count); 63262306a36Sopenharmony_ci if (IS_ERR(buf)) { 63362306a36Sopenharmony_ci pr_err("host%ld: fail to copy user buffer.", 63462306a36Sopenharmony_ci vha->host_no); 63562306a36Sopenharmony_ci return PTR_ERR(buf); 63662306a36Sopenharmony_ci } 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ci num_act_qp = simple_strtoul(buf, NULL, 0); 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_ci if (num_act_qp >= vha->hw->max_qpairs) { 64162306a36Sopenharmony_ci pr_err("User set invalid number of qpairs %lu. Max = %d", 64262306a36Sopenharmony_ci num_act_qp, vha->hw->max_qpairs); 64362306a36Sopenharmony_ci rc = -EINVAL; 64462306a36Sopenharmony_ci goto out_free; 64562306a36Sopenharmony_ci } 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ci if (num_act_qp != ha->tgt.num_act_qpairs) { 64862306a36Sopenharmony_ci ha->tgt.num_act_qpairs = num_act_qp; 64962306a36Sopenharmony_ci qlt_clr_qp_table(vha); 65062306a36Sopenharmony_ci } 65162306a36Sopenharmony_ci rc = count; 65262306a36Sopenharmony_ciout_free: 65362306a36Sopenharmony_ci kfree(buf); 65462306a36Sopenharmony_ci return rc; 65562306a36Sopenharmony_ci} 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_cistatic const struct file_operations dfs_naqp_ops = { 65862306a36Sopenharmony_ci .open = qla_dfs_naqp_open, 65962306a36Sopenharmony_ci .read = seq_read, 66062306a36Sopenharmony_ci .llseek = seq_lseek, 66162306a36Sopenharmony_ci .release = single_release, 66262306a36Sopenharmony_ci .write = qla_dfs_naqp_write, 66362306a36Sopenharmony_ci}; 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_ciint 66762306a36Sopenharmony_ciqla2x00_dfs_setup(scsi_qla_host_t *vha) 66862306a36Sopenharmony_ci{ 66962306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 67062306a36Sopenharmony_ci 67162306a36Sopenharmony_ci if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha) && 67262306a36Sopenharmony_ci !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) 67362306a36Sopenharmony_ci goto out; 67462306a36Sopenharmony_ci if (!ha->fce) 67562306a36Sopenharmony_ci goto out; 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ci if (qla2x00_dfs_root) 67862306a36Sopenharmony_ci goto create_dir; 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ci atomic_set(&qla2x00_dfs_root_count, 0); 68162306a36Sopenharmony_ci qla2x00_dfs_root = debugfs_create_dir(QLA2XXX_DRIVER_NAME, NULL); 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_cicreate_dir: 68462306a36Sopenharmony_ci if (ha->dfs_dir) 68562306a36Sopenharmony_ci goto create_nodes; 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_ci mutex_init(&ha->fce_mutex); 68862306a36Sopenharmony_ci ha->dfs_dir = debugfs_create_dir(vha->host_str, qla2x00_dfs_root); 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ci atomic_inc(&qla2x00_dfs_root_count); 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_cicreate_nodes: 69362306a36Sopenharmony_ci ha->dfs_fw_resource_cnt = debugfs_create_file("fw_resource_count", 69462306a36Sopenharmony_ci S_IRUSR, ha->dfs_dir, vha, &qla_dfs_fw_resource_cnt_fops); 69562306a36Sopenharmony_ci 69662306a36Sopenharmony_ci ha->dfs_tgt_counters = debugfs_create_file("tgt_counters", S_IRUSR, 69762306a36Sopenharmony_ci ha->dfs_dir, vha, &qla_dfs_tgt_counters_fops); 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_ci ha->tgt.dfs_tgt_port_database = debugfs_create_file("tgt_port_database", 70062306a36Sopenharmony_ci S_IRUSR, ha->dfs_dir, vha, &qla2x00_dfs_tgt_port_database_fops); 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ci ha->dfs_fce = debugfs_create_file("fce", S_IRUSR, ha->dfs_dir, vha, 70362306a36Sopenharmony_ci &dfs_fce_ops); 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ci ha->tgt.dfs_tgt_sess = debugfs_create_file("tgt_sess", 70662306a36Sopenharmony_ci S_IRUSR, ha->dfs_dir, vha, &qla2x00_dfs_tgt_sess_fops); 70762306a36Sopenharmony_ci 70862306a36Sopenharmony_ci if (IS_QLA27XX(ha) || IS_QLA83XX(ha) || IS_QLA28XX(ha)) { 70962306a36Sopenharmony_ci ha->tgt.dfs_naqp = debugfs_create_file("naqp", 71062306a36Sopenharmony_ci 0400, ha->dfs_dir, vha, &dfs_naqp_ops); 71162306a36Sopenharmony_ci if (IS_ERR(ha->tgt.dfs_naqp)) { 71262306a36Sopenharmony_ci ql_log(ql_log_warn, vha, 0xd011, 71362306a36Sopenharmony_ci "Unable to create debugFS naqp node.\n"); 71462306a36Sopenharmony_ci goto out; 71562306a36Sopenharmony_ci } 71662306a36Sopenharmony_ci } 71762306a36Sopenharmony_ci vha->dfs_rport_root = debugfs_create_dir("rports", ha->dfs_dir); 71862306a36Sopenharmony_ci if (IS_ERR(vha->dfs_rport_root)) { 71962306a36Sopenharmony_ci ql_log(ql_log_warn, vha, 0xd012, 72062306a36Sopenharmony_ci "Unable to create debugFS rports node.\n"); 72162306a36Sopenharmony_ci goto out; 72262306a36Sopenharmony_ci } 72362306a36Sopenharmony_ciout: 72462306a36Sopenharmony_ci return 0; 72562306a36Sopenharmony_ci} 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_ciint 72862306a36Sopenharmony_ciqla2x00_dfs_remove(scsi_qla_host_t *vha) 72962306a36Sopenharmony_ci{ 73062306a36Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_ci if (ha->tgt.dfs_naqp) { 73362306a36Sopenharmony_ci debugfs_remove(ha->tgt.dfs_naqp); 73462306a36Sopenharmony_ci ha->tgt.dfs_naqp = NULL; 73562306a36Sopenharmony_ci } 73662306a36Sopenharmony_ci 73762306a36Sopenharmony_ci if (ha->tgt.dfs_tgt_sess) { 73862306a36Sopenharmony_ci debugfs_remove(ha->tgt.dfs_tgt_sess); 73962306a36Sopenharmony_ci ha->tgt.dfs_tgt_sess = NULL; 74062306a36Sopenharmony_ci } 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_ci if (ha->tgt.dfs_tgt_port_database) { 74362306a36Sopenharmony_ci debugfs_remove(ha->tgt.dfs_tgt_port_database); 74462306a36Sopenharmony_ci ha->tgt.dfs_tgt_port_database = NULL; 74562306a36Sopenharmony_ci } 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_ci if (ha->dfs_fw_resource_cnt) { 74862306a36Sopenharmony_ci debugfs_remove(ha->dfs_fw_resource_cnt); 74962306a36Sopenharmony_ci ha->dfs_fw_resource_cnt = NULL; 75062306a36Sopenharmony_ci } 75162306a36Sopenharmony_ci 75262306a36Sopenharmony_ci if (ha->dfs_tgt_counters) { 75362306a36Sopenharmony_ci debugfs_remove(ha->dfs_tgt_counters); 75462306a36Sopenharmony_ci ha->dfs_tgt_counters = NULL; 75562306a36Sopenharmony_ci } 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_ci if (ha->dfs_fce) { 75862306a36Sopenharmony_ci debugfs_remove(ha->dfs_fce); 75962306a36Sopenharmony_ci ha->dfs_fce = NULL; 76062306a36Sopenharmony_ci } 76162306a36Sopenharmony_ci 76262306a36Sopenharmony_ci if (vha->dfs_rport_root) { 76362306a36Sopenharmony_ci debugfs_remove_recursive(vha->dfs_rport_root); 76462306a36Sopenharmony_ci vha->dfs_rport_root = NULL; 76562306a36Sopenharmony_ci } 76662306a36Sopenharmony_ci 76762306a36Sopenharmony_ci if (ha->dfs_dir) { 76862306a36Sopenharmony_ci debugfs_remove(ha->dfs_dir); 76962306a36Sopenharmony_ci ha->dfs_dir = NULL; 77062306a36Sopenharmony_ci atomic_dec(&qla2x00_dfs_root_count); 77162306a36Sopenharmony_ci } 77262306a36Sopenharmony_ci 77362306a36Sopenharmony_ci if (atomic_read(&qla2x00_dfs_root_count) == 0 && 77462306a36Sopenharmony_ci qla2x00_dfs_root) { 77562306a36Sopenharmony_ci debugfs_remove(qla2x00_dfs_root); 77662306a36Sopenharmony_ci qla2x00_dfs_root = NULL; 77762306a36Sopenharmony_ci } 77862306a36Sopenharmony_ci 77962306a36Sopenharmony_ci return 0; 78062306a36Sopenharmony_ci} 781