18c2ecf20Sopenharmony_ci/******************************************************************* 28c2ecf20Sopenharmony_ci * This file is part of the Emulex Linux Device Driver for * 38c2ecf20Sopenharmony_ci * Fibre Channel Host Bus Adapters. * 48c2ecf20Sopenharmony_ci * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term * 58c2ecf20Sopenharmony_ci * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * 68c2ecf20Sopenharmony_ci * Copyright (C) 2007-2015 Emulex. All rights reserved. * 78c2ecf20Sopenharmony_ci * EMULEX and SLI are trademarks of Emulex. * 88c2ecf20Sopenharmony_ci * www.broadcom.com * 98c2ecf20Sopenharmony_ci * * 108c2ecf20Sopenharmony_ci * This program is free software; you can redistribute it and/or * 118c2ecf20Sopenharmony_ci * modify it under the terms of version 2 of the GNU General * 128c2ecf20Sopenharmony_ci * Public License as published by the Free Software Foundation. * 138c2ecf20Sopenharmony_ci * This program is distributed in the hope that it will be useful. * 148c2ecf20Sopenharmony_ci * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * 158c2ecf20Sopenharmony_ci * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * 168c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE * 178c2ecf20Sopenharmony_ci * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD * 188c2ecf20Sopenharmony_ci * TO BE LEGALLY INVALID. See the GNU General Public License for * 198c2ecf20Sopenharmony_ci * more details, a copy of which can be found in the file COPYING * 208c2ecf20Sopenharmony_ci * included with this package. * 218c2ecf20Sopenharmony_ci *******************************************************************/ 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#include <linux/blkdev.h> 248c2ecf20Sopenharmony_ci#include <linux/delay.h> 258c2ecf20Sopenharmony_ci#include <linux/module.h> 268c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h> 278c2ecf20Sopenharmony_ci#include <linux/idr.h> 288c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 298c2ecf20Sopenharmony_ci#include <linux/kthread.h> 308c2ecf20Sopenharmony_ci#include <linux/slab.h> 318c2ecf20Sopenharmony_ci#include <linux/pci.h> 328c2ecf20Sopenharmony_ci#include <linux/spinlock.h> 338c2ecf20Sopenharmony_ci#include <linux/ctype.h> 348c2ecf20Sopenharmony_ci#include <linux/vmalloc.h> 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci#include <scsi/scsi.h> 378c2ecf20Sopenharmony_ci#include <scsi/scsi_device.h> 388c2ecf20Sopenharmony_ci#include <scsi/scsi_host.h> 398c2ecf20Sopenharmony_ci#include <scsi/scsi_transport_fc.h> 408c2ecf20Sopenharmony_ci#include <scsi/fc/fc_fs.h> 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci#include "lpfc_hw4.h" 438c2ecf20Sopenharmony_ci#include "lpfc_hw.h" 448c2ecf20Sopenharmony_ci#include "lpfc_sli.h" 458c2ecf20Sopenharmony_ci#include "lpfc_sli4.h" 468c2ecf20Sopenharmony_ci#include "lpfc_nl.h" 478c2ecf20Sopenharmony_ci#include "lpfc_disc.h" 488c2ecf20Sopenharmony_ci#include "lpfc.h" 498c2ecf20Sopenharmony_ci#include "lpfc_scsi.h" 508c2ecf20Sopenharmony_ci#include "lpfc_nvme.h" 518c2ecf20Sopenharmony_ci#include "lpfc_logmsg.h" 528c2ecf20Sopenharmony_ci#include "lpfc_crtn.h" 538c2ecf20Sopenharmony_ci#include "lpfc_vport.h" 548c2ecf20Sopenharmony_ci#include "lpfc_version.h" 558c2ecf20Sopenharmony_ci#include "lpfc_compat.h" 568c2ecf20Sopenharmony_ci#include "lpfc_debugfs.h" 578c2ecf20Sopenharmony_ci#include "lpfc_bsg.h" 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci#ifdef CONFIG_SCSI_LPFC_DEBUG_FS 608c2ecf20Sopenharmony_ci/* 618c2ecf20Sopenharmony_ci * debugfs interface 628c2ecf20Sopenharmony_ci * 638c2ecf20Sopenharmony_ci * To access this interface the user should: 648c2ecf20Sopenharmony_ci * # mount -t debugfs none /sys/kernel/debug 658c2ecf20Sopenharmony_ci * 668c2ecf20Sopenharmony_ci * The lpfc debugfs directory hierarchy is: 678c2ecf20Sopenharmony_ci * /sys/kernel/debug/lpfc/fnX/vportY 688c2ecf20Sopenharmony_ci * where X is the lpfc hba function unique_id 698c2ecf20Sopenharmony_ci * where Y is the vport VPI on that hba 708c2ecf20Sopenharmony_ci * 718c2ecf20Sopenharmony_ci * Debugging services available per vport: 728c2ecf20Sopenharmony_ci * discovery_trace 738c2ecf20Sopenharmony_ci * This is an ACSII readable file that contains a trace of the last 748c2ecf20Sopenharmony_ci * lpfc_debugfs_max_disc_trc events that happened on a specific vport. 758c2ecf20Sopenharmony_ci * See lpfc_debugfs.h for different categories of discovery events. 768c2ecf20Sopenharmony_ci * To enable the discovery trace, the following module parameters must be set: 778c2ecf20Sopenharmony_ci * lpfc_debugfs_enable=1 Turns on lpfc debugfs filesystem support 788c2ecf20Sopenharmony_ci * lpfc_debugfs_max_disc_trc=X Where X is the event trace depth for 798c2ecf20Sopenharmony_ci * EACH vport. X MUST also be a power of 2. 808c2ecf20Sopenharmony_ci * lpfc_debugfs_mask_disc_trc=Y Where Y is an event mask as defined in 818c2ecf20Sopenharmony_ci * lpfc_debugfs.h . 828c2ecf20Sopenharmony_ci * 838c2ecf20Sopenharmony_ci * slow_ring_trace 848c2ecf20Sopenharmony_ci * This is an ACSII readable file that contains a trace of the last 858c2ecf20Sopenharmony_ci * lpfc_debugfs_max_slow_ring_trc events that happened on a specific HBA. 868c2ecf20Sopenharmony_ci * To enable the slow ring trace, the following module parameters must be set: 878c2ecf20Sopenharmony_ci * lpfc_debugfs_enable=1 Turns on lpfc debugfs filesystem support 888c2ecf20Sopenharmony_ci * lpfc_debugfs_max_slow_ring_trc=X Where X is the event trace depth for 898c2ecf20Sopenharmony_ci * the HBA. X MUST also be a power of 2. 908c2ecf20Sopenharmony_ci */ 918c2ecf20Sopenharmony_cistatic int lpfc_debugfs_enable = 1; 928c2ecf20Sopenharmony_cimodule_param(lpfc_debugfs_enable, int, S_IRUGO); 938c2ecf20Sopenharmony_ciMODULE_PARM_DESC(lpfc_debugfs_enable, "Enable debugfs services"); 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci/* This MUST be a power of 2 */ 968c2ecf20Sopenharmony_cistatic int lpfc_debugfs_max_disc_trc; 978c2ecf20Sopenharmony_cimodule_param(lpfc_debugfs_max_disc_trc, int, S_IRUGO); 988c2ecf20Sopenharmony_ciMODULE_PARM_DESC(lpfc_debugfs_max_disc_trc, 998c2ecf20Sopenharmony_ci "Set debugfs discovery trace depth"); 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci/* This MUST be a power of 2 */ 1028c2ecf20Sopenharmony_cistatic int lpfc_debugfs_max_slow_ring_trc; 1038c2ecf20Sopenharmony_cimodule_param(lpfc_debugfs_max_slow_ring_trc, int, S_IRUGO); 1048c2ecf20Sopenharmony_ciMODULE_PARM_DESC(lpfc_debugfs_max_slow_ring_trc, 1058c2ecf20Sopenharmony_ci "Set debugfs slow ring trace depth"); 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci/* This MUST be a power of 2 */ 1088c2ecf20Sopenharmony_cistatic int lpfc_debugfs_max_nvmeio_trc; 1098c2ecf20Sopenharmony_cimodule_param(lpfc_debugfs_max_nvmeio_trc, int, 0444); 1108c2ecf20Sopenharmony_ciMODULE_PARM_DESC(lpfc_debugfs_max_nvmeio_trc, 1118c2ecf20Sopenharmony_ci "Set debugfs NVME IO trace depth"); 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_cistatic int lpfc_debugfs_mask_disc_trc; 1148c2ecf20Sopenharmony_cimodule_param(lpfc_debugfs_mask_disc_trc, int, S_IRUGO); 1158c2ecf20Sopenharmony_ciMODULE_PARM_DESC(lpfc_debugfs_mask_disc_trc, 1168c2ecf20Sopenharmony_ci "Set debugfs discovery trace mask"); 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci#include <linux/debugfs.h> 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_cistatic atomic_t lpfc_debugfs_seq_trc_cnt = ATOMIC_INIT(0); 1218c2ecf20Sopenharmony_cistatic unsigned long lpfc_debugfs_start_time = 0L; 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci/* iDiag */ 1248c2ecf20Sopenharmony_cistatic struct lpfc_idiag idiag; 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci/** 1278c2ecf20Sopenharmony_ci * lpfc_debugfs_disc_trc_data - Dump discovery logging to a buffer 1288c2ecf20Sopenharmony_ci * @vport: The vport to gather the log info from. 1298c2ecf20Sopenharmony_ci * @buf: The buffer to dump log into. 1308c2ecf20Sopenharmony_ci * @size: The maximum amount of data to process. 1318c2ecf20Sopenharmony_ci * 1328c2ecf20Sopenharmony_ci * Description: 1338c2ecf20Sopenharmony_ci * This routine gathers the lpfc discovery debugfs data from the @vport and 1348c2ecf20Sopenharmony_ci * dumps it to @buf up to @size number of bytes. It will start at the next entry 1358c2ecf20Sopenharmony_ci * in the log and process the log until the end of the buffer. Then it will 1368c2ecf20Sopenharmony_ci * gather from the beginning of the log and process until the current entry. 1378c2ecf20Sopenharmony_ci * 1388c2ecf20Sopenharmony_ci * Notes: 1398c2ecf20Sopenharmony_ci * Discovery logging will be disabled while while this routine dumps the log. 1408c2ecf20Sopenharmony_ci * 1418c2ecf20Sopenharmony_ci * Return Value: 1428c2ecf20Sopenharmony_ci * This routine returns the amount of bytes that were dumped into @buf and will 1438c2ecf20Sopenharmony_ci * not exceed @size. 1448c2ecf20Sopenharmony_ci **/ 1458c2ecf20Sopenharmony_cistatic int 1468c2ecf20Sopenharmony_cilpfc_debugfs_disc_trc_data(struct lpfc_vport *vport, char *buf, int size) 1478c2ecf20Sopenharmony_ci{ 1488c2ecf20Sopenharmony_ci int i, index, len, enable; 1498c2ecf20Sopenharmony_ci uint32_t ms; 1508c2ecf20Sopenharmony_ci struct lpfc_debugfs_trc *dtp; 1518c2ecf20Sopenharmony_ci char *buffer; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci buffer = kmalloc(LPFC_DEBUG_TRC_ENTRY_SIZE, GFP_KERNEL); 1548c2ecf20Sopenharmony_ci if (!buffer) 1558c2ecf20Sopenharmony_ci return 0; 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci enable = lpfc_debugfs_enable; 1588c2ecf20Sopenharmony_ci lpfc_debugfs_enable = 0; 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci len = 0; 1618c2ecf20Sopenharmony_ci index = (atomic_read(&vport->disc_trc_cnt) + 1) & 1628c2ecf20Sopenharmony_ci (lpfc_debugfs_max_disc_trc - 1); 1638c2ecf20Sopenharmony_ci for (i = index; i < lpfc_debugfs_max_disc_trc; i++) { 1648c2ecf20Sopenharmony_ci dtp = vport->disc_trc + i; 1658c2ecf20Sopenharmony_ci if (!dtp->fmt) 1668c2ecf20Sopenharmony_ci continue; 1678c2ecf20Sopenharmony_ci ms = jiffies_to_msecs(dtp->jif - lpfc_debugfs_start_time); 1688c2ecf20Sopenharmony_ci snprintf(buffer, 1698c2ecf20Sopenharmony_ci LPFC_DEBUG_TRC_ENTRY_SIZE, "%010d:%010d ms:%s\n", 1708c2ecf20Sopenharmony_ci dtp->seq_cnt, ms, dtp->fmt); 1718c2ecf20Sopenharmony_ci len += scnprintf(buf+len, size-len, buffer, 1728c2ecf20Sopenharmony_ci dtp->data1, dtp->data2, dtp->data3); 1738c2ecf20Sopenharmony_ci } 1748c2ecf20Sopenharmony_ci for (i = 0; i < index; i++) { 1758c2ecf20Sopenharmony_ci dtp = vport->disc_trc + i; 1768c2ecf20Sopenharmony_ci if (!dtp->fmt) 1778c2ecf20Sopenharmony_ci continue; 1788c2ecf20Sopenharmony_ci ms = jiffies_to_msecs(dtp->jif - lpfc_debugfs_start_time); 1798c2ecf20Sopenharmony_ci snprintf(buffer, 1808c2ecf20Sopenharmony_ci LPFC_DEBUG_TRC_ENTRY_SIZE, "%010d:%010d ms:%s\n", 1818c2ecf20Sopenharmony_ci dtp->seq_cnt, ms, dtp->fmt); 1828c2ecf20Sopenharmony_ci len += scnprintf(buf+len, size-len, buffer, 1838c2ecf20Sopenharmony_ci dtp->data1, dtp->data2, dtp->data3); 1848c2ecf20Sopenharmony_ci } 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci lpfc_debugfs_enable = enable; 1878c2ecf20Sopenharmony_ci kfree(buffer); 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci return len; 1908c2ecf20Sopenharmony_ci} 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci/** 1938c2ecf20Sopenharmony_ci * lpfc_debugfs_slow_ring_trc_data - Dump slow ring logging to a buffer 1948c2ecf20Sopenharmony_ci * @phba: The HBA to gather the log info from. 1958c2ecf20Sopenharmony_ci * @buf: The buffer to dump log into. 1968c2ecf20Sopenharmony_ci * @size: The maximum amount of data to process. 1978c2ecf20Sopenharmony_ci * 1988c2ecf20Sopenharmony_ci * Description: 1998c2ecf20Sopenharmony_ci * This routine gathers the lpfc slow ring debugfs data from the @phba and 2008c2ecf20Sopenharmony_ci * dumps it to @buf up to @size number of bytes. It will start at the next entry 2018c2ecf20Sopenharmony_ci * in the log and process the log until the end of the buffer. Then it will 2028c2ecf20Sopenharmony_ci * gather from the beginning of the log and process until the current entry. 2038c2ecf20Sopenharmony_ci * 2048c2ecf20Sopenharmony_ci * Notes: 2058c2ecf20Sopenharmony_ci * Slow ring logging will be disabled while while this routine dumps the log. 2068c2ecf20Sopenharmony_ci * 2078c2ecf20Sopenharmony_ci * Return Value: 2088c2ecf20Sopenharmony_ci * This routine returns the amount of bytes that were dumped into @buf and will 2098c2ecf20Sopenharmony_ci * not exceed @size. 2108c2ecf20Sopenharmony_ci **/ 2118c2ecf20Sopenharmony_cistatic int 2128c2ecf20Sopenharmony_cilpfc_debugfs_slow_ring_trc_data(struct lpfc_hba *phba, char *buf, int size) 2138c2ecf20Sopenharmony_ci{ 2148c2ecf20Sopenharmony_ci int i, index, len, enable; 2158c2ecf20Sopenharmony_ci uint32_t ms; 2168c2ecf20Sopenharmony_ci struct lpfc_debugfs_trc *dtp; 2178c2ecf20Sopenharmony_ci char *buffer; 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci buffer = kmalloc(LPFC_DEBUG_TRC_ENTRY_SIZE, GFP_KERNEL); 2208c2ecf20Sopenharmony_ci if (!buffer) 2218c2ecf20Sopenharmony_ci return 0; 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci enable = lpfc_debugfs_enable; 2248c2ecf20Sopenharmony_ci lpfc_debugfs_enable = 0; 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci len = 0; 2278c2ecf20Sopenharmony_ci index = (atomic_read(&phba->slow_ring_trc_cnt) + 1) & 2288c2ecf20Sopenharmony_ci (lpfc_debugfs_max_slow_ring_trc - 1); 2298c2ecf20Sopenharmony_ci for (i = index; i < lpfc_debugfs_max_slow_ring_trc; i++) { 2308c2ecf20Sopenharmony_ci dtp = phba->slow_ring_trc + i; 2318c2ecf20Sopenharmony_ci if (!dtp->fmt) 2328c2ecf20Sopenharmony_ci continue; 2338c2ecf20Sopenharmony_ci ms = jiffies_to_msecs(dtp->jif - lpfc_debugfs_start_time); 2348c2ecf20Sopenharmony_ci snprintf(buffer, 2358c2ecf20Sopenharmony_ci LPFC_DEBUG_TRC_ENTRY_SIZE, "%010d:%010d ms:%s\n", 2368c2ecf20Sopenharmony_ci dtp->seq_cnt, ms, dtp->fmt); 2378c2ecf20Sopenharmony_ci len += scnprintf(buf+len, size-len, buffer, 2388c2ecf20Sopenharmony_ci dtp->data1, dtp->data2, dtp->data3); 2398c2ecf20Sopenharmony_ci } 2408c2ecf20Sopenharmony_ci for (i = 0; i < index; i++) { 2418c2ecf20Sopenharmony_ci dtp = phba->slow_ring_trc + i; 2428c2ecf20Sopenharmony_ci if (!dtp->fmt) 2438c2ecf20Sopenharmony_ci continue; 2448c2ecf20Sopenharmony_ci ms = jiffies_to_msecs(dtp->jif - lpfc_debugfs_start_time); 2458c2ecf20Sopenharmony_ci snprintf(buffer, 2468c2ecf20Sopenharmony_ci LPFC_DEBUG_TRC_ENTRY_SIZE, "%010d:%010d ms:%s\n", 2478c2ecf20Sopenharmony_ci dtp->seq_cnt, ms, dtp->fmt); 2488c2ecf20Sopenharmony_ci len += scnprintf(buf+len, size-len, buffer, 2498c2ecf20Sopenharmony_ci dtp->data1, dtp->data2, dtp->data3); 2508c2ecf20Sopenharmony_ci } 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci lpfc_debugfs_enable = enable; 2538c2ecf20Sopenharmony_ci kfree(buffer); 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci return len; 2568c2ecf20Sopenharmony_ci} 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_cistatic int lpfc_debugfs_last_hbq = -1; 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci/** 2618c2ecf20Sopenharmony_ci * lpfc_debugfs_hbqinfo_data - Dump host buffer queue info to a buffer 2628c2ecf20Sopenharmony_ci * @phba: The HBA to gather host buffer info from. 2638c2ecf20Sopenharmony_ci * @buf: The buffer to dump log into. 2648c2ecf20Sopenharmony_ci * @size: The maximum amount of data to process. 2658c2ecf20Sopenharmony_ci * 2668c2ecf20Sopenharmony_ci * Description: 2678c2ecf20Sopenharmony_ci * This routine dumps the host buffer queue info from the @phba to @buf up to 2688c2ecf20Sopenharmony_ci * @size number of bytes. A header that describes the current hbq state will be 2698c2ecf20Sopenharmony_ci * dumped to @buf first and then info on each hbq entry will be dumped to @buf 2708c2ecf20Sopenharmony_ci * until @size bytes have been dumped or all the hbq info has been dumped. 2718c2ecf20Sopenharmony_ci * 2728c2ecf20Sopenharmony_ci * Notes: 2738c2ecf20Sopenharmony_ci * This routine will rotate through each configured HBQ each time called. 2748c2ecf20Sopenharmony_ci * 2758c2ecf20Sopenharmony_ci * Return Value: 2768c2ecf20Sopenharmony_ci * This routine returns the amount of bytes that were dumped into @buf and will 2778c2ecf20Sopenharmony_ci * not exceed @size. 2788c2ecf20Sopenharmony_ci **/ 2798c2ecf20Sopenharmony_cistatic int 2808c2ecf20Sopenharmony_cilpfc_debugfs_hbqinfo_data(struct lpfc_hba *phba, char *buf, int size) 2818c2ecf20Sopenharmony_ci{ 2828c2ecf20Sopenharmony_ci int len = 0; 2838c2ecf20Sopenharmony_ci int i, j, found, posted, low; 2848c2ecf20Sopenharmony_ci uint32_t phys, raw_index, getidx; 2858c2ecf20Sopenharmony_ci struct lpfc_hbq_init *hip; 2868c2ecf20Sopenharmony_ci struct hbq_s *hbqs; 2878c2ecf20Sopenharmony_ci struct lpfc_hbq_entry *hbqe; 2888c2ecf20Sopenharmony_ci struct lpfc_dmabuf *d_buf; 2898c2ecf20Sopenharmony_ci struct hbq_dmabuf *hbq_buf; 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci if (phba->sli_rev != 3) 2928c2ecf20Sopenharmony_ci return 0; 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci spin_lock_irq(&phba->hbalock); 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci /* toggle between multiple hbqs, if any */ 2978c2ecf20Sopenharmony_ci i = lpfc_sli_hbq_count(); 2988c2ecf20Sopenharmony_ci if (i > 1) { 2998c2ecf20Sopenharmony_ci lpfc_debugfs_last_hbq++; 3008c2ecf20Sopenharmony_ci if (lpfc_debugfs_last_hbq >= i) 3018c2ecf20Sopenharmony_ci lpfc_debugfs_last_hbq = 0; 3028c2ecf20Sopenharmony_ci } 3038c2ecf20Sopenharmony_ci else 3048c2ecf20Sopenharmony_ci lpfc_debugfs_last_hbq = 0; 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci i = lpfc_debugfs_last_hbq; 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci len += scnprintf(buf+len, size-len, "HBQ %d Info\n", i); 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci hbqs = &phba->hbqs[i]; 3118c2ecf20Sopenharmony_ci posted = 0; 3128c2ecf20Sopenharmony_ci list_for_each_entry(d_buf, &hbqs->hbq_buffer_list, list) 3138c2ecf20Sopenharmony_ci posted++; 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci hip = lpfc_hbq_defs[i]; 3168c2ecf20Sopenharmony_ci len += scnprintf(buf+len, size-len, 3178c2ecf20Sopenharmony_ci "idx:%d prof:%d rn:%d bufcnt:%d icnt:%d acnt:%d posted %d\n", 3188c2ecf20Sopenharmony_ci hip->hbq_index, hip->profile, hip->rn, 3198c2ecf20Sopenharmony_ci hip->buffer_count, hip->init_count, hip->add_count, posted); 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci raw_index = phba->hbq_get[i]; 3228c2ecf20Sopenharmony_ci getidx = le32_to_cpu(raw_index); 3238c2ecf20Sopenharmony_ci len += scnprintf(buf+len, size-len, 3248c2ecf20Sopenharmony_ci "entries:%d bufcnt:%d Put:%d nPut:%d localGet:%d hbaGet:%d\n", 3258c2ecf20Sopenharmony_ci hbqs->entry_count, hbqs->buffer_count, hbqs->hbqPutIdx, 3268c2ecf20Sopenharmony_ci hbqs->next_hbqPutIdx, hbqs->local_hbqGetIdx, getidx); 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci hbqe = (struct lpfc_hbq_entry *) phba->hbqs[i].hbq_virt; 3298c2ecf20Sopenharmony_ci for (j=0; j<hbqs->entry_count; j++) { 3308c2ecf20Sopenharmony_ci len += scnprintf(buf+len, size-len, 3318c2ecf20Sopenharmony_ci "%03d: %08x %04x %05x ", j, 3328c2ecf20Sopenharmony_ci le32_to_cpu(hbqe->bde.addrLow), 3338c2ecf20Sopenharmony_ci le32_to_cpu(hbqe->bde.tus.w), 3348c2ecf20Sopenharmony_ci le32_to_cpu(hbqe->buffer_tag)); 3358c2ecf20Sopenharmony_ci i = 0; 3368c2ecf20Sopenharmony_ci found = 0; 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci /* First calculate if slot has an associated posted buffer */ 3398c2ecf20Sopenharmony_ci low = hbqs->hbqPutIdx - posted; 3408c2ecf20Sopenharmony_ci if (low >= 0) { 3418c2ecf20Sopenharmony_ci if ((j >= hbqs->hbqPutIdx) || (j < low)) { 3428c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 3438c2ecf20Sopenharmony_ci "Unused\n"); 3448c2ecf20Sopenharmony_ci goto skipit; 3458c2ecf20Sopenharmony_ci } 3468c2ecf20Sopenharmony_ci } 3478c2ecf20Sopenharmony_ci else { 3488c2ecf20Sopenharmony_ci if ((j >= hbqs->hbqPutIdx) && 3498c2ecf20Sopenharmony_ci (j < (hbqs->entry_count+low))) { 3508c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 3518c2ecf20Sopenharmony_ci "Unused\n"); 3528c2ecf20Sopenharmony_ci goto skipit; 3538c2ecf20Sopenharmony_ci } 3548c2ecf20Sopenharmony_ci } 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci /* Get the Buffer info for the posted buffer */ 3578c2ecf20Sopenharmony_ci list_for_each_entry(d_buf, &hbqs->hbq_buffer_list, list) { 3588c2ecf20Sopenharmony_ci hbq_buf = container_of(d_buf, struct hbq_dmabuf, dbuf); 3598c2ecf20Sopenharmony_ci phys = ((uint64_t)hbq_buf->dbuf.phys & 0xffffffff); 3608c2ecf20Sopenharmony_ci if (phys == le32_to_cpu(hbqe->bde.addrLow)) { 3618c2ecf20Sopenharmony_ci len += scnprintf(buf+len, size-len, 3628c2ecf20Sopenharmony_ci "Buf%d: x%px %06x\n", i, 3638c2ecf20Sopenharmony_ci hbq_buf->dbuf.virt, hbq_buf->tag); 3648c2ecf20Sopenharmony_ci found = 1; 3658c2ecf20Sopenharmony_ci break; 3668c2ecf20Sopenharmony_ci } 3678c2ecf20Sopenharmony_ci i++; 3688c2ecf20Sopenharmony_ci } 3698c2ecf20Sopenharmony_ci if (!found) { 3708c2ecf20Sopenharmony_ci len += scnprintf(buf+len, size-len, "No DMAinfo?\n"); 3718c2ecf20Sopenharmony_ci } 3728c2ecf20Sopenharmony_ciskipit: 3738c2ecf20Sopenharmony_ci hbqe++; 3748c2ecf20Sopenharmony_ci if (len > LPFC_HBQINFO_SIZE - 54) 3758c2ecf20Sopenharmony_ci break; 3768c2ecf20Sopenharmony_ci } 3778c2ecf20Sopenharmony_ci spin_unlock_irq(&phba->hbalock); 3788c2ecf20Sopenharmony_ci return len; 3798c2ecf20Sopenharmony_ci} 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_cistatic int lpfc_debugfs_last_xripool; 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci/** 3848c2ecf20Sopenharmony_ci * lpfc_debugfs_common_xri_data - Dump Hardware Queue info to a buffer 3858c2ecf20Sopenharmony_ci * @phba: The HBA to gather host buffer info from. 3868c2ecf20Sopenharmony_ci * @buf: The buffer to dump log into. 3878c2ecf20Sopenharmony_ci * @size: The maximum amount of data to process. 3888c2ecf20Sopenharmony_ci * 3898c2ecf20Sopenharmony_ci * Description: 3908c2ecf20Sopenharmony_ci * This routine dumps the Hardware Queue info from the @phba to @buf up to 3918c2ecf20Sopenharmony_ci * @size number of bytes. A header that describes the current hdwq state will be 3928c2ecf20Sopenharmony_ci * dumped to @buf first and then info on each hdwq entry will be dumped to @buf 3938c2ecf20Sopenharmony_ci * until @size bytes have been dumped or all the hdwq info has been dumped. 3948c2ecf20Sopenharmony_ci * 3958c2ecf20Sopenharmony_ci * Notes: 3968c2ecf20Sopenharmony_ci * This routine will rotate through each configured Hardware Queue each 3978c2ecf20Sopenharmony_ci * time called. 3988c2ecf20Sopenharmony_ci * 3998c2ecf20Sopenharmony_ci * Return Value: 4008c2ecf20Sopenharmony_ci * This routine returns the amount of bytes that were dumped into @buf and will 4018c2ecf20Sopenharmony_ci * not exceed @size. 4028c2ecf20Sopenharmony_ci **/ 4038c2ecf20Sopenharmony_cistatic int 4048c2ecf20Sopenharmony_cilpfc_debugfs_commonxripools_data(struct lpfc_hba *phba, char *buf, int size) 4058c2ecf20Sopenharmony_ci{ 4068c2ecf20Sopenharmony_ci struct lpfc_sli4_hdw_queue *qp; 4078c2ecf20Sopenharmony_ci int len = 0; 4088c2ecf20Sopenharmony_ci int i, out; 4098c2ecf20Sopenharmony_ci unsigned long iflag; 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci for (i = 0; i < phba->cfg_hdw_queue; i++) { 4128c2ecf20Sopenharmony_ci if (len > (LPFC_DUMP_MULTIXRIPOOL_SIZE - 80)) 4138c2ecf20Sopenharmony_ci break; 4148c2ecf20Sopenharmony_ci qp = &phba->sli4_hba.hdwq[lpfc_debugfs_last_xripool]; 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, "HdwQ %d Info ", i); 4178c2ecf20Sopenharmony_ci spin_lock_irqsave(&qp->abts_io_buf_list_lock, iflag); 4188c2ecf20Sopenharmony_ci spin_lock(&qp->io_buf_list_get_lock); 4198c2ecf20Sopenharmony_ci spin_lock(&qp->io_buf_list_put_lock); 4208c2ecf20Sopenharmony_ci out = qp->total_io_bufs - (qp->get_io_bufs + qp->put_io_bufs + 4218c2ecf20Sopenharmony_ci qp->abts_scsi_io_bufs + qp->abts_nvme_io_bufs); 4228c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 4238c2ecf20Sopenharmony_ci "tot:%d get:%d put:%d mt:%d " 4248c2ecf20Sopenharmony_ci "ABTS scsi:%d nvme:%d Out:%d\n", 4258c2ecf20Sopenharmony_ci qp->total_io_bufs, qp->get_io_bufs, qp->put_io_bufs, 4268c2ecf20Sopenharmony_ci qp->empty_io_bufs, qp->abts_scsi_io_bufs, 4278c2ecf20Sopenharmony_ci qp->abts_nvme_io_bufs, out); 4288c2ecf20Sopenharmony_ci spin_unlock(&qp->io_buf_list_put_lock); 4298c2ecf20Sopenharmony_ci spin_unlock(&qp->io_buf_list_get_lock); 4308c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&qp->abts_io_buf_list_lock, iflag); 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci lpfc_debugfs_last_xripool++; 4338c2ecf20Sopenharmony_ci if (lpfc_debugfs_last_xripool >= phba->cfg_hdw_queue) 4348c2ecf20Sopenharmony_ci lpfc_debugfs_last_xripool = 0; 4358c2ecf20Sopenharmony_ci } 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci return len; 4388c2ecf20Sopenharmony_ci} 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci/** 4418c2ecf20Sopenharmony_ci * lpfc_debugfs_multixripools_data - Display multi-XRI pools information 4428c2ecf20Sopenharmony_ci * @phba: The HBA to gather host buffer info from. 4438c2ecf20Sopenharmony_ci * @buf: The buffer to dump log into. 4448c2ecf20Sopenharmony_ci * @size: The maximum amount of data to process. 4458c2ecf20Sopenharmony_ci * 4468c2ecf20Sopenharmony_ci * Description: 4478c2ecf20Sopenharmony_ci * This routine displays current multi-XRI pools information including XRI 4488c2ecf20Sopenharmony_ci * count in public, private and txcmplq. It also displays current high and 4498c2ecf20Sopenharmony_ci * low watermark. 4508c2ecf20Sopenharmony_ci * 4518c2ecf20Sopenharmony_ci * Return Value: 4528c2ecf20Sopenharmony_ci * This routine returns the amount of bytes that were dumped into @buf and will 4538c2ecf20Sopenharmony_ci * not exceed @size. 4548c2ecf20Sopenharmony_ci **/ 4558c2ecf20Sopenharmony_cistatic int 4568c2ecf20Sopenharmony_cilpfc_debugfs_multixripools_data(struct lpfc_hba *phba, char *buf, int size) 4578c2ecf20Sopenharmony_ci{ 4588c2ecf20Sopenharmony_ci u32 i; 4598c2ecf20Sopenharmony_ci u32 hwq_count; 4608c2ecf20Sopenharmony_ci struct lpfc_sli4_hdw_queue *qp; 4618c2ecf20Sopenharmony_ci struct lpfc_multixri_pool *multixri_pool; 4628c2ecf20Sopenharmony_ci struct lpfc_pvt_pool *pvt_pool; 4638c2ecf20Sopenharmony_ci struct lpfc_pbl_pool *pbl_pool; 4648c2ecf20Sopenharmony_ci u32 txcmplq_cnt; 4658c2ecf20Sopenharmony_ci char tmp[LPFC_DEBUG_OUT_LINE_SZ] = {0}; 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ci if (phba->sli_rev != LPFC_SLI_REV4) 4688c2ecf20Sopenharmony_ci return 0; 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ci if (!phba->sli4_hba.hdwq) 4718c2ecf20Sopenharmony_ci return 0; 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_ci if (!phba->cfg_xri_rebalancing) { 4748c2ecf20Sopenharmony_ci i = lpfc_debugfs_commonxripools_data(phba, buf, size); 4758c2ecf20Sopenharmony_ci return i; 4768c2ecf20Sopenharmony_ci } 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_ci /* 4798c2ecf20Sopenharmony_ci * Pbl: Current number of free XRIs in public pool 4808c2ecf20Sopenharmony_ci * Pvt: Current number of free XRIs in private pool 4818c2ecf20Sopenharmony_ci * Busy: Current number of outstanding XRIs 4828c2ecf20Sopenharmony_ci * HWM: Current high watermark 4838c2ecf20Sopenharmony_ci * pvt_empty: Incremented by 1 when IO submission fails (no xri) 4848c2ecf20Sopenharmony_ci * pbl_empty: Incremented by 1 when all pbl_pool are empty during 4858c2ecf20Sopenharmony_ci * IO submission 4868c2ecf20Sopenharmony_ci */ 4878c2ecf20Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 4888c2ecf20Sopenharmony_ci "HWQ: Pbl Pvt Busy HWM | pvt_empty pbl_empty "); 4898c2ecf20Sopenharmony_ci if (strlcat(buf, tmp, size) >= size) 4908c2ecf20Sopenharmony_ci return strnlen(buf, size); 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_ci#ifdef LPFC_MXP_STAT 4938c2ecf20Sopenharmony_ci /* 4948c2ecf20Sopenharmony_ci * MAXH: Max high watermark seen so far 4958c2ecf20Sopenharmony_ci * above_lmt: Incremented by 1 if xri_owned > xri_limit during 4968c2ecf20Sopenharmony_ci * IO submission 4978c2ecf20Sopenharmony_ci * below_lmt: Incremented by 1 if xri_owned <= xri_limit during 4988c2ecf20Sopenharmony_ci * IO submission 4998c2ecf20Sopenharmony_ci * locPbl_hit: Incremented by 1 if successfully get a batch of XRI from 5008c2ecf20Sopenharmony_ci * local pbl_pool 5018c2ecf20Sopenharmony_ci * othPbl_hit: Incremented by 1 if successfully get a batch of XRI from 5028c2ecf20Sopenharmony_ci * other pbl_pool 5038c2ecf20Sopenharmony_ci */ 5048c2ecf20Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 5058c2ecf20Sopenharmony_ci "MAXH above_lmt below_lmt locPbl_hit othPbl_hit"); 5068c2ecf20Sopenharmony_ci if (strlcat(buf, tmp, size) >= size) 5078c2ecf20Sopenharmony_ci return strnlen(buf, size); 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci /* 5108c2ecf20Sopenharmony_ci * sPbl: snapshot of Pbl 15 sec after stat gets cleared 5118c2ecf20Sopenharmony_ci * sPvt: snapshot of Pvt 15 sec after stat gets cleared 5128c2ecf20Sopenharmony_ci * sBusy: snapshot of Busy 15 sec after stat gets cleared 5138c2ecf20Sopenharmony_ci */ 5148c2ecf20Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 5158c2ecf20Sopenharmony_ci " | sPbl sPvt sBusy"); 5168c2ecf20Sopenharmony_ci if (strlcat(buf, tmp, size) >= size) 5178c2ecf20Sopenharmony_ci return strnlen(buf, size); 5188c2ecf20Sopenharmony_ci#endif 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_ci scnprintf(tmp, sizeof(tmp), "\n"); 5218c2ecf20Sopenharmony_ci if (strlcat(buf, tmp, size) >= size) 5228c2ecf20Sopenharmony_ci return strnlen(buf, size); 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_ci hwq_count = phba->cfg_hdw_queue; 5258c2ecf20Sopenharmony_ci for (i = 0; i < hwq_count; i++) { 5268c2ecf20Sopenharmony_ci qp = &phba->sli4_hba.hdwq[i]; 5278c2ecf20Sopenharmony_ci multixri_pool = qp->p_multixri_pool; 5288c2ecf20Sopenharmony_ci if (!multixri_pool) 5298c2ecf20Sopenharmony_ci continue; 5308c2ecf20Sopenharmony_ci pbl_pool = &multixri_pool->pbl_pool; 5318c2ecf20Sopenharmony_ci pvt_pool = &multixri_pool->pvt_pool; 5328c2ecf20Sopenharmony_ci txcmplq_cnt = qp->io_wq->pring->txcmplq_cnt; 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 5358c2ecf20Sopenharmony_ci "%03d: %4d %4d %4d %4d | %10d %10d ", 5368c2ecf20Sopenharmony_ci i, pbl_pool->count, pvt_pool->count, 5378c2ecf20Sopenharmony_ci txcmplq_cnt, pvt_pool->high_watermark, 5388c2ecf20Sopenharmony_ci qp->empty_io_bufs, multixri_pool->pbl_empty_count); 5398c2ecf20Sopenharmony_ci if (strlcat(buf, tmp, size) >= size) 5408c2ecf20Sopenharmony_ci break; 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_ci#ifdef LPFC_MXP_STAT 5438c2ecf20Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 5448c2ecf20Sopenharmony_ci "%4d %10d %10d %10d %10d", 5458c2ecf20Sopenharmony_ci multixri_pool->stat_max_hwm, 5468c2ecf20Sopenharmony_ci multixri_pool->above_limit_count, 5478c2ecf20Sopenharmony_ci multixri_pool->below_limit_count, 5488c2ecf20Sopenharmony_ci multixri_pool->local_pbl_hit_count, 5498c2ecf20Sopenharmony_ci multixri_pool->other_pbl_hit_count); 5508c2ecf20Sopenharmony_ci if (strlcat(buf, tmp, size) >= size) 5518c2ecf20Sopenharmony_ci break; 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 5548c2ecf20Sopenharmony_ci " | %4d %4d %5d", 5558c2ecf20Sopenharmony_ci multixri_pool->stat_pbl_count, 5568c2ecf20Sopenharmony_ci multixri_pool->stat_pvt_count, 5578c2ecf20Sopenharmony_ci multixri_pool->stat_busy_count); 5588c2ecf20Sopenharmony_ci if (strlcat(buf, tmp, size) >= size) 5598c2ecf20Sopenharmony_ci break; 5608c2ecf20Sopenharmony_ci#endif 5618c2ecf20Sopenharmony_ci 5628c2ecf20Sopenharmony_ci scnprintf(tmp, sizeof(tmp), "\n"); 5638c2ecf20Sopenharmony_ci if (strlcat(buf, tmp, size) >= size) 5648c2ecf20Sopenharmony_ci break; 5658c2ecf20Sopenharmony_ci } 5668c2ecf20Sopenharmony_ci return strnlen(buf, size); 5678c2ecf20Sopenharmony_ci} 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_ci#ifdef LPFC_HDWQ_LOCK_STAT 5718c2ecf20Sopenharmony_cistatic int lpfc_debugfs_last_lock; 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_ci/** 5748c2ecf20Sopenharmony_ci * lpfc_debugfs_lockstat_data - Dump Hardware Queue info to a buffer 5758c2ecf20Sopenharmony_ci * @phba: The HBA to gather host buffer info from. 5768c2ecf20Sopenharmony_ci * @buf: The buffer to dump log into. 5778c2ecf20Sopenharmony_ci * @size: The maximum amount of data to process. 5788c2ecf20Sopenharmony_ci * 5798c2ecf20Sopenharmony_ci * Description: 5808c2ecf20Sopenharmony_ci * This routine dumps the Hardware Queue info from the @phba to @buf up to 5818c2ecf20Sopenharmony_ci * @size number of bytes. A header that describes the current hdwq state will be 5828c2ecf20Sopenharmony_ci * dumped to @buf first and then info on each hdwq entry will be dumped to @buf 5838c2ecf20Sopenharmony_ci * until @size bytes have been dumped or all the hdwq info has been dumped. 5848c2ecf20Sopenharmony_ci * 5858c2ecf20Sopenharmony_ci * Notes: 5868c2ecf20Sopenharmony_ci * This routine will rotate through each configured Hardware Queue each 5878c2ecf20Sopenharmony_ci * time called. 5888c2ecf20Sopenharmony_ci * 5898c2ecf20Sopenharmony_ci * Return Value: 5908c2ecf20Sopenharmony_ci * This routine returns the amount of bytes that were dumped into @buf and will 5918c2ecf20Sopenharmony_ci * not exceed @size. 5928c2ecf20Sopenharmony_ci **/ 5938c2ecf20Sopenharmony_cistatic int 5948c2ecf20Sopenharmony_cilpfc_debugfs_lockstat_data(struct lpfc_hba *phba, char *buf, int size) 5958c2ecf20Sopenharmony_ci{ 5968c2ecf20Sopenharmony_ci struct lpfc_sli4_hdw_queue *qp; 5978c2ecf20Sopenharmony_ci int len = 0; 5988c2ecf20Sopenharmony_ci int i; 5998c2ecf20Sopenharmony_ci 6008c2ecf20Sopenharmony_ci if (phba->sli_rev != LPFC_SLI_REV4) 6018c2ecf20Sopenharmony_ci return 0; 6028c2ecf20Sopenharmony_ci 6038c2ecf20Sopenharmony_ci if (!phba->sli4_hba.hdwq) 6048c2ecf20Sopenharmony_ci return 0; 6058c2ecf20Sopenharmony_ci 6068c2ecf20Sopenharmony_ci for (i = 0; i < phba->cfg_hdw_queue; i++) { 6078c2ecf20Sopenharmony_ci if (len > (LPFC_HDWQINFO_SIZE - 100)) 6088c2ecf20Sopenharmony_ci break; 6098c2ecf20Sopenharmony_ci qp = &phba->sli4_hba.hdwq[lpfc_debugfs_last_lock]; 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, "HdwQ %03d Lock ", i); 6128c2ecf20Sopenharmony_ci if (phba->cfg_xri_rebalancing) { 6138c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 6148c2ecf20Sopenharmony_ci "get_pvt:%d mv_pvt:%d " 6158c2ecf20Sopenharmony_ci "mv2pub:%d mv2pvt:%d " 6168c2ecf20Sopenharmony_ci "put_pvt:%d put_pub:%d wq:%d\n", 6178c2ecf20Sopenharmony_ci qp->lock_conflict.alloc_pvt_pool, 6188c2ecf20Sopenharmony_ci qp->lock_conflict.mv_from_pvt_pool, 6198c2ecf20Sopenharmony_ci qp->lock_conflict.mv_to_pub_pool, 6208c2ecf20Sopenharmony_ci qp->lock_conflict.mv_to_pvt_pool, 6218c2ecf20Sopenharmony_ci qp->lock_conflict.free_pvt_pool, 6228c2ecf20Sopenharmony_ci qp->lock_conflict.free_pub_pool, 6238c2ecf20Sopenharmony_ci qp->lock_conflict.wq_access); 6248c2ecf20Sopenharmony_ci } else { 6258c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 6268c2ecf20Sopenharmony_ci "get:%d put:%d free:%d wq:%d\n", 6278c2ecf20Sopenharmony_ci qp->lock_conflict.alloc_xri_get, 6288c2ecf20Sopenharmony_ci qp->lock_conflict.alloc_xri_put, 6298c2ecf20Sopenharmony_ci qp->lock_conflict.free_xri, 6308c2ecf20Sopenharmony_ci qp->lock_conflict.wq_access); 6318c2ecf20Sopenharmony_ci } 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_ci lpfc_debugfs_last_lock++; 6348c2ecf20Sopenharmony_ci if (lpfc_debugfs_last_lock >= phba->cfg_hdw_queue) 6358c2ecf20Sopenharmony_ci lpfc_debugfs_last_lock = 0; 6368c2ecf20Sopenharmony_ci } 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_ci return len; 6398c2ecf20Sopenharmony_ci} 6408c2ecf20Sopenharmony_ci#endif 6418c2ecf20Sopenharmony_ci 6428c2ecf20Sopenharmony_cistatic int lpfc_debugfs_last_hba_slim_off; 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_ci/** 6458c2ecf20Sopenharmony_ci * lpfc_debugfs_dumpHBASlim_data - Dump HBA SLIM info to a buffer 6468c2ecf20Sopenharmony_ci * @phba: The HBA to gather SLIM info from. 6478c2ecf20Sopenharmony_ci * @buf: The buffer to dump log into. 6488c2ecf20Sopenharmony_ci * @size: The maximum amount of data to process. 6498c2ecf20Sopenharmony_ci * 6508c2ecf20Sopenharmony_ci * Description: 6518c2ecf20Sopenharmony_ci * This routine dumps the current contents of HBA SLIM for the HBA associated 6528c2ecf20Sopenharmony_ci * with @phba to @buf up to @size bytes of data. This is the raw HBA SLIM data. 6538c2ecf20Sopenharmony_ci * 6548c2ecf20Sopenharmony_ci * Notes: 6558c2ecf20Sopenharmony_ci * This routine will only dump up to 1024 bytes of data each time called and 6568c2ecf20Sopenharmony_ci * should be called multiple times to dump the entire HBA SLIM. 6578c2ecf20Sopenharmony_ci * 6588c2ecf20Sopenharmony_ci * Return Value: 6598c2ecf20Sopenharmony_ci * This routine returns the amount of bytes that were dumped into @buf and will 6608c2ecf20Sopenharmony_ci * not exceed @size. 6618c2ecf20Sopenharmony_ci **/ 6628c2ecf20Sopenharmony_cistatic int 6638c2ecf20Sopenharmony_cilpfc_debugfs_dumpHBASlim_data(struct lpfc_hba *phba, char *buf, int size) 6648c2ecf20Sopenharmony_ci{ 6658c2ecf20Sopenharmony_ci int len = 0; 6668c2ecf20Sopenharmony_ci int i, off; 6678c2ecf20Sopenharmony_ci uint32_t *ptr; 6688c2ecf20Sopenharmony_ci char *buffer; 6698c2ecf20Sopenharmony_ci 6708c2ecf20Sopenharmony_ci buffer = kmalloc(1024, GFP_KERNEL); 6718c2ecf20Sopenharmony_ci if (!buffer) 6728c2ecf20Sopenharmony_ci return 0; 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_ci off = 0; 6758c2ecf20Sopenharmony_ci spin_lock_irq(&phba->hbalock); 6768c2ecf20Sopenharmony_ci 6778c2ecf20Sopenharmony_ci len += scnprintf(buf+len, size-len, "HBA SLIM\n"); 6788c2ecf20Sopenharmony_ci lpfc_memcpy_from_slim(buffer, 6798c2ecf20Sopenharmony_ci phba->MBslimaddr + lpfc_debugfs_last_hba_slim_off, 1024); 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_ci ptr = (uint32_t *)&buffer[0]; 6828c2ecf20Sopenharmony_ci off = lpfc_debugfs_last_hba_slim_off; 6838c2ecf20Sopenharmony_ci 6848c2ecf20Sopenharmony_ci /* Set it up for the next time */ 6858c2ecf20Sopenharmony_ci lpfc_debugfs_last_hba_slim_off += 1024; 6868c2ecf20Sopenharmony_ci if (lpfc_debugfs_last_hba_slim_off >= 4096) 6878c2ecf20Sopenharmony_ci lpfc_debugfs_last_hba_slim_off = 0; 6888c2ecf20Sopenharmony_ci 6898c2ecf20Sopenharmony_ci i = 1024; 6908c2ecf20Sopenharmony_ci while (i > 0) { 6918c2ecf20Sopenharmony_ci len += scnprintf(buf+len, size-len, 6928c2ecf20Sopenharmony_ci "%08x: %08x %08x %08x %08x %08x %08x %08x %08x\n", 6938c2ecf20Sopenharmony_ci off, *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4), 6948c2ecf20Sopenharmony_ci *(ptr+5), *(ptr+6), *(ptr+7)); 6958c2ecf20Sopenharmony_ci ptr += 8; 6968c2ecf20Sopenharmony_ci i -= (8 * sizeof(uint32_t)); 6978c2ecf20Sopenharmony_ci off += (8 * sizeof(uint32_t)); 6988c2ecf20Sopenharmony_ci } 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_ci spin_unlock_irq(&phba->hbalock); 7018c2ecf20Sopenharmony_ci kfree(buffer); 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_ci return len; 7048c2ecf20Sopenharmony_ci} 7058c2ecf20Sopenharmony_ci 7068c2ecf20Sopenharmony_ci/** 7078c2ecf20Sopenharmony_ci * lpfc_debugfs_dumpHostSlim_data - Dump host SLIM info to a buffer 7088c2ecf20Sopenharmony_ci * @phba: The HBA to gather Host SLIM info from. 7098c2ecf20Sopenharmony_ci * @buf: The buffer to dump log into. 7108c2ecf20Sopenharmony_ci * @size: The maximum amount of data to process. 7118c2ecf20Sopenharmony_ci * 7128c2ecf20Sopenharmony_ci * Description: 7138c2ecf20Sopenharmony_ci * This routine dumps the current contents of host SLIM for the host associated 7148c2ecf20Sopenharmony_ci * with @phba to @buf up to @size bytes of data. The dump will contain the 7158c2ecf20Sopenharmony_ci * Mailbox, PCB, Rings, and Registers that are located in host memory. 7168c2ecf20Sopenharmony_ci * 7178c2ecf20Sopenharmony_ci * Return Value: 7188c2ecf20Sopenharmony_ci * This routine returns the amount of bytes that were dumped into @buf and will 7198c2ecf20Sopenharmony_ci * not exceed @size. 7208c2ecf20Sopenharmony_ci **/ 7218c2ecf20Sopenharmony_cistatic int 7228c2ecf20Sopenharmony_cilpfc_debugfs_dumpHostSlim_data(struct lpfc_hba *phba, char *buf, int size) 7238c2ecf20Sopenharmony_ci{ 7248c2ecf20Sopenharmony_ci int len = 0; 7258c2ecf20Sopenharmony_ci int i, off; 7268c2ecf20Sopenharmony_ci uint32_t word0, word1, word2, word3; 7278c2ecf20Sopenharmony_ci uint32_t *ptr; 7288c2ecf20Sopenharmony_ci struct lpfc_pgp *pgpp; 7298c2ecf20Sopenharmony_ci struct lpfc_sli *psli = &phba->sli; 7308c2ecf20Sopenharmony_ci struct lpfc_sli_ring *pring; 7318c2ecf20Sopenharmony_ci 7328c2ecf20Sopenharmony_ci off = 0; 7338c2ecf20Sopenharmony_ci spin_lock_irq(&phba->hbalock); 7348c2ecf20Sopenharmony_ci 7358c2ecf20Sopenharmony_ci len += scnprintf(buf+len, size-len, "SLIM Mailbox\n"); 7368c2ecf20Sopenharmony_ci ptr = (uint32_t *)phba->slim2p.virt; 7378c2ecf20Sopenharmony_ci i = sizeof(MAILBOX_t); 7388c2ecf20Sopenharmony_ci while (i > 0) { 7398c2ecf20Sopenharmony_ci len += scnprintf(buf+len, size-len, 7408c2ecf20Sopenharmony_ci "%08x: %08x %08x %08x %08x %08x %08x %08x %08x\n", 7418c2ecf20Sopenharmony_ci off, *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4), 7428c2ecf20Sopenharmony_ci *(ptr+5), *(ptr+6), *(ptr+7)); 7438c2ecf20Sopenharmony_ci ptr += 8; 7448c2ecf20Sopenharmony_ci i -= (8 * sizeof(uint32_t)); 7458c2ecf20Sopenharmony_ci off += (8 * sizeof(uint32_t)); 7468c2ecf20Sopenharmony_ci } 7478c2ecf20Sopenharmony_ci 7488c2ecf20Sopenharmony_ci len += scnprintf(buf+len, size-len, "SLIM PCB\n"); 7498c2ecf20Sopenharmony_ci ptr = (uint32_t *)phba->pcb; 7508c2ecf20Sopenharmony_ci i = sizeof(PCB_t); 7518c2ecf20Sopenharmony_ci while (i > 0) { 7528c2ecf20Sopenharmony_ci len += scnprintf(buf+len, size-len, 7538c2ecf20Sopenharmony_ci "%08x: %08x %08x %08x %08x %08x %08x %08x %08x\n", 7548c2ecf20Sopenharmony_ci off, *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4), 7558c2ecf20Sopenharmony_ci *(ptr+5), *(ptr+6), *(ptr+7)); 7568c2ecf20Sopenharmony_ci ptr += 8; 7578c2ecf20Sopenharmony_ci i -= (8 * sizeof(uint32_t)); 7588c2ecf20Sopenharmony_ci off += (8 * sizeof(uint32_t)); 7598c2ecf20Sopenharmony_ci } 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_ci if (phba->sli_rev <= LPFC_SLI_REV3) { 7628c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) { 7638c2ecf20Sopenharmony_ci pgpp = &phba->port_gp[i]; 7648c2ecf20Sopenharmony_ci pring = &psli->sli3_ring[i]; 7658c2ecf20Sopenharmony_ci len += scnprintf(buf+len, size-len, 7668c2ecf20Sopenharmony_ci "Ring %d: CMD GetInx:%d " 7678c2ecf20Sopenharmony_ci "(Max:%d Next:%d " 7688c2ecf20Sopenharmony_ci "Local:%d flg:x%x) " 7698c2ecf20Sopenharmony_ci "RSP PutInx:%d Max:%d\n", 7708c2ecf20Sopenharmony_ci i, pgpp->cmdGetInx, 7718c2ecf20Sopenharmony_ci pring->sli.sli3.numCiocb, 7728c2ecf20Sopenharmony_ci pring->sli.sli3.next_cmdidx, 7738c2ecf20Sopenharmony_ci pring->sli.sli3.local_getidx, 7748c2ecf20Sopenharmony_ci pring->flag, pgpp->rspPutInx, 7758c2ecf20Sopenharmony_ci pring->sli.sli3.numRiocb); 7768c2ecf20Sopenharmony_ci } 7778c2ecf20Sopenharmony_ci 7788c2ecf20Sopenharmony_ci word0 = readl(phba->HAregaddr); 7798c2ecf20Sopenharmony_ci word1 = readl(phba->CAregaddr); 7808c2ecf20Sopenharmony_ci word2 = readl(phba->HSregaddr); 7818c2ecf20Sopenharmony_ci word3 = readl(phba->HCregaddr); 7828c2ecf20Sopenharmony_ci len += scnprintf(buf+len, size-len, "HA:%08x CA:%08x HS:%08x " 7838c2ecf20Sopenharmony_ci "HC:%08x\n", word0, word1, word2, word3); 7848c2ecf20Sopenharmony_ci } 7858c2ecf20Sopenharmony_ci spin_unlock_irq(&phba->hbalock); 7868c2ecf20Sopenharmony_ci return len; 7878c2ecf20Sopenharmony_ci} 7888c2ecf20Sopenharmony_ci 7898c2ecf20Sopenharmony_ci/** 7908c2ecf20Sopenharmony_ci * lpfc_debugfs_nodelist_data - Dump target node list to a buffer 7918c2ecf20Sopenharmony_ci * @vport: The vport to gather target node info from. 7928c2ecf20Sopenharmony_ci * @buf: The buffer to dump log into. 7938c2ecf20Sopenharmony_ci * @size: The maximum amount of data to process. 7948c2ecf20Sopenharmony_ci * 7958c2ecf20Sopenharmony_ci * Description: 7968c2ecf20Sopenharmony_ci * This routine dumps the current target node list associated with @vport to 7978c2ecf20Sopenharmony_ci * @buf up to @size bytes of data. Each node entry in the dump will contain a 7988c2ecf20Sopenharmony_ci * node state, DID, WWPN, WWNN, RPI, flags, type, and other useful fields. 7998c2ecf20Sopenharmony_ci * 8008c2ecf20Sopenharmony_ci * Return Value: 8018c2ecf20Sopenharmony_ci * This routine returns the amount of bytes that were dumped into @buf and will 8028c2ecf20Sopenharmony_ci * not exceed @size. 8038c2ecf20Sopenharmony_ci **/ 8048c2ecf20Sopenharmony_cistatic int 8058c2ecf20Sopenharmony_cilpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size) 8068c2ecf20Sopenharmony_ci{ 8078c2ecf20Sopenharmony_ci int len = 0; 8088c2ecf20Sopenharmony_ci int i, iocnt, outio, cnt; 8098c2ecf20Sopenharmony_ci struct Scsi_Host *shost = lpfc_shost_from_vport(vport); 8108c2ecf20Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 8118c2ecf20Sopenharmony_ci struct lpfc_nodelist *ndlp; 8128c2ecf20Sopenharmony_ci unsigned char *statep; 8138c2ecf20Sopenharmony_ci struct nvme_fc_local_port *localport; 8148c2ecf20Sopenharmony_ci struct nvme_fc_remote_port *nrport = NULL; 8158c2ecf20Sopenharmony_ci struct lpfc_nvme_rport *rport; 8168c2ecf20Sopenharmony_ci 8178c2ecf20Sopenharmony_ci cnt = (LPFC_NODELIST_SIZE / LPFC_NODELIST_ENTRY_SIZE); 8188c2ecf20Sopenharmony_ci outio = 0; 8198c2ecf20Sopenharmony_ci 8208c2ecf20Sopenharmony_ci len += scnprintf(buf+len, size-len, "\nFCP Nodelist Entries ...\n"); 8218c2ecf20Sopenharmony_ci spin_lock_irq(shost->host_lock); 8228c2ecf20Sopenharmony_ci list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) { 8238c2ecf20Sopenharmony_ci iocnt = 0; 8248c2ecf20Sopenharmony_ci if (!cnt) { 8258c2ecf20Sopenharmony_ci len += scnprintf(buf+len, size-len, 8268c2ecf20Sopenharmony_ci "Missing Nodelist Entries\n"); 8278c2ecf20Sopenharmony_ci break; 8288c2ecf20Sopenharmony_ci } 8298c2ecf20Sopenharmony_ci cnt--; 8308c2ecf20Sopenharmony_ci switch (ndlp->nlp_state) { 8318c2ecf20Sopenharmony_ci case NLP_STE_UNUSED_NODE: 8328c2ecf20Sopenharmony_ci statep = "UNUSED"; 8338c2ecf20Sopenharmony_ci break; 8348c2ecf20Sopenharmony_ci case NLP_STE_PLOGI_ISSUE: 8358c2ecf20Sopenharmony_ci statep = "PLOGI "; 8368c2ecf20Sopenharmony_ci break; 8378c2ecf20Sopenharmony_ci case NLP_STE_ADISC_ISSUE: 8388c2ecf20Sopenharmony_ci statep = "ADISC "; 8398c2ecf20Sopenharmony_ci break; 8408c2ecf20Sopenharmony_ci case NLP_STE_REG_LOGIN_ISSUE: 8418c2ecf20Sopenharmony_ci statep = "REGLOG"; 8428c2ecf20Sopenharmony_ci break; 8438c2ecf20Sopenharmony_ci case NLP_STE_PRLI_ISSUE: 8448c2ecf20Sopenharmony_ci statep = "PRLI "; 8458c2ecf20Sopenharmony_ci break; 8468c2ecf20Sopenharmony_ci case NLP_STE_LOGO_ISSUE: 8478c2ecf20Sopenharmony_ci statep = "LOGO "; 8488c2ecf20Sopenharmony_ci break; 8498c2ecf20Sopenharmony_ci case NLP_STE_UNMAPPED_NODE: 8508c2ecf20Sopenharmony_ci statep = "UNMAP "; 8518c2ecf20Sopenharmony_ci iocnt = 1; 8528c2ecf20Sopenharmony_ci break; 8538c2ecf20Sopenharmony_ci case NLP_STE_MAPPED_NODE: 8548c2ecf20Sopenharmony_ci statep = "MAPPED"; 8558c2ecf20Sopenharmony_ci iocnt = 1; 8568c2ecf20Sopenharmony_ci break; 8578c2ecf20Sopenharmony_ci case NLP_STE_NPR_NODE: 8588c2ecf20Sopenharmony_ci statep = "NPR "; 8598c2ecf20Sopenharmony_ci break; 8608c2ecf20Sopenharmony_ci default: 8618c2ecf20Sopenharmony_ci statep = "UNKNOWN"; 8628c2ecf20Sopenharmony_ci } 8638c2ecf20Sopenharmony_ci len += scnprintf(buf+len, size-len, "%s DID:x%06x ", 8648c2ecf20Sopenharmony_ci statep, ndlp->nlp_DID); 8658c2ecf20Sopenharmony_ci len += scnprintf(buf+len, size-len, 8668c2ecf20Sopenharmony_ci "WWPN x%llx ", 8678c2ecf20Sopenharmony_ci wwn_to_u64(ndlp->nlp_portname.u.wwn)); 8688c2ecf20Sopenharmony_ci len += scnprintf(buf+len, size-len, 8698c2ecf20Sopenharmony_ci "WWNN x%llx ", 8708c2ecf20Sopenharmony_ci wwn_to_u64(ndlp->nlp_nodename.u.wwn)); 8718c2ecf20Sopenharmony_ci if (ndlp->nlp_flag & NLP_RPI_REGISTERED) 8728c2ecf20Sopenharmony_ci len += scnprintf(buf+len, size-len, "RPI:%03d ", 8738c2ecf20Sopenharmony_ci ndlp->nlp_rpi); 8748c2ecf20Sopenharmony_ci else 8758c2ecf20Sopenharmony_ci len += scnprintf(buf+len, size-len, "RPI:none "); 8768c2ecf20Sopenharmony_ci len += scnprintf(buf+len, size-len, "flag:x%08x ", 8778c2ecf20Sopenharmony_ci ndlp->nlp_flag); 8788c2ecf20Sopenharmony_ci if (!ndlp->nlp_type) 8798c2ecf20Sopenharmony_ci len += scnprintf(buf+len, size-len, "UNKNOWN_TYPE "); 8808c2ecf20Sopenharmony_ci if (ndlp->nlp_type & NLP_FC_NODE) 8818c2ecf20Sopenharmony_ci len += scnprintf(buf+len, size-len, "FC_NODE "); 8828c2ecf20Sopenharmony_ci if (ndlp->nlp_type & NLP_FABRIC) { 8838c2ecf20Sopenharmony_ci len += scnprintf(buf+len, size-len, "FABRIC "); 8848c2ecf20Sopenharmony_ci iocnt = 0; 8858c2ecf20Sopenharmony_ci } 8868c2ecf20Sopenharmony_ci if (ndlp->nlp_type & NLP_FCP_TARGET) 8878c2ecf20Sopenharmony_ci len += scnprintf(buf+len, size-len, "FCP_TGT sid:%d ", 8888c2ecf20Sopenharmony_ci ndlp->nlp_sid); 8898c2ecf20Sopenharmony_ci if (ndlp->nlp_type & NLP_FCP_INITIATOR) 8908c2ecf20Sopenharmony_ci len += scnprintf(buf+len, size-len, "FCP_INITIATOR "); 8918c2ecf20Sopenharmony_ci if (ndlp->nlp_type & NLP_NVME_TARGET) 8928c2ecf20Sopenharmony_ci len += scnprintf(buf + len, 8938c2ecf20Sopenharmony_ci size - len, "NVME_TGT sid:%d ", 8948c2ecf20Sopenharmony_ci NLP_NO_SID); 8958c2ecf20Sopenharmony_ci if (ndlp->nlp_type & NLP_NVME_INITIATOR) 8968c2ecf20Sopenharmony_ci len += scnprintf(buf + len, 8978c2ecf20Sopenharmony_ci size - len, "NVME_INITIATOR "); 8988c2ecf20Sopenharmony_ci len += scnprintf(buf+len, size-len, "usgmap:%x ", 8998c2ecf20Sopenharmony_ci ndlp->nlp_usg_map); 9008c2ecf20Sopenharmony_ci len += scnprintf(buf+len, size-len, "refcnt:%x", 9018c2ecf20Sopenharmony_ci kref_read(&ndlp->kref)); 9028c2ecf20Sopenharmony_ci if (iocnt) { 9038c2ecf20Sopenharmony_ci i = atomic_read(&ndlp->cmd_pending); 9048c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 9058c2ecf20Sopenharmony_ci " OutIO:x%x Qdepth x%x", 9068c2ecf20Sopenharmony_ci i, ndlp->cmd_qdepth); 9078c2ecf20Sopenharmony_ci outio += i; 9088c2ecf20Sopenharmony_ci } 9098c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, "defer:%x ", 9108c2ecf20Sopenharmony_ci ndlp->nlp_defer_did); 9118c2ecf20Sopenharmony_ci len += scnprintf(buf+len, size-len, "\n"); 9128c2ecf20Sopenharmony_ci } 9138c2ecf20Sopenharmony_ci spin_unlock_irq(shost->host_lock); 9148c2ecf20Sopenharmony_ci 9158c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 9168c2ecf20Sopenharmony_ci "\nOutstanding IO x%x\n", outio); 9178c2ecf20Sopenharmony_ci 9188c2ecf20Sopenharmony_ci if (phba->nvmet_support && phba->targetport && (vport == phba->pport)) { 9198c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 9208c2ecf20Sopenharmony_ci "\nNVME Targetport Entry ...\n"); 9218c2ecf20Sopenharmony_ci 9228c2ecf20Sopenharmony_ci /* Port state is only one of two values for now. */ 9238c2ecf20Sopenharmony_ci if (phba->targetport->port_id) 9248c2ecf20Sopenharmony_ci statep = "REGISTERED"; 9258c2ecf20Sopenharmony_ci else 9268c2ecf20Sopenharmony_ci statep = "INIT"; 9278c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 9288c2ecf20Sopenharmony_ci "TGT WWNN x%llx WWPN x%llx State %s\n", 9298c2ecf20Sopenharmony_ci wwn_to_u64(vport->fc_nodename.u.wwn), 9308c2ecf20Sopenharmony_ci wwn_to_u64(vport->fc_portname.u.wwn), 9318c2ecf20Sopenharmony_ci statep); 9328c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 9338c2ecf20Sopenharmony_ci " Targetport DID x%06x\n", 9348c2ecf20Sopenharmony_ci phba->targetport->port_id); 9358c2ecf20Sopenharmony_ci goto out_exit; 9368c2ecf20Sopenharmony_ci } 9378c2ecf20Sopenharmony_ci 9388c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 9398c2ecf20Sopenharmony_ci "\nNVME Lport/Rport Entries ...\n"); 9408c2ecf20Sopenharmony_ci 9418c2ecf20Sopenharmony_ci localport = vport->localport; 9428c2ecf20Sopenharmony_ci if (!localport) 9438c2ecf20Sopenharmony_ci goto out_exit; 9448c2ecf20Sopenharmony_ci 9458c2ecf20Sopenharmony_ci spin_lock_irq(shost->host_lock); 9468c2ecf20Sopenharmony_ci 9478c2ecf20Sopenharmony_ci /* Port state is only one of two values for now. */ 9488c2ecf20Sopenharmony_ci if (localport->port_id) 9498c2ecf20Sopenharmony_ci statep = "ONLINE"; 9508c2ecf20Sopenharmony_ci else 9518c2ecf20Sopenharmony_ci statep = "UNKNOWN "; 9528c2ecf20Sopenharmony_ci 9538c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 9548c2ecf20Sopenharmony_ci "Lport DID x%06x PortState %s\n", 9558c2ecf20Sopenharmony_ci localport->port_id, statep); 9568c2ecf20Sopenharmony_ci 9578c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, "\tRport List:\n"); 9588c2ecf20Sopenharmony_ci list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) { 9598c2ecf20Sopenharmony_ci /* local short-hand pointer. */ 9608c2ecf20Sopenharmony_ci spin_lock(&phba->hbalock); 9618c2ecf20Sopenharmony_ci rport = lpfc_ndlp_get_nrport(ndlp); 9628c2ecf20Sopenharmony_ci if (rport) 9638c2ecf20Sopenharmony_ci nrport = rport->remoteport; 9648c2ecf20Sopenharmony_ci else 9658c2ecf20Sopenharmony_ci nrport = NULL; 9668c2ecf20Sopenharmony_ci spin_unlock(&phba->hbalock); 9678c2ecf20Sopenharmony_ci if (!nrport) 9688c2ecf20Sopenharmony_ci continue; 9698c2ecf20Sopenharmony_ci 9708c2ecf20Sopenharmony_ci /* Port state is only one of two values for now. */ 9718c2ecf20Sopenharmony_ci switch (nrport->port_state) { 9728c2ecf20Sopenharmony_ci case FC_OBJSTATE_ONLINE: 9738c2ecf20Sopenharmony_ci statep = "ONLINE"; 9748c2ecf20Sopenharmony_ci break; 9758c2ecf20Sopenharmony_ci case FC_OBJSTATE_UNKNOWN: 9768c2ecf20Sopenharmony_ci statep = "UNKNOWN "; 9778c2ecf20Sopenharmony_ci break; 9788c2ecf20Sopenharmony_ci default: 9798c2ecf20Sopenharmony_ci statep = "UNSUPPORTED"; 9808c2ecf20Sopenharmony_ci break; 9818c2ecf20Sopenharmony_ci } 9828c2ecf20Sopenharmony_ci 9838c2ecf20Sopenharmony_ci /* Tab in to show lport ownership. */ 9848c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 9858c2ecf20Sopenharmony_ci "\t%s Port ID:x%06x ", 9868c2ecf20Sopenharmony_ci statep, nrport->port_id); 9878c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, "WWPN x%llx ", 9888c2ecf20Sopenharmony_ci nrport->port_name); 9898c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, "WWNN x%llx ", 9908c2ecf20Sopenharmony_ci nrport->node_name); 9918c2ecf20Sopenharmony_ci 9928c2ecf20Sopenharmony_ci /* An NVME rport can have multiple roles. */ 9938c2ecf20Sopenharmony_ci if (nrport->port_role & FC_PORT_ROLE_NVME_INITIATOR) 9948c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 9958c2ecf20Sopenharmony_ci "INITIATOR "); 9968c2ecf20Sopenharmony_ci if (nrport->port_role & FC_PORT_ROLE_NVME_TARGET) 9978c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 9988c2ecf20Sopenharmony_ci "TARGET "); 9998c2ecf20Sopenharmony_ci if (nrport->port_role & FC_PORT_ROLE_NVME_DISCOVERY) 10008c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 10018c2ecf20Sopenharmony_ci "DISCSRVC "); 10028c2ecf20Sopenharmony_ci if (nrport->port_role & ~(FC_PORT_ROLE_NVME_INITIATOR | 10038c2ecf20Sopenharmony_ci FC_PORT_ROLE_NVME_TARGET | 10048c2ecf20Sopenharmony_ci FC_PORT_ROLE_NVME_DISCOVERY)) 10058c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 10068c2ecf20Sopenharmony_ci "UNKNOWN ROLE x%x", 10078c2ecf20Sopenharmony_ci nrport->port_role); 10088c2ecf20Sopenharmony_ci /* Terminate the string. */ 10098c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, "\n"); 10108c2ecf20Sopenharmony_ci } 10118c2ecf20Sopenharmony_ci 10128c2ecf20Sopenharmony_ci spin_unlock_irq(shost->host_lock); 10138c2ecf20Sopenharmony_ci out_exit: 10148c2ecf20Sopenharmony_ci return len; 10158c2ecf20Sopenharmony_ci} 10168c2ecf20Sopenharmony_ci 10178c2ecf20Sopenharmony_ci/** 10188c2ecf20Sopenharmony_ci * lpfc_debugfs_nvmestat_data - Dump target node list to a buffer 10198c2ecf20Sopenharmony_ci * @vport: The vport to gather target node info from. 10208c2ecf20Sopenharmony_ci * @buf: The buffer to dump log into. 10218c2ecf20Sopenharmony_ci * @size: The maximum amount of data to process. 10228c2ecf20Sopenharmony_ci * 10238c2ecf20Sopenharmony_ci * Description: 10248c2ecf20Sopenharmony_ci * This routine dumps the NVME statistics associated with @vport 10258c2ecf20Sopenharmony_ci * 10268c2ecf20Sopenharmony_ci * Return Value: 10278c2ecf20Sopenharmony_ci * This routine returns the amount of bytes that were dumped into @buf and will 10288c2ecf20Sopenharmony_ci * not exceed @size. 10298c2ecf20Sopenharmony_ci **/ 10308c2ecf20Sopenharmony_cistatic int 10318c2ecf20Sopenharmony_cilpfc_debugfs_nvmestat_data(struct lpfc_vport *vport, char *buf, int size) 10328c2ecf20Sopenharmony_ci{ 10338c2ecf20Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 10348c2ecf20Sopenharmony_ci struct lpfc_nvmet_tgtport *tgtp; 10358c2ecf20Sopenharmony_ci struct lpfc_async_xchg_ctx *ctxp, *next_ctxp; 10368c2ecf20Sopenharmony_ci struct nvme_fc_local_port *localport; 10378c2ecf20Sopenharmony_ci struct lpfc_fc4_ctrl_stat *cstat; 10388c2ecf20Sopenharmony_ci struct lpfc_nvme_lport *lport; 10398c2ecf20Sopenharmony_ci uint64_t data1, data2, data3; 10408c2ecf20Sopenharmony_ci uint64_t tot, totin, totout; 10418c2ecf20Sopenharmony_ci int cnt, i; 10428c2ecf20Sopenharmony_ci int len = 0; 10438c2ecf20Sopenharmony_ci 10448c2ecf20Sopenharmony_ci if (phba->nvmet_support) { 10458c2ecf20Sopenharmony_ci if (!phba->targetport) 10468c2ecf20Sopenharmony_ci return len; 10478c2ecf20Sopenharmony_ci tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private; 10488c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 10498c2ecf20Sopenharmony_ci "\nNVME Targetport Statistics\n"); 10508c2ecf20Sopenharmony_ci 10518c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 10528c2ecf20Sopenharmony_ci "LS: Rcv %08x Drop %08x Abort %08x\n", 10538c2ecf20Sopenharmony_ci atomic_read(&tgtp->rcv_ls_req_in), 10548c2ecf20Sopenharmony_ci atomic_read(&tgtp->rcv_ls_req_drop), 10558c2ecf20Sopenharmony_ci atomic_read(&tgtp->xmt_ls_abort)); 10568c2ecf20Sopenharmony_ci if (atomic_read(&tgtp->rcv_ls_req_in) != 10578c2ecf20Sopenharmony_ci atomic_read(&tgtp->rcv_ls_req_out)) { 10588c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 10598c2ecf20Sopenharmony_ci "Rcv LS: in %08x != out %08x\n", 10608c2ecf20Sopenharmony_ci atomic_read(&tgtp->rcv_ls_req_in), 10618c2ecf20Sopenharmony_ci atomic_read(&tgtp->rcv_ls_req_out)); 10628c2ecf20Sopenharmony_ci } 10638c2ecf20Sopenharmony_ci 10648c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 10658c2ecf20Sopenharmony_ci "LS: Xmt %08x Drop %08x Cmpl %08x\n", 10668c2ecf20Sopenharmony_ci atomic_read(&tgtp->xmt_ls_rsp), 10678c2ecf20Sopenharmony_ci atomic_read(&tgtp->xmt_ls_drop), 10688c2ecf20Sopenharmony_ci atomic_read(&tgtp->xmt_ls_rsp_cmpl)); 10698c2ecf20Sopenharmony_ci 10708c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 10718c2ecf20Sopenharmony_ci "LS: RSP Abort %08x xb %08x Err %08x\n", 10728c2ecf20Sopenharmony_ci atomic_read(&tgtp->xmt_ls_rsp_aborted), 10738c2ecf20Sopenharmony_ci atomic_read(&tgtp->xmt_ls_rsp_xb_set), 10748c2ecf20Sopenharmony_ci atomic_read(&tgtp->xmt_ls_rsp_error)); 10758c2ecf20Sopenharmony_ci 10768c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 10778c2ecf20Sopenharmony_ci "FCP: Rcv %08x Defer %08x Release %08x " 10788c2ecf20Sopenharmony_ci "Drop %08x\n", 10798c2ecf20Sopenharmony_ci atomic_read(&tgtp->rcv_fcp_cmd_in), 10808c2ecf20Sopenharmony_ci atomic_read(&tgtp->rcv_fcp_cmd_defer), 10818c2ecf20Sopenharmony_ci atomic_read(&tgtp->xmt_fcp_release), 10828c2ecf20Sopenharmony_ci atomic_read(&tgtp->rcv_fcp_cmd_drop)); 10838c2ecf20Sopenharmony_ci 10848c2ecf20Sopenharmony_ci if (atomic_read(&tgtp->rcv_fcp_cmd_in) != 10858c2ecf20Sopenharmony_ci atomic_read(&tgtp->rcv_fcp_cmd_out)) { 10868c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 10878c2ecf20Sopenharmony_ci "Rcv FCP: in %08x != out %08x\n", 10888c2ecf20Sopenharmony_ci atomic_read(&tgtp->rcv_fcp_cmd_in), 10898c2ecf20Sopenharmony_ci atomic_read(&tgtp->rcv_fcp_cmd_out)); 10908c2ecf20Sopenharmony_ci } 10918c2ecf20Sopenharmony_ci 10928c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 10938c2ecf20Sopenharmony_ci "FCP Rsp: read %08x readrsp %08x " 10948c2ecf20Sopenharmony_ci "write %08x rsp %08x\n", 10958c2ecf20Sopenharmony_ci atomic_read(&tgtp->xmt_fcp_read), 10968c2ecf20Sopenharmony_ci atomic_read(&tgtp->xmt_fcp_read_rsp), 10978c2ecf20Sopenharmony_ci atomic_read(&tgtp->xmt_fcp_write), 10988c2ecf20Sopenharmony_ci atomic_read(&tgtp->xmt_fcp_rsp)); 10998c2ecf20Sopenharmony_ci 11008c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 11018c2ecf20Sopenharmony_ci "FCP Rsp Cmpl: %08x err %08x drop %08x\n", 11028c2ecf20Sopenharmony_ci atomic_read(&tgtp->xmt_fcp_rsp_cmpl), 11038c2ecf20Sopenharmony_ci atomic_read(&tgtp->xmt_fcp_rsp_error), 11048c2ecf20Sopenharmony_ci atomic_read(&tgtp->xmt_fcp_rsp_drop)); 11058c2ecf20Sopenharmony_ci 11068c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 11078c2ecf20Sopenharmony_ci "FCP Rsp Abort: %08x xb %08x xricqe %08x\n", 11088c2ecf20Sopenharmony_ci atomic_read(&tgtp->xmt_fcp_rsp_aborted), 11098c2ecf20Sopenharmony_ci atomic_read(&tgtp->xmt_fcp_rsp_xb_set), 11108c2ecf20Sopenharmony_ci atomic_read(&tgtp->xmt_fcp_xri_abort_cqe)); 11118c2ecf20Sopenharmony_ci 11128c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 11138c2ecf20Sopenharmony_ci "ABORT: Xmt %08x Cmpl %08x\n", 11148c2ecf20Sopenharmony_ci atomic_read(&tgtp->xmt_fcp_abort), 11158c2ecf20Sopenharmony_ci atomic_read(&tgtp->xmt_fcp_abort_cmpl)); 11168c2ecf20Sopenharmony_ci 11178c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 11188c2ecf20Sopenharmony_ci "ABORT: Sol %08x Usol %08x Err %08x Cmpl %08x", 11198c2ecf20Sopenharmony_ci atomic_read(&tgtp->xmt_abort_sol), 11208c2ecf20Sopenharmony_ci atomic_read(&tgtp->xmt_abort_unsol), 11218c2ecf20Sopenharmony_ci atomic_read(&tgtp->xmt_abort_rsp), 11228c2ecf20Sopenharmony_ci atomic_read(&tgtp->xmt_abort_rsp_error)); 11238c2ecf20Sopenharmony_ci 11248c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, "\n"); 11258c2ecf20Sopenharmony_ci 11268c2ecf20Sopenharmony_ci cnt = 0; 11278c2ecf20Sopenharmony_ci spin_lock(&phba->sli4_hba.abts_nvmet_buf_list_lock); 11288c2ecf20Sopenharmony_ci list_for_each_entry_safe(ctxp, next_ctxp, 11298c2ecf20Sopenharmony_ci &phba->sli4_hba.lpfc_abts_nvmet_ctx_list, 11308c2ecf20Sopenharmony_ci list) { 11318c2ecf20Sopenharmony_ci cnt++; 11328c2ecf20Sopenharmony_ci } 11338c2ecf20Sopenharmony_ci spin_unlock(&phba->sli4_hba.abts_nvmet_buf_list_lock); 11348c2ecf20Sopenharmony_ci if (cnt) { 11358c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 11368c2ecf20Sopenharmony_ci "ABORT: %d ctx entries\n", cnt); 11378c2ecf20Sopenharmony_ci spin_lock(&phba->sli4_hba.abts_nvmet_buf_list_lock); 11388c2ecf20Sopenharmony_ci list_for_each_entry_safe(ctxp, next_ctxp, 11398c2ecf20Sopenharmony_ci &phba->sli4_hba.lpfc_abts_nvmet_ctx_list, 11408c2ecf20Sopenharmony_ci list) { 11418c2ecf20Sopenharmony_ci if (len >= (size - LPFC_DEBUG_OUT_LINE_SZ)) 11428c2ecf20Sopenharmony_ci break; 11438c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 11448c2ecf20Sopenharmony_ci "Entry: oxid %x state %x " 11458c2ecf20Sopenharmony_ci "flag %x\n", 11468c2ecf20Sopenharmony_ci ctxp->oxid, ctxp->state, 11478c2ecf20Sopenharmony_ci ctxp->flag); 11488c2ecf20Sopenharmony_ci } 11498c2ecf20Sopenharmony_ci spin_unlock(&phba->sli4_hba.abts_nvmet_buf_list_lock); 11508c2ecf20Sopenharmony_ci } 11518c2ecf20Sopenharmony_ci 11528c2ecf20Sopenharmony_ci /* Calculate outstanding IOs */ 11538c2ecf20Sopenharmony_ci tot = atomic_read(&tgtp->rcv_fcp_cmd_drop); 11548c2ecf20Sopenharmony_ci tot += atomic_read(&tgtp->xmt_fcp_release); 11558c2ecf20Sopenharmony_ci tot = atomic_read(&tgtp->rcv_fcp_cmd_in) - tot; 11568c2ecf20Sopenharmony_ci 11578c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 11588c2ecf20Sopenharmony_ci "IO_CTX: %08x WAIT: cur %08x tot %08x\n" 11598c2ecf20Sopenharmony_ci "CTX Outstanding %08llx\n", 11608c2ecf20Sopenharmony_ci phba->sli4_hba.nvmet_xri_cnt, 11618c2ecf20Sopenharmony_ci phba->sli4_hba.nvmet_io_wait_cnt, 11628c2ecf20Sopenharmony_ci phba->sli4_hba.nvmet_io_wait_total, 11638c2ecf20Sopenharmony_ci tot); 11648c2ecf20Sopenharmony_ci } else { 11658c2ecf20Sopenharmony_ci if (!(vport->cfg_enable_fc4_type & LPFC_ENABLE_NVME)) 11668c2ecf20Sopenharmony_ci return len; 11678c2ecf20Sopenharmony_ci 11688c2ecf20Sopenharmony_ci localport = vport->localport; 11698c2ecf20Sopenharmony_ci if (!localport) 11708c2ecf20Sopenharmony_ci return len; 11718c2ecf20Sopenharmony_ci lport = (struct lpfc_nvme_lport *)localport->private; 11728c2ecf20Sopenharmony_ci if (!lport) 11738c2ecf20Sopenharmony_ci return len; 11748c2ecf20Sopenharmony_ci 11758c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 11768c2ecf20Sopenharmony_ci "\nNVME HDWQ Statistics\n"); 11778c2ecf20Sopenharmony_ci 11788c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 11798c2ecf20Sopenharmony_ci "LS: Xmt %016x Cmpl %016x\n", 11808c2ecf20Sopenharmony_ci atomic_read(&lport->fc4NvmeLsRequests), 11818c2ecf20Sopenharmony_ci atomic_read(&lport->fc4NvmeLsCmpls)); 11828c2ecf20Sopenharmony_ci 11838c2ecf20Sopenharmony_ci totin = 0; 11848c2ecf20Sopenharmony_ci totout = 0; 11858c2ecf20Sopenharmony_ci for (i = 0; i < phba->cfg_hdw_queue; i++) { 11868c2ecf20Sopenharmony_ci cstat = &phba->sli4_hba.hdwq[i].nvme_cstat; 11878c2ecf20Sopenharmony_ci tot = cstat->io_cmpls; 11888c2ecf20Sopenharmony_ci totin += tot; 11898c2ecf20Sopenharmony_ci data1 = cstat->input_requests; 11908c2ecf20Sopenharmony_ci data2 = cstat->output_requests; 11918c2ecf20Sopenharmony_ci data3 = cstat->control_requests; 11928c2ecf20Sopenharmony_ci totout += (data1 + data2 + data3); 11938c2ecf20Sopenharmony_ci 11948c2ecf20Sopenharmony_ci /* Limit to 32, debugfs display buffer limitation */ 11958c2ecf20Sopenharmony_ci if (i >= 32) 11968c2ecf20Sopenharmony_ci continue; 11978c2ecf20Sopenharmony_ci 11988c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, 11998c2ecf20Sopenharmony_ci "HDWQ (%d): Rd %016llx Wr %016llx " 12008c2ecf20Sopenharmony_ci "IO %016llx ", 12018c2ecf20Sopenharmony_ci i, data1, data2, data3); 12028c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, 12038c2ecf20Sopenharmony_ci "Cmpl %016llx OutIO %016llx\n", 12048c2ecf20Sopenharmony_ci tot, ((data1 + data2 + data3) - tot)); 12058c2ecf20Sopenharmony_ci } 12068c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, 12078c2ecf20Sopenharmony_ci "Total FCP Cmpl %016llx Issue %016llx " 12088c2ecf20Sopenharmony_ci "OutIO %016llx\n", 12098c2ecf20Sopenharmony_ci totin, totout, totout - totin); 12108c2ecf20Sopenharmony_ci 12118c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 12128c2ecf20Sopenharmony_ci "LS Xmt Err: Abrt %08x Err %08x " 12138c2ecf20Sopenharmony_ci "Cmpl Err: xb %08x Err %08x\n", 12148c2ecf20Sopenharmony_ci atomic_read(&lport->xmt_ls_abort), 12158c2ecf20Sopenharmony_ci atomic_read(&lport->xmt_ls_err), 12168c2ecf20Sopenharmony_ci atomic_read(&lport->cmpl_ls_xb), 12178c2ecf20Sopenharmony_ci atomic_read(&lport->cmpl_ls_err)); 12188c2ecf20Sopenharmony_ci 12198c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 12208c2ecf20Sopenharmony_ci "FCP Xmt Err: noxri %06x nondlp %06x " 12218c2ecf20Sopenharmony_ci "qdepth %06x wqerr %06x err %06x Abrt %06x\n", 12228c2ecf20Sopenharmony_ci atomic_read(&lport->xmt_fcp_noxri), 12238c2ecf20Sopenharmony_ci atomic_read(&lport->xmt_fcp_bad_ndlp), 12248c2ecf20Sopenharmony_ci atomic_read(&lport->xmt_fcp_qdepth), 12258c2ecf20Sopenharmony_ci atomic_read(&lport->xmt_fcp_wqerr), 12268c2ecf20Sopenharmony_ci atomic_read(&lport->xmt_fcp_err), 12278c2ecf20Sopenharmony_ci atomic_read(&lport->xmt_fcp_abort)); 12288c2ecf20Sopenharmony_ci 12298c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 12308c2ecf20Sopenharmony_ci "FCP Cmpl Err: xb %08x Err %08x\n", 12318c2ecf20Sopenharmony_ci atomic_read(&lport->cmpl_fcp_xb), 12328c2ecf20Sopenharmony_ci atomic_read(&lport->cmpl_fcp_err)); 12338c2ecf20Sopenharmony_ci 12348c2ecf20Sopenharmony_ci } 12358c2ecf20Sopenharmony_ci 12368c2ecf20Sopenharmony_ci return len; 12378c2ecf20Sopenharmony_ci} 12388c2ecf20Sopenharmony_ci 12398c2ecf20Sopenharmony_ci/** 12408c2ecf20Sopenharmony_ci * lpfc_debugfs_scsistat_data - Dump target node list to a buffer 12418c2ecf20Sopenharmony_ci * @vport: The vport to gather target node info from. 12428c2ecf20Sopenharmony_ci * @buf: The buffer to dump log into. 12438c2ecf20Sopenharmony_ci * @size: The maximum amount of data to process. 12448c2ecf20Sopenharmony_ci * 12458c2ecf20Sopenharmony_ci * Description: 12468c2ecf20Sopenharmony_ci * This routine dumps the SCSI statistics associated with @vport 12478c2ecf20Sopenharmony_ci * 12488c2ecf20Sopenharmony_ci * Return Value: 12498c2ecf20Sopenharmony_ci * This routine returns the amount of bytes that were dumped into @buf and will 12508c2ecf20Sopenharmony_ci * not exceed @size. 12518c2ecf20Sopenharmony_ci **/ 12528c2ecf20Sopenharmony_cistatic int 12538c2ecf20Sopenharmony_cilpfc_debugfs_scsistat_data(struct lpfc_vport *vport, char *buf, int size) 12548c2ecf20Sopenharmony_ci{ 12558c2ecf20Sopenharmony_ci int len; 12568c2ecf20Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 12578c2ecf20Sopenharmony_ci struct lpfc_fc4_ctrl_stat *cstat; 12588c2ecf20Sopenharmony_ci u64 data1, data2, data3; 12598c2ecf20Sopenharmony_ci u64 tot, totin, totout; 12608c2ecf20Sopenharmony_ci int i; 12618c2ecf20Sopenharmony_ci char tmp[LPFC_MAX_SCSI_INFO_TMP_LEN] = {0}; 12628c2ecf20Sopenharmony_ci 12638c2ecf20Sopenharmony_ci if (!(vport->cfg_enable_fc4_type & LPFC_ENABLE_FCP) || 12648c2ecf20Sopenharmony_ci (phba->sli_rev != LPFC_SLI_REV4)) 12658c2ecf20Sopenharmony_ci return 0; 12668c2ecf20Sopenharmony_ci 12678c2ecf20Sopenharmony_ci scnprintf(buf, size, "SCSI HDWQ Statistics\n"); 12688c2ecf20Sopenharmony_ci 12698c2ecf20Sopenharmony_ci totin = 0; 12708c2ecf20Sopenharmony_ci totout = 0; 12718c2ecf20Sopenharmony_ci for (i = 0; i < phba->cfg_hdw_queue; i++) { 12728c2ecf20Sopenharmony_ci cstat = &phba->sli4_hba.hdwq[i].scsi_cstat; 12738c2ecf20Sopenharmony_ci tot = cstat->io_cmpls; 12748c2ecf20Sopenharmony_ci totin += tot; 12758c2ecf20Sopenharmony_ci data1 = cstat->input_requests; 12768c2ecf20Sopenharmony_ci data2 = cstat->output_requests; 12778c2ecf20Sopenharmony_ci data3 = cstat->control_requests; 12788c2ecf20Sopenharmony_ci totout += (data1 + data2 + data3); 12798c2ecf20Sopenharmony_ci 12808c2ecf20Sopenharmony_ci scnprintf(tmp, sizeof(tmp), "HDWQ (%d): Rd %016llx Wr %016llx " 12818c2ecf20Sopenharmony_ci "IO %016llx ", i, data1, data2, data3); 12828c2ecf20Sopenharmony_ci if (strlcat(buf, tmp, size) >= size) 12838c2ecf20Sopenharmony_ci goto buffer_done; 12848c2ecf20Sopenharmony_ci 12858c2ecf20Sopenharmony_ci scnprintf(tmp, sizeof(tmp), "Cmpl %016llx OutIO %016llx\n", 12868c2ecf20Sopenharmony_ci tot, ((data1 + data2 + data3) - tot)); 12878c2ecf20Sopenharmony_ci if (strlcat(buf, tmp, size) >= size) 12888c2ecf20Sopenharmony_ci goto buffer_done; 12898c2ecf20Sopenharmony_ci } 12908c2ecf20Sopenharmony_ci scnprintf(tmp, sizeof(tmp), "Total FCP Cmpl %016llx Issue %016llx " 12918c2ecf20Sopenharmony_ci "OutIO %016llx\n", totin, totout, totout - totin); 12928c2ecf20Sopenharmony_ci strlcat(buf, tmp, size); 12938c2ecf20Sopenharmony_ci 12948c2ecf20Sopenharmony_cibuffer_done: 12958c2ecf20Sopenharmony_ci len = strnlen(buf, size); 12968c2ecf20Sopenharmony_ci 12978c2ecf20Sopenharmony_ci return len; 12988c2ecf20Sopenharmony_ci} 12998c2ecf20Sopenharmony_ci 13008c2ecf20Sopenharmony_civoid 13018c2ecf20Sopenharmony_cilpfc_io_ktime(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd) 13028c2ecf20Sopenharmony_ci{ 13038c2ecf20Sopenharmony_ci uint64_t seg1, seg2, seg3, seg4; 13048c2ecf20Sopenharmony_ci uint64_t segsum; 13058c2ecf20Sopenharmony_ci 13068c2ecf20Sopenharmony_ci if (!lpfc_cmd->ts_last_cmd || 13078c2ecf20Sopenharmony_ci !lpfc_cmd->ts_cmd_start || 13088c2ecf20Sopenharmony_ci !lpfc_cmd->ts_cmd_wqput || 13098c2ecf20Sopenharmony_ci !lpfc_cmd->ts_isr_cmpl || 13108c2ecf20Sopenharmony_ci !lpfc_cmd->ts_data_io) 13118c2ecf20Sopenharmony_ci return; 13128c2ecf20Sopenharmony_ci 13138c2ecf20Sopenharmony_ci if (lpfc_cmd->ts_data_io < lpfc_cmd->ts_cmd_start) 13148c2ecf20Sopenharmony_ci return; 13158c2ecf20Sopenharmony_ci if (lpfc_cmd->ts_cmd_start < lpfc_cmd->ts_last_cmd) 13168c2ecf20Sopenharmony_ci return; 13178c2ecf20Sopenharmony_ci if (lpfc_cmd->ts_cmd_wqput < lpfc_cmd->ts_cmd_start) 13188c2ecf20Sopenharmony_ci return; 13198c2ecf20Sopenharmony_ci if (lpfc_cmd->ts_isr_cmpl < lpfc_cmd->ts_cmd_wqput) 13208c2ecf20Sopenharmony_ci return; 13218c2ecf20Sopenharmony_ci if (lpfc_cmd->ts_data_io < lpfc_cmd->ts_isr_cmpl) 13228c2ecf20Sopenharmony_ci return; 13238c2ecf20Sopenharmony_ci /* 13248c2ecf20Sopenharmony_ci * Segment 1 - Time from Last FCP command cmpl is handed 13258c2ecf20Sopenharmony_ci * off to NVME Layer to start of next command. 13268c2ecf20Sopenharmony_ci * Segment 2 - Time from Driver receives a IO cmd start 13278c2ecf20Sopenharmony_ci * from NVME Layer to WQ put is done on IO cmd. 13288c2ecf20Sopenharmony_ci * Segment 3 - Time from Driver WQ put is done on IO cmd 13298c2ecf20Sopenharmony_ci * to MSI-X ISR for IO cmpl. 13308c2ecf20Sopenharmony_ci * Segment 4 - Time from MSI-X ISR for IO cmpl to when 13318c2ecf20Sopenharmony_ci * cmpl is handled off to the NVME Layer. 13328c2ecf20Sopenharmony_ci */ 13338c2ecf20Sopenharmony_ci seg1 = lpfc_cmd->ts_cmd_start - lpfc_cmd->ts_last_cmd; 13348c2ecf20Sopenharmony_ci if (seg1 > 5000000) /* 5 ms - for sequential IOs only */ 13358c2ecf20Sopenharmony_ci seg1 = 0; 13368c2ecf20Sopenharmony_ci 13378c2ecf20Sopenharmony_ci /* Calculate times relative to start of IO */ 13388c2ecf20Sopenharmony_ci seg2 = (lpfc_cmd->ts_cmd_wqput - lpfc_cmd->ts_cmd_start); 13398c2ecf20Sopenharmony_ci segsum = seg2; 13408c2ecf20Sopenharmony_ci seg3 = lpfc_cmd->ts_isr_cmpl - lpfc_cmd->ts_cmd_start; 13418c2ecf20Sopenharmony_ci if (segsum > seg3) 13428c2ecf20Sopenharmony_ci return; 13438c2ecf20Sopenharmony_ci seg3 -= segsum; 13448c2ecf20Sopenharmony_ci segsum += seg3; 13458c2ecf20Sopenharmony_ci 13468c2ecf20Sopenharmony_ci seg4 = lpfc_cmd->ts_data_io - lpfc_cmd->ts_cmd_start; 13478c2ecf20Sopenharmony_ci if (segsum > seg4) 13488c2ecf20Sopenharmony_ci return; 13498c2ecf20Sopenharmony_ci seg4 -= segsum; 13508c2ecf20Sopenharmony_ci 13518c2ecf20Sopenharmony_ci phba->ktime_data_samples++; 13528c2ecf20Sopenharmony_ci phba->ktime_seg1_total += seg1; 13538c2ecf20Sopenharmony_ci if (seg1 < phba->ktime_seg1_min) 13548c2ecf20Sopenharmony_ci phba->ktime_seg1_min = seg1; 13558c2ecf20Sopenharmony_ci else if (seg1 > phba->ktime_seg1_max) 13568c2ecf20Sopenharmony_ci phba->ktime_seg1_max = seg1; 13578c2ecf20Sopenharmony_ci phba->ktime_seg2_total += seg2; 13588c2ecf20Sopenharmony_ci if (seg2 < phba->ktime_seg2_min) 13598c2ecf20Sopenharmony_ci phba->ktime_seg2_min = seg2; 13608c2ecf20Sopenharmony_ci else if (seg2 > phba->ktime_seg2_max) 13618c2ecf20Sopenharmony_ci phba->ktime_seg2_max = seg2; 13628c2ecf20Sopenharmony_ci phba->ktime_seg3_total += seg3; 13638c2ecf20Sopenharmony_ci if (seg3 < phba->ktime_seg3_min) 13648c2ecf20Sopenharmony_ci phba->ktime_seg3_min = seg3; 13658c2ecf20Sopenharmony_ci else if (seg3 > phba->ktime_seg3_max) 13668c2ecf20Sopenharmony_ci phba->ktime_seg3_max = seg3; 13678c2ecf20Sopenharmony_ci phba->ktime_seg4_total += seg4; 13688c2ecf20Sopenharmony_ci if (seg4 < phba->ktime_seg4_min) 13698c2ecf20Sopenharmony_ci phba->ktime_seg4_min = seg4; 13708c2ecf20Sopenharmony_ci else if (seg4 > phba->ktime_seg4_max) 13718c2ecf20Sopenharmony_ci phba->ktime_seg4_max = seg4; 13728c2ecf20Sopenharmony_ci 13738c2ecf20Sopenharmony_ci lpfc_cmd->ts_last_cmd = 0; 13748c2ecf20Sopenharmony_ci lpfc_cmd->ts_cmd_start = 0; 13758c2ecf20Sopenharmony_ci lpfc_cmd->ts_cmd_wqput = 0; 13768c2ecf20Sopenharmony_ci lpfc_cmd->ts_isr_cmpl = 0; 13778c2ecf20Sopenharmony_ci lpfc_cmd->ts_data_io = 0; 13788c2ecf20Sopenharmony_ci} 13798c2ecf20Sopenharmony_ci 13808c2ecf20Sopenharmony_ci/** 13818c2ecf20Sopenharmony_ci * lpfc_debugfs_ioktime_data - Dump target node list to a buffer 13828c2ecf20Sopenharmony_ci * @vport: The vport to gather target node info from. 13838c2ecf20Sopenharmony_ci * @buf: The buffer to dump log into. 13848c2ecf20Sopenharmony_ci * @size: The maximum amount of data to process. 13858c2ecf20Sopenharmony_ci * 13868c2ecf20Sopenharmony_ci * Description: 13878c2ecf20Sopenharmony_ci * This routine dumps the NVME statistics associated with @vport 13888c2ecf20Sopenharmony_ci * 13898c2ecf20Sopenharmony_ci * Return Value: 13908c2ecf20Sopenharmony_ci * This routine returns the amount of bytes that were dumped into @buf and will 13918c2ecf20Sopenharmony_ci * not exceed @size. 13928c2ecf20Sopenharmony_ci **/ 13938c2ecf20Sopenharmony_cistatic int 13948c2ecf20Sopenharmony_cilpfc_debugfs_ioktime_data(struct lpfc_vport *vport, char *buf, int size) 13958c2ecf20Sopenharmony_ci{ 13968c2ecf20Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 13978c2ecf20Sopenharmony_ci int len = 0; 13988c2ecf20Sopenharmony_ci 13998c2ecf20Sopenharmony_ci if (phba->nvmet_support == 0) { 14008c2ecf20Sopenharmony_ci /* Initiator */ 14018c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, 14028c2ecf20Sopenharmony_ci "ktime %s: Total Samples: %lld\n", 14038c2ecf20Sopenharmony_ci (phba->ktime_on ? "Enabled" : "Disabled"), 14048c2ecf20Sopenharmony_ci phba->ktime_data_samples); 14058c2ecf20Sopenharmony_ci if (phba->ktime_data_samples == 0) 14068c2ecf20Sopenharmony_ci return len; 14078c2ecf20Sopenharmony_ci 14088c2ecf20Sopenharmony_ci len += scnprintf( 14098c2ecf20Sopenharmony_ci buf + len, PAGE_SIZE - len, 14108c2ecf20Sopenharmony_ci "Segment 1: Last Cmd cmpl " 14118c2ecf20Sopenharmony_ci "done -to- Start of next Cmd (in driver)\n"); 14128c2ecf20Sopenharmony_ci len += scnprintf( 14138c2ecf20Sopenharmony_ci buf + len, PAGE_SIZE - len, 14148c2ecf20Sopenharmony_ci "avg:%08lld min:%08lld max %08lld\n", 14158c2ecf20Sopenharmony_ci div_u64(phba->ktime_seg1_total, 14168c2ecf20Sopenharmony_ci phba->ktime_data_samples), 14178c2ecf20Sopenharmony_ci phba->ktime_seg1_min, 14188c2ecf20Sopenharmony_ci phba->ktime_seg1_max); 14198c2ecf20Sopenharmony_ci len += scnprintf( 14208c2ecf20Sopenharmony_ci buf + len, PAGE_SIZE - len, 14218c2ecf20Sopenharmony_ci "Segment 2: Driver start of Cmd " 14228c2ecf20Sopenharmony_ci "-to- Firmware WQ doorbell\n"); 14238c2ecf20Sopenharmony_ci len += scnprintf( 14248c2ecf20Sopenharmony_ci buf + len, PAGE_SIZE - len, 14258c2ecf20Sopenharmony_ci "avg:%08lld min:%08lld max %08lld\n", 14268c2ecf20Sopenharmony_ci div_u64(phba->ktime_seg2_total, 14278c2ecf20Sopenharmony_ci phba->ktime_data_samples), 14288c2ecf20Sopenharmony_ci phba->ktime_seg2_min, 14298c2ecf20Sopenharmony_ci phba->ktime_seg2_max); 14308c2ecf20Sopenharmony_ci len += scnprintf( 14318c2ecf20Sopenharmony_ci buf + len, PAGE_SIZE - len, 14328c2ecf20Sopenharmony_ci "Segment 3: Firmware WQ doorbell -to- " 14338c2ecf20Sopenharmony_ci "MSI-X ISR cmpl\n"); 14348c2ecf20Sopenharmony_ci len += scnprintf( 14358c2ecf20Sopenharmony_ci buf + len, PAGE_SIZE - len, 14368c2ecf20Sopenharmony_ci "avg:%08lld min:%08lld max %08lld\n", 14378c2ecf20Sopenharmony_ci div_u64(phba->ktime_seg3_total, 14388c2ecf20Sopenharmony_ci phba->ktime_data_samples), 14398c2ecf20Sopenharmony_ci phba->ktime_seg3_min, 14408c2ecf20Sopenharmony_ci phba->ktime_seg3_max); 14418c2ecf20Sopenharmony_ci len += scnprintf( 14428c2ecf20Sopenharmony_ci buf + len, PAGE_SIZE - len, 14438c2ecf20Sopenharmony_ci "Segment 4: MSI-X ISR cmpl -to- " 14448c2ecf20Sopenharmony_ci "Cmd cmpl done\n"); 14458c2ecf20Sopenharmony_ci len += scnprintf( 14468c2ecf20Sopenharmony_ci buf + len, PAGE_SIZE - len, 14478c2ecf20Sopenharmony_ci "avg:%08lld min:%08lld max %08lld\n", 14488c2ecf20Sopenharmony_ci div_u64(phba->ktime_seg4_total, 14498c2ecf20Sopenharmony_ci phba->ktime_data_samples), 14508c2ecf20Sopenharmony_ci phba->ktime_seg4_min, 14518c2ecf20Sopenharmony_ci phba->ktime_seg4_max); 14528c2ecf20Sopenharmony_ci len += scnprintf( 14538c2ecf20Sopenharmony_ci buf + len, PAGE_SIZE - len, 14548c2ecf20Sopenharmony_ci "Total IO avg time: %08lld\n", 14558c2ecf20Sopenharmony_ci div_u64(phba->ktime_seg1_total + 14568c2ecf20Sopenharmony_ci phba->ktime_seg2_total + 14578c2ecf20Sopenharmony_ci phba->ktime_seg3_total + 14588c2ecf20Sopenharmony_ci phba->ktime_seg4_total, 14598c2ecf20Sopenharmony_ci phba->ktime_data_samples)); 14608c2ecf20Sopenharmony_ci return len; 14618c2ecf20Sopenharmony_ci } 14628c2ecf20Sopenharmony_ci 14638c2ecf20Sopenharmony_ci /* NVME Target */ 14648c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, 14658c2ecf20Sopenharmony_ci "ktime %s: Total Samples: %lld %lld\n", 14668c2ecf20Sopenharmony_ci (phba->ktime_on ? "Enabled" : "Disabled"), 14678c2ecf20Sopenharmony_ci phba->ktime_data_samples, 14688c2ecf20Sopenharmony_ci phba->ktime_status_samples); 14698c2ecf20Sopenharmony_ci if (phba->ktime_data_samples == 0) 14708c2ecf20Sopenharmony_ci return len; 14718c2ecf20Sopenharmony_ci 14728c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, 14738c2ecf20Sopenharmony_ci "Segment 1: MSI-X ISR Rcv cmd -to- " 14748c2ecf20Sopenharmony_ci "cmd pass to NVME Layer\n"); 14758c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, 14768c2ecf20Sopenharmony_ci "avg:%08lld min:%08lld max %08lld\n", 14778c2ecf20Sopenharmony_ci div_u64(phba->ktime_seg1_total, 14788c2ecf20Sopenharmony_ci phba->ktime_data_samples), 14798c2ecf20Sopenharmony_ci phba->ktime_seg1_min, 14808c2ecf20Sopenharmony_ci phba->ktime_seg1_max); 14818c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, 14828c2ecf20Sopenharmony_ci "Segment 2: cmd pass to NVME Layer- " 14838c2ecf20Sopenharmony_ci "-to- Driver rcv cmd OP (action)\n"); 14848c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, 14858c2ecf20Sopenharmony_ci "avg:%08lld min:%08lld max %08lld\n", 14868c2ecf20Sopenharmony_ci div_u64(phba->ktime_seg2_total, 14878c2ecf20Sopenharmony_ci phba->ktime_data_samples), 14888c2ecf20Sopenharmony_ci phba->ktime_seg2_min, 14898c2ecf20Sopenharmony_ci phba->ktime_seg2_max); 14908c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, 14918c2ecf20Sopenharmony_ci "Segment 3: Driver rcv cmd OP -to- " 14928c2ecf20Sopenharmony_ci "Firmware WQ doorbell: cmd\n"); 14938c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, 14948c2ecf20Sopenharmony_ci "avg:%08lld min:%08lld max %08lld\n", 14958c2ecf20Sopenharmony_ci div_u64(phba->ktime_seg3_total, 14968c2ecf20Sopenharmony_ci phba->ktime_data_samples), 14978c2ecf20Sopenharmony_ci phba->ktime_seg3_min, 14988c2ecf20Sopenharmony_ci phba->ktime_seg3_max); 14998c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, 15008c2ecf20Sopenharmony_ci "Segment 4: Firmware WQ doorbell: cmd " 15018c2ecf20Sopenharmony_ci "-to- MSI-X ISR for cmd cmpl\n"); 15028c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, 15038c2ecf20Sopenharmony_ci "avg:%08lld min:%08lld max %08lld\n", 15048c2ecf20Sopenharmony_ci div_u64(phba->ktime_seg4_total, 15058c2ecf20Sopenharmony_ci phba->ktime_data_samples), 15068c2ecf20Sopenharmony_ci phba->ktime_seg4_min, 15078c2ecf20Sopenharmony_ci phba->ktime_seg4_max); 15088c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, 15098c2ecf20Sopenharmony_ci "Segment 5: MSI-X ISR for cmd cmpl " 15108c2ecf20Sopenharmony_ci "-to- NVME layer passed cmd done\n"); 15118c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, 15128c2ecf20Sopenharmony_ci "avg:%08lld min:%08lld max %08lld\n", 15138c2ecf20Sopenharmony_ci div_u64(phba->ktime_seg5_total, 15148c2ecf20Sopenharmony_ci phba->ktime_data_samples), 15158c2ecf20Sopenharmony_ci phba->ktime_seg5_min, 15168c2ecf20Sopenharmony_ci phba->ktime_seg5_max); 15178c2ecf20Sopenharmony_ci 15188c2ecf20Sopenharmony_ci if (phba->ktime_status_samples == 0) { 15198c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, 15208c2ecf20Sopenharmony_ci "Total: cmd received by MSI-X ISR " 15218c2ecf20Sopenharmony_ci "-to- cmd completed on wire\n"); 15228c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, 15238c2ecf20Sopenharmony_ci "avg:%08lld min:%08lld " 15248c2ecf20Sopenharmony_ci "max %08lld\n", 15258c2ecf20Sopenharmony_ci div_u64(phba->ktime_seg10_total, 15268c2ecf20Sopenharmony_ci phba->ktime_data_samples), 15278c2ecf20Sopenharmony_ci phba->ktime_seg10_min, 15288c2ecf20Sopenharmony_ci phba->ktime_seg10_max); 15298c2ecf20Sopenharmony_ci return len; 15308c2ecf20Sopenharmony_ci } 15318c2ecf20Sopenharmony_ci 15328c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, 15338c2ecf20Sopenharmony_ci "Segment 6: NVME layer passed cmd done " 15348c2ecf20Sopenharmony_ci "-to- Driver rcv rsp status OP\n"); 15358c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, 15368c2ecf20Sopenharmony_ci "avg:%08lld min:%08lld max %08lld\n", 15378c2ecf20Sopenharmony_ci div_u64(phba->ktime_seg6_total, 15388c2ecf20Sopenharmony_ci phba->ktime_status_samples), 15398c2ecf20Sopenharmony_ci phba->ktime_seg6_min, 15408c2ecf20Sopenharmony_ci phba->ktime_seg6_max); 15418c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, 15428c2ecf20Sopenharmony_ci "Segment 7: Driver rcv rsp status OP " 15438c2ecf20Sopenharmony_ci "-to- Firmware WQ doorbell: status\n"); 15448c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, 15458c2ecf20Sopenharmony_ci "avg:%08lld min:%08lld max %08lld\n", 15468c2ecf20Sopenharmony_ci div_u64(phba->ktime_seg7_total, 15478c2ecf20Sopenharmony_ci phba->ktime_status_samples), 15488c2ecf20Sopenharmony_ci phba->ktime_seg7_min, 15498c2ecf20Sopenharmony_ci phba->ktime_seg7_max); 15508c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, 15518c2ecf20Sopenharmony_ci "Segment 8: Firmware WQ doorbell: status" 15528c2ecf20Sopenharmony_ci " -to- MSI-X ISR for status cmpl\n"); 15538c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, 15548c2ecf20Sopenharmony_ci "avg:%08lld min:%08lld max %08lld\n", 15558c2ecf20Sopenharmony_ci div_u64(phba->ktime_seg8_total, 15568c2ecf20Sopenharmony_ci phba->ktime_status_samples), 15578c2ecf20Sopenharmony_ci phba->ktime_seg8_min, 15588c2ecf20Sopenharmony_ci phba->ktime_seg8_max); 15598c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, 15608c2ecf20Sopenharmony_ci "Segment 9: MSI-X ISR for status cmpl " 15618c2ecf20Sopenharmony_ci "-to- NVME layer passed status done\n"); 15628c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, 15638c2ecf20Sopenharmony_ci "avg:%08lld min:%08lld max %08lld\n", 15648c2ecf20Sopenharmony_ci div_u64(phba->ktime_seg9_total, 15658c2ecf20Sopenharmony_ci phba->ktime_status_samples), 15668c2ecf20Sopenharmony_ci phba->ktime_seg9_min, 15678c2ecf20Sopenharmony_ci phba->ktime_seg9_max); 15688c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, 15698c2ecf20Sopenharmony_ci "Total: cmd received by MSI-X ISR -to- " 15708c2ecf20Sopenharmony_ci "cmd completed on wire\n"); 15718c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, 15728c2ecf20Sopenharmony_ci "avg:%08lld min:%08lld max %08lld\n", 15738c2ecf20Sopenharmony_ci div_u64(phba->ktime_seg10_total, 15748c2ecf20Sopenharmony_ci phba->ktime_status_samples), 15758c2ecf20Sopenharmony_ci phba->ktime_seg10_min, 15768c2ecf20Sopenharmony_ci phba->ktime_seg10_max); 15778c2ecf20Sopenharmony_ci return len; 15788c2ecf20Sopenharmony_ci} 15798c2ecf20Sopenharmony_ci 15808c2ecf20Sopenharmony_ci/** 15818c2ecf20Sopenharmony_ci * lpfc_debugfs_nvmeio_trc_data - Dump NVME IO trace list to a buffer 15828c2ecf20Sopenharmony_ci * @phba: The phba to gather target node info from. 15838c2ecf20Sopenharmony_ci * @buf: The buffer to dump log into. 15848c2ecf20Sopenharmony_ci * @size: The maximum amount of data to process. 15858c2ecf20Sopenharmony_ci * 15868c2ecf20Sopenharmony_ci * Description: 15878c2ecf20Sopenharmony_ci * This routine dumps the NVME IO trace associated with @phba 15888c2ecf20Sopenharmony_ci * 15898c2ecf20Sopenharmony_ci * Return Value: 15908c2ecf20Sopenharmony_ci * This routine returns the amount of bytes that were dumped into @buf and will 15918c2ecf20Sopenharmony_ci * not exceed @size. 15928c2ecf20Sopenharmony_ci **/ 15938c2ecf20Sopenharmony_cistatic int 15948c2ecf20Sopenharmony_cilpfc_debugfs_nvmeio_trc_data(struct lpfc_hba *phba, char *buf, int size) 15958c2ecf20Sopenharmony_ci{ 15968c2ecf20Sopenharmony_ci struct lpfc_debugfs_nvmeio_trc *dtp; 15978c2ecf20Sopenharmony_ci int i, state, index, skip; 15988c2ecf20Sopenharmony_ci int len = 0; 15998c2ecf20Sopenharmony_ci 16008c2ecf20Sopenharmony_ci state = phba->nvmeio_trc_on; 16018c2ecf20Sopenharmony_ci 16028c2ecf20Sopenharmony_ci index = (atomic_read(&phba->nvmeio_trc_cnt) + 1) & 16038c2ecf20Sopenharmony_ci (phba->nvmeio_trc_size - 1); 16048c2ecf20Sopenharmony_ci skip = phba->nvmeio_trc_output_idx; 16058c2ecf20Sopenharmony_ci 16068c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 16078c2ecf20Sopenharmony_ci "%s IO Trace %s: next_idx %d skip %d size %d\n", 16088c2ecf20Sopenharmony_ci (phba->nvmet_support ? "NVME" : "NVMET"), 16098c2ecf20Sopenharmony_ci (state ? "Enabled" : "Disabled"), 16108c2ecf20Sopenharmony_ci index, skip, phba->nvmeio_trc_size); 16118c2ecf20Sopenharmony_ci 16128c2ecf20Sopenharmony_ci if (!phba->nvmeio_trc || state) 16138c2ecf20Sopenharmony_ci return len; 16148c2ecf20Sopenharmony_ci 16158c2ecf20Sopenharmony_ci /* trace MUST bhe off to continue */ 16168c2ecf20Sopenharmony_ci 16178c2ecf20Sopenharmony_ci for (i = index; i < phba->nvmeio_trc_size; i++) { 16188c2ecf20Sopenharmony_ci if (skip) { 16198c2ecf20Sopenharmony_ci skip--; 16208c2ecf20Sopenharmony_ci continue; 16218c2ecf20Sopenharmony_ci } 16228c2ecf20Sopenharmony_ci dtp = phba->nvmeio_trc + i; 16238c2ecf20Sopenharmony_ci phba->nvmeio_trc_output_idx++; 16248c2ecf20Sopenharmony_ci 16258c2ecf20Sopenharmony_ci if (!dtp->fmt) 16268c2ecf20Sopenharmony_ci continue; 16278c2ecf20Sopenharmony_ci 16288c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, dtp->fmt, 16298c2ecf20Sopenharmony_ci dtp->data1, dtp->data2, dtp->data3); 16308c2ecf20Sopenharmony_ci 16318c2ecf20Sopenharmony_ci if (phba->nvmeio_trc_output_idx >= phba->nvmeio_trc_size) { 16328c2ecf20Sopenharmony_ci phba->nvmeio_trc_output_idx = 0; 16338c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 16348c2ecf20Sopenharmony_ci "Trace Complete\n"); 16358c2ecf20Sopenharmony_ci goto out; 16368c2ecf20Sopenharmony_ci } 16378c2ecf20Sopenharmony_ci 16388c2ecf20Sopenharmony_ci if (len >= (size - LPFC_DEBUG_OUT_LINE_SZ)) { 16398c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 16408c2ecf20Sopenharmony_ci "Trace Continue (%d of %d)\n", 16418c2ecf20Sopenharmony_ci phba->nvmeio_trc_output_idx, 16428c2ecf20Sopenharmony_ci phba->nvmeio_trc_size); 16438c2ecf20Sopenharmony_ci goto out; 16448c2ecf20Sopenharmony_ci } 16458c2ecf20Sopenharmony_ci } 16468c2ecf20Sopenharmony_ci for (i = 0; i < index; i++) { 16478c2ecf20Sopenharmony_ci if (skip) { 16488c2ecf20Sopenharmony_ci skip--; 16498c2ecf20Sopenharmony_ci continue; 16508c2ecf20Sopenharmony_ci } 16518c2ecf20Sopenharmony_ci dtp = phba->nvmeio_trc + i; 16528c2ecf20Sopenharmony_ci phba->nvmeio_trc_output_idx++; 16538c2ecf20Sopenharmony_ci 16548c2ecf20Sopenharmony_ci if (!dtp->fmt) 16558c2ecf20Sopenharmony_ci continue; 16568c2ecf20Sopenharmony_ci 16578c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, dtp->fmt, 16588c2ecf20Sopenharmony_ci dtp->data1, dtp->data2, dtp->data3); 16598c2ecf20Sopenharmony_ci 16608c2ecf20Sopenharmony_ci if (phba->nvmeio_trc_output_idx >= phba->nvmeio_trc_size) { 16618c2ecf20Sopenharmony_ci phba->nvmeio_trc_output_idx = 0; 16628c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 16638c2ecf20Sopenharmony_ci "Trace Complete\n"); 16648c2ecf20Sopenharmony_ci goto out; 16658c2ecf20Sopenharmony_ci } 16668c2ecf20Sopenharmony_ci 16678c2ecf20Sopenharmony_ci if (len >= (size - LPFC_DEBUG_OUT_LINE_SZ)) { 16688c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 16698c2ecf20Sopenharmony_ci "Trace Continue (%d of %d)\n", 16708c2ecf20Sopenharmony_ci phba->nvmeio_trc_output_idx, 16718c2ecf20Sopenharmony_ci phba->nvmeio_trc_size); 16728c2ecf20Sopenharmony_ci goto out; 16738c2ecf20Sopenharmony_ci } 16748c2ecf20Sopenharmony_ci } 16758c2ecf20Sopenharmony_ci 16768c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 16778c2ecf20Sopenharmony_ci "Trace Done\n"); 16788c2ecf20Sopenharmony_ciout: 16798c2ecf20Sopenharmony_ci return len; 16808c2ecf20Sopenharmony_ci} 16818c2ecf20Sopenharmony_ci 16828c2ecf20Sopenharmony_ci/** 16838c2ecf20Sopenharmony_ci * lpfc_debugfs_hdwqstat_data - Dump I/O stats to a buffer 16848c2ecf20Sopenharmony_ci * @vport: The vport to gather target node info from. 16858c2ecf20Sopenharmony_ci * @buf: The buffer to dump log into. 16868c2ecf20Sopenharmony_ci * @size: The maximum amount of data to process. 16878c2ecf20Sopenharmony_ci * 16888c2ecf20Sopenharmony_ci * Description: 16898c2ecf20Sopenharmony_ci * This routine dumps the NVME + SCSI statistics associated with @vport 16908c2ecf20Sopenharmony_ci * 16918c2ecf20Sopenharmony_ci * Return Value: 16928c2ecf20Sopenharmony_ci * This routine returns the amount of bytes that were dumped into @buf and will 16938c2ecf20Sopenharmony_ci * not exceed @size. 16948c2ecf20Sopenharmony_ci **/ 16958c2ecf20Sopenharmony_cistatic int 16968c2ecf20Sopenharmony_cilpfc_debugfs_hdwqstat_data(struct lpfc_vport *vport, char *buf, int size) 16978c2ecf20Sopenharmony_ci{ 16988c2ecf20Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 16998c2ecf20Sopenharmony_ci struct lpfc_hdwq_stat *c_stat; 17008c2ecf20Sopenharmony_ci int i, j, len; 17018c2ecf20Sopenharmony_ci uint32_t tot_xmt; 17028c2ecf20Sopenharmony_ci uint32_t tot_rcv; 17038c2ecf20Sopenharmony_ci uint32_t tot_cmpl; 17048c2ecf20Sopenharmony_ci char tmp[LPFC_MAX_SCSI_INFO_TMP_LEN] = {0}; 17058c2ecf20Sopenharmony_ci 17068c2ecf20Sopenharmony_ci scnprintf(tmp, sizeof(tmp), "HDWQ Stats:\n\n"); 17078c2ecf20Sopenharmony_ci if (strlcat(buf, tmp, size) >= size) 17088c2ecf20Sopenharmony_ci goto buffer_done; 17098c2ecf20Sopenharmony_ci 17108c2ecf20Sopenharmony_ci scnprintf(tmp, sizeof(tmp), "(NVME Accounting: %s) ", 17118c2ecf20Sopenharmony_ci (phba->hdwqstat_on & 17128c2ecf20Sopenharmony_ci (LPFC_CHECK_NVME_IO | LPFC_CHECK_NVMET_IO) ? 17138c2ecf20Sopenharmony_ci "Enabled" : "Disabled")); 17148c2ecf20Sopenharmony_ci if (strlcat(buf, tmp, size) >= size) 17158c2ecf20Sopenharmony_ci goto buffer_done; 17168c2ecf20Sopenharmony_ci 17178c2ecf20Sopenharmony_ci scnprintf(tmp, sizeof(tmp), "(SCSI Accounting: %s) ", 17188c2ecf20Sopenharmony_ci (phba->hdwqstat_on & LPFC_CHECK_SCSI_IO ? 17198c2ecf20Sopenharmony_ci "Enabled" : "Disabled")); 17208c2ecf20Sopenharmony_ci if (strlcat(buf, tmp, size) >= size) 17218c2ecf20Sopenharmony_ci goto buffer_done; 17228c2ecf20Sopenharmony_ci 17238c2ecf20Sopenharmony_ci scnprintf(tmp, sizeof(tmp), "\n\n"); 17248c2ecf20Sopenharmony_ci if (strlcat(buf, tmp, size) >= size) 17258c2ecf20Sopenharmony_ci goto buffer_done; 17268c2ecf20Sopenharmony_ci 17278c2ecf20Sopenharmony_ci for (i = 0; i < phba->cfg_hdw_queue; i++) { 17288c2ecf20Sopenharmony_ci tot_rcv = 0; 17298c2ecf20Sopenharmony_ci tot_xmt = 0; 17308c2ecf20Sopenharmony_ci tot_cmpl = 0; 17318c2ecf20Sopenharmony_ci 17328c2ecf20Sopenharmony_ci for_each_present_cpu(j) { 17338c2ecf20Sopenharmony_ci c_stat = per_cpu_ptr(phba->sli4_hba.c_stat, j); 17348c2ecf20Sopenharmony_ci 17358c2ecf20Sopenharmony_ci /* Only display for this HDWQ */ 17368c2ecf20Sopenharmony_ci if (i != c_stat->hdwq_no) 17378c2ecf20Sopenharmony_ci continue; 17388c2ecf20Sopenharmony_ci 17398c2ecf20Sopenharmony_ci /* Only display non-zero counters */ 17408c2ecf20Sopenharmony_ci if (!c_stat->xmt_io && !c_stat->cmpl_io && 17418c2ecf20Sopenharmony_ci !c_stat->rcv_io) 17428c2ecf20Sopenharmony_ci continue; 17438c2ecf20Sopenharmony_ci 17448c2ecf20Sopenharmony_ci if (!tot_xmt && !tot_cmpl && !tot_rcv) { 17458c2ecf20Sopenharmony_ci /* Print HDWQ string only the first time */ 17468c2ecf20Sopenharmony_ci scnprintf(tmp, sizeof(tmp), "[HDWQ %d]:\t", i); 17478c2ecf20Sopenharmony_ci if (strlcat(buf, tmp, size) >= size) 17488c2ecf20Sopenharmony_ci goto buffer_done; 17498c2ecf20Sopenharmony_ci } 17508c2ecf20Sopenharmony_ci 17518c2ecf20Sopenharmony_ci tot_xmt += c_stat->xmt_io; 17528c2ecf20Sopenharmony_ci tot_cmpl += c_stat->cmpl_io; 17538c2ecf20Sopenharmony_ci if (phba->nvmet_support) 17548c2ecf20Sopenharmony_ci tot_rcv += c_stat->rcv_io; 17558c2ecf20Sopenharmony_ci 17568c2ecf20Sopenharmony_ci scnprintf(tmp, sizeof(tmp), "| [CPU %d]: ", j); 17578c2ecf20Sopenharmony_ci if (strlcat(buf, tmp, size) >= size) 17588c2ecf20Sopenharmony_ci goto buffer_done; 17598c2ecf20Sopenharmony_ci 17608c2ecf20Sopenharmony_ci if (phba->nvmet_support) { 17618c2ecf20Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 17628c2ecf20Sopenharmony_ci "XMT 0x%x CMPL 0x%x RCV 0x%x |", 17638c2ecf20Sopenharmony_ci c_stat->xmt_io, c_stat->cmpl_io, 17648c2ecf20Sopenharmony_ci c_stat->rcv_io); 17658c2ecf20Sopenharmony_ci if (strlcat(buf, tmp, size) >= size) 17668c2ecf20Sopenharmony_ci goto buffer_done; 17678c2ecf20Sopenharmony_ci } else { 17688c2ecf20Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 17698c2ecf20Sopenharmony_ci "XMT 0x%x CMPL 0x%x |", 17708c2ecf20Sopenharmony_ci c_stat->xmt_io, c_stat->cmpl_io); 17718c2ecf20Sopenharmony_ci if (strlcat(buf, tmp, size) >= size) 17728c2ecf20Sopenharmony_ci goto buffer_done; 17738c2ecf20Sopenharmony_ci } 17748c2ecf20Sopenharmony_ci } 17758c2ecf20Sopenharmony_ci 17768c2ecf20Sopenharmony_ci /* Check if nothing to display */ 17778c2ecf20Sopenharmony_ci if (!tot_xmt && !tot_cmpl && !tot_rcv) 17788c2ecf20Sopenharmony_ci continue; 17798c2ecf20Sopenharmony_ci 17808c2ecf20Sopenharmony_ci scnprintf(tmp, sizeof(tmp), "\t->\t[HDWQ Total: "); 17818c2ecf20Sopenharmony_ci if (strlcat(buf, tmp, size) >= size) 17828c2ecf20Sopenharmony_ci goto buffer_done; 17838c2ecf20Sopenharmony_ci 17848c2ecf20Sopenharmony_ci if (phba->nvmet_support) { 17858c2ecf20Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 17868c2ecf20Sopenharmony_ci "XMT 0x%x CMPL 0x%x RCV 0x%x]\n\n", 17878c2ecf20Sopenharmony_ci tot_xmt, tot_cmpl, tot_rcv); 17888c2ecf20Sopenharmony_ci if (strlcat(buf, tmp, size) >= size) 17898c2ecf20Sopenharmony_ci goto buffer_done; 17908c2ecf20Sopenharmony_ci } else { 17918c2ecf20Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 17928c2ecf20Sopenharmony_ci "XMT 0x%x CMPL 0x%x]\n\n", 17938c2ecf20Sopenharmony_ci tot_xmt, tot_cmpl); 17948c2ecf20Sopenharmony_ci if (strlcat(buf, tmp, size) >= size) 17958c2ecf20Sopenharmony_ci goto buffer_done; 17968c2ecf20Sopenharmony_ci } 17978c2ecf20Sopenharmony_ci } 17988c2ecf20Sopenharmony_ci 17998c2ecf20Sopenharmony_cibuffer_done: 18008c2ecf20Sopenharmony_ci len = strnlen(buf, size); 18018c2ecf20Sopenharmony_ci return len; 18028c2ecf20Sopenharmony_ci} 18038c2ecf20Sopenharmony_ci 18048c2ecf20Sopenharmony_ci#endif 18058c2ecf20Sopenharmony_ci 18068c2ecf20Sopenharmony_ci/** 18078c2ecf20Sopenharmony_ci * lpfc_debugfs_disc_trc - Store discovery trace log 18088c2ecf20Sopenharmony_ci * @vport: The vport to associate this trace string with for retrieval. 18098c2ecf20Sopenharmony_ci * @mask: Log entry classification. 18108c2ecf20Sopenharmony_ci * @fmt: Format string to be displayed when dumping the log. 18118c2ecf20Sopenharmony_ci * @data1: 1st data parameter to be applied to @fmt. 18128c2ecf20Sopenharmony_ci * @data2: 2nd data parameter to be applied to @fmt. 18138c2ecf20Sopenharmony_ci * @data3: 3rd data parameter to be applied to @fmt. 18148c2ecf20Sopenharmony_ci * 18158c2ecf20Sopenharmony_ci * Description: 18168c2ecf20Sopenharmony_ci * This routine is used by the driver code to add a debugfs log entry to the 18178c2ecf20Sopenharmony_ci * discovery trace buffer associated with @vport. Only entries with a @mask that 18188c2ecf20Sopenharmony_ci * match the current debugfs discovery mask will be saved. Entries that do not 18198c2ecf20Sopenharmony_ci * match will be thrown away. @fmt, @data1, @data2, and @data3 are used like 18208c2ecf20Sopenharmony_ci * printf when displaying the log. 18218c2ecf20Sopenharmony_ci **/ 18228c2ecf20Sopenharmony_ciinline void 18238c2ecf20Sopenharmony_cilpfc_debugfs_disc_trc(struct lpfc_vport *vport, int mask, char *fmt, 18248c2ecf20Sopenharmony_ci uint32_t data1, uint32_t data2, uint32_t data3) 18258c2ecf20Sopenharmony_ci{ 18268c2ecf20Sopenharmony_ci#ifdef CONFIG_SCSI_LPFC_DEBUG_FS 18278c2ecf20Sopenharmony_ci struct lpfc_debugfs_trc *dtp; 18288c2ecf20Sopenharmony_ci int index; 18298c2ecf20Sopenharmony_ci 18308c2ecf20Sopenharmony_ci if (!(lpfc_debugfs_mask_disc_trc & mask)) 18318c2ecf20Sopenharmony_ci return; 18328c2ecf20Sopenharmony_ci 18338c2ecf20Sopenharmony_ci if (!lpfc_debugfs_enable || !lpfc_debugfs_max_disc_trc || 18348c2ecf20Sopenharmony_ci !vport || !vport->disc_trc) 18358c2ecf20Sopenharmony_ci return; 18368c2ecf20Sopenharmony_ci 18378c2ecf20Sopenharmony_ci index = atomic_inc_return(&vport->disc_trc_cnt) & 18388c2ecf20Sopenharmony_ci (lpfc_debugfs_max_disc_trc - 1); 18398c2ecf20Sopenharmony_ci dtp = vport->disc_trc + index; 18408c2ecf20Sopenharmony_ci dtp->fmt = fmt; 18418c2ecf20Sopenharmony_ci dtp->data1 = data1; 18428c2ecf20Sopenharmony_ci dtp->data2 = data2; 18438c2ecf20Sopenharmony_ci dtp->data3 = data3; 18448c2ecf20Sopenharmony_ci dtp->seq_cnt = atomic_inc_return(&lpfc_debugfs_seq_trc_cnt); 18458c2ecf20Sopenharmony_ci dtp->jif = jiffies; 18468c2ecf20Sopenharmony_ci#endif 18478c2ecf20Sopenharmony_ci return; 18488c2ecf20Sopenharmony_ci} 18498c2ecf20Sopenharmony_ci 18508c2ecf20Sopenharmony_ci/** 18518c2ecf20Sopenharmony_ci * lpfc_debugfs_slow_ring_trc - Store slow ring trace log 18528c2ecf20Sopenharmony_ci * @phba: The phba to associate this trace string with for retrieval. 18538c2ecf20Sopenharmony_ci * @fmt: Format string to be displayed when dumping the log. 18548c2ecf20Sopenharmony_ci * @data1: 1st data parameter to be applied to @fmt. 18558c2ecf20Sopenharmony_ci * @data2: 2nd data parameter to be applied to @fmt. 18568c2ecf20Sopenharmony_ci * @data3: 3rd data parameter to be applied to @fmt. 18578c2ecf20Sopenharmony_ci * 18588c2ecf20Sopenharmony_ci * Description: 18598c2ecf20Sopenharmony_ci * This routine is used by the driver code to add a debugfs log entry to the 18608c2ecf20Sopenharmony_ci * discovery trace buffer associated with @vport. @fmt, @data1, @data2, and 18618c2ecf20Sopenharmony_ci * @data3 are used like printf when displaying the log. 18628c2ecf20Sopenharmony_ci **/ 18638c2ecf20Sopenharmony_ciinline void 18648c2ecf20Sopenharmony_cilpfc_debugfs_slow_ring_trc(struct lpfc_hba *phba, char *fmt, 18658c2ecf20Sopenharmony_ci uint32_t data1, uint32_t data2, uint32_t data3) 18668c2ecf20Sopenharmony_ci{ 18678c2ecf20Sopenharmony_ci#ifdef CONFIG_SCSI_LPFC_DEBUG_FS 18688c2ecf20Sopenharmony_ci struct lpfc_debugfs_trc *dtp; 18698c2ecf20Sopenharmony_ci int index; 18708c2ecf20Sopenharmony_ci 18718c2ecf20Sopenharmony_ci if (!lpfc_debugfs_enable || !lpfc_debugfs_max_slow_ring_trc || 18728c2ecf20Sopenharmony_ci !phba || !phba->slow_ring_trc) 18738c2ecf20Sopenharmony_ci return; 18748c2ecf20Sopenharmony_ci 18758c2ecf20Sopenharmony_ci index = atomic_inc_return(&phba->slow_ring_trc_cnt) & 18768c2ecf20Sopenharmony_ci (lpfc_debugfs_max_slow_ring_trc - 1); 18778c2ecf20Sopenharmony_ci dtp = phba->slow_ring_trc + index; 18788c2ecf20Sopenharmony_ci dtp->fmt = fmt; 18798c2ecf20Sopenharmony_ci dtp->data1 = data1; 18808c2ecf20Sopenharmony_ci dtp->data2 = data2; 18818c2ecf20Sopenharmony_ci dtp->data3 = data3; 18828c2ecf20Sopenharmony_ci dtp->seq_cnt = atomic_inc_return(&lpfc_debugfs_seq_trc_cnt); 18838c2ecf20Sopenharmony_ci dtp->jif = jiffies; 18848c2ecf20Sopenharmony_ci#endif 18858c2ecf20Sopenharmony_ci return; 18868c2ecf20Sopenharmony_ci} 18878c2ecf20Sopenharmony_ci 18888c2ecf20Sopenharmony_ci/** 18898c2ecf20Sopenharmony_ci * lpfc_debugfs_nvme_trc - Store NVME/NVMET trace log 18908c2ecf20Sopenharmony_ci * @phba: The phba to associate this trace string with for retrieval. 18918c2ecf20Sopenharmony_ci * @fmt: Format string to be displayed when dumping the log. 18928c2ecf20Sopenharmony_ci * @data1: 1st data parameter to be applied to @fmt. 18938c2ecf20Sopenharmony_ci * @data2: 2nd data parameter to be applied to @fmt. 18948c2ecf20Sopenharmony_ci * @data3: 3rd data parameter to be applied to @fmt. 18958c2ecf20Sopenharmony_ci * 18968c2ecf20Sopenharmony_ci * Description: 18978c2ecf20Sopenharmony_ci * This routine is used by the driver code to add a debugfs log entry to the 18988c2ecf20Sopenharmony_ci * nvme trace buffer associated with @phba. @fmt, @data1, @data2, and 18998c2ecf20Sopenharmony_ci * @data3 are used like printf when displaying the log. 19008c2ecf20Sopenharmony_ci **/ 19018c2ecf20Sopenharmony_ciinline void 19028c2ecf20Sopenharmony_cilpfc_debugfs_nvme_trc(struct lpfc_hba *phba, char *fmt, 19038c2ecf20Sopenharmony_ci uint16_t data1, uint16_t data2, uint32_t data3) 19048c2ecf20Sopenharmony_ci{ 19058c2ecf20Sopenharmony_ci#ifdef CONFIG_SCSI_LPFC_DEBUG_FS 19068c2ecf20Sopenharmony_ci struct lpfc_debugfs_nvmeio_trc *dtp; 19078c2ecf20Sopenharmony_ci int index; 19088c2ecf20Sopenharmony_ci 19098c2ecf20Sopenharmony_ci if (!phba->nvmeio_trc_on || !phba->nvmeio_trc) 19108c2ecf20Sopenharmony_ci return; 19118c2ecf20Sopenharmony_ci 19128c2ecf20Sopenharmony_ci index = atomic_inc_return(&phba->nvmeio_trc_cnt) & 19138c2ecf20Sopenharmony_ci (phba->nvmeio_trc_size - 1); 19148c2ecf20Sopenharmony_ci dtp = phba->nvmeio_trc + index; 19158c2ecf20Sopenharmony_ci dtp->fmt = fmt; 19168c2ecf20Sopenharmony_ci dtp->data1 = data1; 19178c2ecf20Sopenharmony_ci dtp->data2 = data2; 19188c2ecf20Sopenharmony_ci dtp->data3 = data3; 19198c2ecf20Sopenharmony_ci#endif 19208c2ecf20Sopenharmony_ci} 19218c2ecf20Sopenharmony_ci 19228c2ecf20Sopenharmony_ci#ifdef CONFIG_SCSI_LPFC_DEBUG_FS 19238c2ecf20Sopenharmony_ci/** 19248c2ecf20Sopenharmony_ci * lpfc_debugfs_disc_trc_open - Open the discovery trace log 19258c2ecf20Sopenharmony_ci * @inode: The inode pointer that contains a vport pointer. 19268c2ecf20Sopenharmony_ci * @file: The file pointer to attach the log output. 19278c2ecf20Sopenharmony_ci * 19288c2ecf20Sopenharmony_ci * Description: 19298c2ecf20Sopenharmony_ci * This routine is the entry point for the debugfs open file operation. It gets 19308c2ecf20Sopenharmony_ci * the vport from the i_private field in @inode, allocates the necessary buffer 19318c2ecf20Sopenharmony_ci * for the log, fills the buffer from the in-memory log for this vport, and then 19328c2ecf20Sopenharmony_ci * returns a pointer to that log in the private_data field in @file. 19338c2ecf20Sopenharmony_ci * 19348c2ecf20Sopenharmony_ci * Returns: 19358c2ecf20Sopenharmony_ci * This function returns zero if successful. On error it will return a negative 19368c2ecf20Sopenharmony_ci * error value. 19378c2ecf20Sopenharmony_ci **/ 19388c2ecf20Sopenharmony_cistatic int 19398c2ecf20Sopenharmony_cilpfc_debugfs_disc_trc_open(struct inode *inode, struct file *file) 19408c2ecf20Sopenharmony_ci{ 19418c2ecf20Sopenharmony_ci struct lpfc_vport *vport = inode->i_private; 19428c2ecf20Sopenharmony_ci struct lpfc_debug *debug; 19438c2ecf20Sopenharmony_ci int size; 19448c2ecf20Sopenharmony_ci int rc = -ENOMEM; 19458c2ecf20Sopenharmony_ci 19468c2ecf20Sopenharmony_ci if (!lpfc_debugfs_max_disc_trc) { 19478c2ecf20Sopenharmony_ci rc = -ENOSPC; 19488c2ecf20Sopenharmony_ci goto out; 19498c2ecf20Sopenharmony_ci } 19508c2ecf20Sopenharmony_ci 19518c2ecf20Sopenharmony_ci debug = kmalloc(sizeof(*debug), GFP_KERNEL); 19528c2ecf20Sopenharmony_ci if (!debug) 19538c2ecf20Sopenharmony_ci goto out; 19548c2ecf20Sopenharmony_ci 19558c2ecf20Sopenharmony_ci /* Round to page boundary */ 19568c2ecf20Sopenharmony_ci size = (lpfc_debugfs_max_disc_trc * LPFC_DEBUG_TRC_ENTRY_SIZE); 19578c2ecf20Sopenharmony_ci size = PAGE_ALIGN(size); 19588c2ecf20Sopenharmony_ci 19598c2ecf20Sopenharmony_ci debug->buffer = kmalloc(size, GFP_KERNEL); 19608c2ecf20Sopenharmony_ci if (!debug->buffer) { 19618c2ecf20Sopenharmony_ci kfree(debug); 19628c2ecf20Sopenharmony_ci goto out; 19638c2ecf20Sopenharmony_ci } 19648c2ecf20Sopenharmony_ci 19658c2ecf20Sopenharmony_ci debug->len = lpfc_debugfs_disc_trc_data(vport, debug->buffer, size); 19668c2ecf20Sopenharmony_ci file->private_data = debug; 19678c2ecf20Sopenharmony_ci 19688c2ecf20Sopenharmony_ci rc = 0; 19698c2ecf20Sopenharmony_ciout: 19708c2ecf20Sopenharmony_ci return rc; 19718c2ecf20Sopenharmony_ci} 19728c2ecf20Sopenharmony_ci 19738c2ecf20Sopenharmony_ci/** 19748c2ecf20Sopenharmony_ci * lpfc_debugfs_slow_ring_trc_open - Open the Slow Ring trace log 19758c2ecf20Sopenharmony_ci * @inode: The inode pointer that contains a vport pointer. 19768c2ecf20Sopenharmony_ci * @file: The file pointer to attach the log output. 19778c2ecf20Sopenharmony_ci * 19788c2ecf20Sopenharmony_ci * Description: 19798c2ecf20Sopenharmony_ci * This routine is the entry point for the debugfs open file operation. It gets 19808c2ecf20Sopenharmony_ci * the vport from the i_private field in @inode, allocates the necessary buffer 19818c2ecf20Sopenharmony_ci * for the log, fills the buffer from the in-memory log for this vport, and then 19828c2ecf20Sopenharmony_ci * returns a pointer to that log in the private_data field in @file. 19838c2ecf20Sopenharmony_ci * 19848c2ecf20Sopenharmony_ci * Returns: 19858c2ecf20Sopenharmony_ci * This function returns zero if successful. On error it will return a negative 19868c2ecf20Sopenharmony_ci * error value. 19878c2ecf20Sopenharmony_ci **/ 19888c2ecf20Sopenharmony_cistatic int 19898c2ecf20Sopenharmony_cilpfc_debugfs_slow_ring_trc_open(struct inode *inode, struct file *file) 19908c2ecf20Sopenharmony_ci{ 19918c2ecf20Sopenharmony_ci struct lpfc_hba *phba = inode->i_private; 19928c2ecf20Sopenharmony_ci struct lpfc_debug *debug; 19938c2ecf20Sopenharmony_ci int size; 19948c2ecf20Sopenharmony_ci int rc = -ENOMEM; 19958c2ecf20Sopenharmony_ci 19968c2ecf20Sopenharmony_ci if (!lpfc_debugfs_max_slow_ring_trc) { 19978c2ecf20Sopenharmony_ci rc = -ENOSPC; 19988c2ecf20Sopenharmony_ci goto out; 19998c2ecf20Sopenharmony_ci } 20008c2ecf20Sopenharmony_ci 20018c2ecf20Sopenharmony_ci debug = kmalloc(sizeof(*debug), GFP_KERNEL); 20028c2ecf20Sopenharmony_ci if (!debug) 20038c2ecf20Sopenharmony_ci goto out; 20048c2ecf20Sopenharmony_ci 20058c2ecf20Sopenharmony_ci /* Round to page boundary */ 20068c2ecf20Sopenharmony_ci size = (lpfc_debugfs_max_slow_ring_trc * LPFC_DEBUG_TRC_ENTRY_SIZE); 20078c2ecf20Sopenharmony_ci size = PAGE_ALIGN(size); 20088c2ecf20Sopenharmony_ci 20098c2ecf20Sopenharmony_ci debug->buffer = kmalloc(size, GFP_KERNEL); 20108c2ecf20Sopenharmony_ci if (!debug->buffer) { 20118c2ecf20Sopenharmony_ci kfree(debug); 20128c2ecf20Sopenharmony_ci goto out; 20138c2ecf20Sopenharmony_ci } 20148c2ecf20Sopenharmony_ci 20158c2ecf20Sopenharmony_ci debug->len = lpfc_debugfs_slow_ring_trc_data(phba, debug->buffer, size); 20168c2ecf20Sopenharmony_ci file->private_data = debug; 20178c2ecf20Sopenharmony_ci 20188c2ecf20Sopenharmony_ci rc = 0; 20198c2ecf20Sopenharmony_ciout: 20208c2ecf20Sopenharmony_ci return rc; 20218c2ecf20Sopenharmony_ci} 20228c2ecf20Sopenharmony_ci 20238c2ecf20Sopenharmony_ci/** 20248c2ecf20Sopenharmony_ci * lpfc_debugfs_hbqinfo_open - Open the hbqinfo debugfs buffer 20258c2ecf20Sopenharmony_ci * @inode: The inode pointer that contains a vport pointer. 20268c2ecf20Sopenharmony_ci * @file: The file pointer to attach the log output. 20278c2ecf20Sopenharmony_ci * 20288c2ecf20Sopenharmony_ci * Description: 20298c2ecf20Sopenharmony_ci * This routine is the entry point for the debugfs open file operation. It gets 20308c2ecf20Sopenharmony_ci * the vport from the i_private field in @inode, allocates the necessary buffer 20318c2ecf20Sopenharmony_ci * for the log, fills the buffer from the in-memory log for this vport, and then 20328c2ecf20Sopenharmony_ci * returns a pointer to that log in the private_data field in @file. 20338c2ecf20Sopenharmony_ci * 20348c2ecf20Sopenharmony_ci * Returns: 20358c2ecf20Sopenharmony_ci * This function returns zero if successful. On error it will return a negative 20368c2ecf20Sopenharmony_ci * error value. 20378c2ecf20Sopenharmony_ci **/ 20388c2ecf20Sopenharmony_cistatic int 20398c2ecf20Sopenharmony_cilpfc_debugfs_hbqinfo_open(struct inode *inode, struct file *file) 20408c2ecf20Sopenharmony_ci{ 20418c2ecf20Sopenharmony_ci struct lpfc_hba *phba = inode->i_private; 20428c2ecf20Sopenharmony_ci struct lpfc_debug *debug; 20438c2ecf20Sopenharmony_ci int rc = -ENOMEM; 20448c2ecf20Sopenharmony_ci 20458c2ecf20Sopenharmony_ci debug = kmalloc(sizeof(*debug), GFP_KERNEL); 20468c2ecf20Sopenharmony_ci if (!debug) 20478c2ecf20Sopenharmony_ci goto out; 20488c2ecf20Sopenharmony_ci 20498c2ecf20Sopenharmony_ci /* Round to page boundary */ 20508c2ecf20Sopenharmony_ci debug->buffer = kmalloc(LPFC_HBQINFO_SIZE, GFP_KERNEL); 20518c2ecf20Sopenharmony_ci if (!debug->buffer) { 20528c2ecf20Sopenharmony_ci kfree(debug); 20538c2ecf20Sopenharmony_ci goto out; 20548c2ecf20Sopenharmony_ci } 20558c2ecf20Sopenharmony_ci 20568c2ecf20Sopenharmony_ci debug->len = lpfc_debugfs_hbqinfo_data(phba, debug->buffer, 20578c2ecf20Sopenharmony_ci LPFC_HBQINFO_SIZE); 20588c2ecf20Sopenharmony_ci file->private_data = debug; 20598c2ecf20Sopenharmony_ci 20608c2ecf20Sopenharmony_ci rc = 0; 20618c2ecf20Sopenharmony_ciout: 20628c2ecf20Sopenharmony_ci return rc; 20638c2ecf20Sopenharmony_ci} 20648c2ecf20Sopenharmony_ci 20658c2ecf20Sopenharmony_ci/** 20668c2ecf20Sopenharmony_ci * lpfc_debugfs_multixripools_open - Open the multixripool debugfs buffer 20678c2ecf20Sopenharmony_ci * @inode: The inode pointer that contains a hba pointer. 20688c2ecf20Sopenharmony_ci * @file: The file pointer to attach the log output. 20698c2ecf20Sopenharmony_ci * 20708c2ecf20Sopenharmony_ci * Description: 20718c2ecf20Sopenharmony_ci * This routine is the entry point for the debugfs open file operation. It gets 20728c2ecf20Sopenharmony_ci * the hba from the i_private field in @inode, allocates the necessary buffer 20738c2ecf20Sopenharmony_ci * for the log, fills the buffer from the in-memory log for this hba, and then 20748c2ecf20Sopenharmony_ci * returns a pointer to that log in the private_data field in @file. 20758c2ecf20Sopenharmony_ci * 20768c2ecf20Sopenharmony_ci * Returns: 20778c2ecf20Sopenharmony_ci * This function returns zero if successful. On error it will return a negative 20788c2ecf20Sopenharmony_ci * error value. 20798c2ecf20Sopenharmony_ci **/ 20808c2ecf20Sopenharmony_cistatic int 20818c2ecf20Sopenharmony_cilpfc_debugfs_multixripools_open(struct inode *inode, struct file *file) 20828c2ecf20Sopenharmony_ci{ 20838c2ecf20Sopenharmony_ci struct lpfc_hba *phba = inode->i_private; 20848c2ecf20Sopenharmony_ci struct lpfc_debug *debug; 20858c2ecf20Sopenharmony_ci int rc = -ENOMEM; 20868c2ecf20Sopenharmony_ci 20878c2ecf20Sopenharmony_ci debug = kmalloc(sizeof(*debug), GFP_KERNEL); 20888c2ecf20Sopenharmony_ci if (!debug) 20898c2ecf20Sopenharmony_ci goto out; 20908c2ecf20Sopenharmony_ci 20918c2ecf20Sopenharmony_ci /* Round to page boundary */ 20928c2ecf20Sopenharmony_ci debug->buffer = kzalloc(LPFC_DUMP_MULTIXRIPOOL_SIZE, GFP_KERNEL); 20938c2ecf20Sopenharmony_ci if (!debug->buffer) { 20948c2ecf20Sopenharmony_ci kfree(debug); 20958c2ecf20Sopenharmony_ci goto out; 20968c2ecf20Sopenharmony_ci } 20978c2ecf20Sopenharmony_ci 20988c2ecf20Sopenharmony_ci debug->len = lpfc_debugfs_multixripools_data( 20998c2ecf20Sopenharmony_ci phba, debug->buffer, LPFC_DUMP_MULTIXRIPOOL_SIZE); 21008c2ecf20Sopenharmony_ci 21018c2ecf20Sopenharmony_ci debug->i_private = inode->i_private; 21028c2ecf20Sopenharmony_ci file->private_data = debug; 21038c2ecf20Sopenharmony_ci 21048c2ecf20Sopenharmony_ci rc = 0; 21058c2ecf20Sopenharmony_ciout: 21068c2ecf20Sopenharmony_ci return rc; 21078c2ecf20Sopenharmony_ci} 21088c2ecf20Sopenharmony_ci 21098c2ecf20Sopenharmony_ci#ifdef LPFC_HDWQ_LOCK_STAT 21108c2ecf20Sopenharmony_ci/** 21118c2ecf20Sopenharmony_ci * lpfc_debugfs_lockstat_open - Open the lockstat debugfs buffer 21128c2ecf20Sopenharmony_ci * @inode: The inode pointer that contains a vport pointer. 21138c2ecf20Sopenharmony_ci * @file: The file pointer to attach the log output. 21148c2ecf20Sopenharmony_ci * 21158c2ecf20Sopenharmony_ci * Description: 21168c2ecf20Sopenharmony_ci * This routine is the entry point for the debugfs open file operation. It gets 21178c2ecf20Sopenharmony_ci * the vport from the i_private field in @inode, allocates the necessary buffer 21188c2ecf20Sopenharmony_ci * for the log, fills the buffer from the in-memory log for this vport, and then 21198c2ecf20Sopenharmony_ci * returns a pointer to that log in the private_data field in @file. 21208c2ecf20Sopenharmony_ci * 21218c2ecf20Sopenharmony_ci * Returns: 21228c2ecf20Sopenharmony_ci * This function returns zero if successful. On error it will return a negative 21238c2ecf20Sopenharmony_ci * error value. 21248c2ecf20Sopenharmony_ci **/ 21258c2ecf20Sopenharmony_cistatic int 21268c2ecf20Sopenharmony_cilpfc_debugfs_lockstat_open(struct inode *inode, struct file *file) 21278c2ecf20Sopenharmony_ci{ 21288c2ecf20Sopenharmony_ci struct lpfc_hba *phba = inode->i_private; 21298c2ecf20Sopenharmony_ci struct lpfc_debug *debug; 21308c2ecf20Sopenharmony_ci int rc = -ENOMEM; 21318c2ecf20Sopenharmony_ci 21328c2ecf20Sopenharmony_ci debug = kmalloc(sizeof(*debug), GFP_KERNEL); 21338c2ecf20Sopenharmony_ci if (!debug) 21348c2ecf20Sopenharmony_ci goto out; 21358c2ecf20Sopenharmony_ci 21368c2ecf20Sopenharmony_ci /* Round to page boundary */ 21378c2ecf20Sopenharmony_ci debug->buffer = kmalloc(LPFC_HDWQINFO_SIZE, GFP_KERNEL); 21388c2ecf20Sopenharmony_ci if (!debug->buffer) { 21398c2ecf20Sopenharmony_ci kfree(debug); 21408c2ecf20Sopenharmony_ci goto out; 21418c2ecf20Sopenharmony_ci } 21428c2ecf20Sopenharmony_ci 21438c2ecf20Sopenharmony_ci debug->len = lpfc_debugfs_lockstat_data(phba, debug->buffer, 21448c2ecf20Sopenharmony_ci LPFC_HBQINFO_SIZE); 21458c2ecf20Sopenharmony_ci file->private_data = debug; 21468c2ecf20Sopenharmony_ci 21478c2ecf20Sopenharmony_ci rc = 0; 21488c2ecf20Sopenharmony_ciout: 21498c2ecf20Sopenharmony_ci return rc; 21508c2ecf20Sopenharmony_ci} 21518c2ecf20Sopenharmony_ci 21528c2ecf20Sopenharmony_cistatic ssize_t 21538c2ecf20Sopenharmony_cilpfc_debugfs_lockstat_write(struct file *file, const char __user *buf, 21548c2ecf20Sopenharmony_ci size_t nbytes, loff_t *ppos) 21558c2ecf20Sopenharmony_ci{ 21568c2ecf20Sopenharmony_ci struct lpfc_debug *debug = file->private_data; 21578c2ecf20Sopenharmony_ci struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private; 21588c2ecf20Sopenharmony_ci struct lpfc_sli4_hdw_queue *qp; 21598c2ecf20Sopenharmony_ci char mybuf[64]; 21608c2ecf20Sopenharmony_ci char *pbuf; 21618c2ecf20Sopenharmony_ci int i; 21628c2ecf20Sopenharmony_ci size_t bsize; 21638c2ecf20Sopenharmony_ci 21648c2ecf20Sopenharmony_ci memset(mybuf, 0, sizeof(mybuf)); 21658c2ecf20Sopenharmony_ci 21668c2ecf20Sopenharmony_ci bsize = min(nbytes, (sizeof(mybuf) - 1)); 21678c2ecf20Sopenharmony_ci 21688c2ecf20Sopenharmony_ci if (copy_from_user(mybuf, buf, bsize)) 21698c2ecf20Sopenharmony_ci return -EFAULT; 21708c2ecf20Sopenharmony_ci pbuf = &mybuf[0]; 21718c2ecf20Sopenharmony_ci 21728c2ecf20Sopenharmony_ci if ((strncmp(pbuf, "reset", strlen("reset")) == 0) || 21738c2ecf20Sopenharmony_ci (strncmp(pbuf, "zero", strlen("zero")) == 0)) { 21748c2ecf20Sopenharmony_ci for (i = 0; i < phba->cfg_hdw_queue; i++) { 21758c2ecf20Sopenharmony_ci qp = &phba->sli4_hba.hdwq[i]; 21768c2ecf20Sopenharmony_ci qp->lock_conflict.alloc_xri_get = 0; 21778c2ecf20Sopenharmony_ci qp->lock_conflict.alloc_xri_put = 0; 21788c2ecf20Sopenharmony_ci qp->lock_conflict.free_xri = 0; 21798c2ecf20Sopenharmony_ci qp->lock_conflict.wq_access = 0; 21808c2ecf20Sopenharmony_ci qp->lock_conflict.alloc_pvt_pool = 0; 21818c2ecf20Sopenharmony_ci qp->lock_conflict.mv_from_pvt_pool = 0; 21828c2ecf20Sopenharmony_ci qp->lock_conflict.mv_to_pub_pool = 0; 21838c2ecf20Sopenharmony_ci qp->lock_conflict.mv_to_pvt_pool = 0; 21848c2ecf20Sopenharmony_ci qp->lock_conflict.free_pvt_pool = 0; 21858c2ecf20Sopenharmony_ci qp->lock_conflict.free_pub_pool = 0; 21868c2ecf20Sopenharmony_ci qp->lock_conflict.wq_access = 0; 21878c2ecf20Sopenharmony_ci } 21888c2ecf20Sopenharmony_ci } 21898c2ecf20Sopenharmony_ci return bsize; 21908c2ecf20Sopenharmony_ci} 21918c2ecf20Sopenharmony_ci#endif 21928c2ecf20Sopenharmony_ci 21938c2ecf20Sopenharmony_cistatic int lpfc_debugfs_ras_log_data(struct lpfc_hba *phba, 21948c2ecf20Sopenharmony_ci char *buffer, int size) 21958c2ecf20Sopenharmony_ci{ 21968c2ecf20Sopenharmony_ci int copied = 0; 21978c2ecf20Sopenharmony_ci struct lpfc_dmabuf *dmabuf, *next; 21988c2ecf20Sopenharmony_ci 21998c2ecf20Sopenharmony_ci memset(buffer, 0, size); 22008c2ecf20Sopenharmony_ci 22018c2ecf20Sopenharmony_ci spin_lock_irq(&phba->hbalock); 22028c2ecf20Sopenharmony_ci if (phba->ras_fwlog.state != ACTIVE) { 22038c2ecf20Sopenharmony_ci spin_unlock_irq(&phba->hbalock); 22048c2ecf20Sopenharmony_ci return -EINVAL; 22058c2ecf20Sopenharmony_ci } 22068c2ecf20Sopenharmony_ci spin_unlock_irq(&phba->hbalock); 22078c2ecf20Sopenharmony_ci 22088c2ecf20Sopenharmony_ci list_for_each_entry_safe(dmabuf, next, 22098c2ecf20Sopenharmony_ci &phba->ras_fwlog.fwlog_buff_list, list) { 22108c2ecf20Sopenharmony_ci /* Check if copying will go over size and a '\0' char */ 22118c2ecf20Sopenharmony_ci if ((copied + LPFC_RAS_MAX_ENTRY_SIZE) >= (size - 1)) { 22128c2ecf20Sopenharmony_ci memcpy(buffer + copied, dmabuf->virt, 22138c2ecf20Sopenharmony_ci size - copied - 1); 22148c2ecf20Sopenharmony_ci copied += size - copied - 1; 22158c2ecf20Sopenharmony_ci break; 22168c2ecf20Sopenharmony_ci } 22178c2ecf20Sopenharmony_ci memcpy(buffer + copied, dmabuf->virt, LPFC_RAS_MAX_ENTRY_SIZE); 22188c2ecf20Sopenharmony_ci copied += LPFC_RAS_MAX_ENTRY_SIZE; 22198c2ecf20Sopenharmony_ci } 22208c2ecf20Sopenharmony_ci return copied; 22218c2ecf20Sopenharmony_ci} 22228c2ecf20Sopenharmony_ci 22238c2ecf20Sopenharmony_cistatic int 22248c2ecf20Sopenharmony_cilpfc_debugfs_ras_log_release(struct inode *inode, struct file *file) 22258c2ecf20Sopenharmony_ci{ 22268c2ecf20Sopenharmony_ci struct lpfc_debug *debug = file->private_data; 22278c2ecf20Sopenharmony_ci 22288c2ecf20Sopenharmony_ci vfree(debug->buffer); 22298c2ecf20Sopenharmony_ci kfree(debug); 22308c2ecf20Sopenharmony_ci 22318c2ecf20Sopenharmony_ci return 0; 22328c2ecf20Sopenharmony_ci} 22338c2ecf20Sopenharmony_ci 22348c2ecf20Sopenharmony_ci/** 22358c2ecf20Sopenharmony_ci * lpfc_debugfs_ras_log_open - Open the RAS log debugfs buffer 22368c2ecf20Sopenharmony_ci * @inode: The inode pointer that contains a vport pointer. 22378c2ecf20Sopenharmony_ci * @file: The file pointer to attach the log output. 22388c2ecf20Sopenharmony_ci * 22398c2ecf20Sopenharmony_ci * Description: 22408c2ecf20Sopenharmony_ci * This routine is the entry point for the debugfs open file operation. It gets 22418c2ecf20Sopenharmony_ci * the vport from the i_private field in @inode, allocates the necessary buffer 22428c2ecf20Sopenharmony_ci * for the log, fills the buffer from the in-memory log for this vport, and then 22438c2ecf20Sopenharmony_ci * returns a pointer to that log in the private_data field in @file. 22448c2ecf20Sopenharmony_ci * 22458c2ecf20Sopenharmony_ci * Returns: 22468c2ecf20Sopenharmony_ci * This function returns zero if successful. On error it will return a negative 22478c2ecf20Sopenharmony_ci * error value. 22488c2ecf20Sopenharmony_ci **/ 22498c2ecf20Sopenharmony_cistatic int 22508c2ecf20Sopenharmony_cilpfc_debugfs_ras_log_open(struct inode *inode, struct file *file) 22518c2ecf20Sopenharmony_ci{ 22528c2ecf20Sopenharmony_ci struct lpfc_hba *phba = inode->i_private; 22538c2ecf20Sopenharmony_ci struct lpfc_debug *debug; 22548c2ecf20Sopenharmony_ci int size; 22558c2ecf20Sopenharmony_ci int rc = -ENOMEM; 22568c2ecf20Sopenharmony_ci 22578c2ecf20Sopenharmony_ci spin_lock_irq(&phba->hbalock); 22588c2ecf20Sopenharmony_ci if (phba->ras_fwlog.state != ACTIVE) { 22598c2ecf20Sopenharmony_ci spin_unlock_irq(&phba->hbalock); 22608c2ecf20Sopenharmony_ci rc = -EINVAL; 22618c2ecf20Sopenharmony_ci goto out; 22628c2ecf20Sopenharmony_ci } 22638c2ecf20Sopenharmony_ci spin_unlock_irq(&phba->hbalock); 22648c2ecf20Sopenharmony_ci debug = kmalloc(sizeof(*debug), GFP_KERNEL); 22658c2ecf20Sopenharmony_ci if (!debug) 22668c2ecf20Sopenharmony_ci goto out; 22678c2ecf20Sopenharmony_ci 22688c2ecf20Sopenharmony_ci size = LPFC_RAS_MIN_BUFF_POST_SIZE * phba->cfg_ras_fwlog_buffsize; 22698c2ecf20Sopenharmony_ci debug->buffer = vmalloc(size); 22708c2ecf20Sopenharmony_ci if (!debug->buffer) 22718c2ecf20Sopenharmony_ci goto free_debug; 22728c2ecf20Sopenharmony_ci 22738c2ecf20Sopenharmony_ci debug->len = lpfc_debugfs_ras_log_data(phba, debug->buffer, size); 22748c2ecf20Sopenharmony_ci if (debug->len < 0) { 22758c2ecf20Sopenharmony_ci rc = -EINVAL; 22768c2ecf20Sopenharmony_ci goto free_buffer; 22778c2ecf20Sopenharmony_ci } 22788c2ecf20Sopenharmony_ci file->private_data = debug; 22798c2ecf20Sopenharmony_ci 22808c2ecf20Sopenharmony_ci return 0; 22818c2ecf20Sopenharmony_ci 22828c2ecf20Sopenharmony_cifree_buffer: 22838c2ecf20Sopenharmony_ci vfree(debug->buffer); 22848c2ecf20Sopenharmony_cifree_debug: 22858c2ecf20Sopenharmony_ci kfree(debug); 22868c2ecf20Sopenharmony_ciout: 22878c2ecf20Sopenharmony_ci return rc; 22888c2ecf20Sopenharmony_ci} 22898c2ecf20Sopenharmony_ci 22908c2ecf20Sopenharmony_ci/** 22918c2ecf20Sopenharmony_ci * lpfc_debugfs_dumpHBASlim_open - Open the Dump HBA SLIM debugfs buffer 22928c2ecf20Sopenharmony_ci * @inode: The inode pointer that contains a vport pointer. 22938c2ecf20Sopenharmony_ci * @file: The file pointer to attach the log output. 22948c2ecf20Sopenharmony_ci * 22958c2ecf20Sopenharmony_ci * Description: 22968c2ecf20Sopenharmony_ci * This routine is the entry point for the debugfs open file operation. It gets 22978c2ecf20Sopenharmony_ci * the vport from the i_private field in @inode, allocates the necessary buffer 22988c2ecf20Sopenharmony_ci * for the log, fills the buffer from the in-memory log for this vport, and then 22998c2ecf20Sopenharmony_ci * returns a pointer to that log in the private_data field in @file. 23008c2ecf20Sopenharmony_ci * 23018c2ecf20Sopenharmony_ci * Returns: 23028c2ecf20Sopenharmony_ci * This function returns zero if successful. On error it will return a negative 23038c2ecf20Sopenharmony_ci * error value. 23048c2ecf20Sopenharmony_ci **/ 23058c2ecf20Sopenharmony_cistatic int 23068c2ecf20Sopenharmony_cilpfc_debugfs_dumpHBASlim_open(struct inode *inode, struct file *file) 23078c2ecf20Sopenharmony_ci{ 23088c2ecf20Sopenharmony_ci struct lpfc_hba *phba = inode->i_private; 23098c2ecf20Sopenharmony_ci struct lpfc_debug *debug; 23108c2ecf20Sopenharmony_ci int rc = -ENOMEM; 23118c2ecf20Sopenharmony_ci 23128c2ecf20Sopenharmony_ci debug = kmalloc(sizeof(*debug), GFP_KERNEL); 23138c2ecf20Sopenharmony_ci if (!debug) 23148c2ecf20Sopenharmony_ci goto out; 23158c2ecf20Sopenharmony_ci 23168c2ecf20Sopenharmony_ci /* Round to page boundary */ 23178c2ecf20Sopenharmony_ci debug->buffer = kmalloc(LPFC_DUMPHBASLIM_SIZE, GFP_KERNEL); 23188c2ecf20Sopenharmony_ci if (!debug->buffer) { 23198c2ecf20Sopenharmony_ci kfree(debug); 23208c2ecf20Sopenharmony_ci goto out; 23218c2ecf20Sopenharmony_ci } 23228c2ecf20Sopenharmony_ci 23238c2ecf20Sopenharmony_ci debug->len = lpfc_debugfs_dumpHBASlim_data(phba, debug->buffer, 23248c2ecf20Sopenharmony_ci LPFC_DUMPHBASLIM_SIZE); 23258c2ecf20Sopenharmony_ci file->private_data = debug; 23268c2ecf20Sopenharmony_ci 23278c2ecf20Sopenharmony_ci rc = 0; 23288c2ecf20Sopenharmony_ciout: 23298c2ecf20Sopenharmony_ci return rc; 23308c2ecf20Sopenharmony_ci} 23318c2ecf20Sopenharmony_ci 23328c2ecf20Sopenharmony_ci/** 23338c2ecf20Sopenharmony_ci * lpfc_debugfs_dumpHostSlim_open - Open the Dump Host SLIM debugfs buffer 23348c2ecf20Sopenharmony_ci * @inode: The inode pointer that contains a vport pointer. 23358c2ecf20Sopenharmony_ci * @file: The file pointer to attach the log output. 23368c2ecf20Sopenharmony_ci * 23378c2ecf20Sopenharmony_ci * Description: 23388c2ecf20Sopenharmony_ci * This routine is the entry point for the debugfs open file operation. It gets 23398c2ecf20Sopenharmony_ci * the vport from the i_private field in @inode, allocates the necessary buffer 23408c2ecf20Sopenharmony_ci * for the log, fills the buffer from the in-memory log for this vport, and then 23418c2ecf20Sopenharmony_ci * returns a pointer to that log in the private_data field in @file. 23428c2ecf20Sopenharmony_ci * 23438c2ecf20Sopenharmony_ci * Returns: 23448c2ecf20Sopenharmony_ci * This function returns zero if successful. On error it will return a negative 23458c2ecf20Sopenharmony_ci * error value. 23468c2ecf20Sopenharmony_ci **/ 23478c2ecf20Sopenharmony_cistatic int 23488c2ecf20Sopenharmony_cilpfc_debugfs_dumpHostSlim_open(struct inode *inode, struct file *file) 23498c2ecf20Sopenharmony_ci{ 23508c2ecf20Sopenharmony_ci struct lpfc_hba *phba = inode->i_private; 23518c2ecf20Sopenharmony_ci struct lpfc_debug *debug; 23528c2ecf20Sopenharmony_ci int rc = -ENOMEM; 23538c2ecf20Sopenharmony_ci 23548c2ecf20Sopenharmony_ci debug = kmalloc(sizeof(*debug), GFP_KERNEL); 23558c2ecf20Sopenharmony_ci if (!debug) 23568c2ecf20Sopenharmony_ci goto out; 23578c2ecf20Sopenharmony_ci 23588c2ecf20Sopenharmony_ci /* Round to page boundary */ 23598c2ecf20Sopenharmony_ci debug->buffer = kmalloc(LPFC_DUMPHOSTSLIM_SIZE, GFP_KERNEL); 23608c2ecf20Sopenharmony_ci if (!debug->buffer) { 23618c2ecf20Sopenharmony_ci kfree(debug); 23628c2ecf20Sopenharmony_ci goto out; 23638c2ecf20Sopenharmony_ci } 23648c2ecf20Sopenharmony_ci 23658c2ecf20Sopenharmony_ci debug->len = lpfc_debugfs_dumpHostSlim_data(phba, debug->buffer, 23668c2ecf20Sopenharmony_ci LPFC_DUMPHOSTSLIM_SIZE); 23678c2ecf20Sopenharmony_ci file->private_data = debug; 23688c2ecf20Sopenharmony_ci 23698c2ecf20Sopenharmony_ci rc = 0; 23708c2ecf20Sopenharmony_ciout: 23718c2ecf20Sopenharmony_ci return rc; 23728c2ecf20Sopenharmony_ci} 23738c2ecf20Sopenharmony_ci 23748c2ecf20Sopenharmony_cistatic ssize_t 23758c2ecf20Sopenharmony_cilpfc_debugfs_dif_err_read(struct file *file, char __user *buf, 23768c2ecf20Sopenharmony_ci size_t nbytes, loff_t *ppos) 23778c2ecf20Sopenharmony_ci{ 23788c2ecf20Sopenharmony_ci struct dentry *dent = file->f_path.dentry; 23798c2ecf20Sopenharmony_ci struct lpfc_hba *phba = file->private_data; 23808c2ecf20Sopenharmony_ci char cbuf[32]; 23818c2ecf20Sopenharmony_ci uint64_t tmp = 0; 23828c2ecf20Sopenharmony_ci int cnt = 0; 23838c2ecf20Sopenharmony_ci 23848c2ecf20Sopenharmony_ci if (dent == phba->debug_writeGuard) 23858c2ecf20Sopenharmony_ci cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_wgrd_cnt); 23868c2ecf20Sopenharmony_ci else if (dent == phba->debug_writeApp) 23878c2ecf20Sopenharmony_ci cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_wapp_cnt); 23888c2ecf20Sopenharmony_ci else if (dent == phba->debug_writeRef) 23898c2ecf20Sopenharmony_ci cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_wref_cnt); 23908c2ecf20Sopenharmony_ci else if (dent == phba->debug_readGuard) 23918c2ecf20Sopenharmony_ci cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_rgrd_cnt); 23928c2ecf20Sopenharmony_ci else if (dent == phba->debug_readApp) 23938c2ecf20Sopenharmony_ci cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_rapp_cnt); 23948c2ecf20Sopenharmony_ci else if (dent == phba->debug_readRef) 23958c2ecf20Sopenharmony_ci cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_rref_cnt); 23968c2ecf20Sopenharmony_ci else if (dent == phba->debug_InjErrNPortID) 23978c2ecf20Sopenharmony_ci cnt = scnprintf(cbuf, 32, "0x%06x\n", 23988c2ecf20Sopenharmony_ci phba->lpfc_injerr_nportid); 23998c2ecf20Sopenharmony_ci else if (dent == phba->debug_InjErrWWPN) { 24008c2ecf20Sopenharmony_ci memcpy(&tmp, &phba->lpfc_injerr_wwpn, sizeof(struct lpfc_name)); 24018c2ecf20Sopenharmony_ci tmp = cpu_to_be64(tmp); 24028c2ecf20Sopenharmony_ci cnt = scnprintf(cbuf, 32, "0x%016llx\n", tmp); 24038c2ecf20Sopenharmony_ci } else if (dent == phba->debug_InjErrLBA) { 24048c2ecf20Sopenharmony_ci if (phba->lpfc_injerr_lba == (sector_t)(-1)) 24058c2ecf20Sopenharmony_ci cnt = scnprintf(cbuf, 32, "off\n"); 24068c2ecf20Sopenharmony_ci else 24078c2ecf20Sopenharmony_ci cnt = scnprintf(cbuf, 32, "0x%llx\n", 24088c2ecf20Sopenharmony_ci (uint64_t) phba->lpfc_injerr_lba); 24098c2ecf20Sopenharmony_ci } else 24108c2ecf20Sopenharmony_ci lpfc_printf_log(phba, KERN_ERR, LOG_INIT, 24118c2ecf20Sopenharmony_ci "0547 Unknown debugfs error injection entry\n"); 24128c2ecf20Sopenharmony_ci 24138c2ecf20Sopenharmony_ci return simple_read_from_buffer(buf, nbytes, ppos, &cbuf, cnt); 24148c2ecf20Sopenharmony_ci} 24158c2ecf20Sopenharmony_ci 24168c2ecf20Sopenharmony_cistatic ssize_t 24178c2ecf20Sopenharmony_cilpfc_debugfs_dif_err_write(struct file *file, const char __user *buf, 24188c2ecf20Sopenharmony_ci size_t nbytes, loff_t *ppos) 24198c2ecf20Sopenharmony_ci{ 24208c2ecf20Sopenharmony_ci struct dentry *dent = file->f_path.dentry; 24218c2ecf20Sopenharmony_ci struct lpfc_hba *phba = file->private_data; 24228c2ecf20Sopenharmony_ci char dstbuf[33]; 24238c2ecf20Sopenharmony_ci uint64_t tmp = 0; 24248c2ecf20Sopenharmony_ci int size; 24258c2ecf20Sopenharmony_ci 24268c2ecf20Sopenharmony_ci memset(dstbuf, 0, 33); 24278c2ecf20Sopenharmony_ci size = (nbytes < 32) ? nbytes : 32; 24288c2ecf20Sopenharmony_ci if (copy_from_user(dstbuf, buf, size)) 24298c2ecf20Sopenharmony_ci return -EFAULT; 24308c2ecf20Sopenharmony_ci 24318c2ecf20Sopenharmony_ci if (dent == phba->debug_InjErrLBA) { 24328c2ecf20Sopenharmony_ci if ((dstbuf[0] == 'o') && (dstbuf[1] == 'f') && 24338c2ecf20Sopenharmony_ci (dstbuf[2] == 'f')) 24348c2ecf20Sopenharmony_ci tmp = (uint64_t)(-1); 24358c2ecf20Sopenharmony_ci } 24368c2ecf20Sopenharmony_ci 24378c2ecf20Sopenharmony_ci if ((tmp == 0) && (kstrtoull(dstbuf, 0, &tmp))) 24388c2ecf20Sopenharmony_ci return -EINVAL; 24398c2ecf20Sopenharmony_ci 24408c2ecf20Sopenharmony_ci if (dent == phba->debug_writeGuard) 24418c2ecf20Sopenharmony_ci phba->lpfc_injerr_wgrd_cnt = (uint32_t)tmp; 24428c2ecf20Sopenharmony_ci else if (dent == phba->debug_writeApp) 24438c2ecf20Sopenharmony_ci phba->lpfc_injerr_wapp_cnt = (uint32_t)tmp; 24448c2ecf20Sopenharmony_ci else if (dent == phba->debug_writeRef) 24458c2ecf20Sopenharmony_ci phba->lpfc_injerr_wref_cnt = (uint32_t)tmp; 24468c2ecf20Sopenharmony_ci else if (dent == phba->debug_readGuard) 24478c2ecf20Sopenharmony_ci phba->lpfc_injerr_rgrd_cnt = (uint32_t)tmp; 24488c2ecf20Sopenharmony_ci else if (dent == phba->debug_readApp) 24498c2ecf20Sopenharmony_ci phba->lpfc_injerr_rapp_cnt = (uint32_t)tmp; 24508c2ecf20Sopenharmony_ci else if (dent == phba->debug_readRef) 24518c2ecf20Sopenharmony_ci phba->lpfc_injerr_rref_cnt = (uint32_t)tmp; 24528c2ecf20Sopenharmony_ci else if (dent == phba->debug_InjErrLBA) 24538c2ecf20Sopenharmony_ci phba->lpfc_injerr_lba = (sector_t)tmp; 24548c2ecf20Sopenharmony_ci else if (dent == phba->debug_InjErrNPortID) 24558c2ecf20Sopenharmony_ci phba->lpfc_injerr_nportid = (uint32_t)(tmp & Mask_DID); 24568c2ecf20Sopenharmony_ci else if (dent == phba->debug_InjErrWWPN) { 24578c2ecf20Sopenharmony_ci tmp = cpu_to_be64(tmp); 24588c2ecf20Sopenharmony_ci memcpy(&phba->lpfc_injerr_wwpn, &tmp, sizeof(struct lpfc_name)); 24598c2ecf20Sopenharmony_ci } else 24608c2ecf20Sopenharmony_ci lpfc_printf_log(phba, KERN_ERR, LOG_INIT, 24618c2ecf20Sopenharmony_ci "0548 Unknown debugfs error injection entry\n"); 24628c2ecf20Sopenharmony_ci 24638c2ecf20Sopenharmony_ci return nbytes; 24648c2ecf20Sopenharmony_ci} 24658c2ecf20Sopenharmony_ci 24668c2ecf20Sopenharmony_cistatic int 24678c2ecf20Sopenharmony_cilpfc_debugfs_dif_err_release(struct inode *inode, struct file *file) 24688c2ecf20Sopenharmony_ci{ 24698c2ecf20Sopenharmony_ci return 0; 24708c2ecf20Sopenharmony_ci} 24718c2ecf20Sopenharmony_ci 24728c2ecf20Sopenharmony_ci/** 24738c2ecf20Sopenharmony_ci * lpfc_debugfs_nodelist_open - Open the nodelist debugfs file 24748c2ecf20Sopenharmony_ci * @inode: The inode pointer that contains a vport pointer. 24758c2ecf20Sopenharmony_ci * @file: The file pointer to attach the log output. 24768c2ecf20Sopenharmony_ci * 24778c2ecf20Sopenharmony_ci * Description: 24788c2ecf20Sopenharmony_ci * This routine is the entry point for the debugfs open file operation. It gets 24798c2ecf20Sopenharmony_ci * the vport from the i_private field in @inode, allocates the necessary buffer 24808c2ecf20Sopenharmony_ci * for the log, fills the buffer from the in-memory log for this vport, and then 24818c2ecf20Sopenharmony_ci * returns a pointer to that log in the private_data field in @file. 24828c2ecf20Sopenharmony_ci * 24838c2ecf20Sopenharmony_ci * Returns: 24848c2ecf20Sopenharmony_ci * This function returns zero if successful. On error it will return a negative 24858c2ecf20Sopenharmony_ci * error value. 24868c2ecf20Sopenharmony_ci **/ 24878c2ecf20Sopenharmony_cistatic int 24888c2ecf20Sopenharmony_cilpfc_debugfs_nodelist_open(struct inode *inode, struct file *file) 24898c2ecf20Sopenharmony_ci{ 24908c2ecf20Sopenharmony_ci struct lpfc_vport *vport = inode->i_private; 24918c2ecf20Sopenharmony_ci struct lpfc_debug *debug; 24928c2ecf20Sopenharmony_ci int rc = -ENOMEM; 24938c2ecf20Sopenharmony_ci 24948c2ecf20Sopenharmony_ci debug = kmalloc(sizeof(*debug), GFP_KERNEL); 24958c2ecf20Sopenharmony_ci if (!debug) 24968c2ecf20Sopenharmony_ci goto out; 24978c2ecf20Sopenharmony_ci 24988c2ecf20Sopenharmony_ci /* Round to page boundary */ 24998c2ecf20Sopenharmony_ci debug->buffer = kmalloc(LPFC_NODELIST_SIZE, GFP_KERNEL); 25008c2ecf20Sopenharmony_ci if (!debug->buffer) { 25018c2ecf20Sopenharmony_ci kfree(debug); 25028c2ecf20Sopenharmony_ci goto out; 25038c2ecf20Sopenharmony_ci } 25048c2ecf20Sopenharmony_ci 25058c2ecf20Sopenharmony_ci debug->len = lpfc_debugfs_nodelist_data(vport, debug->buffer, 25068c2ecf20Sopenharmony_ci LPFC_NODELIST_SIZE); 25078c2ecf20Sopenharmony_ci file->private_data = debug; 25088c2ecf20Sopenharmony_ci 25098c2ecf20Sopenharmony_ci rc = 0; 25108c2ecf20Sopenharmony_ciout: 25118c2ecf20Sopenharmony_ci return rc; 25128c2ecf20Sopenharmony_ci} 25138c2ecf20Sopenharmony_ci 25148c2ecf20Sopenharmony_ci/** 25158c2ecf20Sopenharmony_ci * lpfc_debugfs_lseek - Seek through a debugfs file 25168c2ecf20Sopenharmony_ci * @file: The file pointer to seek through. 25178c2ecf20Sopenharmony_ci * @off: The offset to seek to or the amount to seek by. 25188c2ecf20Sopenharmony_ci * @whence: Indicates how to seek. 25198c2ecf20Sopenharmony_ci * 25208c2ecf20Sopenharmony_ci * Description: 25218c2ecf20Sopenharmony_ci * This routine is the entry point for the debugfs lseek file operation. The 25228c2ecf20Sopenharmony_ci * @whence parameter indicates whether @off is the offset to directly seek to, 25238c2ecf20Sopenharmony_ci * or if it is a value to seek forward or reverse by. This function figures out 25248c2ecf20Sopenharmony_ci * what the new offset of the debugfs file will be and assigns that value to the 25258c2ecf20Sopenharmony_ci * f_pos field of @file. 25268c2ecf20Sopenharmony_ci * 25278c2ecf20Sopenharmony_ci * Returns: 25288c2ecf20Sopenharmony_ci * This function returns the new offset if successful and returns a negative 25298c2ecf20Sopenharmony_ci * error if unable to process the seek. 25308c2ecf20Sopenharmony_ci **/ 25318c2ecf20Sopenharmony_cistatic loff_t 25328c2ecf20Sopenharmony_cilpfc_debugfs_lseek(struct file *file, loff_t off, int whence) 25338c2ecf20Sopenharmony_ci{ 25348c2ecf20Sopenharmony_ci struct lpfc_debug *debug = file->private_data; 25358c2ecf20Sopenharmony_ci return fixed_size_llseek(file, off, whence, debug->len); 25368c2ecf20Sopenharmony_ci} 25378c2ecf20Sopenharmony_ci 25388c2ecf20Sopenharmony_ci/** 25398c2ecf20Sopenharmony_ci * lpfc_debugfs_read - Read a debugfs file 25408c2ecf20Sopenharmony_ci * @file: The file pointer to read from. 25418c2ecf20Sopenharmony_ci * @buf: The buffer to copy the data to. 25428c2ecf20Sopenharmony_ci * @nbytes: The number of bytes to read. 25438c2ecf20Sopenharmony_ci * @ppos: The position in the file to start reading from. 25448c2ecf20Sopenharmony_ci * 25458c2ecf20Sopenharmony_ci * Description: 25468c2ecf20Sopenharmony_ci * This routine reads data from from the buffer indicated in the private_data 25478c2ecf20Sopenharmony_ci * field of @file. It will start reading at @ppos and copy up to @nbytes of 25488c2ecf20Sopenharmony_ci * data to @buf. 25498c2ecf20Sopenharmony_ci * 25508c2ecf20Sopenharmony_ci * Returns: 25518c2ecf20Sopenharmony_ci * This function returns the amount of data that was read (this could be less 25528c2ecf20Sopenharmony_ci * than @nbytes if the end of the file was reached) or a negative error value. 25538c2ecf20Sopenharmony_ci **/ 25548c2ecf20Sopenharmony_cistatic ssize_t 25558c2ecf20Sopenharmony_cilpfc_debugfs_read(struct file *file, char __user *buf, 25568c2ecf20Sopenharmony_ci size_t nbytes, loff_t *ppos) 25578c2ecf20Sopenharmony_ci{ 25588c2ecf20Sopenharmony_ci struct lpfc_debug *debug = file->private_data; 25598c2ecf20Sopenharmony_ci 25608c2ecf20Sopenharmony_ci return simple_read_from_buffer(buf, nbytes, ppos, debug->buffer, 25618c2ecf20Sopenharmony_ci debug->len); 25628c2ecf20Sopenharmony_ci} 25638c2ecf20Sopenharmony_ci 25648c2ecf20Sopenharmony_ci/** 25658c2ecf20Sopenharmony_ci * lpfc_debugfs_release - Release the buffer used to store debugfs file data 25668c2ecf20Sopenharmony_ci * @inode: The inode pointer that contains a vport pointer. (unused) 25678c2ecf20Sopenharmony_ci * @file: The file pointer that contains the buffer to release. 25688c2ecf20Sopenharmony_ci * 25698c2ecf20Sopenharmony_ci * Description: 25708c2ecf20Sopenharmony_ci * This routine frees the buffer that was allocated when the debugfs file was 25718c2ecf20Sopenharmony_ci * opened. 25728c2ecf20Sopenharmony_ci * 25738c2ecf20Sopenharmony_ci * Returns: 25748c2ecf20Sopenharmony_ci * This function returns zero. 25758c2ecf20Sopenharmony_ci **/ 25768c2ecf20Sopenharmony_cistatic int 25778c2ecf20Sopenharmony_cilpfc_debugfs_release(struct inode *inode, struct file *file) 25788c2ecf20Sopenharmony_ci{ 25798c2ecf20Sopenharmony_ci struct lpfc_debug *debug = file->private_data; 25808c2ecf20Sopenharmony_ci 25818c2ecf20Sopenharmony_ci kfree(debug->buffer); 25828c2ecf20Sopenharmony_ci kfree(debug); 25838c2ecf20Sopenharmony_ci 25848c2ecf20Sopenharmony_ci return 0; 25858c2ecf20Sopenharmony_ci} 25868c2ecf20Sopenharmony_ci 25878c2ecf20Sopenharmony_ci/** 25888c2ecf20Sopenharmony_ci * lpfc_debugfs_multixripools_write - Clear multi-XRI pools statistics 25898c2ecf20Sopenharmony_ci * @file: The file pointer to read from. 25908c2ecf20Sopenharmony_ci * @buf: The buffer to copy the user data from. 25918c2ecf20Sopenharmony_ci * @nbytes: The number of bytes to get. 25928c2ecf20Sopenharmony_ci * @ppos: The position in the file to start reading from. 25938c2ecf20Sopenharmony_ci * 25948c2ecf20Sopenharmony_ci * Description: 25958c2ecf20Sopenharmony_ci * This routine clears multi-XRI pools statistics when buf contains "clear". 25968c2ecf20Sopenharmony_ci * 25978c2ecf20Sopenharmony_ci * Return Value: 25988c2ecf20Sopenharmony_ci * It returns the @nbytges passing in from debugfs user space when successful. 25998c2ecf20Sopenharmony_ci * In case of error conditions, it returns proper error code back to the user 26008c2ecf20Sopenharmony_ci * space. 26018c2ecf20Sopenharmony_ci **/ 26028c2ecf20Sopenharmony_cistatic ssize_t 26038c2ecf20Sopenharmony_cilpfc_debugfs_multixripools_write(struct file *file, const char __user *buf, 26048c2ecf20Sopenharmony_ci size_t nbytes, loff_t *ppos) 26058c2ecf20Sopenharmony_ci{ 26068c2ecf20Sopenharmony_ci struct lpfc_debug *debug = file->private_data; 26078c2ecf20Sopenharmony_ci struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private; 26088c2ecf20Sopenharmony_ci char mybuf[64]; 26098c2ecf20Sopenharmony_ci char *pbuf; 26108c2ecf20Sopenharmony_ci u32 i; 26118c2ecf20Sopenharmony_ci u32 hwq_count; 26128c2ecf20Sopenharmony_ci struct lpfc_sli4_hdw_queue *qp; 26138c2ecf20Sopenharmony_ci struct lpfc_multixri_pool *multixri_pool; 26148c2ecf20Sopenharmony_ci 26158c2ecf20Sopenharmony_ci if (nbytes > sizeof(mybuf) - 1) 26168c2ecf20Sopenharmony_ci nbytes = sizeof(mybuf) - 1; 26178c2ecf20Sopenharmony_ci 26188c2ecf20Sopenharmony_ci memset(mybuf, 0, sizeof(mybuf)); 26198c2ecf20Sopenharmony_ci 26208c2ecf20Sopenharmony_ci if (copy_from_user(mybuf, buf, nbytes)) 26218c2ecf20Sopenharmony_ci return -EFAULT; 26228c2ecf20Sopenharmony_ci pbuf = &mybuf[0]; 26238c2ecf20Sopenharmony_ci 26248c2ecf20Sopenharmony_ci if ((strncmp(pbuf, "clear", strlen("clear"))) == 0) { 26258c2ecf20Sopenharmony_ci hwq_count = phba->cfg_hdw_queue; 26268c2ecf20Sopenharmony_ci for (i = 0; i < hwq_count; i++) { 26278c2ecf20Sopenharmony_ci qp = &phba->sli4_hba.hdwq[i]; 26288c2ecf20Sopenharmony_ci multixri_pool = qp->p_multixri_pool; 26298c2ecf20Sopenharmony_ci if (!multixri_pool) 26308c2ecf20Sopenharmony_ci continue; 26318c2ecf20Sopenharmony_ci 26328c2ecf20Sopenharmony_ci qp->empty_io_bufs = 0; 26338c2ecf20Sopenharmony_ci multixri_pool->pbl_empty_count = 0; 26348c2ecf20Sopenharmony_ci#ifdef LPFC_MXP_STAT 26358c2ecf20Sopenharmony_ci multixri_pool->above_limit_count = 0; 26368c2ecf20Sopenharmony_ci multixri_pool->below_limit_count = 0; 26378c2ecf20Sopenharmony_ci multixri_pool->stat_max_hwm = 0; 26388c2ecf20Sopenharmony_ci multixri_pool->local_pbl_hit_count = 0; 26398c2ecf20Sopenharmony_ci multixri_pool->other_pbl_hit_count = 0; 26408c2ecf20Sopenharmony_ci 26418c2ecf20Sopenharmony_ci multixri_pool->stat_pbl_count = 0; 26428c2ecf20Sopenharmony_ci multixri_pool->stat_pvt_count = 0; 26438c2ecf20Sopenharmony_ci multixri_pool->stat_busy_count = 0; 26448c2ecf20Sopenharmony_ci multixri_pool->stat_snapshot_taken = 0; 26458c2ecf20Sopenharmony_ci#endif 26468c2ecf20Sopenharmony_ci } 26478c2ecf20Sopenharmony_ci return strlen(pbuf); 26488c2ecf20Sopenharmony_ci } 26498c2ecf20Sopenharmony_ci 26508c2ecf20Sopenharmony_ci return -EINVAL; 26518c2ecf20Sopenharmony_ci} 26528c2ecf20Sopenharmony_ci 26538c2ecf20Sopenharmony_cistatic int 26548c2ecf20Sopenharmony_cilpfc_debugfs_nvmestat_open(struct inode *inode, struct file *file) 26558c2ecf20Sopenharmony_ci{ 26568c2ecf20Sopenharmony_ci struct lpfc_vport *vport = inode->i_private; 26578c2ecf20Sopenharmony_ci struct lpfc_debug *debug; 26588c2ecf20Sopenharmony_ci int rc = -ENOMEM; 26598c2ecf20Sopenharmony_ci 26608c2ecf20Sopenharmony_ci debug = kmalloc(sizeof(*debug), GFP_KERNEL); 26618c2ecf20Sopenharmony_ci if (!debug) 26628c2ecf20Sopenharmony_ci goto out; 26638c2ecf20Sopenharmony_ci 26648c2ecf20Sopenharmony_ci /* Round to page boundary */ 26658c2ecf20Sopenharmony_ci debug->buffer = kmalloc(LPFC_NVMESTAT_SIZE, GFP_KERNEL); 26668c2ecf20Sopenharmony_ci if (!debug->buffer) { 26678c2ecf20Sopenharmony_ci kfree(debug); 26688c2ecf20Sopenharmony_ci goto out; 26698c2ecf20Sopenharmony_ci } 26708c2ecf20Sopenharmony_ci 26718c2ecf20Sopenharmony_ci debug->len = lpfc_debugfs_nvmestat_data(vport, debug->buffer, 26728c2ecf20Sopenharmony_ci LPFC_NVMESTAT_SIZE); 26738c2ecf20Sopenharmony_ci 26748c2ecf20Sopenharmony_ci debug->i_private = inode->i_private; 26758c2ecf20Sopenharmony_ci file->private_data = debug; 26768c2ecf20Sopenharmony_ci 26778c2ecf20Sopenharmony_ci rc = 0; 26788c2ecf20Sopenharmony_ciout: 26798c2ecf20Sopenharmony_ci return rc; 26808c2ecf20Sopenharmony_ci} 26818c2ecf20Sopenharmony_ci 26828c2ecf20Sopenharmony_cistatic ssize_t 26838c2ecf20Sopenharmony_cilpfc_debugfs_nvmestat_write(struct file *file, const char __user *buf, 26848c2ecf20Sopenharmony_ci size_t nbytes, loff_t *ppos) 26858c2ecf20Sopenharmony_ci{ 26868c2ecf20Sopenharmony_ci struct lpfc_debug *debug = file->private_data; 26878c2ecf20Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *)debug->i_private; 26888c2ecf20Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 26898c2ecf20Sopenharmony_ci struct lpfc_nvmet_tgtport *tgtp; 26908c2ecf20Sopenharmony_ci char mybuf[64]; 26918c2ecf20Sopenharmony_ci char *pbuf; 26928c2ecf20Sopenharmony_ci 26938c2ecf20Sopenharmony_ci if (!phba->targetport) 26948c2ecf20Sopenharmony_ci return -ENXIO; 26958c2ecf20Sopenharmony_ci 26968c2ecf20Sopenharmony_ci if (nbytes > sizeof(mybuf) - 1) 26978c2ecf20Sopenharmony_ci nbytes = sizeof(mybuf) - 1; 26988c2ecf20Sopenharmony_ci 26998c2ecf20Sopenharmony_ci memset(mybuf, 0, sizeof(mybuf)); 27008c2ecf20Sopenharmony_ci 27018c2ecf20Sopenharmony_ci if (copy_from_user(mybuf, buf, nbytes)) 27028c2ecf20Sopenharmony_ci return -EFAULT; 27038c2ecf20Sopenharmony_ci pbuf = &mybuf[0]; 27048c2ecf20Sopenharmony_ci 27058c2ecf20Sopenharmony_ci tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private; 27068c2ecf20Sopenharmony_ci if ((strncmp(pbuf, "reset", strlen("reset")) == 0) || 27078c2ecf20Sopenharmony_ci (strncmp(pbuf, "zero", strlen("zero")) == 0)) { 27088c2ecf20Sopenharmony_ci atomic_set(&tgtp->rcv_ls_req_in, 0); 27098c2ecf20Sopenharmony_ci atomic_set(&tgtp->rcv_ls_req_out, 0); 27108c2ecf20Sopenharmony_ci atomic_set(&tgtp->rcv_ls_req_drop, 0); 27118c2ecf20Sopenharmony_ci atomic_set(&tgtp->xmt_ls_abort, 0); 27128c2ecf20Sopenharmony_ci atomic_set(&tgtp->xmt_ls_abort_cmpl, 0); 27138c2ecf20Sopenharmony_ci atomic_set(&tgtp->xmt_ls_rsp, 0); 27148c2ecf20Sopenharmony_ci atomic_set(&tgtp->xmt_ls_drop, 0); 27158c2ecf20Sopenharmony_ci atomic_set(&tgtp->xmt_ls_rsp_error, 0); 27168c2ecf20Sopenharmony_ci atomic_set(&tgtp->xmt_ls_rsp_cmpl, 0); 27178c2ecf20Sopenharmony_ci 27188c2ecf20Sopenharmony_ci atomic_set(&tgtp->rcv_fcp_cmd_in, 0); 27198c2ecf20Sopenharmony_ci atomic_set(&tgtp->rcv_fcp_cmd_out, 0); 27208c2ecf20Sopenharmony_ci atomic_set(&tgtp->rcv_fcp_cmd_drop, 0); 27218c2ecf20Sopenharmony_ci atomic_set(&tgtp->xmt_fcp_drop, 0); 27228c2ecf20Sopenharmony_ci atomic_set(&tgtp->xmt_fcp_read_rsp, 0); 27238c2ecf20Sopenharmony_ci atomic_set(&tgtp->xmt_fcp_read, 0); 27248c2ecf20Sopenharmony_ci atomic_set(&tgtp->xmt_fcp_write, 0); 27258c2ecf20Sopenharmony_ci atomic_set(&tgtp->xmt_fcp_rsp, 0); 27268c2ecf20Sopenharmony_ci atomic_set(&tgtp->xmt_fcp_release, 0); 27278c2ecf20Sopenharmony_ci atomic_set(&tgtp->xmt_fcp_rsp_cmpl, 0); 27288c2ecf20Sopenharmony_ci atomic_set(&tgtp->xmt_fcp_rsp_error, 0); 27298c2ecf20Sopenharmony_ci atomic_set(&tgtp->xmt_fcp_rsp_drop, 0); 27308c2ecf20Sopenharmony_ci 27318c2ecf20Sopenharmony_ci atomic_set(&tgtp->xmt_fcp_abort, 0); 27328c2ecf20Sopenharmony_ci atomic_set(&tgtp->xmt_fcp_abort_cmpl, 0); 27338c2ecf20Sopenharmony_ci atomic_set(&tgtp->xmt_abort_sol, 0); 27348c2ecf20Sopenharmony_ci atomic_set(&tgtp->xmt_abort_unsol, 0); 27358c2ecf20Sopenharmony_ci atomic_set(&tgtp->xmt_abort_rsp, 0); 27368c2ecf20Sopenharmony_ci atomic_set(&tgtp->xmt_abort_rsp_error, 0); 27378c2ecf20Sopenharmony_ci } 27388c2ecf20Sopenharmony_ci return nbytes; 27398c2ecf20Sopenharmony_ci} 27408c2ecf20Sopenharmony_ci 27418c2ecf20Sopenharmony_cistatic int 27428c2ecf20Sopenharmony_cilpfc_debugfs_scsistat_open(struct inode *inode, struct file *file) 27438c2ecf20Sopenharmony_ci{ 27448c2ecf20Sopenharmony_ci struct lpfc_vport *vport = inode->i_private; 27458c2ecf20Sopenharmony_ci struct lpfc_debug *debug; 27468c2ecf20Sopenharmony_ci int rc = -ENOMEM; 27478c2ecf20Sopenharmony_ci 27488c2ecf20Sopenharmony_ci debug = kmalloc(sizeof(*debug), GFP_KERNEL); 27498c2ecf20Sopenharmony_ci if (!debug) 27508c2ecf20Sopenharmony_ci goto out; 27518c2ecf20Sopenharmony_ci 27528c2ecf20Sopenharmony_ci /* Round to page boundary */ 27538c2ecf20Sopenharmony_ci debug->buffer = kzalloc(LPFC_SCSISTAT_SIZE, GFP_KERNEL); 27548c2ecf20Sopenharmony_ci if (!debug->buffer) { 27558c2ecf20Sopenharmony_ci kfree(debug); 27568c2ecf20Sopenharmony_ci goto out; 27578c2ecf20Sopenharmony_ci } 27588c2ecf20Sopenharmony_ci 27598c2ecf20Sopenharmony_ci debug->len = lpfc_debugfs_scsistat_data(vport, debug->buffer, 27608c2ecf20Sopenharmony_ci LPFC_SCSISTAT_SIZE); 27618c2ecf20Sopenharmony_ci 27628c2ecf20Sopenharmony_ci debug->i_private = inode->i_private; 27638c2ecf20Sopenharmony_ci file->private_data = debug; 27648c2ecf20Sopenharmony_ci 27658c2ecf20Sopenharmony_ci rc = 0; 27668c2ecf20Sopenharmony_ciout: 27678c2ecf20Sopenharmony_ci return rc; 27688c2ecf20Sopenharmony_ci} 27698c2ecf20Sopenharmony_ci 27708c2ecf20Sopenharmony_cistatic ssize_t 27718c2ecf20Sopenharmony_cilpfc_debugfs_scsistat_write(struct file *file, const char __user *buf, 27728c2ecf20Sopenharmony_ci size_t nbytes, loff_t *ppos) 27738c2ecf20Sopenharmony_ci{ 27748c2ecf20Sopenharmony_ci struct lpfc_debug *debug = file->private_data; 27758c2ecf20Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *)debug->i_private; 27768c2ecf20Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 27778c2ecf20Sopenharmony_ci char mybuf[6] = {0}; 27788c2ecf20Sopenharmony_ci int i; 27798c2ecf20Sopenharmony_ci 27808c2ecf20Sopenharmony_ci if (copy_from_user(mybuf, buf, (nbytes >= sizeof(mybuf)) ? 27818c2ecf20Sopenharmony_ci (sizeof(mybuf) - 1) : nbytes)) 27828c2ecf20Sopenharmony_ci return -EFAULT; 27838c2ecf20Sopenharmony_ci 27848c2ecf20Sopenharmony_ci if ((strncmp(&mybuf[0], "reset", strlen("reset")) == 0) || 27858c2ecf20Sopenharmony_ci (strncmp(&mybuf[0], "zero", strlen("zero")) == 0)) { 27868c2ecf20Sopenharmony_ci for (i = 0; i < phba->cfg_hdw_queue; i++) { 27878c2ecf20Sopenharmony_ci memset(&phba->sli4_hba.hdwq[i].scsi_cstat, 0, 27888c2ecf20Sopenharmony_ci sizeof(phba->sli4_hba.hdwq[i].scsi_cstat)); 27898c2ecf20Sopenharmony_ci } 27908c2ecf20Sopenharmony_ci } 27918c2ecf20Sopenharmony_ci 27928c2ecf20Sopenharmony_ci return nbytes; 27938c2ecf20Sopenharmony_ci} 27948c2ecf20Sopenharmony_ci 27958c2ecf20Sopenharmony_cistatic int 27968c2ecf20Sopenharmony_cilpfc_debugfs_ioktime_open(struct inode *inode, struct file *file) 27978c2ecf20Sopenharmony_ci{ 27988c2ecf20Sopenharmony_ci struct lpfc_vport *vport = inode->i_private; 27998c2ecf20Sopenharmony_ci struct lpfc_debug *debug; 28008c2ecf20Sopenharmony_ci int rc = -ENOMEM; 28018c2ecf20Sopenharmony_ci 28028c2ecf20Sopenharmony_ci debug = kmalloc(sizeof(*debug), GFP_KERNEL); 28038c2ecf20Sopenharmony_ci if (!debug) 28048c2ecf20Sopenharmony_ci goto out; 28058c2ecf20Sopenharmony_ci 28068c2ecf20Sopenharmony_ci /* Round to page boundary */ 28078c2ecf20Sopenharmony_ci debug->buffer = kmalloc(LPFC_IOKTIME_SIZE, GFP_KERNEL); 28088c2ecf20Sopenharmony_ci if (!debug->buffer) { 28098c2ecf20Sopenharmony_ci kfree(debug); 28108c2ecf20Sopenharmony_ci goto out; 28118c2ecf20Sopenharmony_ci } 28128c2ecf20Sopenharmony_ci 28138c2ecf20Sopenharmony_ci debug->len = lpfc_debugfs_ioktime_data(vport, debug->buffer, 28148c2ecf20Sopenharmony_ci LPFC_IOKTIME_SIZE); 28158c2ecf20Sopenharmony_ci 28168c2ecf20Sopenharmony_ci debug->i_private = inode->i_private; 28178c2ecf20Sopenharmony_ci file->private_data = debug; 28188c2ecf20Sopenharmony_ci 28198c2ecf20Sopenharmony_ci rc = 0; 28208c2ecf20Sopenharmony_ciout: 28218c2ecf20Sopenharmony_ci return rc; 28228c2ecf20Sopenharmony_ci} 28238c2ecf20Sopenharmony_ci 28248c2ecf20Sopenharmony_cistatic ssize_t 28258c2ecf20Sopenharmony_cilpfc_debugfs_ioktime_write(struct file *file, const char __user *buf, 28268c2ecf20Sopenharmony_ci size_t nbytes, loff_t *ppos) 28278c2ecf20Sopenharmony_ci{ 28288c2ecf20Sopenharmony_ci struct lpfc_debug *debug = file->private_data; 28298c2ecf20Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *)debug->i_private; 28308c2ecf20Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 28318c2ecf20Sopenharmony_ci char mybuf[64]; 28328c2ecf20Sopenharmony_ci char *pbuf; 28338c2ecf20Sopenharmony_ci 28348c2ecf20Sopenharmony_ci if (nbytes > sizeof(mybuf) - 1) 28358c2ecf20Sopenharmony_ci nbytes = sizeof(mybuf) - 1; 28368c2ecf20Sopenharmony_ci 28378c2ecf20Sopenharmony_ci memset(mybuf, 0, sizeof(mybuf)); 28388c2ecf20Sopenharmony_ci 28398c2ecf20Sopenharmony_ci if (copy_from_user(mybuf, buf, nbytes)) 28408c2ecf20Sopenharmony_ci return -EFAULT; 28418c2ecf20Sopenharmony_ci pbuf = &mybuf[0]; 28428c2ecf20Sopenharmony_ci 28438c2ecf20Sopenharmony_ci if ((strncmp(pbuf, "on", sizeof("on") - 1) == 0)) { 28448c2ecf20Sopenharmony_ci phba->ktime_data_samples = 0; 28458c2ecf20Sopenharmony_ci phba->ktime_status_samples = 0; 28468c2ecf20Sopenharmony_ci phba->ktime_seg1_total = 0; 28478c2ecf20Sopenharmony_ci phba->ktime_seg1_max = 0; 28488c2ecf20Sopenharmony_ci phba->ktime_seg1_min = 0xffffffff; 28498c2ecf20Sopenharmony_ci phba->ktime_seg2_total = 0; 28508c2ecf20Sopenharmony_ci phba->ktime_seg2_max = 0; 28518c2ecf20Sopenharmony_ci phba->ktime_seg2_min = 0xffffffff; 28528c2ecf20Sopenharmony_ci phba->ktime_seg3_total = 0; 28538c2ecf20Sopenharmony_ci phba->ktime_seg3_max = 0; 28548c2ecf20Sopenharmony_ci phba->ktime_seg3_min = 0xffffffff; 28558c2ecf20Sopenharmony_ci phba->ktime_seg4_total = 0; 28568c2ecf20Sopenharmony_ci phba->ktime_seg4_max = 0; 28578c2ecf20Sopenharmony_ci phba->ktime_seg4_min = 0xffffffff; 28588c2ecf20Sopenharmony_ci phba->ktime_seg5_total = 0; 28598c2ecf20Sopenharmony_ci phba->ktime_seg5_max = 0; 28608c2ecf20Sopenharmony_ci phba->ktime_seg5_min = 0xffffffff; 28618c2ecf20Sopenharmony_ci phba->ktime_seg6_total = 0; 28628c2ecf20Sopenharmony_ci phba->ktime_seg6_max = 0; 28638c2ecf20Sopenharmony_ci phba->ktime_seg6_min = 0xffffffff; 28648c2ecf20Sopenharmony_ci phba->ktime_seg7_total = 0; 28658c2ecf20Sopenharmony_ci phba->ktime_seg7_max = 0; 28668c2ecf20Sopenharmony_ci phba->ktime_seg7_min = 0xffffffff; 28678c2ecf20Sopenharmony_ci phba->ktime_seg8_total = 0; 28688c2ecf20Sopenharmony_ci phba->ktime_seg8_max = 0; 28698c2ecf20Sopenharmony_ci phba->ktime_seg8_min = 0xffffffff; 28708c2ecf20Sopenharmony_ci phba->ktime_seg9_total = 0; 28718c2ecf20Sopenharmony_ci phba->ktime_seg9_max = 0; 28728c2ecf20Sopenharmony_ci phba->ktime_seg9_min = 0xffffffff; 28738c2ecf20Sopenharmony_ci phba->ktime_seg10_total = 0; 28748c2ecf20Sopenharmony_ci phba->ktime_seg10_max = 0; 28758c2ecf20Sopenharmony_ci phba->ktime_seg10_min = 0xffffffff; 28768c2ecf20Sopenharmony_ci 28778c2ecf20Sopenharmony_ci phba->ktime_on = 1; 28788c2ecf20Sopenharmony_ci return strlen(pbuf); 28798c2ecf20Sopenharmony_ci } else if ((strncmp(pbuf, "off", 28808c2ecf20Sopenharmony_ci sizeof("off") - 1) == 0)) { 28818c2ecf20Sopenharmony_ci phba->ktime_on = 0; 28828c2ecf20Sopenharmony_ci return strlen(pbuf); 28838c2ecf20Sopenharmony_ci } else if ((strncmp(pbuf, "zero", 28848c2ecf20Sopenharmony_ci sizeof("zero") - 1) == 0)) { 28858c2ecf20Sopenharmony_ci phba->ktime_data_samples = 0; 28868c2ecf20Sopenharmony_ci phba->ktime_status_samples = 0; 28878c2ecf20Sopenharmony_ci phba->ktime_seg1_total = 0; 28888c2ecf20Sopenharmony_ci phba->ktime_seg1_max = 0; 28898c2ecf20Sopenharmony_ci phba->ktime_seg1_min = 0xffffffff; 28908c2ecf20Sopenharmony_ci phba->ktime_seg2_total = 0; 28918c2ecf20Sopenharmony_ci phba->ktime_seg2_max = 0; 28928c2ecf20Sopenharmony_ci phba->ktime_seg2_min = 0xffffffff; 28938c2ecf20Sopenharmony_ci phba->ktime_seg3_total = 0; 28948c2ecf20Sopenharmony_ci phba->ktime_seg3_max = 0; 28958c2ecf20Sopenharmony_ci phba->ktime_seg3_min = 0xffffffff; 28968c2ecf20Sopenharmony_ci phba->ktime_seg4_total = 0; 28978c2ecf20Sopenharmony_ci phba->ktime_seg4_max = 0; 28988c2ecf20Sopenharmony_ci phba->ktime_seg4_min = 0xffffffff; 28998c2ecf20Sopenharmony_ci phba->ktime_seg5_total = 0; 29008c2ecf20Sopenharmony_ci phba->ktime_seg5_max = 0; 29018c2ecf20Sopenharmony_ci phba->ktime_seg5_min = 0xffffffff; 29028c2ecf20Sopenharmony_ci phba->ktime_seg6_total = 0; 29038c2ecf20Sopenharmony_ci phba->ktime_seg6_max = 0; 29048c2ecf20Sopenharmony_ci phba->ktime_seg6_min = 0xffffffff; 29058c2ecf20Sopenharmony_ci phba->ktime_seg7_total = 0; 29068c2ecf20Sopenharmony_ci phba->ktime_seg7_max = 0; 29078c2ecf20Sopenharmony_ci phba->ktime_seg7_min = 0xffffffff; 29088c2ecf20Sopenharmony_ci phba->ktime_seg8_total = 0; 29098c2ecf20Sopenharmony_ci phba->ktime_seg8_max = 0; 29108c2ecf20Sopenharmony_ci phba->ktime_seg8_min = 0xffffffff; 29118c2ecf20Sopenharmony_ci phba->ktime_seg9_total = 0; 29128c2ecf20Sopenharmony_ci phba->ktime_seg9_max = 0; 29138c2ecf20Sopenharmony_ci phba->ktime_seg9_min = 0xffffffff; 29148c2ecf20Sopenharmony_ci phba->ktime_seg10_total = 0; 29158c2ecf20Sopenharmony_ci phba->ktime_seg10_max = 0; 29168c2ecf20Sopenharmony_ci phba->ktime_seg10_min = 0xffffffff; 29178c2ecf20Sopenharmony_ci return strlen(pbuf); 29188c2ecf20Sopenharmony_ci } 29198c2ecf20Sopenharmony_ci return -EINVAL; 29208c2ecf20Sopenharmony_ci} 29218c2ecf20Sopenharmony_ci 29228c2ecf20Sopenharmony_cistatic int 29238c2ecf20Sopenharmony_cilpfc_debugfs_nvmeio_trc_open(struct inode *inode, struct file *file) 29248c2ecf20Sopenharmony_ci{ 29258c2ecf20Sopenharmony_ci struct lpfc_hba *phba = inode->i_private; 29268c2ecf20Sopenharmony_ci struct lpfc_debug *debug; 29278c2ecf20Sopenharmony_ci int rc = -ENOMEM; 29288c2ecf20Sopenharmony_ci 29298c2ecf20Sopenharmony_ci debug = kmalloc(sizeof(*debug), GFP_KERNEL); 29308c2ecf20Sopenharmony_ci if (!debug) 29318c2ecf20Sopenharmony_ci goto out; 29328c2ecf20Sopenharmony_ci 29338c2ecf20Sopenharmony_ci /* Round to page boundary */ 29348c2ecf20Sopenharmony_ci debug->buffer = kmalloc(LPFC_NVMEIO_TRC_SIZE, GFP_KERNEL); 29358c2ecf20Sopenharmony_ci if (!debug->buffer) { 29368c2ecf20Sopenharmony_ci kfree(debug); 29378c2ecf20Sopenharmony_ci goto out; 29388c2ecf20Sopenharmony_ci } 29398c2ecf20Sopenharmony_ci 29408c2ecf20Sopenharmony_ci debug->len = lpfc_debugfs_nvmeio_trc_data(phba, debug->buffer, 29418c2ecf20Sopenharmony_ci LPFC_NVMEIO_TRC_SIZE); 29428c2ecf20Sopenharmony_ci 29438c2ecf20Sopenharmony_ci debug->i_private = inode->i_private; 29448c2ecf20Sopenharmony_ci file->private_data = debug; 29458c2ecf20Sopenharmony_ci 29468c2ecf20Sopenharmony_ci rc = 0; 29478c2ecf20Sopenharmony_ciout: 29488c2ecf20Sopenharmony_ci return rc; 29498c2ecf20Sopenharmony_ci} 29508c2ecf20Sopenharmony_ci 29518c2ecf20Sopenharmony_cistatic ssize_t 29528c2ecf20Sopenharmony_cilpfc_debugfs_nvmeio_trc_write(struct file *file, const char __user *buf, 29538c2ecf20Sopenharmony_ci size_t nbytes, loff_t *ppos) 29548c2ecf20Sopenharmony_ci{ 29558c2ecf20Sopenharmony_ci struct lpfc_debug *debug = file->private_data; 29568c2ecf20Sopenharmony_ci struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private; 29578c2ecf20Sopenharmony_ci int i; 29588c2ecf20Sopenharmony_ci unsigned long sz; 29598c2ecf20Sopenharmony_ci char mybuf[64]; 29608c2ecf20Sopenharmony_ci char *pbuf; 29618c2ecf20Sopenharmony_ci 29628c2ecf20Sopenharmony_ci if (nbytes > sizeof(mybuf) - 1) 29638c2ecf20Sopenharmony_ci nbytes = sizeof(mybuf) - 1; 29648c2ecf20Sopenharmony_ci 29658c2ecf20Sopenharmony_ci memset(mybuf, 0, sizeof(mybuf)); 29668c2ecf20Sopenharmony_ci 29678c2ecf20Sopenharmony_ci if (copy_from_user(mybuf, buf, nbytes)) 29688c2ecf20Sopenharmony_ci return -EFAULT; 29698c2ecf20Sopenharmony_ci pbuf = &mybuf[0]; 29708c2ecf20Sopenharmony_ci 29718c2ecf20Sopenharmony_ci if ((strncmp(pbuf, "off", sizeof("off") - 1) == 0)) { 29728c2ecf20Sopenharmony_ci lpfc_printf_log(phba, KERN_ERR, LOG_INIT, 29738c2ecf20Sopenharmony_ci "0570 nvmeio_trc_off\n"); 29748c2ecf20Sopenharmony_ci phba->nvmeio_trc_output_idx = 0; 29758c2ecf20Sopenharmony_ci phba->nvmeio_trc_on = 0; 29768c2ecf20Sopenharmony_ci return strlen(pbuf); 29778c2ecf20Sopenharmony_ci } else if ((strncmp(pbuf, "on", sizeof("on") - 1) == 0)) { 29788c2ecf20Sopenharmony_ci lpfc_printf_log(phba, KERN_ERR, LOG_INIT, 29798c2ecf20Sopenharmony_ci "0571 nvmeio_trc_on\n"); 29808c2ecf20Sopenharmony_ci phba->nvmeio_trc_output_idx = 0; 29818c2ecf20Sopenharmony_ci phba->nvmeio_trc_on = 1; 29828c2ecf20Sopenharmony_ci return strlen(pbuf); 29838c2ecf20Sopenharmony_ci } 29848c2ecf20Sopenharmony_ci 29858c2ecf20Sopenharmony_ci /* We must be off to allocate the trace buffer */ 29868c2ecf20Sopenharmony_ci if (phba->nvmeio_trc_on != 0) 29878c2ecf20Sopenharmony_ci return -EINVAL; 29888c2ecf20Sopenharmony_ci 29898c2ecf20Sopenharmony_ci /* If not on or off, the parameter is the trace buffer size */ 29908c2ecf20Sopenharmony_ci i = kstrtoul(pbuf, 0, &sz); 29918c2ecf20Sopenharmony_ci if (i) 29928c2ecf20Sopenharmony_ci return -EINVAL; 29938c2ecf20Sopenharmony_ci phba->nvmeio_trc_size = (uint32_t)sz; 29948c2ecf20Sopenharmony_ci 29958c2ecf20Sopenharmony_ci /* It must be a power of 2 - round down */ 29968c2ecf20Sopenharmony_ci i = 0; 29978c2ecf20Sopenharmony_ci while (sz > 1) { 29988c2ecf20Sopenharmony_ci sz = sz >> 1; 29998c2ecf20Sopenharmony_ci i++; 30008c2ecf20Sopenharmony_ci } 30018c2ecf20Sopenharmony_ci sz = (1 << i); 30028c2ecf20Sopenharmony_ci if (phba->nvmeio_trc_size != sz) 30038c2ecf20Sopenharmony_ci lpfc_printf_log(phba, KERN_ERR, LOG_INIT, 30048c2ecf20Sopenharmony_ci "0572 nvmeio_trc_size changed to %ld\n", 30058c2ecf20Sopenharmony_ci sz); 30068c2ecf20Sopenharmony_ci phba->nvmeio_trc_size = (uint32_t)sz; 30078c2ecf20Sopenharmony_ci 30088c2ecf20Sopenharmony_ci /* If one previously exists, free it */ 30098c2ecf20Sopenharmony_ci kfree(phba->nvmeio_trc); 30108c2ecf20Sopenharmony_ci 30118c2ecf20Sopenharmony_ci /* Allocate new trace buffer and initialize */ 30128c2ecf20Sopenharmony_ci phba->nvmeio_trc = kzalloc((sizeof(struct lpfc_debugfs_nvmeio_trc) * 30138c2ecf20Sopenharmony_ci sz), GFP_KERNEL); 30148c2ecf20Sopenharmony_ci if (!phba->nvmeio_trc) { 30158c2ecf20Sopenharmony_ci lpfc_printf_log(phba, KERN_ERR, LOG_INIT, 30168c2ecf20Sopenharmony_ci "0573 Cannot create debugfs " 30178c2ecf20Sopenharmony_ci "nvmeio_trc buffer\n"); 30188c2ecf20Sopenharmony_ci return -ENOMEM; 30198c2ecf20Sopenharmony_ci } 30208c2ecf20Sopenharmony_ci atomic_set(&phba->nvmeio_trc_cnt, 0); 30218c2ecf20Sopenharmony_ci phba->nvmeio_trc_on = 0; 30228c2ecf20Sopenharmony_ci phba->nvmeio_trc_output_idx = 0; 30238c2ecf20Sopenharmony_ci 30248c2ecf20Sopenharmony_ci return strlen(pbuf); 30258c2ecf20Sopenharmony_ci} 30268c2ecf20Sopenharmony_ci 30278c2ecf20Sopenharmony_cistatic int 30288c2ecf20Sopenharmony_cilpfc_debugfs_hdwqstat_open(struct inode *inode, struct file *file) 30298c2ecf20Sopenharmony_ci{ 30308c2ecf20Sopenharmony_ci struct lpfc_vport *vport = inode->i_private; 30318c2ecf20Sopenharmony_ci struct lpfc_debug *debug; 30328c2ecf20Sopenharmony_ci int rc = -ENOMEM; 30338c2ecf20Sopenharmony_ci 30348c2ecf20Sopenharmony_ci debug = kmalloc(sizeof(*debug), GFP_KERNEL); 30358c2ecf20Sopenharmony_ci if (!debug) 30368c2ecf20Sopenharmony_ci goto out; 30378c2ecf20Sopenharmony_ci 30388c2ecf20Sopenharmony_ci /* Round to page boundary */ 30398c2ecf20Sopenharmony_ci debug->buffer = kcalloc(1, LPFC_SCSISTAT_SIZE, GFP_KERNEL); 30408c2ecf20Sopenharmony_ci if (!debug->buffer) { 30418c2ecf20Sopenharmony_ci kfree(debug); 30428c2ecf20Sopenharmony_ci goto out; 30438c2ecf20Sopenharmony_ci } 30448c2ecf20Sopenharmony_ci 30458c2ecf20Sopenharmony_ci debug->len = lpfc_debugfs_hdwqstat_data(vport, debug->buffer, 30468c2ecf20Sopenharmony_ci LPFC_SCSISTAT_SIZE); 30478c2ecf20Sopenharmony_ci 30488c2ecf20Sopenharmony_ci debug->i_private = inode->i_private; 30498c2ecf20Sopenharmony_ci file->private_data = debug; 30508c2ecf20Sopenharmony_ci 30518c2ecf20Sopenharmony_ci rc = 0; 30528c2ecf20Sopenharmony_ciout: 30538c2ecf20Sopenharmony_ci return rc; 30548c2ecf20Sopenharmony_ci} 30558c2ecf20Sopenharmony_ci 30568c2ecf20Sopenharmony_cistatic ssize_t 30578c2ecf20Sopenharmony_cilpfc_debugfs_hdwqstat_write(struct file *file, const char __user *buf, 30588c2ecf20Sopenharmony_ci size_t nbytes, loff_t *ppos) 30598c2ecf20Sopenharmony_ci{ 30608c2ecf20Sopenharmony_ci struct lpfc_debug *debug = file->private_data; 30618c2ecf20Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *)debug->i_private; 30628c2ecf20Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 30638c2ecf20Sopenharmony_ci struct lpfc_hdwq_stat *c_stat; 30648c2ecf20Sopenharmony_ci char mybuf[64]; 30658c2ecf20Sopenharmony_ci char *pbuf; 30668c2ecf20Sopenharmony_ci int i; 30678c2ecf20Sopenharmony_ci 30688c2ecf20Sopenharmony_ci if (nbytes > sizeof(mybuf) - 1) 30698c2ecf20Sopenharmony_ci nbytes = sizeof(mybuf) - 1; 30708c2ecf20Sopenharmony_ci 30718c2ecf20Sopenharmony_ci memset(mybuf, 0, sizeof(mybuf)); 30728c2ecf20Sopenharmony_ci 30738c2ecf20Sopenharmony_ci if (copy_from_user(mybuf, buf, nbytes)) 30748c2ecf20Sopenharmony_ci return -EFAULT; 30758c2ecf20Sopenharmony_ci pbuf = &mybuf[0]; 30768c2ecf20Sopenharmony_ci 30778c2ecf20Sopenharmony_ci if ((strncmp(pbuf, "on", sizeof("on") - 1) == 0)) { 30788c2ecf20Sopenharmony_ci if (phba->nvmet_support) 30798c2ecf20Sopenharmony_ci phba->hdwqstat_on |= LPFC_CHECK_NVMET_IO; 30808c2ecf20Sopenharmony_ci else 30818c2ecf20Sopenharmony_ci phba->hdwqstat_on |= (LPFC_CHECK_NVME_IO | 30828c2ecf20Sopenharmony_ci LPFC_CHECK_SCSI_IO); 30838c2ecf20Sopenharmony_ci return strlen(pbuf); 30848c2ecf20Sopenharmony_ci } else if ((strncmp(pbuf, "nvme_on", sizeof("nvme_on") - 1) == 0)) { 30858c2ecf20Sopenharmony_ci if (phba->nvmet_support) 30868c2ecf20Sopenharmony_ci phba->hdwqstat_on |= LPFC_CHECK_NVMET_IO; 30878c2ecf20Sopenharmony_ci else 30888c2ecf20Sopenharmony_ci phba->hdwqstat_on |= LPFC_CHECK_NVME_IO; 30898c2ecf20Sopenharmony_ci return strlen(pbuf); 30908c2ecf20Sopenharmony_ci } else if ((strncmp(pbuf, "scsi_on", sizeof("scsi_on") - 1) == 0)) { 30918c2ecf20Sopenharmony_ci if (!phba->nvmet_support) 30928c2ecf20Sopenharmony_ci phba->hdwqstat_on |= LPFC_CHECK_SCSI_IO; 30938c2ecf20Sopenharmony_ci return strlen(pbuf); 30948c2ecf20Sopenharmony_ci } else if ((strncmp(pbuf, "nvme_off", sizeof("nvme_off") - 1) == 0)) { 30958c2ecf20Sopenharmony_ci phba->hdwqstat_on &= ~(LPFC_CHECK_NVME_IO | 30968c2ecf20Sopenharmony_ci LPFC_CHECK_NVMET_IO); 30978c2ecf20Sopenharmony_ci return strlen(pbuf); 30988c2ecf20Sopenharmony_ci } else if ((strncmp(pbuf, "scsi_off", sizeof("scsi_off") - 1) == 0)) { 30998c2ecf20Sopenharmony_ci phba->hdwqstat_on &= ~LPFC_CHECK_SCSI_IO; 31008c2ecf20Sopenharmony_ci return strlen(pbuf); 31018c2ecf20Sopenharmony_ci } else if ((strncmp(pbuf, "off", 31028c2ecf20Sopenharmony_ci sizeof("off") - 1) == 0)) { 31038c2ecf20Sopenharmony_ci phba->hdwqstat_on = LPFC_CHECK_OFF; 31048c2ecf20Sopenharmony_ci return strlen(pbuf); 31058c2ecf20Sopenharmony_ci } else if ((strncmp(pbuf, "zero", 31068c2ecf20Sopenharmony_ci sizeof("zero") - 1) == 0)) { 31078c2ecf20Sopenharmony_ci for_each_present_cpu(i) { 31088c2ecf20Sopenharmony_ci c_stat = per_cpu_ptr(phba->sli4_hba.c_stat, i); 31098c2ecf20Sopenharmony_ci c_stat->xmt_io = 0; 31108c2ecf20Sopenharmony_ci c_stat->cmpl_io = 0; 31118c2ecf20Sopenharmony_ci c_stat->rcv_io = 0; 31128c2ecf20Sopenharmony_ci } 31138c2ecf20Sopenharmony_ci return strlen(pbuf); 31148c2ecf20Sopenharmony_ci } 31158c2ecf20Sopenharmony_ci return -EINVAL; 31168c2ecf20Sopenharmony_ci} 31178c2ecf20Sopenharmony_ci 31188c2ecf20Sopenharmony_ci/* 31198c2ecf20Sopenharmony_ci * --------------------------------- 31208c2ecf20Sopenharmony_ci * iDiag debugfs file access methods 31218c2ecf20Sopenharmony_ci * --------------------------------- 31228c2ecf20Sopenharmony_ci * 31238c2ecf20Sopenharmony_ci * All access methods are through the proper SLI4 PCI function's debugfs 31248c2ecf20Sopenharmony_ci * iDiag directory: 31258c2ecf20Sopenharmony_ci * 31268c2ecf20Sopenharmony_ci * /sys/kernel/debug/lpfc/fn<#>/iDiag 31278c2ecf20Sopenharmony_ci */ 31288c2ecf20Sopenharmony_ci 31298c2ecf20Sopenharmony_ci/** 31308c2ecf20Sopenharmony_ci * lpfc_idiag_cmd_get - Get and parse idiag debugfs comands from user space 31318c2ecf20Sopenharmony_ci * @buf: The pointer to the user space buffer. 31328c2ecf20Sopenharmony_ci * @nbytes: The number of bytes in the user space buffer. 31338c2ecf20Sopenharmony_ci * @idiag_cmd: pointer to the idiag command struct. 31348c2ecf20Sopenharmony_ci * 31358c2ecf20Sopenharmony_ci * This routine reads data from debugfs user space buffer and parses the 31368c2ecf20Sopenharmony_ci * buffer for getting the idiag command and arguments. The while space in 31378c2ecf20Sopenharmony_ci * between the set of data is used as the parsing separator. 31388c2ecf20Sopenharmony_ci * 31398c2ecf20Sopenharmony_ci * This routine returns 0 when successful, it returns proper error code 31408c2ecf20Sopenharmony_ci * back to the user space in error conditions. 31418c2ecf20Sopenharmony_ci */ 31428c2ecf20Sopenharmony_cistatic int lpfc_idiag_cmd_get(const char __user *buf, size_t nbytes, 31438c2ecf20Sopenharmony_ci struct lpfc_idiag_cmd *idiag_cmd) 31448c2ecf20Sopenharmony_ci{ 31458c2ecf20Sopenharmony_ci char mybuf[64]; 31468c2ecf20Sopenharmony_ci char *pbuf, *step_str; 31478c2ecf20Sopenharmony_ci int i; 31488c2ecf20Sopenharmony_ci size_t bsize; 31498c2ecf20Sopenharmony_ci 31508c2ecf20Sopenharmony_ci memset(mybuf, 0, sizeof(mybuf)); 31518c2ecf20Sopenharmony_ci memset(idiag_cmd, 0, sizeof(*idiag_cmd)); 31528c2ecf20Sopenharmony_ci bsize = min(nbytes, (sizeof(mybuf)-1)); 31538c2ecf20Sopenharmony_ci 31548c2ecf20Sopenharmony_ci if (copy_from_user(mybuf, buf, bsize)) 31558c2ecf20Sopenharmony_ci return -EFAULT; 31568c2ecf20Sopenharmony_ci pbuf = &mybuf[0]; 31578c2ecf20Sopenharmony_ci step_str = strsep(&pbuf, "\t "); 31588c2ecf20Sopenharmony_ci 31598c2ecf20Sopenharmony_ci /* The opcode must present */ 31608c2ecf20Sopenharmony_ci if (!step_str) 31618c2ecf20Sopenharmony_ci return -EINVAL; 31628c2ecf20Sopenharmony_ci 31638c2ecf20Sopenharmony_ci idiag_cmd->opcode = simple_strtol(step_str, NULL, 0); 31648c2ecf20Sopenharmony_ci if (idiag_cmd->opcode == 0) 31658c2ecf20Sopenharmony_ci return -EINVAL; 31668c2ecf20Sopenharmony_ci 31678c2ecf20Sopenharmony_ci for (i = 0; i < LPFC_IDIAG_CMD_DATA_SIZE; i++) { 31688c2ecf20Sopenharmony_ci step_str = strsep(&pbuf, "\t "); 31698c2ecf20Sopenharmony_ci if (!step_str) 31708c2ecf20Sopenharmony_ci return i; 31718c2ecf20Sopenharmony_ci idiag_cmd->data[i] = simple_strtol(step_str, NULL, 0); 31728c2ecf20Sopenharmony_ci } 31738c2ecf20Sopenharmony_ci return i; 31748c2ecf20Sopenharmony_ci} 31758c2ecf20Sopenharmony_ci 31768c2ecf20Sopenharmony_ci/** 31778c2ecf20Sopenharmony_ci * lpfc_idiag_open - idiag open debugfs 31788c2ecf20Sopenharmony_ci * @inode: The inode pointer that contains a pointer to phba. 31798c2ecf20Sopenharmony_ci * @file: The file pointer to attach the file operation. 31808c2ecf20Sopenharmony_ci * 31818c2ecf20Sopenharmony_ci * Description: 31828c2ecf20Sopenharmony_ci * This routine is the entry point for the debugfs open file operation. It 31838c2ecf20Sopenharmony_ci * gets the reference to phba from the i_private field in @inode, it then 31848c2ecf20Sopenharmony_ci * allocates buffer for the file operation, performs the necessary PCI config 31858c2ecf20Sopenharmony_ci * space read into the allocated buffer according to the idiag user command 31868c2ecf20Sopenharmony_ci * setup, and then returns a pointer to buffer in the private_data field in 31878c2ecf20Sopenharmony_ci * @file. 31888c2ecf20Sopenharmony_ci * 31898c2ecf20Sopenharmony_ci * Returns: 31908c2ecf20Sopenharmony_ci * This function returns zero if successful. On error it will return an 31918c2ecf20Sopenharmony_ci * negative error value. 31928c2ecf20Sopenharmony_ci **/ 31938c2ecf20Sopenharmony_cistatic int 31948c2ecf20Sopenharmony_cilpfc_idiag_open(struct inode *inode, struct file *file) 31958c2ecf20Sopenharmony_ci{ 31968c2ecf20Sopenharmony_ci struct lpfc_debug *debug; 31978c2ecf20Sopenharmony_ci 31988c2ecf20Sopenharmony_ci debug = kmalloc(sizeof(*debug), GFP_KERNEL); 31998c2ecf20Sopenharmony_ci if (!debug) 32008c2ecf20Sopenharmony_ci return -ENOMEM; 32018c2ecf20Sopenharmony_ci 32028c2ecf20Sopenharmony_ci debug->i_private = inode->i_private; 32038c2ecf20Sopenharmony_ci debug->buffer = NULL; 32048c2ecf20Sopenharmony_ci file->private_data = debug; 32058c2ecf20Sopenharmony_ci 32068c2ecf20Sopenharmony_ci return 0; 32078c2ecf20Sopenharmony_ci} 32088c2ecf20Sopenharmony_ci 32098c2ecf20Sopenharmony_ci/** 32108c2ecf20Sopenharmony_ci * lpfc_idiag_release - Release idiag access file operation 32118c2ecf20Sopenharmony_ci * @inode: The inode pointer that contains a vport pointer. (unused) 32128c2ecf20Sopenharmony_ci * @file: The file pointer that contains the buffer to release. 32138c2ecf20Sopenharmony_ci * 32148c2ecf20Sopenharmony_ci * Description: 32158c2ecf20Sopenharmony_ci * This routine is the generic release routine for the idiag access file 32168c2ecf20Sopenharmony_ci * operation, it frees the buffer that was allocated when the debugfs file 32178c2ecf20Sopenharmony_ci * was opened. 32188c2ecf20Sopenharmony_ci * 32198c2ecf20Sopenharmony_ci * Returns: 32208c2ecf20Sopenharmony_ci * This function returns zero. 32218c2ecf20Sopenharmony_ci **/ 32228c2ecf20Sopenharmony_cistatic int 32238c2ecf20Sopenharmony_cilpfc_idiag_release(struct inode *inode, struct file *file) 32248c2ecf20Sopenharmony_ci{ 32258c2ecf20Sopenharmony_ci struct lpfc_debug *debug = file->private_data; 32268c2ecf20Sopenharmony_ci 32278c2ecf20Sopenharmony_ci /* Free the buffers to the file operation */ 32288c2ecf20Sopenharmony_ci kfree(debug->buffer); 32298c2ecf20Sopenharmony_ci kfree(debug); 32308c2ecf20Sopenharmony_ci 32318c2ecf20Sopenharmony_ci return 0; 32328c2ecf20Sopenharmony_ci} 32338c2ecf20Sopenharmony_ci 32348c2ecf20Sopenharmony_ci/** 32358c2ecf20Sopenharmony_ci * lpfc_idiag_cmd_release - Release idiag cmd access file operation 32368c2ecf20Sopenharmony_ci * @inode: The inode pointer that contains a vport pointer. (unused) 32378c2ecf20Sopenharmony_ci * @file: The file pointer that contains the buffer to release. 32388c2ecf20Sopenharmony_ci * 32398c2ecf20Sopenharmony_ci * Description: 32408c2ecf20Sopenharmony_ci * This routine frees the buffer that was allocated when the debugfs file 32418c2ecf20Sopenharmony_ci * was opened. It also reset the fields in the idiag command struct in the 32428c2ecf20Sopenharmony_ci * case of command for write operation. 32438c2ecf20Sopenharmony_ci * 32448c2ecf20Sopenharmony_ci * Returns: 32458c2ecf20Sopenharmony_ci * This function returns zero. 32468c2ecf20Sopenharmony_ci **/ 32478c2ecf20Sopenharmony_cistatic int 32488c2ecf20Sopenharmony_cilpfc_idiag_cmd_release(struct inode *inode, struct file *file) 32498c2ecf20Sopenharmony_ci{ 32508c2ecf20Sopenharmony_ci struct lpfc_debug *debug = file->private_data; 32518c2ecf20Sopenharmony_ci 32528c2ecf20Sopenharmony_ci if (debug->op == LPFC_IDIAG_OP_WR) { 32538c2ecf20Sopenharmony_ci switch (idiag.cmd.opcode) { 32548c2ecf20Sopenharmony_ci case LPFC_IDIAG_CMD_PCICFG_WR: 32558c2ecf20Sopenharmony_ci case LPFC_IDIAG_CMD_PCICFG_ST: 32568c2ecf20Sopenharmony_ci case LPFC_IDIAG_CMD_PCICFG_CL: 32578c2ecf20Sopenharmony_ci case LPFC_IDIAG_CMD_QUEACC_WR: 32588c2ecf20Sopenharmony_ci case LPFC_IDIAG_CMD_QUEACC_ST: 32598c2ecf20Sopenharmony_ci case LPFC_IDIAG_CMD_QUEACC_CL: 32608c2ecf20Sopenharmony_ci memset(&idiag, 0, sizeof(idiag)); 32618c2ecf20Sopenharmony_ci break; 32628c2ecf20Sopenharmony_ci default: 32638c2ecf20Sopenharmony_ci break; 32648c2ecf20Sopenharmony_ci } 32658c2ecf20Sopenharmony_ci } 32668c2ecf20Sopenharmony_ci 32678c2ecf20Sopenharmony_ci /* Free the buffers to the file operation */ 32688c2ecf20Sopenharmony_ci kfree(debug->buffer); 32698c2ecf20Sopenharmony_ci kfree(debug); 32708c2ecf20Sopenharmony_ci 32718c2ecf20Sopenharmony_ci return 0; 32728c2ecf20Sopenharmony_ci} 32738c2ecf20Sopenharmony_ci 32748c2ecf20Sopenharmony_ci/** 32758c2ecf20Sopenharmony_ci * lpfc_idiag_pcicfg_read - idiag debugfs read pcicfg 32768c2ecf20Sopenharmony_ci * @file: The file pointer to read from. 32778c2ecf20Sopenharmony_ci * @buf: The buffer to copy the data to. 32788c2ecf20Sopenharmony_ci * @nbytes: The number of bytes to read. 32798c2ecf20Sopenharmony_ci * @ppos: The position in the file to start reading from. 32808c2ecf20Sopenharmony_ci * 32818c2ecf20Sopenharmony_ci * Description: 32828c2ecf20Sopenharmony_ci * This routine reads data from the @phba pci config space according to the 32838c2ecf20Sopenharmony_ci * idiag command, and copies to user @buf. Depending on the PCI config space 32848c2ecf20Sopenharmony_ci * read command setup, it does either a single register read of a byte 32858c2ecf20Sopenharmony_ci * (8 bits), a word (16 bits), or a dword (32 bits) or browsing through all 32868c2ecf20Sopenharmony_ci * registers from the 4K extended PCI config space. 32878c2ecf20Sopenharmony_ci * 32888c2ecf20Sopenharmony_ci * Returns: 32898c2ecf20Sopenharmony_ci * This function returns the amount of data that was read (this could be less 32908c2ecf20Sopenharmony_ci * than @nbytes if the end of the file was reached) or a negative error value. 32918c2ecf20Sopenharmony_ci **/ 32928c2ecf20Sopenharmony_cistatic ssize_t 32938c2ecf20Sopenharmony_cilpfc_idiag_pcicfg_read(struct file *file, char __user *buf, size_t nbytes, 32948c2ecf20Sopenharmony_ci loff_t *ppos) 32958c2ecf20Sopenharmony_ci{ 32968c2ecf20Sopenharmony_ci struct lpfc_debug *debug = file->private_data; 32978c2ecf20Sopenharmony_ci struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private; 32988c2ecf20Sopenharmony_ci int offset_label, offset, len = 0, index = LPFC_PCI_CFG_RD_SIZE; 32998c2ecf20Sopenharmony_ci int where, count; 33008c2ecf20Sopenharmony_ci char *pbuffer; 33018c2ecf20Sopenharmony_ci struct pci_dev *pdev; 33028c2ecf20Sopenharmony_ci uint32_t u32val; 33038c2ecf20Sopenharmony_ci uint16_t u16val; 33048c2ecf20Sopenharmony_ci uint8_t u8val; 33058c2ecf20Sopenharmony_ci 33068c2ecf20Sopenharmony_ci pdev = phba->pcidev; 33078c2ecf20Sopenharmony_ci if (!pdev) 33088c2ecf20Sopenharmony_ci return 0; 33098c2ecf20Sopenharmony_ci 33108c2ecf20Sopenharmony_ci /* This is a user read operation */ 33118c2ecf20Sopenharmony_ci debug->op = LPFC_IDIAG_OP_RD; 33128c2ecf20Sopenharmony_ci 33138c2ecf20Sopenharmony_ci if (!debug->buffer) 33148c2ecf20Sopenharmony_ci debug->buffer = kmalloc(LPFC_PCI_CFG_SIZE, GFP_KERNEL); 33158c2ecf20Sopenharmony_ci if (!debug->buffer) 33168c2ecf20Sopenharmony_ci return 0; 33178c2ecf20Sopenharmony_ci pbuffer = debug->buffer; 33188c2ecf20Sopenharmony_ci 33198c2ecf20Sopenharmony_ci if (*ppos) 33208c2ecf20Sopenharmony_ci return 0; 33218c2ecf20Sopenharmony_ci 33228c2ecf20Sopenharmony_ci if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_RD) { 33238c2ecf20Sopenharmony_ci where = idiag.cmd.data[IDIAG_PCICFG_WHERE_INDX]; 33248c2ecf20Sopenharmony_ci count = idiag.cmd.data[IDIAG_PCICFG_COUNT_INDX]; 33258c2ecf20Sopenharmony_ci } else 33268c2ecf20Sopenharmony_ci return 0; 33278c2ecf20Sopenharmony_ci 33288c2ecf20Sopenharmony_ci /* Read single PCI config space register */ 33298c2ecf20Sopenharmony_ci switch (count) { 33308c2ecf20Sopenharmony_ci case SIZE_U8: /* byte (8 bits) */ 33318c2ecf20Sopenharmony_ci pci_read_config_byte(pdev, where, &u8val); 33328c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len, 33338c2ecf20Sopenharmony_ci "%03x: %02x\n", where, u8val); 33348c2ecf20Sopenharmony_ci break; 33358c2ecf20Sopenharmony_ci case SIZE_U16: /* word (16 bits) */ 33368c2ecf20Sopenharmony_ci pci_read_config_word(pdev, where, &u16val); 33378c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len, 33388c2ecf20Sopenharmony_ci "%03x: %04x\n", where, u16val); 33398c2ecf20Sopenharmony_ci break; 33408c2ecf20Sopenharmony_ci case SIZE_U32: /* double word (32 bits) */ 33418c2ecf20Sopenharmony_ci pci_read_config_dword(pdev, where, &u32val); 33428c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len, 33438c2ecf20Sopenharmony_ci "%03x: %08x\n", where, u32val); 33448c2ecf20Sopenharmony_ci break; 33458c2ecf20Sopenharmony_ci case LPFC_PCI_CFG_BROWSE: /* browse all */ 33468c2ecf20Sopenharmony_ci goto pcicfg_browse; 33478c2ecf20Sopenharmony_ci break; 33488c2ecf20Sopenharmony_ci default: 33498c2ecf20Sopenharmony_ci /* illegal count */ 33508c2ecf20Sopenharmony_ci len = 0; 33518c2ecf20Sopenharmony_ci break; 33528c2ecf20Sopenharmony_ci } 33538c2ecf20Sopenharmony_ci return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len); 33548c2ecf20Sopenharmony_ci 33558c2ecf20Sopenharmony_cipcicfg_browse: 33568c2ecf20Sopenharmony_ci 33578c2ecf20Sopenharmony_ci /* Browse all PCI config space registers */ 33588c2ecf20Sopenharmony_ci offset_label = idiag.offset.last_rd; 33598c2ecf20Sopenharmony_ci offset = offset_label; 33608c2ecf20Sopenharmony_ci 33618c2ecf20Sopenharmony_ci /* Read PCI config space */ 33628c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len, 33638c2ecf20Sopenharmony_ci "%03x: ", offset_label); 33648c2ecf20Sopenharmony_ci while (index > 0) { 33658c2ecf20Sopenharmony_ci pci_read_config_dword(pdev, offset, &u32val); 33668c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len, 33678c2ecf20Sopenharmony_ci "%08x ", u32val); 33688c2ecf20Sopenharmony_ci offset += sizeof(uint32_t); 33698c2ecf20Sopenharmony_ci if (offset >= LPFC_PCI_CFG_SIZE) { 33708c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, 33718c2ecf20Sopenharmony_ci LPFC_PCI_CFG_SIZE-len, "\n"); 33728c2ecf20Sopenharmony_ci break; 33738c2ecf20Sopenharmony_ci } 33748c2ecf20Sopenharmony_ci index -= sizeof(uint32_t); 33758c2ecf20Sopenharmony_ci if (!index) 33768c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len, 33778c2ecf20Sopenharmony_ci "\n"); 33788c2ecf20Sopenharmony_ci else if (!(index % (8 * sizeof(uint32_t)))) { 33798c2ecf20Sopenharmony_ci offset_label += (8 * sizeof(uint32_t)); 33808c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len, 33818c2ecf20Sopenharmony_ci "\n%03x: ", offset_label); 33828c2ecf20Sopenharmony_ci } 33838c2ecf20Sopenharmony_ci } 33848c2ecf20Sopenharmony_ci 33858c2ecf20Sopenharmony_ci /* Set up the offset for next portion of pci cfg read */ 33868c2ecf20Sopenharmony_ci if (index == 0) { 33878c2ecf20Sopenharmony_ci idiag.offset.last_rd += LPFC_PCI_CFG_RD_SIZE; 33888c2ecf20Sopenharmony_ci if (idiag.offset.last_rd >= LPFC_PCI_CFG_SIZE) 33898c2ecf20Sopenharmony_ci idiag.offset.last_rd = 0; 33908c2ecf20Sopenharmony_ci } else 33918c2ecf20Sopenharmony_ci idiag.offset.last_rd = 0; 33928c2ecf20Sopenharmony_ci 33938c2ecf20Sopenharmony_ci return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len); 33948c2ecf20Sopenharmony_ci} 33958c2ecf20Sopenharmony_ci 33968c2ecf20Sopenharmony_ci/** 33978c2ecf20Sopenharmony_ci * lpfc_idiag_pcicfg_write - Syntax check and set up idiag pcicfg commands 33988c2ecf20Sopenharmony_ci * @file: The file pointer to read from. 33998c2ecf20Sopenharmony_ci * @buf: The buffer to copy the user data from. 34008c2ecf20Sopenharmony_ci * @nbytes: The number of bytes to get. 34018c2ecf20Sopenharmony_ci * @ppos: The position in the file to start reading from. 34028c2ecf20Sopenharmony_ci * 34038c2ecf20Sopenharmony_ci * This routine get the debugfs idiag command struct from user space and 34048c2ecf20Sopenharmony_ci * then perform the syntax check for PCI config space read or write command 34058c2ecf20Sopenharmony_ci * accordingly. In the case of PCI config space read command, it sets up 34068c2ecf20Sopenharmony_ci * the command in the idiag command struct for the debugfs read operation. 34078c2ecf20Sopenharmony_ci * In the case of PCI config space write operation, it executes the write 34088c2ecf20Sopenharmony_ci * operation into the PCI config space accordingly. 34098c2ecf20Sopenharmony_ci * 34108c2ecf20Sopenharmony_ci * It returns the @nbytges passing in from debugfs user space when successful. 34118c2ecf20Sopenharmony_ci * In case of error conditions, it returns proper error code back to the user 34128c2ecf20Sopenharmony_ci * space. 34138c2ecf20Sopenharmony_ci */ 34148c2ecf20Sopenharmony_cistatic ssize_t 34158c2ecf20Sopenharmony_cilpfc_idiag_pcicfg_write(struct file *file, const char __user *buf, 34168c2ecf20Sopenharmony_ci size_t nbytes, loff_t *ppos) 34178c2ecf20Sopenharmony_ci{ 34188c2ecf20Sopenharmony_ci struct lpfc_debug *debug = file->private_data; 34198c2ecf20Sopenharmony_ci struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private; 34208c2ecf20Sopenharmony_ci uint32_t where, value, count; 34218c2ecf20Sopenharmony_ci uint32_t u32val; 34228c2ecf20Sopenharmony_ci uint16_t u16val; 34238c2ecf20Sopenharmony_ci uint8_t u8val; 34248c2ecf20Sopenharmony_ci struct pci_dev *pdev; 34258c2ecf20Sopenharmony_ci int rc; 34268c2ecf20Sopenharmony_ci 34278c2ecf20Sopenharmony_ci pdev = phba->pcidev; 34288c2ecf20Sopenharmony_ci if (!pdev) 34298c2ecf20Sopenharmony_ci return -EFAULT; 34308c2ecf20Sopenharmony_ci 34318c2ecf20Sopenharmony_ci /* This is a user write operation */ 34328c2ecf20Sopenharmony_ci debug->op = LPFC_IDIAG_OP_WR; 34338c2ecf20Sopenharmony_ci 34348c2ecf20Sopenharmony_ci rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd); 34358c2ecf20Sopenharmony_ci if (rc < 0) 34368c2ecf20Sopenharmony_ci return rc; 34378c2ecf20Sopenharmony_ci 34388c2ecf20Sopenharmony_ci if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_RD) { 34398c2ecf20Sopenharmony_ci /* Sanity check on PCI config read command line arguments */ 34408c2ecf20Sopenharmony_ci if (rc != LPFC_PCI_CFG_RD_CMD_ARG) 34418c2ecf20Sopenharmony_ci goto error_out; 34428c2ecf20Sopenharmony_ci /* Read command from PCI config space, set up command fields */ 34438c2ecf20Sopenharmony_ci where = idiag.cmd.data[IDIAG_PCICFG_WHERE_INDX]; 34448c2ecf20Sopenharmony_ci count = idiag.cmd.data[IDIAG_PCICFG_COUNT_INDX]; 34458c2ecf20Sopenharmony_ci if (count == LPFC_PCI_CFG_BROWSE) { 34468c2ecf20Sopenharmony_ci if (where % sizeof(uint32_t)) 34478c2ecf20Sopenharmony_ci goto error_out; 34488c2ecf20Sopenharmony_ci /* Starting offset to browse */ 34498c2ecf20Sopenharmony_ci idiag.offset.last_rd = where; 34508c2ecf20Sopenharmony_ci } else if ((count != sizeof(uint8_t)) && 34518c2ecf20Sopenharmony_ci (count != sizeof(uint16_t)) && 34528c2ecf20Sopenharmony_ci (count != sizeof(uint32_t))) 34538c2ecf20Sopenharmony_ci goto error_out; 34548c2ecf20Sopenharmony_ci if (count == sizeof(uint8_t)) { 34558c2ecf20Sopenharmony_ci if (where > LPFC_PCI_CFG_SIZE - sizeof(uint8_t)) 34568c2ecf20Sopenharmony_ci goto error_out; 34578c2ecf20Sopenharmony_ci if (where % sizeof(uint8_t)) 34588c2ecf20Sopenharmony_ci goto error_out; 34598c2ecf20Sopenharmony_ci } 34608c2ecf20Sopenharmony_ci if (count == sizeof(uint16_t)) { 34618c2ecf20Sopenharmony_ci if (where > LPFC_PCI_CFG_SIZE - sizeof(uint16_t)) 34628c2ecf20Sopenharmony_ci goto error_out; 34638c2ecf20Sopenharmony_ci if (where % sizeof(uint16_t)) 34648c2ecf20Sopenharmony_ci goto error_out; 34658c2ecf20Sopenharmony_ci } 34668c2ecf20Sopenharmony_ci if (count == sizeof(uint32_t)) { 34678c2ecf20Sopenharmony_ci if (where > LPFC_PCI_CFG_SIZE - sizeof(uint32_t)) 34688c2ecf20Sopenharmony_ci goto error_out; 34698c2ecf20Sopenharmony_ci if (where % sizeof(uint32_t)) 34708c2ecf20Sopenharmony_ci goto error_out; 34718c2ecf20Sopenharmony_ci } 34728c2ecf20Sopenharmony_ci } else if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_WR || 34738c2ecf20Sopenharmony_ci idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_ST || 34748c2ecf20Sopenharmony_ci idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_CL) { 34758c2ecf20Sopenharmony_ci /* Sanity check on PCI config write command line arguments */ 34768c2ecf20Sopenharmony_ci if (rc != LPFC_PCI_CFG_WR_CMD_ARG) 34778c2ecf20Sopenharmony_ci goto error_out; 34788c2ecf20Sopenharmony_ci /* Write command to PCI config space, read-modify-write */ 34798c2ecf20Sopenharmony_ci where = idiag.cmd.data[IDIAG_PCICFG_WHERE_INDX]; 34808c2ecf20Sopenharmony_ci count = idiag.cmd.data[IDIAG_PCICFG_COUNT_INDX]; 34818c2ecf20Sopenharmony_ci value = idiag.cmd.data[IDIAG_PCICFG_VALUE_INDX]; 34828c2ecf20Sopenharmony_ci /* Sanity checks */ 34838c2ecf20Sopenharmony_ci if ((count != sizeof(uint8_t)) && 34848c2ecf20Sopenharmony_ci (count != sizeof(uint16_t)) && 34858c2ecf20Sopenharmony_ci (count != sizeof(uint32_t))) 34868c2ecf20Sopenharmony_ci goto error_out; 34878c2ecf20Sopenharmony_ci if (count == sizeof(uint8_t)) { 34888c2ecf20Sopenharmony_ci if (where > LPFC_PCI_CFG_SIZE - sizeof(uint8_t)) 34898c2ecf20Sopenharmony_ci goto error_out; 34908c2ecf20Sopenharmony_ci if (where % sizeof(uint8_t)) 34918c2ecf20Sopenharmony_ci goto error_out; 34928c2ecf20Sopenharmony_ci if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_WR) 34938c2ecf20Sopenharmony_ci pci_write_config_byte(pdev, where, 34948c2ecf20Sopenharmony_ci (uint8_t)value); 34958c2ecf20Sopenharmony_ci if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_ST) { 34968c2ecf20Sopenharmony_ci rc = pci_read_config_byte(pdev, where, &u8val); 34978c2ecf20Sopenharmony_ci if (!rc) { 34988c2ecf20Sopenharmony_ci u8val |= (uint8_t)value; 34998c2ecf20Sopenharmony_ci pci_write_config_byte(pdev, where, 35008c2ecf20Sopenharmony_ci u8val); 35018c2ecf20Sopenharmony_ci } 35028c2ecf20Sopenharmony_ci } 35038c2ecf20Sopenharmony_ci if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_CL) { 35048c2ecf20Sopenharmony_ci rc = pci_read_config_byte(pdev, where, &u8val); 35058c2ecf20Sopenharmony_ci if (!rc) { 35068c2ecf20Sopenharmony_ci u8val &= (uint8_t)(~value); 35078c2ecf20Sopenharmony_ci pci_write_config_byte(pdev, where, 35088c2ecf20Sopenharmony_ci u8val); 35098c2ecf20Sopenharmony_ci } 35108c2ecf20Sopenharmony_ci } 35118c2ecf20Sopenharmony_ci } 35128c2ecf20Sopenharmony_ci if (count == sizeof(uint16_t)) { 35138c2ecf20Sopenharmony_ci if (where > LPFC_PCI_CFG_SIZE - sizeof(uint16_t)) 35148c2ecf20Sopenharmony_ci goto error_out; 35158c2ecf20Sopenharmony_ci if (where % sizeof(uint16_t)) 35168c2ecf20Sopenharmony_ci goto error_out; 35178c2ecf20Sopenharmony_ci if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_WR) 35188c2ecf20Sopenharmony_ci pci_write_config_word(pdev, where, 35198c2ecf20Sopenharmony_ci (uint16_t)value); 35208c2ecf20Sopenharmony_ci if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_ST) { 35218c2ecf20Sopenharmony_ci rc = pci_read_config_word(pdev, where, &u16val); 35228c2ecf20Sopenharmony_ci if (!rc) { 35238c2ecf20Sopenharmony_ci u16val |= (uint16_t)value; 35248c2ecf20Sopenharmony_ci pci_write_config_word(pdev, where, 35258c2ecf20Sopenharmony_ci u16val); 35268c2ecf20Sopenharmony_ci } 35278c2ecf20Sopenharmony_ci } 35288c2ecf20Sopenharmony_ci if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_CL) { 35298c2ecf20Sopenharmony_ci rc = pci_read_config_word(pdev, where, &u16val); 35308c2ecf20Sopenharmony_ci if (!rc) { 35318c2ecf20Sopenharmony_ci u16val &= (uint16_t)(~value); 35328c2ecf20Sopenharmony_ci pci_write_config_word(pdev, where, 35338c2ecf20Sopenharmony_ci u16val); 35348c2ecf20Sopenharmony_ci } 35358c2ecf20Sopenharmony_ci } 35368c2ecf20Sopenharmony_ci } 35378c2ecf20Sopenharmony_ci if (count == sizeof(uint32_t)) { 35388c2ecf20Sopenharmony_ci if (where > LPFC_PCI_CFG_SIZE - sizeof(uint32_t)) 35398c2ecf20Sopenharmony_ci goto error_out; 35408c2ecf20Sopenharmony_ci if (where % sizeof(uint32_t)) 35418c2ecf20Sopenharmony_ci goto error_out; 35428c2ecf20Sopenharmony_ci if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_WR) 35438c2ecf20Sopenharmony_ci pci_write_config_dword(pdev, where, value); 35448c2ecf20Sopenharmony_ci if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_ST) { 35458c2ecf20Sopenharmony_ci rc = pci_read_config_dword(pdev, where, 35468c2ecf20Sopenharmony_ci &u32val); 35478c2ecf20Sopenharmony_ci if (!rc) { 35488c2ecf20Sopenharmony_ci u32val |= value; 35498c2ecf20Sopenharmony_ci pci_write_config_dword(pdev, where, 35508c2ecf20Sopenharmony_ci u32val); 35518c2ecf20Sopenharmony_ci } 35528c2ecf20Sopenharmony_ci } 35538c2ecf20Sopenharmony_ci if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_CL) { 35548c2ecf20Sopenharmony_ci rc = pci_read_config_dword(pdev, where, 35558c2ecf20Sopenharmony_ci &u32val); 35568c2ecf20Sopenharmony_ci if (!rc) { 35578c2ecf20Sopenharmony_ci u32val &= ~value; 35588c2ecf20Sopenharmony_ci pci_write_config_dword(pdev, where, 35598c2ecf20Sopenharmony_ci u32val); 35608c2ecf20Sopenharmony_ci } 35618c2ecf20Sopenharmony_ci } 35628c2ecf20Sopenharmony_ci } 35638c2ecf20Sopenharmony_ci } else 35648c2ecf20Sopenharmony_ci /* All other opecodes are illegal for now */ 35658c2ecf20Sopenharmony_ci goto error_out; 35668c2ecf20Sopenharmony_ci 35678c2ecf20Sopenharmony_ci return nbytes; 35688c2ecf20Sopenharmony_cierror_out: 35698c2ecf20Sopenharmony_ci memset(&idiag, 0, sizeof(idiag)); 35708c2ecf20Sopenharmony_ci return -EINVAL; 35718c2ecf20Sopenharmony_ci} 35728c2ecf20Sopenharmony_ci 35738c2ecf20Sopenharmony_ci/** 35748c2ecf20Sopenharmony_ci * lpfc_idiag_baracc_read - idiag debugfs pci bar access read 35758c2ecf20Sopenharmony_ci * @file: The file pointer to read from. 35768c2ecf20Sopenharmony_ci * @buf: The buffer to copy the data to. 35778c2ecf20Sopenharmony_ci * @nbytes: The number of bytes to read. 35788c2ecf20Sopenharmony_ci * @ppos: The position in the file to start reading from. 35798c2ecf20Sopenharmony_ci * 35808c2ecf20Sopenharmony_ci * Description: 35818c2ecf20Sopenharmony_ci * This routine reads data from the @phba pci bar memory mapped space 35828c2ecf20Sopenharmony_ci * according to the idiag command, and copies to user @buf. 35838c2ecf20Sopenharmony_ci * 35848c2ecf20Sopenharmony_ci * Returns: 35858c2ecf20Sopenharmony_ci * This function returns the amount of data that was read (this could be less 35868c2ecf20Sopenharmony_ci * than @nbytes if the end of the file was reached) or a negative error value. 35878c2ecf20Sopenharmony_ci **/ 35888c2ecf20Sopenharmony_cistatic ssize_t 35898c2ecf20Sopenharmony_cilpfc_idiag_baracc_read(struct file *file, char __user *buf, size_t nbytes, 35908c2ecf20Sopenharmony_ci loff_t *ppos) 35918c2ecf20Sopenharmony_ci{ 35928c2ecf20Sopenharmony_ci struct lpfc_debug *debug = file->private_data; 35938c2ecf20Sopenharmony_ci struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private; 35948c2ecf20Sopenharmony_ci int offset_label, offset, offset_run, len = 0, index; 35958c2ecf20Sopenharmony_ci int bar_num, acc_range, bar_size; 35968c2ecf20Sopenharmony_ci char *pbuffer; 35978c2ecf20Sopenharmony_ci void __iomem *mem_mapped_bar; 35988c2ecf20Sopenharmony_ci uint32_t if_type; 35998c2ecf20Sopenharmony_ci struct pci_dev *pdev; 36008c2ecf20Sopenharmony_ci uint32_t u32val; 36018c2ecf20Sopenharmony_ci 36028c2ecf20Sopenharmony_ci pdev = phba->pcidev; 36038c2ecf20Sopenharmony_ci if (!pdev) 36048c2ecf20Sopenharmony_ci return 0; 36058c2ecf20Sopenharmony_ci 36068c2ecf20Sopenharmony_ci /* This is a user read operation */ 36078c2ecf20Sopenharmony_ci debug->op = LPFC_IDIAG_OP_RD; 36088c2ecf20Sopenharmony_ci 36098c2ecf20Sopenharmony_ci if (!debug->buffer) 36108c2ecf20Sopenharmony_ci debug->buffer = kmalloc(LPFC_PCI_BAR_RD_BUF_SIZE, GFP_KERNEL); 36118c2ecf20Sopenharmony_ci if (!debug->buffer) 36128c2ecf20Sopenharmony_ci return 0; 36138c2ecf20Sopenharmony_ci pbuffer = debug->buffer; 36148c2ecf20Sopenharmony_ci 36158c2ecf20Sopenharmony_ci if (*ppos) 36168c2ecf20Sopenharmony_ci return 0; 36178c2ecf20Sopenharmony_ci 36188c2ecf20Sopenharmony_ci if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_RD) { 36198c2ecf20Sopenharmony_ci bar_num = idiag.cmd.data[IDIAG_BARACC_BAR_NUM_INDX]; 36208c2ecf20Sopenharmony_ci offset = idiag.cmd.data[IDIAG_BARACC_OFF_SET_INDX]; 36218c2ecf20Sopenharmony_ci acc_range = idiag.cmd.data[IDIAG_BARACC_ACC_MOD_INDX]; 36228c2ecf20Sopenharmony_ci bar_size = idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX]; 36238c2ecf20Sopenharmony_ci } else 36248c2ecf20Sopenharmony_ci return 0; 36258c2ecf20Sopenharmony_ci 36268c2ecf20Sopenharmony_ci if (acc_range == 0) 36278c2ecf20Sopenharmony_ci return 0; 36288c2ecf20Sopenharmony_ci 36298c2ecf20Sopenharmony_ci if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf); 36308c2ecf20Sopenharmony_ci if (if_type == LPFC_SLI_INTF_IF_TYPE_0) { 36318c2ecf20Sopenharmony_ci if (bar_num == IDIAG_BARACC_BAR_0) 36328c2ecf20Sopenharmony_ci mem_mapped_bar = phba->sli4_hba.conf_regs_memmap_p; 36338c2ecf20Sopenharmony_ci else if (bar_num == IDIAG_BARACC_BAR_1) 36348c2ecf20Sopenharmony_ci mem_mapped_bar = phba->sli4_hba.ctrl_regs_memmap_p; 36358c2ecf20Sopenharmony_ci else if (bar_num == IDIAG_BARACC_BAR_2) 36368c2ecf20Sopenharmony_ci mem_mapped_bar = phba->sli4_hba.drbl_regs_memmap_p; 36378c2ecf20Sopenharmony_ci else 36388c2ecf20Sopenharmony_ci return 0; 36398c2ecf20Sopenharmony_ci } else if (if_type == LPFC_SLI_INTF_IF_TYPE_2) { 36408c2ecf20Sopenharmony_ci if (bar_num == IDIAG_BARACC_BAR_0) 36418c2ecf20Sopenharmony_ci mem_mapped_bar = phba->sli4_hba.conf_regs_memmap_p; 36428c2ecf20Sopenharmony_ci else 36438c2ecf20Sopenharmony_ci return 0; 36448c2ecf20Sopenharmony_ci } else 36458c2ecf20Sopenharmony_ci return 0; 36468c2ecf20Sopenharmony_ci 36478c2ecf20Sopenharmony_ci /* Read single PCI bar space register */ 36488c2ecf20Sopenharmony_ci if (acc_range == SINGLE_WORD) { 36498c2ecf20Sopenharmony_ci offset_run = offset; 36508c2ecf20Sopenharmony_ci u32val = readl(mem_mapped_bar + offset_run); 36518c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_PCI_BAR_RD_BUF_SIZE-len, 36528c2ecf20Sopenharmony_ci "%05x: %08x\n", offset_run, u32val); 36538c2ecf20Sopenharmony_ci } else 36548c2ecf20Sopenharmony_ci goto baracc_browse; 36558c2ecf20Sopenharmony_ci 36568c2ecf20Sopenharmony_ci return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len); 36578c2ecf20Sopenharmony_ci 36588c2ecf20Sopenharmony_cibaracc_browse: 36598c2ecf20Sopenharmony_ci 36608c2ecf20Sopenharmony_ci /* Browse all PCI bar space registers */ 36618c2ecf20Sopenharmony_ci offset_label = idiag.offset.last_rd; 36628c2ecf20Sopenharmony_ci offset_run = offset_label; 36638c2ecf20Sopenharmony_ci 36648c2ecf20Sopenharmony_ci /* Read PCI bar memory mapped space */ 36658c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_PCI_BAR_RD_BUF_SIZE-len, 36668c2ecf20Sopenharmony_ci "%05x: ", offset_label); 36678c2ecf20Sopenharmony_ci index = LPFC_PCI_BAR_RD_SIZE; 36688c2ecf20Sopenharmony_ci while (index > 0) { 36698c2ecf20Sopenharmony_ci u32val = readl(mem_mapped_bar + offset_run); 36708c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_PCI_BAR_RD_BUF_SIZE-len, 36718c2ecf20Sopenharmony_ci "%08x ", u32val); 36728c2ecf20Sopenharmony_ci offset_run += sizeof(uint32_t); 36738c2ecf20Sopenharmony_ci if (acc_range == LPFC_PCI_BAR_BROWSE) { 36748c2ecf20Sopenharmony_ci if (offset_run >= bar_size) { 36758c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, 36768c2ecf20Sopenharmony_ci LPFC_PCI_BAR_RD_BUF_SIZE-len, "\n"); 36778c2ecf20Sopenharmony_ci break; 36788c2ecf20Sopenharmony_ci } 36798c2ecf20Sopenharmony_ci } else { 36808c2ecf20Sopenharmony_ci if (offset_run >= offset + 36818c2ecf20Sopenharmony_ci (acc_range * sizeof(uint32_t))) { 36828c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, 36838c2ecf20Sopenharmony_ci LPFC_PCI_BAR_RD_BUF_SIZE-len, "\n"); 36848c2ecf20Sopenharmony_ci break; 36858c2ecf20Sopenharmony_ci } 36868c2ecf20Sopenharmony_ci } 36878c2ecf20Sopenharmony_ci index -= sizeof(uint32_t); 36888c2ecf20Sopenharmony_ci if (!index) 36898c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, 36908c2ecf20Sopenharmony_ci LPFC_PCI_BAR_RD_BUF_SIZE-len, "\n"); 36918c2ecf20Sopenharmony_ci else if (!(index % (8 * sizeof(uint32_t)))) { 36928c2ecf20Sopenharmony_ci offset_label += (8 * sizeof(uint32_t)); 36938c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, 36948c2ecf20Sopenharmony_ci LPFC_PCI_BAR_RD_BUF_SIZE-len, 36958c2ecf20Sopenharmony_ci "\n%05x: ", offset_label); 36968c2ecf20Sopenharmony_ci } 36978c2ecf20Sopenharmony_ci } 36988c2ecf20Sopenharmony_ci 36998c2ecf20Sopenharmony_ci /* Set up the offset for next portion of pci bar read */ 37008c2ecf20Sopenharmony_ci if (index == 0) { 37018c2ecf20Sopenharmony_ci idiag.offset.last_rd += LPFC_PCI_BAR_RD_SIZE; 37028c2ecf20Sopenharmony_ci if (acc_range == LPFC_PCI_BAR_BROWSE) { 37038c2ecf20Sopenharmony_ci if (idiag.offset.last_rd >= bar_size) 37048c2ecf20Sopenharmony_ci idiag.offset.last_rd = 0; 37058c2ecf20Sopenharmony_ci } else { 37068c2ecf20Sopenharmony_ci if (offset_run >= offset + 37078c2ecf20Sopenharmony_ci (acc_range * sizeof(uint32_t))) 37088c2ecf20Sopenharmony_ci idiag.offset.last_rd = offset; 37098c2ecf20Sopenharmony_ci } 37108c2ecf20Sopenharmony_ci } else { 37118c2ecf20Sopenharmony_ci if (acc_range == LPFC_PCI_BAR_BROWSE) 37128c2ecf20Sopenharmony_ci idiag.offset.last_rd = 0; 37138c2ecf20Sopenharmony_ci else 37148c2ecf20Sopenharmony_ci idiag.offset.last_rd = offset; 37158c2ecf20Sopenharmony_ci } 37168c2ecf20Sopenharmony_ci 37178c2ecf20Sopenharmony_ci return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len); 37188c2ecf20Sopenharmony_ci} 37198c2ecf20Sopenharmony_ci 37208c2ecf20Sopenharmony_ci/** 37218c2ecf20Sopenharmony_ci * lpfc_idiag_baracc_write - Syntax check and set up idiag bar access commands 37228c2ecf20Sopenharmony_ci * @file: The file pointer to read from. 37238c2ecf20Sopenharmony_ci * @buf: The buffer to copy the user data from. 37248c2ecf20Sopenharmony_ci * @nbytes: The number of bytes to get. 37258c2ecf20Sopenharmony_ci * @ppos: The position in the file to start reading from. 37268c2ecf20Sopenharmony_ci * 37278c2ecf20Sopenharmony_ci * This routine get the debugfs idiag command struct from user space and 37288c2ecf20Sopenharmony_ci * then perform the syntax check for PCI bar memory mapped space read or 37298c2ecf20Sopenharmony_ci * write command accordingly. In the case of PCI bar memory mapped space 37308c2ecf20Sopenharmony_ci * read command, it sets up the command in the idiag command struct for 37318c2ecf20Sopenharmony_ci * the debugfs read operation. In the case of PCI bar memorpy mapped space 37328c2ecf20Sopenharmony_ci * write operation, it executes the write operation into the PCI bar memory 37338c2ecf20Sopenharmony_ci * mapped space accordingly. 37348c2ecf20Sopenharmony_ci * 37358c2ecf20Sopenharmony_ci * It returns the @nbytges passing in from debugfs user space when successful. 37368c2ecf20Sopenharmony_ci * In case of error conditions, it returns proper error code back to the user 37378c2ecf20Sopenharmony_ci * space. 37388c2ecf20Sopenharmony_ci */ 37398c2ecf20Sopenharmony_cistatic ssize_t 37408c2ecf20Sopenharmony_cilpfc_idiag_baracc_write(struct file *file, const char __user *buf, 37418c2ecf20Sopenharmony_ci size_t nbytes, loff_t *ppos) 37428c2ecf20Sopenharmony_ci{ 37438c2ecf20Sopenharmony_ci struct lpfc_debug *debug = file->private_data; 37448c2ecf20Sopenharmony_ci struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private; 37458c2ecf20Sopenharmony_ci uint32_t bar_num, bar_size, offset, value, acc_range; 37468c2ecf20Sopenharmony_ci struct pci_dev *pdev; 37478c2ecf20Sopenharmony_ci void __iomem *mem_mapped_bar; 37488c2ecf20Sopenharmony_ci uint32_t if_type; 37498c2ecf20Sopenharmony_ci uint32_t u32val; 37508c2ecf20Sopenharmony_ci int rc; 37518c2ecf20Sopenharmony_ci 37528c2ecf20Sopenharmony_ci pdev = phba->pcidev; 37538c2ecf20Sopenharmony_ci if (!pdev) 37548c2ecf20Sopenharmony_ci return -EFAULT; 37558c2ecf20Sopenharmony_ci 37568c2ecf20Sopenharmony_ci /* This is a user write operation */ 37578c2ecf20Sopenharmony_ci debug->op = LPFC_IDIAG_OP_WR; 37588c2ecf20Sopenharmony_ci 37598c2ecf20Sopenharmony_ci rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd); 37608c2ecf20Sopenharmony_ci if (rc < 0) 37618c2ecf20Sopenharmony_ci return rc; 37628c2ecf20Sopenharmony_ci 37638c2ecf20Sopenharmony_ci if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf); 37648c2ecf20Sopenharmony_ci bar_num = idiag.cmd.data[IDIAG_BARACC_BAR_NUM_INDX]; 37658c2ecf20Sopenharmony_ci 37668c2ecf20Sopenharmony_ci if (if_type == LPFC_SLI_INTF_IF_TYPE_0) { 37678c2ecf20Sopenharmony_ci if ((bar_num != IDIAG_BARACC_BAR_0) && 37688c2ecf20Sopenharmony_ci (bar_num != IDIAG_BARACC_BAR_1) && 37698c2ecf20Sopenharmony_ci (bar_num != IDIAG_BARACC_BAR_2)) 37708c2ecf20Sopenharmony_ci goto error_out; 37718c2ecf20Sopenharmony_ci } else if (if_type == LPFC_SLI_INTF_IF_TYPE_2) { 37728c2ecf20Sopenharmony_ci if (bar_num != IDIAG_BARACC_BAR_0) 37738c2ecf20Sopenharmony_ci goto error_out; 37748c2ecf20Sopenharmony_ci } else 37758c2ecf20Sopenharmony_ci goto error_out; 37768c2ecf20Sopenharmony_ci 37778c2ecf20Sopenharmony_ci if (if_type == LPFC_SLI_INTF_IF_TYPE_0) { 37788c2ecf20Sopenharmony_ci if (bar_num == IDIAG_BARACC_BAR_0) { 37798c2ecf20Sopenharmony_ci idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX] = 37808c2ecf20Sopenharmony_ci LPFC_PCI_IF0_BAR0_SIZE; 37818c2ecf20Sopenharmony_ci mem_mapped_bar = phba->sli4_hba.conf_regs_memmap_p; 37828c2ecf20Sopenharmony_ci } else if (bar_num == IDIAG_BARACC_BAR_1) { 37838c2ecf20Sopenharmony_ci idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX] = 37848c2ecf20Sopenharmony_ci LPFC_PCI_IF0_BAR1_SIZE; 37858c2ecf20Sopenharmony_ci mem_mapped_bar = phba->sli4_hba.ctrl_regs_memmap_p; 37868c2ecf20Sopenharmony_ci } else if (bar_num == IDIAG_BARACC_BAR_2) { 37878c2ecf20Sopenharmony_ci idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX] = 37888c2ecf20Sopenharmony_ci LPFC_PCI_IF0_BAR2_SIZE; 37898c2ecf20Sopenharmony_ci mem_mapped_bar = phba->sli4_hba.drbl_regs_memmap_p; 37908c2ecf20Sopenharmony_ci } else 37918c2ecf20Sopenharmony_ci goto error_out; 37928c2ecf20Sopenharmony_ci } else if (if_type == LPFC_SLI_INTF_IF_TYPE_2) { 37938c2ecf20Sopenharmony_ci if (bar_num == IDIAG_BARACC_BAR_0) { 37948c2ecf20Sopenharmony_ci idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX] = 37958c2ecf20Sopenharmony_ci LPFC_PCI_IF2_BAR0_SIZE; 37968c2ecf20Sopenharmony_ci mem_mapped_bar = phba->sli4_hba.conf_regs_memmap_p; 37978c2ecf20Sopenharmony_ci } else 37988c2ecf20Sopenharmony_ci goto error_out; 37998c2ecf20Sopenharmony_ci } else 38008c2ecf20Sopenharmony_ci goto error_out; 38018c2ecf20Sopenharmony_ci 38028c2ecf20Sopenharmony_ci offset = idiag.cmd.data[IDIAG_BARACC_OFF_SET_INDX]; 38038c2ecf20Sopenharmony_ci if (offset % sizeof(uint32_t)) 38048c2ecf20Sopenharmony_ci goto error_out; 38058c2ecf20Sopenharmony_ci 38068c2ecf20Sopenharmony_ci bar_size = idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX]; 38078c2ecf20Sopenharmony_ci if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_RD) { 38088c2ecf20Sopenharmony_ci /* Sanity check on PCI config read command line arguments */ 38098c2ecf20Sopenharmony_ci if (rc != LPFC_PCI_BAR_RD_CMD_ARG) 38108c2ecf20Sopenharmony_ci goto error_out; 38118c2ecf20Sopenharmony_ci acc_range = idiag.cmd.data[IDIAG_BARACC_ACC_MOD_INDX]; 38128c2ecf20Sopenharmony_ci if (acc_range == LPFC_PCI_BAR_BROWSE) { 38138c2ecf20Sopenharmony_ci if (offset > bar_size - sizeof(uint32_t)) 38148c2ecf20Sopenharmony_ci goto error_out; 38158c2ecf20Sopenharmony_ci /* Starting offset to browse */ 38168c2ecf20Sopenharmony_ci idiag.offset.last_rd = offset; 38178c2ecf20Sopenharmony_ci } else if (acc_range > SINGLE_WORD) { 38188c2ecf20Sopenharmony_ci if (offset + acc_range * sizeof(uint32_t) > bar_size) 38198c2ecf20Sopenharmony_ci goto error_out; 38208c2ecf20Sopenharmony_ci /* Starting offset to browse */ 38218c2ecf20Sopenharmony_ci idiag.offset.last_rd = offset; 38228c2ecf20Sopenharmony_ci } else if (acc_range != SINGLE_WORD) 38238c2ecf20Sopenharmony_ci goto error_out; 38248c2ecf20Sopenharmony_ci } else if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_WR || 38258c2ecf20Sopenharmony_ci idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_ST || 38268c2ecf20Sopenharmony_ci idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_CL) { 38278c2ecf20Sopenharmony_ci /* Sanity check on PCI bar write command line arguments */ 38288c2ecf20Sopenharmony_ci if (rc != LPFC_PCI_BAR_WR_CMD_ARG) 38298c2ecf20Sopenharmony_ci goto error_out; 38308c2ecf20Sopenharmony_ci /* Write command to PCI bar space, read-modify-write */ 38318c2ecf20Sopenharmony_ci acc_range = SINGLE_WORD; 38328c2ecf20Sopenharmony_ci value = idiag.cmd.data[IDIAG_BARACC_REG_VAL_INDX]; 38338c2ecf20Sopenharmony_ci if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_WR) { 38348c2ecf20Sopenharmony_ci writel(value, mem_mapped_bar + offset); 38358c2ecf20Sopenharmony_ci readl(mem_mapped_bar + offset); 38368c2ecf20Sopenharmony_ci } 38378c2ecf20Sopenharmony_ci if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_ST) { 38388c2ecf20Sopenharmony_ci u32val = readl(mem_mapped_bar + offset); 38398c2ecf20Sopenharmony_ci u32val |= value; 38408c2ecf20Sopenharmony_ci writel(u32val, mem_mapped_bar + offset); 38418c2ecf20Sopenharmony_ci readl(mem_mapped_bar + offset); 38428c2ecf20Sopenharmony_ci } 38438c2ecf20Sopenharmony_ci if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_CL) { 38448c2ecf20Sopenharmony_ci u32val = readl(mem_mapped_bar + offset); 38458c2ecf20Sopenharmony_ci u32val &= ~value; 38468c2ecf20Sopenharmony_ci writel(u32val, mem_mapped_bar + offset); 38478c2ecf20Sopenharmony_ci readl(mem_mapped_bar + offset); 38488c2ecf20Sopenharmony_ci } 38498c2ecf20Sopenharmony_ci } else 38508c2ecf20Sopenharmony_ci /* All other opecodes are illegal for now */ 38518c2ecf20Sopenharmony_ci goto error_out; 38528c2ecf20Sopenharmony_ci 38538c2ecf20Sopenharmony_ci return nbytes; 38548c2ecf20Sopenharmony_cierror_out: 38558c2ecf20Sopenharmony_ci memset(&idiag, 0, sizeof(idiag)); 38568c2ecf20Sopenharmony_ci return -EINVAL; 38578c2ecf20Sopenharmony_ci} 38588c2ecf20Sopenharmony_ci 38598c2ecf20Sopenharmony_cistatic int 38608c2ecf20Sopenharmony_ci__lpfc_idiag_print_wq(struct lpfc_queue *qp, char *wqtype, 38618c2ecf20Sopenharmony_ci char *pbuffer, int len) 38628c2ecf20Sopenharmony_ci{ 38638c2ecf20Sopenharmony_ci if (!qp) 38648c2ecf20Sopenharmony_ci return len; 38658c2ecf20Sopenharmony_ci 38668c2ecf20Sopenharmony_ci len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, 38678c2ecf20Sopenharmony_ci "\t\t%s WQ info: ", wqtype); 38688c2ecf20Sopenharmony_ci len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, 38698c2ecf20Sopenharmony_ci "AssocCQID[%04d]: WQ-STAT[oflow:x%x posted:x%llx]\n", 38708c2ecf20Sopenharmony_ci qp->assoc_qid, qp->q_cnt_1, 38718c2ecf20Sopenharmony_ci (unsigned long long)qp->q_cnt_4); 38728c2ecf20Sopenharmony_ci len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, 38738c2ecf20Sopenharmony_ci "\t\tWQID[%02d], QE-CNT[%04d], QE-SZ[%04d], " 38748c2ecf20Sopenharmony_ci "HST-IDX[%04d], PRT-IDX[%04d], NTFI[%03d]", 38758c2ecf20Sopenharmony_ci qp->queue_id, qp->entry_count, 38768c2ecf20Sopenharmony_ci qp->entry_size, qp->host_index, 38778c2ecf20Sopenharmony_ci qp->hba_index, qp->notify_interval); 38788c2ecf20Sopenharmony_ci len += scnprintf(pbuffer + len, 38798c2ecf20Sopenharmony_ci LPFC_QUE_INFO_GET_BUF_SIZE - len, "\n"); 38808c2ecf20Sopenharmony_ci return len; 38818c2ecf20Sopenharmony_ci} 38828c2ecf20Sopenharmony_ci 38838c2ecf20Sopenharmony_cistatic int 38848c2ecf20Sopenharmony_cilpfc_idiag_wqs_for_cq(struct lpfc_hba *phba, char *wqtype, char *pbuffer, 38858c2ecf20Sopenharmony_ci int *len, int max_cnt, int cq_id) 38868c2ecf20Sopenharmony_ci{ 38878c2ecf20Sopenharmony_ci struct lpfc_queue *qp; 38888c2ecf20Sopenharmony_ci int qidx; 38898c2ecf20Sopenharmony_ci 38908c2ecf20Sopenharmony_ci for (qidx = 0; qidx < phba->cfg_hdw_queue; qidx++) { 38918c2ecf20Sopenharmony_ci qp = phba->sli4_hba.hdwq[qidx].io_wq; 38928c2ecf20Sopenharmony_ci if (qp->assoc_qid != cq_id) 38938c2ecf20Sopenharmony_ci continue; 38948c2ecf20Sopenharmony_ci *len = __lpfc_idiag_print_wq(qp, wqtype, pbuffer, *len); 38958c2ecf20Sopenharmony_ci if (*len >= max_cnt) 38968c2ecf20Sopenharmony_ci return 1; 38978c2ecf20Sopenharmony_ci } 38988c2ecf20Sopenharmony_ci return 0; 38998c2ecf20Sopenharmony_ci} 39008c2ecf20Sopenharmony_ci 39018c2ecf20Sopenharmony_cistatic int 39028c2ecf20Sopenharmony_ci__lpfc_idiag_print_cq(struct lpfc_queue *qp, char *cqtype, 39038c2ecf20Sopenharmony_ci char *pbuffer, int len) 39048c2ecf20Sopenharmony_ci{ 39058c2ecf20Sopenharmony_ci if (!qp) 39068c2ecf20Sopenharmony_ci return len; 39078c2ecf20Sopenharmony_ci 39088c2ecf20Sopenharmony_ci len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, 39098c2ecf20Sopenharmony_ci "\t%s CQ info: ", cqtype); 39108c2ecf20Sopenharmony_ci len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, 39118c2ecf20Sopenharmony_ci "AssocEQID[%02d]: CQ STAT[max:x%x relw:x%x " 39128c2ecf20Sopenharmony_ci "xabt:x%x wq:x%llx]\n", 39138c2ecf20Sopenharmony_ci qp->assoc_qid, qp->q_cnt_1, qp->q_cnt_2, 39148c2ecf20Sopenharmony_ci qp->q_cnt_3, (unsigned long long)qp->q_cnt_4); 39158c2ecf20Sopenharmony_ci len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, 39168c2ecf20Sopenharmony_ci "\tCQID[%02d], QE-CNT[%04d], QE-SZ[%04d], " 39178c2ecf20Sopenharmony_ci "HST-IDX[%04d], NTFI[%03d], PLMT[%03d]", 39188c2ecf20Sopenharmony_ci qp->queue_id, qp->entry_count, 39198c2ecf20Sopenharmony_ci qp->entry_size, qp->host_index, 39208c2ecf20Sopenharmony_ci qp->notify_interval, qp->max_proc_limit); 39218c2ecf20Sopenharmony_ci 39228c2ecf20Sopenharmony_ci len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, 39238c2ecf20Sopenharmony_ci "\n"); 39248c2ecf20Sopenharmony_ci 39258c2ecf20Sopenharmony_ci return len; 39268c2ecf20Sopenharmony_ci} 39278c2ecf20Sopenharmony_ci 39288c2ecf20Sopenharmony_cistatic int 39298c2ecf20Sopenharmony_ci__lpfc_idiag_print_rqpair(struct lpfc_queue *qp, struct lpfc_queue *datqp, 39308c2ecf20Sopenharmony_ci char *rqtype, char *pbuffer, int len) 39318c2ecf20Sopenharmony_ci{ 39328c2ecf20Sopenharmony_ci if (!qp || !datqp) 39338c2ecf20Sopenharmony_ci return len; 39348c2ecf20Sopenharmony_ci 39358c2ecf20Sopenharmony_ci len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, 39368c2ecf20Sopenharmony_ci "\t\t%s RQ info: ", rqtype); 39378c2ecf20Sopenharmony_ci len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, 39388c2ecf20Sopenharmony_ci "AssocCQID[%02d]: RQ-STAT[nopost:x%x nobuf:x%x " 39398c2ecf20Sopenharmony_ci "posted:x%x rcv:x%llx]\n", 39408c2ecf20Sopenharmony_ci qp->assoc_qid, qp->q_cnt_1, qp->q_cnt_2, 39418c2ecf20Sopenharmony_ci qp->q_cnt_3, (unsigned long long)qp->q_cnt_4); 39428c2ecf20Sopenharmony_ci len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, 39438c2ecf20Sopenharmony_ci "\t\tHQID[%02d], QE-CNT[%04d], QE-SZ[%04d], " 39448c2ecf20Sopenharmony_ci "HST-IDX[%04d], PRT-IDX[%04d], NTFI[%03d]\n", 39458c2ecf20Sopenharmony_ci qp->queue_id, qp->entry_count, qp->entry_size, 39468c2ecf20Sopenharmony_ci qp->host_index, qp->hba_index, qp->notify_interval); 39478c2ecf20Sopenharmony_ci len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, 39488c2ecf20Sopenharmony_ci "\t\tDQID[%02d], QE-CNT[%04d], QE-SZ[%04d], " 39498c2ecf20Sopenharmony_ci "HST-IDX[%04d], PRT-IDX[%04d], NTFI[%03d]\n", 39508c2ecf20Sopenharmony_ci datqp->queue_id, datqp->entry_count, 39518c2ecf20Sopenharmony_ci datqp->entry_size, datqp->host_index, 39528c2ecf20Sopenharmony_ci datqp->hba_index, datqp->notify_interval); 39538c2ecf20Sopenharmony_ci return len; 39548c2ecf20Sopenharmony_ci} 39558c2ecf20Sopenharmony_ci 39568c2ecf20Sopenharmony_cistatic int 39578c2ecf20Sopenharmony_cilpfc_idiag_cqs_for_eq(struct lpfc_hba *phba, char *pbuffer, 39588c2ecf20Sopenharmony_ci int *len, int max_cnt, int eqidx, int eq_id) 39598c2ecf20Sopenharmony_ci{ 39608c2ecf20Sopenharmony_ci struct lpfc_queue *qp; 39618c2ecf20Sopenharmony_ci int rc; 39628c2ecf20Sopenharmony_ci 39638c2ecf20Sopenharmony_ci qp = phba->sli4_hba.hdwq[eqidx].io_cq; 39648c2ecf20Sopenharmony_ci 39658c2ecf20Sopenharmony_ci *len = __lpfc_idiag_print_cq(qp, "IO", pbuffer, *len); 39668c2ecf20Sopenharmony_ci 39678c2ecf20Sopenharmony_ci /* Reset max counter */ 39688c2ecf20Sopenharmony_ci qp->CQ_max_cqe = 0; 39698c2ecf20Sopenharmony_ci 39708c2ecf20Sopenharmony_ci if (*len >= max_cnt) 39718c2ecf20Sopenharmony_ci return 1; 39728c2ecf20Sopenharmony_ci 39738c2ecf20Sopenharmony_ci rc = lpfc_idiag_wqs_for_cq(phba, "IO", pbuffer, len, 39748c2ecf20Sopenharmony_ci max_cnt, qp->queue_id); 39758c2ecf20Sopenharmony_ci if (rc) 39768c2ecf20Sopenharmony_ci return 1; 39778c2ecf20Sopenharmony_ci 39788c2ecf20Sopenharmony_ci if ((eqidx < phba->cfg_nvmet_mrq) && phba->nvmet_support) { 39798c2ecf20Sopenharmony_ci /* NVMET CQset */ 39808c2ecf20Sopenharmony_ci qp = phba->sli4_hba.nvmet_cqset[eqidx]; 39818c2ecf20Sopenharmony_ci *len = __lpfc_idiag_print_cq(qp, "NVMET CQset", pbuffer, *len); 39828c2ecf20Sopenharmony_ci 39838c2ecf20Sopenharmony_ci /* Reset max counter */ 39848c2ecf20Sopenharmony_ci qp->CQ_max_cqe = 0; 39858c2ecf20Sopenharmony_ci 39868c2ecf20Sopenharmony_ci if (*len >= max_cnt) 39878c2ecf20Sopenharmony_ci return 1; 39888c2ecf20Sopenharmony_ci 39898c2ecf20Sopenharmony_ci /* RQ header */ 39908c2ecf20Sopenharmony_ci qp = phba->sli4_hba.nvmet_mrq_hdr[eqidx]; 39918c2ecf20Sopenharmony_ci *len = __lpfc_idiag_print_rqpair(qp, 39928c2ecf20Sopenharmony_ci phba->sli4_hba.nvmet_mrq_data[eqidx], 39938c2ecf20Sopenharmony_ci "NVMET MRQ", pbuffer, *len); 39948c2ecf20Sopenharmony_ci 39958c2ecf20Sopenharmony_ci if (*len >= max_cnt) 39968c2ecf20Sopenharmony_ci return 1; 39978c2ecf20Sopenharmony_ci } 39988c2ecf20Sopenharmony_ci 39998c2ecf20Sopenharmony_ci return 0; 40008c2ecf20Sopenharmony_ci} 40018c2ecf20Sopenharmony_ci 40028c2ecf20Sopenharmony_cistatic int 40038c2ecf20Sopenharmony_ci__lpfc_idiag_print_eq(struct lpfc_queue *qp, char *eqtype, 40048c2ecf20Sopenharmony_ci char *pbuffer, int len) 40058c2ecf20Sopenharmony_ci{ 40068c2ecf20Sopenharmony_ci if (!qp) 40078c2ecf20Sopenharmony_ci return len; 40088c2ecf20Sopenharmony_ci 40098c2ecf20Sopenharmony_ci len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, 40108c2ecf20Sopenharmony_ci "\n%s EQ info: EQ-STAT[max:x%x noE:x%x " 40118c2ecf20Sopenharmony_ci "cqe_proc:x%x eqe_proc:x%llx eqd %d]\n", 40128c2ecf20Sopenharmony_ci eqtype, qp->q_cnt_1, qp->q_cnt_2, qp->q_cnt_3, 40138c2ecf20Sopenharmony_ci (unsigned long long)qp->q_cnt_4, qp->q_mode); 40148c2ecf20Sopenharmony_ci len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, 40158c2ecf20Sopenharmony_ci "EQID[%02d], QE-CNT[%04d], QE-SZ[%04d], " 40168c2ecf20Sopenharmony_ci "HST-IDX[%04d], NTFI[%03d], PLMT[%03d], AFFIN[%03d]", 40178c2ecf20Sopenharmony_ci qp->queue_id, qp->entry_count, qp->entry_size, 40188c2ecf20Sopenharmony_ci qp->host_index, qp->notify_interval, 40198c2ecf20Sopenharmony_ci qp->max_proc_limit, qp->chann); 40208c2ecf20Sopenharmony_ci len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, 40218c2ecf20Sopenharmony_ci "\n"); 40228c2ecf20Sopenharmony_ci 40238c2ecf20Sopenharmony_ci return len; 40248c2ecf20Sopenharmony_ci} 40258c2ecf20Sopenharmony_ci 40268c2ecf20Sopenharmony_ci/** 40278c2ecf20Sopenharmony_ci * lpfc_idiag_queinfo_read - idiag debugfs read queue information 40288c2ecf20Sopenharmony_ci * @file: The file pointer to read from. 40298c2ecf20Sopenharmony_ci * @buf: The buffer to copy the data to. 40308c2ecf20Sopenharmony_ci * @nbytes: The number of bytes to read. 40318c2ecf20Sopenharmony_ci * @ppos: The position in the file to start reading from. 40328c2ecf20Sopenharmony_ci * 40338c2ecf20Sopenharmony_ci * Description: 40348c2ecf20Sopenharmony_ci * This routine reads data from the @phba SLI4 PCI function queue information, 40358c2ecf20Sopenharmony_ci * and copies to user @buf. 40368c2ecf20Sopenharmony_ci * This routine only returns 1 EQs worth of information. It remembers the last 40378c2ecf20Sopenharmony_ci * EQ read and jumps to the next EQ. Thus subsequent calls to queInfo will 40388c2ecf20Sopenharmony_ci * retrieve all EQs allocated for the phba. 40398c2ecf20Sopenharmony_ci * 40408c2ecf20Sopenharmony_ci * Returns: 40418c2ecf20Sopenharmony_ci * This function returns the amount of data that was read (this could be less 40428c2ecf20Sopenharmony_ci * than @nbytes if the end of the file was reached) or a negative error value. 40438c2ecf20Sopenharmony_ci **/ 40448c2ecf20Sopenharmony_cistatic ssize_t 40458c2ecf20Sopenharmony_cilpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes, 40468c2ecf20Sopenharmony_ci loff_t *ppos) 40478c2ecf20Sopenharmony_ci{ 40488c2ecf20Sopenharmony_ci struct lpfc_debug *debug = file->private_data; 40498c2ecf20Sopenharmony_ci struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private; 40508c2ecf20Sopenharmony_ci char *pbuffer; 40518c2ecf20Sopenharmony_ci int max_cnt, rc, x, len = 0; 40528c2ecf20Sopenharmony_ci struct lpfc_queue *qp = NULL; 40538c2ecf20Sopenharmony_ci 40548c2ecf20Sopenharmony_ci if (!debug->buffer) 40558c2ecf20Sopenharmony_ci debug->buffer = kmalloc(LPFC_QUE_INFO_GET_BUF_SIZE, GFP_KERNEL); 40568c2ecf20Sopenharmony_ci if (!debug->buffer) 40578c2ecf20Sopenharmony_ci return 0; 40588c2ecf20Sopenharmony_ci pbuffer = debug->buffer; 40598c2ecf20Sopenharmony_ci max_cnt = LPFC_QUE_INFO_GET_BUF_SIZE - 256; 40608c2ecf20Sopenharmony_ci 40618c2ecf20Sopenharmony_ci if (*ppos) 40628c2ecf20Sopenharmony_ci return 0; 40638c2ecf20Sopenharmony_ci 40648c2ecf20Sopenharmony_ci spin_lock_irq(&phba->hbalock); 40658c2ecf20Sopenharmony_ci 40668c2ecf20Sopenharmony_ci /* Fast-path event queue */ 40678c2ecf20Sopenharmony_ci if (phba->sli4_hba.hdwq && phba->cfg_hdw_queue) { 40688c2ecf20Sopenharmony_ci 40698c2ecf20Sopenharmony_ci x = phba->lpfc_idiag_last_eq; 40708c2ecf20Sopenharmony_ci phba->lpfc_idiag_last_eq++; 40718c2ecf20Sopenharmony_ci if (phba->lpfc_idiag_last_eq >= phba->cfg_hdw_queue) 40728c2ecf20Sopenharmony_ci phba->lpfc_idiag_last_eq = 0; 40738c2ecf20Sopenharmony_ci 40748c2ecf20Sopenharmony_ci len += scnprintf(pbuffer + len, 40758c2ecf20Sopenharmony_ci LPFC_QUE_INFO_GET_BUF_SIZE - len, 40768c2ecf20Sopenharmony_ci "HDWQ %d out of %d HBA HDWQs\n", 40778c2ecf20Sopenharmony_ci x, phba->cfg_hdw_queue); 40788c2ecf20Sopenharmony_ci 40798c2ecf20Sopenharmony_ci /* Fast-path EQ */ 40808c2ecf20Sopenharmony_ci qp = phba->sli4_hba.hdwq[x].hba_eq; 40818c2ecf20Sopenharmony_ci if (!qp) 40828c2ecf20Sopenharmony_ci goto out; 40838c2ecf20Sopenharmony_ci 40848c2ecf20Sopenharmony_ci len = __lpfc_idiag_print_eq(qp, "HBA", pbuffer, len); 40858c2ecf20Sopenharmony_ci 40868c2ecf20Sopenharmony_ci /* Reset max counter */ 40878c2ecf20Sopenharmony_ci qp->EQ_max_eqe = 0; 40888c2ecf20Sopenharmony_ci 40898c2ecf20Sopenharmony_ci if (len >= max_cnt) 40908c2ecf20Sopenharmony_ci goto too_big; 40918c2ecf20Sopenharmony_ci 40928c2ecf20Sopenharmony_ci /* will dump both fcp and nvme cqs/wqs for the eq */ 40938c2ecf20Sopenharmony_ci rc = lpfc_idiag_cqs_for_eq(phba, pbuffer, &len, 40948c2ecf20Sopenharmony_ci max_cnt, x, qp->queue_id); 40958c2ecf20Sopenharmony_ci if (rc) 40968c2ecf20Sopenharmony_ci goto too_big; 40978c2ecf20Sopenharmony_ci 40988c2ecf20Sopenharmony_ci /* Only EQ 0 has slow path CQs configured */ 40998c2ecf20Sopenharmony_ci if (x) 41008c2ecf20Sopenharmony_ci goto out; 41018c2ecf20Sopenharmony_ci 41028c2ecf20Sopenharmony_ci /* Slow-path mailbox CQ */ 41038c2ecf20Sopenharmony_ci qp = phba->sli4_hba.mbx_cq; 41048c2ecf20Sopenharmony_ci len = __lpfc_idiag_print_cq(qp, "MBX", pbuffer, len); 41058c2ecf20Sopenharmony_ci if (len >= max_cnt) 41068c2ecf20Sopenharmony_ci goto too_big; 41078c2ecf20Sopenharmony_ci 41088c2ecf20Sopenharmony_ci /* Slow-path MBOX MQ */ 41098c2ecf20Sopenharmony_ci qp = phba->sli4_hba.mbx_wq; 41108c2ecf20Sopenharmony_ci len = __lpfc_idiag_print_wq(qp, "MBX", pbuffer, len); 41118c2ecf20Sopenharmony_ci if (len >= max_cnt) 41128c2ecf20Sopenharmony_ci goto too_big; 41138c2ecf20Sopenharmony_ci 41148c2ecf20Sopenharmony_ci /* Slow-path ELS response CQ */ 41158c2ecf20Sopenharmony_ci qp = phba->sli4_hba.els_cq; 41168c2ecf20Sopenharmony_ci len = __lpfc_idiag_print_cq(qp, "ELS", pbuffer, len); 41178c2ecf20Sopenharmony_ci /* Reset max counter */ 41188c2ecf20Sopenharmony_ci if (qp) 41198c2ecf20Sopenharmony_ci qp->CQ_max_cqe = 0; 41208c2ecf20Sopenharmony_ci if (len >= max_cnt) 41218c2ecf20Sopenharmony_ci goto too_big; 41228c2ecf20Sopenharmony_ci 41238c2ecf20Sopenharmony_ci /* Slow-path ELS WQ */ 41248c2ecf20Sopenharmony_ci qp = phba->sli4_hba.els_wq; 41258c2ecf20Sopenharmony_ci len = __lpfc_idiag_print_wq(qp, "ELS", pbuffer, len); 41268c2ecf20Sopenharmony_ci if (len >= max_cnt) 41278c2ecf20Sopenharmony_ci goto too_big; 41288c2ecf20Sopenharmony_ci 41298c2ecf20Sopenharmony_ci qp = phba->sli4_hba.hdr_rq; 41308c2ecf20Sopenharmony_ci len = __lpfc_idiag_print_rqpair(qp, phba->sli4_hba.dat_rq, 41318c2ecf20Sopenharmony_ci "ELS RQpair", pbuffer, len); 41328c2ecf20Sopenharmony_ci if (len >= max_cnt) 41338c2ecf20Sopenharmony_ci goto too_big; 41348c2ecf20Sopenharmony_ci 41358c2ecf20Sopenharmony_ci /* Slow-path NVME LS response CQ */ 41368c2ecf20Sopenharmony_ci qp = phba->sli4_hba.nvmels_cq; 41378c2ecf20Sopenharmony_ci len = __lpfc_idiag_print_cq(qp, "NVME LS", 41388c2ecf20Sopenharmony_ci pbuffer, len); 41398c2ecf20Sopenharmony_ci /* Reset max counter */ 41408c2ecf20Sopenharmony_ci if (qp) 41418c2ecf20Sopenharmony_ci qp->CQ_max_cqe = 0; 41428c2ecf20Sopenharmony_ci if (len >= max_cnt) 41438c2ecf20Sopenharmony_ci goto too_big; 41448c2ecf20Sopenharmony_ci 41458c2ecf20Sopenharmony_ci /* Slow-path NVME LS WQ */ 41468c2ecf20Sopenharmony_ci qp = phba->sli4_hba.nvmels_wq; 41478c2ecf20Sopenharmony_ci len = __lpfc_idiag_print_wq(qp, "NVME LS", 41488c2ecf20Sopenharmony_ci pbuffer, len); 41498c2ecf20Sopenharmony_ci if (len >= max_cnt) 41508c2ecf20Sopenharmony_ci goto too_big; 41518c2ecf20Sopenharmony_ci 41528c2ecf20Sopenharmony_ci goto out; 41538c2ecf20Sopenharmony_ci } 41548c2ecf20Sopenharmony_ci 41558c2ecf20Sopenharmony_ci spin_unlock_irq(&phba->hbalock); 41568c2ecf20Sopenharmony_ci return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len); 41578c2ecf20Sopenharmony_ci 41588c2ecf20Sopenharmony_citoo_big: 41598c2ecf20Sopenharmony_ci len += scnprintf(pbuffer + len, 41608c2ecf20Sopenharmony_ci LPFC_QUE_INFO_GET_BUF_SIZE - len, "Truncated ...\n"); 41618c2ecf20Sopenharmony_ciout: 41628c2ecf20Sopenharmony_ci spin_unlock_irq(&phba->hbalock); 41638c2ecf20Sopenharmony_ci return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len); 41648c2ecf20Sopenharmony_ci} 41658c2ecf20Sopenharmony_ci 41668c2ecf20Sopenharmony_ci/** 41678c2ecf20Sopenharmony_ci * lpfc_idiag_que_param_check - queue access command parameter sanity check 41688c2ecf20Sopenharmony_ci * @q: The pointer to queue structure. 41698c2ecf20Sopenharmony_ci * @index: The index into a queue entry. 41708c2ecf20Sopenharmony_ci * @count: The number of queue entries to access. 41718c2ecf20Sopenharmony_ci * 41728c2ecf20Sopenharmony_ci * Description: 41738c2ecf20Sopenharmony_ci * The routine performs sanity check on device queue access method commands. 41748c2ecf20Sopenharmony_ci * 41758c2ecf20Sopenharmony_ci * Returns: 41768c2ecf20Sopenharmony_ci * This function returns -EINVAL when fails the sanity check, otherwise, it 41778c2ecf20Sopenharmony_ci * returns 0. 41788c2ecf20Sopenharmony_ci **/ 41798c2ecf20Sopenharmony_cistatic int 41808c2ecf20Sopenharmony_cilpfc_idiag_que_param_check(struct lpfc_queue *q, int index, int count) 41818c2ecf20Sopenharmony_ci{ 41828c2ecf20Sopenharmony_ci /* Only support single entry read or browsing */ 41838c2ecf20Sopenharmony_ci if ((count != 1) && (count != LPFC_QUE_ACC_BROWSE)) 41848c2ecf20Sopenharmony_ci return -EINVAL; 41858c2ecf20Sopenharmony_ci if (index > q->entry_count - 1) 41868c2ecf20Sopenharmony_ci return -EINVAL; 41878c2ecf20Sopenharmony_ci return 0; 41888c2ecf20Sopenharmony_ci} 41898c2ecf20Sopenharmony_ci 41908c2ecf20Sopenharmony_ci/** 41918c2ecf20Sopenharmony_ci * lpfc_idiag_queacc_read_qe - read a single entry from the given queue index 41928c2ecf20Sopenharmony_ci * @pbuffer: The pointer to buffer to copy the read data into. 41938c2ecf20Sopenharmony_ci * @pque: The pointer to the queue to be read. 41948c2ecf20Sopenharmony_ci * @index: The index into the queue entry. 41958c2ecf20Sopenharmony_ci * 41968c2ecf20Sopenharmony_ci * Description: 41978c2ecf20Sopenharmony_ci * This routine reads out a single entry from the given queue's index location 41988c2ecf20Sopenharmony_ci * and copies it into the buffer provided. 41998c2ecf20Sopenharmony_ci * 42008c2ecf20Sopenharmony_ci * Returns: 42018c2ecf20Sopenharmony_ci * This function returns 0 when it fails, otherwise, it returns the length of 42028c2ecf20Sopenharmony_ci * the data read into the buffer provided. 42038c2ecf20Sopenharmony_ci **/ 42048c2ecf20Sopenharmony_cistatic int 42058c2ecf20Sopenharmony_cilpfc_idiag_queacc_read_qe(char *pbuffer, int len, struct lpfc_queue *pque, 42068c2ecf20Sopenharmony_ci uint32_t index) 42078c2ecf20Sopenharmony_ci{ 42088c2ecf20Sopenharmony_ci int offset, esize; 42098c2ecf20Sopenharmony_ci uint32_t *pentry; 42108c2ecf20Sopenharmony_ci 42118c2ecf20Sopenharmony_ci if (!pbuffer || !pque) 42128c2ecf20Sopenharmony_ci return 0; 42138c2ecf20Sopenharmony_ci 42148c2ecf20Sopenharmony_ci esize = pque->entry_size; 42158c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_QUE_ACC_BUF_SIZE-len, 42168c2ecf20Sopenharmony_ci "QE-INDEX[%04d]:\n", index); 42178c2ecf20Sopenharmony_ci 42188c2ecf20Sopenharmony_ci offset = 0; 42198c2ecf20Sopenharmony_ci pentry = lpfc_sli4_qe(pque, index); 42208c2ecf20Sopenharmony_ci while (esize > 0) { 42218c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_QUE_ACC_BUF_SIZE-len, 42228c2ecf20Sopenharmony_ci "%08x ", *pentry); 42238c2ecf20Sopenharmony_ci pentry++; 42248c2ecf20Sopenharmony_ci offset += sizeof(uint32_t); 42258c2ecf20Sopenharmony_ci esize -= sizeof(uint32_t); 42268c2ecf20Sopenharmony_ci if (esize > 0 && !(offset % (4 * sizeof(uint32_t)))) 42278c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, 42288c2ecf20Sopenharmony_ci LPFC_QUE_ACC_BUF_SIZE-len, "\n"); 42298c2ecf20Sopenharmony_ci } 42308c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_QUE_ACC_BUF_SIZE-len, "\n"); 42318c2ecf20Sopenharmony_ci 42328c2ecf20Sopenharmony_ci return len; 42338c2ecf20Sopenharmony_ci} 42348c2ecf20Sopenharmony_ci 42358c2ecf20Sopenharmony_ci/** 42368c2ecf20Sopenharmony_ci * lpfc_idiag_queacc_read - idiag debugfs read port queue 42378c2ecf20Sopenharmony_ci * @file: The file pointer to read from. 42388c2ecf20Sopenharmony_ci * @buf: The buffer to copy the data to. 42398c2ecf20Sopenharmony_ci * @nbytes: The number of bytes to read. 42408c2ecf20Sopenharmony_ci * @ppos: The position in the file to start reading from. 42418c2ecf20Sopenharmony_ci * 42428c2ecf20Sopenharmony_ci * Description: 42438c2ecf20Sopenharmony_ci * This routine reads data from the @phba device queue memory according to the 42448c2ecf20Sopenharmony_ci * idiag command, and copies to user @buf. Depending on the queue dump read 42458c2ecf20Sopenharmony_ci * command setup, it does either a single queue entry read or browing through 42468c2ecf20Sopenharmony_ci * all entries of the queue. 42478c2ecf20Sopenharmony_ci * 42488c2ecf20Sopenharmony_ci * Returns: 42498c2ecf20Sopenharmony_ci * This function returns the amount of data that was read (this could be less 42508c2ecf20Sopenharmony_ci * than @nbytes if the end of the file was reached) or a negative error value. 42518c2ecf20Sopenharmony_ci **/ 42528c2ecf20Sopenharmony_cistatic ssize_t 42538c2ecf20Sopenharmony_cilpfc_idiag_queacc_read(struct file *file, char __user *buf, size_t nbytes, 42548c2ecf20Sopenharmony_ci loff_t *ppos) 42558c2ecf20Sopenharmony_ci{ 42568c2ecf20Sopenharmony_ci struct lpfc_debug *debug = file->private_data; 42578c2ecf20Sopenharmony_ci uint32_t last_index, index, count; 42588c2ecf20Sopenharmony_ci struct lpfc_queue *pque = NULL; 42598c2ecf20Sopenharmony_ci char *pbuffer; 42608c2ecf20Sopenharmony_ci int len = 0; 42618c2ecf20Sopenharmony_ci 42628c2ecf20Sopenharmony_ci /* This is a user read operation */ 42638c2ecf20Sopenharmony_ci debug->op = LPFC_IDIAG_OP_RD; 42648c2ecf20Sopenharmony_ci 42658c2ecf20Sopenharmony_ci if (!debug->buffer) 42668c2ecf20Sopenharmony_ci debug->buffer = kmalloc(LPFC_QUE_ACC_BUF_SIZE, GFP_KERNEL); 42678c2ecf20Sopenharmony_ci if (!debug->buffer) 42688c2ecf20Sopenharmony_ci return 0; 42698c2ecf20Sopenharmony_ci pbuffer = debug->buffer; 42708c2ecf20Sopenharmony_ci 42718c2ecf20Sopenharmony_ci if (*ppos) 42728c2ecf20Sopenharmony_ci return 0; 42738c2ecf20Sopenharmony_ci 42748c2ecf20Sopenharmony_ci if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_RD) { 42758c2ecf20Sopenharmony_ci index = idiag.cmd.data[IDIAG_QUEACC_INDEX_INDX]; 42768c2ecf20Sopenharmony_ci count = idiag.cmd.data[IDIAG_QUEACC_COUNT_INDX]; 42778c2ecf20Sopenharmony_ci pque = (struct lpfc_queue *)idiag.ptr_private; 42788c2ecf20Sopenharmony_ci } else 42798c2ecf20Sopenharmony_ci return 0; 42808c2ecf20Sopenharmony_ci 42818c2ecf20Sopenharmony_ci /* Browse the queue starting from index */ 42828c2ecf20Sopenharmony_ci if (count == LPFC_QUE_ACC_BROWSE) 42838c2ecf20Sopenharmony_ci goto que_browse; 42848c2ecf20Sopenharmony_ci 42858c2ecf20Sopenharmony_ci /* Read a single entry from the queue */ 42868c2ecf20Sopenharmony_ci len = lpfc_idiag_queacc_read_qe(pbuffer, len, pque, index); 42878c2ecf20Sopenharmony_ci 42888c2ecf20Sopenharmony_ci return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len); 42898c2ecf20Sopenharmony_ci 42908c2ecf20Sopenharmony_cique_browse: 42918c2ecf20Sopenharmony_ci 42928c2ecf20Sopenharmony_ci /* Browse all entries from the queue */ 42938c2ecf20Sopenharmony_ci last_index = idiag.offset.last_rd; 42948c2ecf20Sopenharmony_ci index = last_index; 42958c2ecf20Sopenharmony_ci 42968c2ecf20Sopenharmony_ci while (len < LPFC_QUE_ACC_SIZE - pque->entry_size) { 42978c2ecf20Sopenharmony_ci len = lpfc_idiag_queacc_read_qe(pbuffer, len, pque, index); 42988c2ecf20Sopenharmony_ci index++; 42998c2ecf20Sopenharmony_ci if (index > pque->entry_count - 1) 43008c2ecf20Sopenharmony_ci break; 43018c2ecf20Sopenharmony_ci } 43028c2ecf20Sopenharmony_ci 43038c2ecf20Sopenharmony_ci /* Set up the offset for next portion of pci cfg read */ 43048c2ecf20Sopenharmony_ci if (index > pque->entry_count - 1) 43058c2ecf20Sopenharmony_ci index = 0; 43068c2ecf20Sopenharmony_ci idiag.offset.last_rd = index; 43078c2ecf20Sopenharmony_ci 43088c2ecf20Sopenharmony_ci return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len); 43098c2ecf20Sopenharmony_ci} 43108c2ecf20Sopenharmony_ci 43118c2ecf20Sopenharmony_ci/** 43128c2ecf20Sopenharmony_ci * lpfc_idiag_queacc_write - Syntax check and set up idiag queacc commands 43138c2ecf20Sopenharmony_ci * @file: The file pointer to read from. 43148c2ecf20Sopenharmony_ci * @buf: The buffer to copy the user data from. 43158c2ecf20Sopenharmony_ci * @nbytes: The number of bytes to get. 43168c2ecf20Sopenharmony_ci * @ppos: The position in the file to start reading from. 43178c2ecf20Sopenharmony_ci * 43188c2ecf20Sopenharmony_ci * This routine get the debugfs idiag command struct from user space and then 43198c2ecf20Sopenharmony_ci * perform the syntax check for port queue read (dump) or write (set) command 43208c2ecf20Sopenharmony_ci * accordingly. In the case of port queue read command, it sets up the command 43218c2ecf20Sopenharmony_ci * in the idiag command struct for the following debugfs read operation. In 43228c2ecf20Sopenharmony_ci * the case of port queue write operation, it executes the write operation 43238c2ecf20Sopenharmony_ci * into the port queue entry accordingly. 43248c2ecf20Sopenharmony_ci * 43258c2ecf20Sopenharmony_ci * It returns the @nbytges passing in from debugfs user space when successful. 43268c2ecf20Sopenharmony_ci * In case of error conditions, it returns proper error code back to the user 43278c2ecf20Sopenharmony_ci * space. 43288c2ecf20Sopenharmony_ci **/ 43298c2ecf20Sopenharmony_cistatic ssize_t 43308c2ecf20Sopenharmony_cilpfc_idiag_queacc_write(struct file *file, const char __user *buf, 43318c2ecf20Sopenharmony_ci size_t nbytes, loff_t *ppos) 43328c2ecf20Sopenharmony_ci{ 43338c2ecf20Sopenharmony_ci struct lpfc_debug *debug = file->private_data; 43348c2ecf20Sopenharmony_ci struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private; 43358c2ecf20Sopenharmony_ci uint32_t qidx, quetp, queid, index, count, offset, value; 43368c2ecf20Sopenharmony_ci uint32_t *pentry; 43378c2ecf20Sopenharmony_ci struct lpfc_queue *pque, *qp; 43388c2ecf20Sopenharmony_ci int rc; 43398c2ecf20Sopenharmony_ci 43408c2ecf20Sopenharmony_ci /* This is a user write operation */ 43418c2ecf20Sopenharmony_ci debug->op = LPFC_IDIAG_OP_WR; 43428c2ecf20Sopenharmony_ci 43438c2ecf20Sopenharmony_ci rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd); 43448c2ecf20Sopenharmony_ci if (rc < 0) 43458c2ecf20Sopenharmony_ci return rc; 43468c2ecf20Sopenharmony_ci 43478c2ecf20Sopenharmony_ci /* Get and sanity check on command feilds */ 43488c2ecf20Sopenharmony_ci quetp = idiag.cmd.data[IDIAG_QUEACC_QUETP_INDX]; 43498c2ecf20Sopenharmony_ci queid = idiag.cmd.data[IDIAG_QUEACC_QUEID_INDX]; 43508c2ecf20Sopenharmony_ci index = idiag.cmd.data[IDIAG_QUEACC_INDEX_INDX]; 43518c2ecf20Sopenharmony_ci count = idiag.cmd.data[IDIAG_QUEACC_COUNT_INDX]; 43528c2ecf20Sopenharmony_ci offset = idiag.cmd.data[IDIAG_QUEACC_OFFST_INDX]; 43538c2ecf20Sopenharmony_ci value = idiag.cmd.data[IDIAG_QUEACC_VALUE_INDX]; 43548c2ecf20Sopenharmony_ci 43558c2ecf20Sopenharmony_ci /* Sanity check on command line arguments */ 43568c2ecf20Sopenharmony_ci if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_WR || 43578c2ecf20Sopenharmony_ci idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_ST || 43588c2ecf20Sopenharmony_ci idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_CL) { 43598c2ecf20Sopenharmony_ci if (rc != LPFC_QUE_ACC_WR_CMD_ARG) 43608c2ecf20Sopenharmony_ci goto error_out; 43618c2ecf20Sopenharmony_ci if (count != 1) 43628c2ecf20Sopenharmony_ci goto error_out; 43638c2ecf20Sopenharmony_ci } else if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_RD) { 43648c2ecf20Sopenharmony_ci if (rc != LPFC_QUE_ACC_RD_CMD_ARG) 43658c2ecf20Sopenharmony_ci goto error_out; 43668c2ecf20Sopenharmony_ci } else 43678c2ecf20Sopenharmony_ci goto error_out; 43688c2ecf20Sopenharmony_ci 43698c2ecf20Sopenharmony_ci switch (quetp) { 43708c2ecf20Sopenharmony_ci case LPFC_IDIAG_EQ: 43718c2ecf20Sopenharmony_ci /* HBA event queue */ 43728c2ecf20Sopenharmony_ci if (phba->sli4_hba.hdwq) { 43738c2ecf20Sopenharmony_ci for (qidx = 0; qidx < phba->cfg_hdw_queue; qidx++) { 43748c2ecf20Sopenharmony_ci qp = phba->sli4_hba.hdwq[qidx].hba_eq; 43758c2ecf20Sopenharmony_ci if (qp && qp->queue_id == queid) { 43768c2ecf20Sopenharmony_ci /* Sanity check */ 43778c2ecf20Sopenharmony_ci rc = lpfc_idiag_que_param_check(qp, 43788c2ecf20Sopenharmony_ci index, count); 43798c2ecf20Sopenharmony_ci if (rc) 43808c2ecf20Sopenharmony_ci goto error_out; 43818c2ecf20Sopenharmony_ci idiag.ptr_private = qp; 43828c2ecf20Sopenharmony_ci goto pass_check; 43838c2ecf20Sopenharmony_ci } 43848c2ecf20Sopenharmony_ci } 43858c2ecf20Sopenharmony_ci } 43868c2ecf20Sopenharmony_ci goto error_out; 43878c2ecf20Sopenharmony_ci break; 43888c2ecf20Sopenharmony_ci case LPFC_IDIAG_CQ: 43898c2ecf20Sopenharmony_ci /* MBX complete queue */ 43908c2ecf20Sopenharmony_ci if (phba->sli4_hba.mbx_cq && 43918c2ecf20Sopenharmony_ci phba->sli4_hba.mbx_cq->queue_id == queid) { 43928c2ecf20Sopenharmony_ci /* Sanity check */ 43938c2ecf20Sopenharmony_ci rc = lpfc_idiag_que_param_check( 43948c2ecf20Sopenharmony_ci phba->sli4_hba.mbx_cq, index, count); 43958c2ecf20Sopenharmony_ci if (rc) 43968c2ecf20Sopenharmony_ci goto error_out; 43978c2ecf20Sopenharmony_ci idiag.ptr_private = phba->sli4_hba.mbx_cq; 43988c2ecf20Sopenharmony_ci goto pass_check; 43998c2ecf20Sopenharmony_ci } 44008c2ecf20Sopenharmony_ci /* ELS complete queue */ 44018c2ecf20Sopenharmony_ci if (phba->sli4_hba.els_cq && 44028c2ecf20Sopenharmony_ci phba->sli4_hba.els_cq->queue_id == queid) { 44038c2ecf20Sopenharmony_ci /* Sanity check */ 44048c2ecf20Sopenharmony_ci rc = lpfc_idiag_que_param_check( 44058c2ecf20Sopenharmony_ci phba->sli4_hba.els_cq, index, count); 44068c2ecf20Sopenharmony_ci if (rc) 44078c2ecf20Sopenharmony_ci goto error_out; 44088c2ecf20Sopenharmony_ci idiag.ptr_private = phba->sli4_hba.els_cq; 44098c2ecf20Sopenharmony_ci goto pass_check; 44108c2ecf20Sopenharmony_ci } 44118c2ecf20Sopenharmony_ci /* NVME LS complete queue */ 44128c2ecf20Sopenharmony_ci if (phba->sli4_hba.nvmels_cq && 44138c2ecf20Sopenharmony_ci phba->sli4_hba.nvmels_cq->queue_id == queid) { 44148c2ecf20Sopenharmony_ci /* Sanity check */ 44158c2ecf20Sopenharmony_ci rc = lpfc_idiag_que_param_check( 44168c2ecf20Sopenharmony_ci phba->sli4_hba.nvmels_cq, index, count); 44178c2ecf20Sopenharmony_ci if (rc) 44188c2ecf20Sopenharmony_ci goto error_out; 44198c2ecf20Sopenharmony_ci idiag.ptr_private = phba->sli4_hba.nvmels_cq; 44208c2ecf20Sopenharmony_ci goto pass_check; 44218c2ecf20Sopenharmony_ci } 44228c2ecf20Sopenharmony_ci /* FCP complete queue */ 44238c2ecf20Sopenharmony_ci if (phba->sli4_hba.hdwq) { 44248c2ecf20Sopenharmony_ci for (qidx = 0; qidx < phba->cfg_hdw_queue; 44258c2ecf20Sopenharmony_ci qidx++) { 44268c2ecf20Sopenharmony_ci qp = phba->sli4_hba.hdwq[qidx].io_cq; 44278c2ecf20Sopenharmony_ci if (qp && qp->queue_id == queid) { 44288c2ecf20Sopenharmony_ci /* Sanity check */ 44298c2ecf20Sopenharmony_ci rc = lpfc_idiag_que_param_check( 44308c2ecf20Sopenharmony_ci qp, index, count); 44318c2ecf20Sopenharmony_ci if (rc) 44328c2ecf20Sopenharmony_ci goto error_out; 44338c2ecf20Sopenharmony_ci idiag.ptr_private = qp; 44348c2ecf20Sopenharmony_ci goto pass_check; 44358c2ecf20Sopenharmony_ci } 44368c2ecf20Sopenharmony_ci } 44378c2ecf20Sopenharmony_ci } 44388c2ecf20Sopenharmony_ci goto error_out; 44398c2ecf20Sopenharmony_ci break; 44408c2ecf20Sopenharmony_ci case LPFC_IDIAG_MQ: 44418c2ecf20Sopenharmony_ci /* MBX work queue */ 44428c2ecf20Sopenharmony_ci if (phba->sli4_hba.mbx_wq && 44438c2ecf20Sopenharmony_ci phba->sli4_hba.mbx_wq->queue_id == queid) { 44448c2ecf20Sopenharmony_ci /* Sanity check */ 44458c2ecf20Sopenharmony_ci rc = lpfc_idiag_que_param_check( 44468c2ecf20Sopenharmony_ci phba->sli4_hba.mbx_wq, index, count); 44478c2ecf20Sopenharmony_ci if (rc) 44488c2ecf20Sopenharmony_ci goto error_out; 44498c2ecf20Sopenharmony_ci idiag.ptr_private = phba->sli4_hba.mbx_wq; 44508c2ecf20Sopenharmony_ci goto pass_check; 44518c2ecf20Sopenharmony_ci } 44528c2ecf20Sopenharmony_ci goto error_out; 44538c2ecf20Sopenharmony_ci break; 44548c2ecf20Sopenharmony_ci case LPFC_IDIAG_WQ: 44558c2ecf20Sopenharmony_ci /* ELS work queue */ 44568c2ecf20Sopenharmony_ci if (phba->sli4_hba.els_wq && 44578c2ecf20Sopenharmony_ci phba->sli4_hba.els_wq->queue_id == queid) { 44588c2ecf20Sopenharmony_ci /* Sanity check */ 44598c2ecf20Sopenharmony_ci rc = lpfc_idiag_que_param_check( 44608c2ecf20Sopenharmony_ci phba->sli4_hba.els_wq, index, count); 44618c2ecf20Sopenharmony_ci if (rc) 44628c2ecf20Sopenharmony_ci goto error_out; 44638c2ecf20Sopenharmony_ci idiag.ptr_private = phba->sli4_hba.els_wq; 44648c2ecf20Sopenharmony_ci goto pass_check; 44658c2ecf20Sopenharmony_ci } 44668c2ecf20Sopenharmony_ci /* NVME LS work queue */ 44678c2ecf20Sopenharmony_ci if (phba->sli4_hba.nvmels_wq && 44688c2ecf20Sopenharmony_ci phba->sli4_hba.nvmels_wq->queue_id == queid) { 44698c2ecf20Sopenharmony_ci /* Sanity check */ 44708c2ecf20Sopenharmony_ci rc = lpfc_idiag_que_param_check( 44718c2ecf20Sopenharmony_ci phba->sli4_hba.nvmels_wq, index, count); 44728c2ecf20Sopenharmony_ci if (rc) 44738c2ecf20Sopenharmony_ci goto error_out; 44748c2ecf20Sopenharmony_ci idiag.ptr_private = phba->sli4_hba.nvmels_wq; 44758c2ecf20Sopenharmony_ci goto pass_check; 44768c2ecf20Sopenharmony_ci } 44778c2ecf20Sopenharmony_ci 44788c2ecf20Sopenharmony_ci if (phba->sli4_hba.hdwq) { 44798c2ecf20Sopenharmony_ci /* FCP/SCSI work queue */ 44808c2ecf20Sopenharmony_ci for (qidx = 0; qidx < phba->cfg_hdw_queue; qidx++) { 44818c2ecf20Sopenharmony_ci qp = phba->sli4_hba.hdwq[qidx].io_wq; 44828c2ecf20Sopenharmony_ci if (qp && qp->queue_id == queid) { 44838c2ecf20Sopenharmony_ci /* Sanity check */ 44848c2ecf20Sopenharmony_ci rc = lpfc_idiag_que_param_check( 44858c2ecf20Sopenharmony_ci qp, index, count); 44868c2ecf20Sopenharmony_ci if (rc) 44878c2ecf20Sopenharmony_ci goto error_out; 44888c2ecf20Sopenharmony_ci idiag.ptr_private = qp; 44898c2ecf20Sopenharmony_ci goto pass_check; 44908c2ecf20Sopenharmony_ci } 44918c2ecf20Sopenharmony_ci } 44928c2ecf20Sopenharmony_ci } 44938c2ecf20Sopenharmony_ci 44948c2ecf20Sopenharmony_ci goto error_out; 44958c2ecf20Sopenharmony_ci break; 44968c2ecf20Sopenharmony_ci case LPFC_IDIAG_RQ: 44978c2ecf20Sopenharmony_ci /* HDR queue */ 44988c2ecf20Sopenharmony_ci if (phba->sli4_hba.hdr_rq && 44998c2ecf20Sopenharmony_ci phba->sli4_hba.hdr_rq->queue_id == queid) { 45008c2ecf20Sopenharmony_ci /* Sanity check */ 45018c2ecf20Sopenharmony_ci rc = lpfc_idiag_que_param_check( 45028c2ecf20Sopenharmony_ci phba->sli4_hba.hdr_rq, index, count); 45038c2ecf20Sopenharmony_ci if (rc) 45048c2ecf20Sopenharmony_ci goto error_out; 45058c2ecf20Sopenharmony_ci idiag.ptr_private = phba->sli4_hba.hdr_rq; 45068c2ecf20Sopenharmony_ci goto pass_check; 45078c2ecf20Sopenharmony_ci } 45088c2ecf20Sopenharmony_ci /* DAT queue */ 45098c2ecf20Sopenharmony_ci if (phba->sli4_hba.dat_rq && 45108c2ecf20Sopenharmony_ci phba->sli4_hba.dat_rq->queue_id == queid) { 45118c2ecf20Sopenharmony_ci /* Sanity check */ 45128c2ecf20Sopenharmony_ci rc = lpfc_idiag_que_param_check( 45138c2ecf20Sopenharmony_ci phba->sli4_hba.dat_rq, index, count); 45148c2ecf20Sopenharmony_ci if (rc) 45158c2ecf20Sopenharmony_ci goto error_out; 45168c2ecf20Sopenharmony_ci idiag.ptr_private = phba->sli4_hba.dat_rq; 45178c2ecf20Sopenharmony_ci goto pass_check; 45188c2ecf20Sopenharmony_ci } 45198c2ecf20Sopenharmony_ci goto error_out; 45208c2ecf20Sopenharmony_ci break; 45218c2ecf20Sopenharmony_ci default: 45228c2ecf20Sopenharmony_ci goto error_out; 45238c2ecf20Sopenharmony_ci break; 45248c2ecf20Sopenharmony_ci } 45258c2ecf20Sopenharmony_ci 45268c2ecf20Sopenharmony_cipass_check: 45278c2ecf20Sopenharmony_ci 45288c2ecf20Sopenharmony_ci if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_RD) { 45298c2ecf20Sopenharmony_ci if (count == LPFC_QUE_ACC_BROWSE) 45308c2ecf20Sopenharmony_ci idiag.offset.last_rd = index; 45318c2ecf20Sopenharmony_ci } 45328c2ecf20Sopenharmony_ci 45338c2ecf20Sopenharmony_ci if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_WR || 45348c2ecf20Sopenharmony_ci idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_ST || 45358c2ecf20Sopenharmony_ci idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_CL) { 45368c2ecf20Sopenharmony_ci /* Additional sanity checks on write operation */ 45378c2ecf20Sopenharmony_ci pque = (struct lpfc_queue *)idiag.ptr_private; 45388c2ecf20Sopenharmony_ci if (offset > pque->entry_size/sizeof(uint32_t) - 1) 45398c2ecf20Sopenharmony_ci goto error_out; 45408c2ecf20Sopenharmony_ci pentry = lpfc_sli4_qe(pque, index); 45418c2ecf20Sopenharmony_ci pentry += offset; 45428c2ecf20Sopenharmony_ci if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_WR) 45438c2ecf20Sopenharmony_ci *pentry = value; 45448c2ecf20Sopenharmony_ci if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_ST) 45458c2ecf20Sopenharmony_ci *pentry |= value; 45468c2ecf20Sopenharmony_ci if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_CL) 45478c2ecf20Sopenharmony_ci *pentry &= ~value; 45488c2ecf20Sopenharmony_ci } 45498c2ecf20Sopenharmony_ci return nbytes; 45508c2ecf20Sopenharmony_ci 45518c2ecf20Sopenharmony_cierror_out: 45528c2ecf20Sopenharmony_ci /* Clean out command structure on command error out */ 45538c2ecf20Sopenharmony_ci memset(&idiag, 0, sizeof(idiag)); 45548c2ecf20Sopenharmony_ci return -EINVAL; 45558c2ecf20Sopenharmony_ci} 45568c2ecf20Sopenharmony_ci 45578c2ecf20Sopenharmony_ci/** 45588c2ecf20Sopenharmony_ci * lpfc_idiag_drbacc_read_reg - idiag debugfs read a doorbell register 45598c2ecf20Sopenharmony_ci * @phba: The pointer to hba structure. 45608c2ecf20Sopenharmony_ci * @pbuffer: The pointer to the buffer to copy the data to. 45618c2ecf20Sopenharmony_ci * @len: The length of bytes to copied. 45628c2ecf20Sopenharmony_ci * @drbregid: The id to doorbell registers. 45638c2ecf20Sopenharmony_ci * 45648c2ecf20Sopenharmony_ci * Description: 45658c2ecf20Sopenharmony_ci * This routine reads a doorbell register and copies its content to the 45668c2ecf20Sopenharmony_ci * user buffer pointed to by @pbuffer. 45678c2ecf20Sopenharmony_ci * 45688c2ecf20Sopenharmony_ci * Returns: 45698c2ecf20Sopenharmony_ci * This function returns the amount of data that was copied into @pbuffer. 45708c2ecf20Sopenharmony_ci **/ 45718c2ecf20Sopenharmony_cistatic int 45728c2ecf20Sopenharmony_cilpfc_idiag_drbacc_read_reg(struct lpfc_hba *phba, char *pbuffer, 45738c2ecf20Sopenharmony_ci int len, uint32_t drbregid) 45748c2ecf20Sopenharmony_ci{ 45758c2ecf20Sopenharmony_ci 45768c2ecf20Sopenharmony_ci if (!pbuffer) 45778c2ecf20Sopenharmony_ci return 0; 45788c2ecf20Sopenharmony_ci 45798c2ecf20Sopenharmony_ci switch (drbregid) { 45808c2ecf20Sopenharmony_ci case LPFC_DRB_EQ: 45818c2ecf20Sopenharmony_ci len += scnprintf(pbuffer + len, LPFC_DRB_ACC_BUF_SIZE-len, 45828c2ecf20Sopenharmony_ci "EQ-DRB-REG: 0x%08x\n", 45838c2ecf20Sopenharmony_ci readl(phba->sli4_hba.EQDBregaddr)); 45848c2ecf20Sopenharmony_ci break; 45858c2ecf20Sopenharmony_ci case LPFC_DRB_CQ: 45868c2ecf20Sopenharmony_ci len += scnprintf(pbuffer + len, LPFC_DRB_ACC_BUF_SIZE - len, 45878c2ecf20Sopenharmony_ci "CQ-DRB-REG: 0x%08x\n", 45888c2ecf20Sopenharmony_ci readl(phba->sli4_hba.CQDBregaddr)); 45898c2ecf20Sopenharmony_ci break; 45908c2ecf20Sopenharmony_ci case LPFC_DRB_MQ: 45918c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_DRB_ACC_BUF_SIZE-len, 45928c2ecf20Sopenharmony_ci "MQ-DRB-REG: 0x%08x\n", 45938c2ecf20Sopenharmony_ci readl(phba->sli4_hba.MQDBregaddr)); 45948c2ecf20Sopenharmony_ci break; 45958c2ecf20Sopenharmony_ci case LPFC_DRB_WQ: 45968c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_DRB_ACC_BUF_SIZE-len, 45978c2ecf20Sopenharmony_ci "WQ-DRB-REG: 0x%08x\n", 45988c2ecf20Sopenharmony_ci readl(phba->sli4_hba.WQDBregaddr)); 45998c2ecf20Sopenharmony_ci break; 46008c2ecf20Sopenharmony_ci case LPFC_DRB_RQ: 46018c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_DRB_ACC_BUF_SIZE-len, 46028c2ecf20Sopenharmony_ci "RQ-DRB-REG: 0x%08x\n", 46038c2ecf20Sopenharmony_ci readl(phba->sli4_hba.RQDBregaddr)); 46048c2ecf20Sopenharmony_ci break; 46058c2ecf20Sopenharmony_ci default: 46068c2ecf20Sopenharmony_ci break; 46078c2ecf20Sopenharmony_ci } 46088c2ecf20Sopenharmony_ci 46098c2ecf20Sopenharmony_ci return len; 46108c2ecf20Sopenharmony_ci} 46118c2ecf20Sopenharmony_ci 46128c2ecf20Sopenharmony_ci/** 46138c2ecf20Sopenharmony_ci * lpfc_idiag_drbacc_read - idiag debugfs read port doorbell 46148c2ecf20Sopenharmony_ci * @file: The file pointer to read from. 46158c2ecf20Sopenharmony_ci * @buf: The buffer to copy the data to. 46168c2ecf20Sopenharmony_ci * @nbytes: The number of bytes to read. 46178c2ecf20Sopenharmony_ci * @ppos: The position in the file to start reading from. 46188c2ecf20Sopenharmony_ci * 46198c2ecf20Sopenharmony_ci * Description: 46208c2ecf20Sopenharmony_ci * This routine reads data from the @phba device doorbell register according 46218c2ecf20Sopenharmony_ci * to the idiag command, and copies to user @buf. Depending on the doorbell 46228c2ecf20Sopenharmony_ci * register read command setup, it does either a single doorbell register 46238c2ecf20Sopenharmony_ci * read or dump all doorbell registers. 46248c2ecf20Sopenharmony_ci * 46258c2ecf20Sopenharmony_ci * Returns: 46268c2ecf20Sopenharmony_ci * This function returns the amount of data that was read (this could be less 46278c2ecf20Sopenharmony_ci * than @nbytes if the end of the file was reached) or a negative error value. 46288c2ecf20Sopenharmony_ci **/ 46298c2ecf20Sopenharmony_cistatic ssize_t 46308c2ecf20Sopenharmony_cilpfc_idiag_drbacc_read(struct file *file, char __user *buf, size_t nbytes, 46318c2ecf20Sopenharmony_ci loff_t *ppos) 46328c2ecf20Sopenharmony_ci{ 46338c2ecf20Sopenharmony_ci struct lpfc_debug *debug = file->private_data; 46348c2ecf20Sopenharmony_ci struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private; 46358c2ecf20Sopenharmony_ci uint32_t drb_reg_id, i; 46368c2ecf20Sopenharmony_ci char *pbuffer; 46378c2ecf20Sopenharmony_ci int len = 0; 46388c2ecf20Sopenharmony_ci 46398c2ecf20Sopenharmony_ci /* This is a user read operation */ 46408c2ecf20Sopenharmony_ci debug->op = LPFC_IDIAG_OP_RD; 46418c2ecf20Sopenharmony_ci 46428c2ecf20Sopenharmony_ci if (!debug->buffer) 46438c2ecf20Sopenharmony_ci debug->buffer = kmalloc(LPFC_DRB_ACC_BUF_SIZE, GFP_KERNEL); 46448c2ecf20Sopenharmony_ci if (!debug->buffer) 46458c2ecf20Sopenharmony_ci return 0; 46468c2ecf20Sopenharmony_ci pbuffer = debug->buffer; 46478c2ecf20Sopenharmony_ci 46488c2ecf20Sopenharmony_ci if (*ppos) 46498c2ecf20Sopenharmony_ci return 0; 46508c2ecf20Sopenharmony_ci 46518c2ecf20Sopenharmony_ci if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_RD) 46528c2ecf20Sopenharmony_ci drb_reg_id = idiag.cmd.data[IDIAG_DRBACC_REGID_INDX]; 46538c2ecf20Sopenharmony_ci else 46548c2ecf20Sopenharmony_ci return 0; 46558c2ecf20Sopenharmony_ci 46568c2ecf20Sopenharmony_ci if (drb_reg_id == LPFC_DRB_ACC_ALL) 46578c2ecf20Sopenharmony_ci for (i = 1; i <= LPFC_DRB_MAX; i++) 46588c2ecf20Sopenharmony_ci len = lpfc_idiag_drbacc_read_reg(phba, 46598c2ecf20Sopenharmony_ci pbuffer, len, i); 46608c2ecf20Sopenharmony_ci else 46618c2ecf20Sopenharmony_ci len = lpfc_idiag_drbacc_read_reg(phba, 46628c2ecf20Sopenharmony_ci pbuffer, len, drb_reg_id); 46638c2ecf20Sopenharmony_ci 46648c2ecf20Sopenharmony_ci return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len); 46658c2ecf20Sopenharmony_ci} 46668c2ecf20Sopenharmony_ci 46678c2ecf20Sopenharmony_ci/** 46688c2ecf20Sopenharmony_ci * lpfc_idiag_drbacc_write - Syntax check and set up idiag drbacc commands 46698c2ecf20Sopenharmony_ci * @file: The file pointer to read from. 46708c2ecf20Sopenharmony_ci * @buf: The buffer to copy the user data from. 46718c2ecf20Sopenharmony_ci * @nbytes: The number of bytes to get. 46728c2ecf20Sopenharmony_ci * @ppos: The position in the file to start reading from. 46738c2ecf20Sopenharmony_ci * 46748c2ecf20Sopenharmony_ci * This routine get the debugfs idiag command struct from user space and then 46758c2ecf20Sopenharmony_ci * perform the syntax check for port doorbell register read (dump) or write 46768c2ecf20Sopenharmony_ci * (set) command accordingly. In the case of port queue read command, it sets 46778c2ecf20Sopenharmony_ci * up the command in the idiag command struct for the following debugfs read 46788c2ecf20Sopenharmony_ci * operation. In the case of port doorbell register write operation, it 46798c2ecf20Sopenharmony_ci * executes the write operation into the port doorbell register accordingly. 46808c2ecf20Sopenharmony_ci * 46818c2ecf20Sopenharmony_ci * It returns the @nbytges passing in from debugfs user space when successful. 46828c2ecf20Sopenharmony_ci * In case of error conditions, it returns proper error code back to the user 46838c2ecf20Sopenharmony_ci * space. 46848c2ecf20Sopenharmony_ci **/ 46858c2ecf20Sopenharmony_cistatic ssize_t 46868c2ecf20Sopenharmony_cilpfc_idiag_drbacc_write(struct file *file, const char __user *buf, 46878c2ecf20Sopenharmony_ci size_t nbytes, loff_t *ppos) 46888c2ecf20Sopenharmony_ci{ 46898c2ecf20Sopenharmony_ci struct lpfc_debug *debug = file->private_data; 46908c2ecf20Sopenharmony_ci struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private; 46918c2ecf20Sopenharmony_ci uint32_t drb_reg_id, value, reg_val = 0; 46928c2ecf20Sopenharmony_ci void __iomem *drb_reg; 46938c2ecf20Sopenharmony_ci int rc; 46948c2ecf20Sopenharmony_ci 46958c2ecf20Sopenharmony_ci /* This is a user write operation */ 46968c2ecf20Sopenharmony_ci debug->op = LPFC_IDIAG_OP_WR; 46978c2ecf20Sopenharmony_ci 46988c2ecf20Sopenharmony_ci rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd); 46998c2ecf20Sopenharmony_ci if (rc < 0) 47008c2ecf20Sopenharmony_ci return rc; 47018c2ecf20Sopenharmony_ci 47028c2ecf20Sopenharmony_ci /* Sanity check on command line arguments */ 47038c2ecf20Sopenharmony_ci drb_reg_id = idiag.cmd.data[IDIAG_DRBACC_REGID_INDX]; 47048c2ecf20Sopenharmony_ci value = idiag.cmd.data[IDIAG_DRBACC_VALUE_INDX]; 47058c2ecf20Sopenharmony_ci 47068c2ecf20Sopenharmony_ci if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_WR || 47078c2ecf20Sopenharmony_ci idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_ST || 47088c2ecf20Sopenharmony_ci idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_CL) { 47098c2ecf20Sopenharmony_ci if (rc != LPFC_DRB_ACC_WR_CMD_ARG) 47108c2ecf20Sopenharmony_ci goto error_out; 47118c2ecf20Sopenharmony_ci if (drb_reg_id > LPFC_DRB_MAX) 47128c2ecf20Sopenharmony_ci goto error_out; 47138c2ecf20Sopenharmony_ci } else if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_RD) { 47148c2ecf20Sopenharmony_ci if (rc != LPFC_DRB_ACC_RD_CMD_ARG) 47158c2ecf20Sopenharmony_ci goto error_out; 47168c2ecf20Sopenharmony_ci if ((drb_reg_id > LPFC_DRB_MAX) && 47178c2ecf20Sopenharmony_ci (drb_reg_id != LPFC_DRB_ACC_ALL)) 47188c2ecf20Sopenharmony_ci goto error_out; 47198c2ecf20Sopenharmony_ci } else 47208c2ecf20Sopenharmony_ci goto error_out; 47218c2ecf20Sopenharmony_ci 47228c2ecf20Sopenharmony_ci /* Perform the write access operation */ 47238c2ecf20Sopenharmony_ci if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_WR || 47248c2ecf20Sopenharmony_ci idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_ST || 47258c2ecf20Sopenharmony_ci idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_CL) { 47268c2ecf20Sopenharmony_ci switch (drb_reg_id) { 47278c2ecf20Sopenharmony_ci case LPFC_DRB_EQ: 47288c2ecf20Sopenharmony_ci drb_reg = phba->sli4_hba.EQDBregaddr; 47298c2ecf20Sopenharmony_ci break; 47308c2ecf20Sopenharmony_ci case LPFC_DRB_CQ: 47318c2ecf20Sopenharmony_ci drb_reg = phba->sli4_hba.CQDBregaddr; 47328c2ecf20Sopenharmony_ci break; 47338c2ecf20Sopenharmony_ci case LPFC_DRB_MQ: 47348c2ecf20Sopenharmony_ci drb_reg = phba->sli4_hba.MQDBregaddr; 47358c2ecf20Sopenharmony_ci break; 47368c2ecf20Sopenharmony_ci case LPFC_DRB_WQ: 47378c2ecf20Sopenharmony_ci drb_reg = phba->sli4_hba.WQDBregaddr; 47388c2ecf20Sopenharmony_ci break; 47398c2ecf20Sopenharmony_ci case LPFC_DRB_RQ: 47408c2ecf20Sopenharmony_ci drb_reg = phba->sli4_hba.RQDBregaddr; 47418c2ecf20Sopenharmony_ci break; 47428c2ecf20Sopenharmony_ci default: 47438c2ecf20Sopenharmony_ci goto error_out; 47448c2ecf20Sopenharmony_ci } 47458c2ecf20Sopenharmony_ci 47468c2ecf20Sopenharmony_ci if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_WR) 47478c2ecf20Sopenharmony_ci reg_val = value; 47488c2ecf20Sopenharmony_ci if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_ST) { 47498c2ecf20Sopenharmony_ci reg_val = readl(drb_reg); 47508c2ecf20Sopenharmony_ci reg_val |= value; 47518c2ecf20Sopenharmony_ci } 47528c2ecf20Sopenharmony_ci if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_CL) { 47538c2ecf20Sopenharmony_ci reg_val = readl(drb_reg); 47548c2ecf20Sopenharmony_ci reg_val &= ~value; 47558c2ecf20Sopenharmony_ci } 47568c2ecf20Sopenharmony_ci writel(reg_val, drb_reg); 47578c2ecf20Sopenharmony_ci readl(drb_reg); /* flush */ 47588c2ecf20Sopenharmony_ci } 47598c2ecf20Sopenharmony_ci return nbytes; 47608c2ecf20Sopenharmony_ci 47618c2ecf20Sopenharmony_cierror_out: 47628c2ecf20Sopenharmony_ci /* Clean out command structure on command error out */ 47638c2ecf20Sopenharmony_ci memset(&idiag, 0, sizeof(idiag)); 47648c2ecf20Sopenharmony_ci return -EINVAL; 47658c2ecf20Sopenharmony_ci} 47668c2ecf20Sopenharmony_ci 47678c2ecf20Sopenharmony_ci/** 47688c2ecf20Sopenharmony_ci * lpfc_idiag_ctlacc_read_reg - idiag debugfs read a control registers 47698c2ecf20Sopenharmony_ci * @phba: The pointer to hba structure. 47708c2ecf20Sopenharmony_ci * @pbuffer: The pointer to the buffer to copy the data to. 47718c2ecf20Sopenharmony_ci * @len: The length of bytes to copied. 47728c2ecf20Sopenharmony_ci * @drbregid: The id to doorbell registers. 47738c2ecf20Sopenharmony_ci * 47748c2ecf20Sopenharmony_ci * Description: 47758c2ecf20Sopenharmony_ci * This routine reads a control register and copies its content to the 47768c2ecf20Sopenharmony_ci * user buffer pointed to by @pbuffer. 47778c2ecf20Sopenharmony_ci * 47788c2ecf20Sopenharmony_ci * Returns: 47798c2ecf20Sopenharmony_ci * This function returns the amount of data that was copied into @pbuffer. 47808c2ecf20Sopenharmony_ci **/ 47818c2ecf20Sopenharmony_cistatic int 47828c2ecf20Sopenharmony_cilpfc_idiag_ctlacc_read_reg(struct lpfc_hba *phba, char *pbuffer, 47838c2ecf20Sopenharmony_ci int len, uint32_t ctlregid) 47848c2ecf20Sopenharmony_ci{ 47858c2ecf20Sopenharmony_ci 47868c2ecf20Sopenharmony_ci if (!pbuffer) 47878c2ecf20Sopenharmony_ci return 0; 47888c2ecf20Sopenharmony_ci 47898c2ecf20Sopenharmony_ci switch (ctlregid) { 47908c2ecf20Sopenharmony_ci case LPFC_CTL_PORT_SEM: 47918c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len, 47928c2ecf20Sopenharmony_ci "Port SemReg: 0x%08x\n", 47938c2ecf20Sopenharmony_ci readl(phba->sli4_hba.conf_regs_memmap_p + 47948c2ecf20Sopenharmony_ci LPFC_CTL_PORT_SEM_OFFSET)); 47958c2ecf20Sopenharmony_ci break; 47968c2ecf20Sopenharmony_ci case LPFC_CTL_PORT_STA: 47978c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len, 47988c2ecf20Sopenharmony_ci "Port StaReg: 0x%08x\n", 47998c2ecf20Sopenharmony_ci readl(phba->sli4_hba.conf_regs_memmap_p + 48008c2ecf20Sopenharmony_ci LPFC_CTL_PORT_STA_OFFSET)); 48018c2ecf20Sopenharmony_ci break; 48028c2ecf20Sopenharmony_ci case LPFC_CTL_PORT_CTL: 48038c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len, 48048c2ecf20Sopenharmony_ci "Port CtlReg: 0x%08x\n", 48058c2ecf20Sopenharmony_ci readl(phba->sli4_hba.conf_regs_memmap_p + 48068c2ecf20Sopenharmony_ci LPFC_CTL_PORT_CTL_OFFSET)); 48078c2ecf20Sopenharmony_ci break; 48088c2ecf20Sopenharmony_ci case LPFC_CTL_PORT_ER1: 48098c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len, 48108c2ecf20Sopenharmony_ci "Port Er1Reg: 0x%08x\n", 48118c2ecf20Sopenharmony_ci readl(phba->sli4_hba.conf_regs_memmap_p + 48128c2ecf20Sopenharmony_ci LPFC_CTL_PORT_ER1_OFFSET)); 48138c2ecf20Sopenharmony_ci break; 48148c2ecf20Sopenharmony_ci case LPFC_CTL_PORT_ER2: 48158c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len, 48168c2ecf20Sopenharmony_ci "Port Er2Reg: 0x%08x\n", 48178c2ecf20Sopenharmony_ci readl(phba->sli4_hba.conf_regs_memmap_p + 48188c2ecf20Sopenharmony_ci LPFC_CTL_PORT_ER2_OFFSET)); 48198c2ecf20Sopenharmony_ci break; 48208c2ecf20Sopenharmony_ci case LPFC_CTL_PDEV_CTL: 48218c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len, 48228c2ecf20Sopenharmony_ci "PDev CtlReg: 0x%08x\n", 48238c2ecf20Sopenharmony_ci readl(phba->sli4_hba.conf_regs_memmap_p + 48248c2ecf20Sopenharmony_ci LPFC_CTL_PDEV_CTL_OFFSET)); 48258c2ecf20Sopenharmony_ci break; 48268c2ecf20Sopenharmony_ci default: 48278c2ecf20Sopenharmony_ci break; 48288c2ecf20Sopenharmony_ci } 48298c2ecf20Sopenharmony_ci return len; 48308c2ecf20Sopenharmony_ci} 48318c2ecf20Sopenharmony_ci 48328c2ecf20Sopenharmony_ci/** 48338c2ecf20Sopenharmony_ci * lpfc_idiag_ctlacc_read - idiag debugfs read port and device control register 48348c2ecf20Sopenharmony_ci * @file: The file pointer to read from. 48358c2ecf20Sopenharmony_ci * @buf: The buffer to copy the data to. 48368c2ecf20Sopenharmony_ci * @nbytes: The number of bytes to read. 48378c2ecf20Sopenharmony_ci * @ppos: The position in the file to start reading from. 48388c2ecf20Sopenharmony_ci * 48398c2ecf20Sopenharmony_ci * Description: 48408c2ecf20Sopenharmony_ci * This routine reads data from the @phba port and device registers according 48418c2ecf20Sopenharmony_ci * to the idiag command, and copies to user @buf. 48428c2ecf20Sopenharmony_ci * 48438c2ecf20Sopenharmony_ci * Returns: 48448c2ecf20Sopenharmony_ci * This function returns the amount of data that was read (this could be less 48458c2ecf20Sopenharmony_ci * than @nbytes if the end of the file was reached) or a negative error value. 48468c2ecf20Sopenharmony_ci **/ 48478c2ecf20Sopenharmony_cistatic ssize_t 48488c2ecf20Sopenharmony_cilpfc_idiag_ctlacc_read(struct file *file, char __user *buf, size_t nbytes, 48498c2ecf20Sopenharmony_ci loff_t *ppos) 48508c2ecf20Sopenharmony_ci{ 48518c2ecf20Sopenharmony_ci struct lpfc_debug *debug = file->private_data; 48528c2ecf20Sopenharmony_ci struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private; 48538c2ecf20Sopenharmony_ci uint32_t ctl_reg_id, i; 48548c2ecf20Sopenharmony_ci char *pbuffer; 48558c2ecf20Sopenharmony_ci int len = 0; 48568c2ecf20Sopenharmony_ci 48578c2ecf20Sopenharmony_ci /* This is a user read operation */ 48588c2ecf20Sopenharmony_ci debug->op = LPFC_IDIAG_OP_RD; 48598c2ecf20Sopenharmony_ci 48608c2ecf20Sopenharmony_ci if (!debug->buffer) 48618c2ecf20Sopenharmony_ci debug->buffer = kmalloc(LPFC_CTL_ACC_BUF_SIZE, GFP_KERNEL); 48628c2ecf20Sopenharmony_ci if (!debug->buffer) 48638c2ecf20Sopenharmony_ci return 0; 48648c2ecf20Sopenharmony_ci pbuffer = debug->buffer; 48658c2ecf20Sopenharmony_ci 48668c2ecf20Sopenharmony_ci if (*ppos) 48678c2ecf20Sopenharmony_ci return 0; 48688c2ecf20Sopenharmony_ci 48698c2ecf20Sopenharmony_ci if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_RD) 48708c2ecf20Sopenharmony_ci ctl_reg_id = idiag.cmd.data[IDIAG_CTLACC_REGID_INDX]; 48718c2ecf20Sopenharmony_ci else 48728c2ecf20Sopenharmony_ci return 0; 48738c2ecf20Sopenharmony_ci 48748c2ecf20Sopenharmony_ci if (ctl_reg_id == LPFC_CTL_ACC_ALL) 48758c2ecf20Sopenharmony_ci for (i = 1; i <= LPFC_CTL_MAX; i++) 48768c2ecf20Sopenharmony_ci len = lpfc_idiag_ctlacc_read_reg(phba, 48778c2ecf20Sopenharmony_ci pbuffer, len, i); 48788c2ecf20Sopenharmony_ci else 48798c2ecf20Sopenharmony_ci len = lpfc_idiag_ctlacc_read_reg(phba, 48808c2ecf20Sopenharmony_ci pbuffer, len, ctl_reg_id); 48818c2ecf20Sopenharmony_ci 48828c2ecf20Sopenharmony_ci return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len); 48838c2ecf20Sopenharmony_ci} 48848c2ecf20Sopenharmony_ci 48858c2ecf20Sopenharmony_ci/** 48868c2ecf20Sopenharmony_ci * lpfc_idiag_ctlacc_write - Syntax check and set up idiag ctlacc commands 48878c2ecf20Sopenharmony_ci * @file: The file pointer to read from. 48888c2ecf20Sopenharmony_ci * @buf: The buffer to copy the user data from. 48898c2ecf20Sopenharmony_ci * @nbytes: The number of bytes to get. 48908c2ecf20Sopenharmony_ci * @ppos: The position in the file to start reading from. 48918c2ecf20Sopenharmony_ci * 48928c2ecf20Sopenharmony_ci * This routine get the debugfs idiag command struct from user space and then 48938c2ecf20Sopenharmony_ci * perform the syntax check for port and device control register read (dump) 48948c2ecf20Sopenharmony_ci * or write (set) command accordingly. 48958c2ecf20Sopenharmony_ci * 48968c2ecf20Sopenharmony_ci * It returns the @nbytges passing in from debugfs user space when successful. 48978c2ecf20Sopenharmony_ci * In case of error conditions, it returns proper error code back to the user 48988c2ecf20Sopenharmony_ci * space. 48998c2ecf20Sopenharmony_ci **/ 49008c2ecf20Sopenharmony_cistatic ssize_t 49018c2ecf20Sopenharmony_cilpfc_idiag_ctlacc_write(struct file *file, const char __user *buf, 49028c2ecf20Sopenharmony_ci size_t nbytes, loff_t *ppos) 49038c2ecf20Sopenharmony_ci{ 49048c2ecf20Sopenharmony_ci struct lpfc_debug *debug = file->private_data; 49058c2ecf20Sopenharmony_ci struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private; 49068c2ecf20Sopenharmony_ci uint32_t ctl_reg_id, value, reg_val = 0; 49078c2ecf20Sopenharmony_ci void __iomem *ctl_reg; 49088c2ecf20Sopenharmony_ci int rc; 49098c2ecf20Sopenharmony_ci 49108c2ecf20Sopenharmony_ci /* This is a user write operation */ 49118c2ecf20Sopenharmony_ci debug->op = LPFC_IDIAG_OP_WR; 49128c2ecf20Sopenharmony_ci 49138c2ecf20Sopenharmony_ci rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd); 49148c2ecf20Sopenharmony_ci if (rc < 0) 49158c2ecf20Sopenharmony_ci return rc; 49168c2ecf20Sopenharmony_ci 49178c2ecf20Sopenharmony_ci /* Sanity check on command line arguments */ 49188c2ecf20Sopenharmony_ci ctl_reg_id = idiag.cmd.data[IDIAG_CTLACC_REGID_INDX]; 49198c2ecf20Sopenharmony_ci value = idiag.cmd.data[IDIAG_CTLACC_VALUE_INDX]; 49208c2ecf20Sopenharmony_ci 49218c2ecf20Sopenharmony_ci if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_WR || 49228c2ecf20Sopenharmony_ci idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_ST || 49238c2ecf20Sopenharmony_ci idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_CL) { 49248c2ecf20Sopenharmony_ci if (rc != LPFC_CTL_ACC_WR_CMD_ARG) 49258c2ecf20Sopenharmony_ci goto error_out; 49268c2ecf20Sopenharmony_ci if (ctl_reg_id > LPFC_CTL_MAX) 49278c2ecf20Sopenharmony_ci goto error_out; 49288c2ecf20Sopenharmony_ci } else if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_RD) { 49298c2ecf20Sopenharmony_ci if (rc != LPFC_CTL_ACC_RD_CMD_ARG) 49308c2ecf20Sopenharmony_ci goto error_out; 49318c2ecf20Sopenharmony_ci if ((ctl_reg_id > LPFC_CTL_MAX) && 49328c2ecf20Sopenharmony_ci (ctl_reg_id != LPFC_CTL_ACC_ALL)) 49338c2ecf20Sopenharmony_ci goto error_out; 49348c2ecf20Sopenharmony_ci } else 49358c2ecf20Sopenharmony_ci goto error_out; 49368c2ecf20Sopenharmony_ci 49378c2ecf20Sopenharmony_ci /* Perform the write access operation */ 49388c2ecf20Sopenharmony_ci if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_WR || 49398c2ecf20Sopenharmony_ci idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_ST || 49408c2ecf20Sopenharmony_ci idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_CL) { 49418c2ecf20Sopenharmony_ci switch (ctl_reg_id) { 49428c2ecf20Sopenharmony_ci case LPFC_CTL_PORT_SEM: 49438c2ecf20Sopenharmony_ci ctl_reg = phba->sli4_hba.conf_regs_memmap_p + 49448c2ecf20Sopenharmony_ci LPFC_CTL_PORT_SEM_OFFSET; 49458c2ecf20Sopenharmony_ci break; 49468c2ecf20Sopenharmony_ci case LPFC_CTL_PORT_STA: 49478c2ecf20Sopenharmony_ci ctl_reg = phba->sli4_hba.conf_regs_memmap_p + 49488c2ecf20Sopenharmony_ci LPFC_CTL_PORT_STA_OFFSET; 49498c2ecf20Sopenharmony_ci break; 49508c2ecf20Sopenharmony_ci case LPFC_CTL_PORT_CTL: 49518c2ecf20Sopenharmony_ci ctl_reg = phba->sli4_hba.conf_regs_memmap_p + 49528c2ecf20Sopenharmony_ci LPFC_CTL_PORT_CTL_OFFSET; 49538c2ecf20Sopenharmony_ci break; 49548c2ecf20Sopenharmony_ci case LPFC_CTL_PORT_ER1: 49558c2ecf20Sopenharmony_ci ctl_reg = phba->sli4_hba.conf_regs_memmap_p + 49568c2ecf20Sopenharmony_ci LPFC_CTL_PORT_ER1_OFFSET; 49578c2ecf20Sopenharmony_ci break; 49588c2ecf20Sopenharmony_ci case LPFC_CTL_PORT_ER2: 49598c2ecf20Sopenharmony_ci ctl_reg = phba->sli4_hba.conf_regs_memmap_p + 49608c2ecf20Sopenharmony_ci LPFC_CTL_PORT_ER2_OFFSET; 49618c2ecf20Sopenharmony_ci break; 49628c2ecf20Sopenharmony_ci case LPFC_CTL_PDEV_CTL: 49638c2ecf20Sopenharmony_ci ctl_reg = phba->sli4_hba.conf_regs_memmap_p + 49648c2ecf20Sopenharmony_ci LPFC_CTL_PDEV_CTL_OFFSET; 49658c2ecf20Sopenharmony_ci break; 49668c2ecf20Sopenharmony_ci default: 49678c2ecf20Sopenharmony_ci goto error_out; 49688c2ecf20Sopenharmony_ci } 49698c2ecf20Sopenharmony_ci 49708c2ecf20Sopenharmony_ci if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_WR) 49718c2ecf20Sopenharmony_ci reg_val = value; 49728c2ecf20Sopenharmony_ci if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_ST) { 49738c2ecf20Sopenharmony_ci reg_val = readl(ctl_reg); 49748c2ecf20Sopenharmony_ci reg_val |= value; 49758c2ecf20Sopenharmony_ci } 49768c2ecf20Sopenharmony_ci if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_CL) { 49778c2ecf20Sopenharmony_ci reg_val = readl(ctl_reg); 49788c2ecf20Sopenharmony_ci reg_val &= ~value; 49798c2ecf20Sopenharmony_ci } 49808c2ecf20Sopenharmony_ci writel(reg_val, ctl_reg); 49818c2ecf20Sopenharmony_ci readl(ctl_reg); /* flush */ 49828c2ecf20Sopenharmony_ci } 49838c2ecf20Sopenharmony_ci return nbytes; 49848c2ecf20Sopenharmony_ci 49858c2ecf20Sopenharmony_cierror_out: 49868c2ecf20Sopenharmony_ci /* Clean out command structure on command error out */ 49878c2ecf20Sopenharmony_ci memset(&idiag, 0, sizeof(idiag)); 49888c2ecf20Sopenharmony_ci return -EINVAL; 49898c2ecf20Sopenharmony_ci} 49908c2ecf20Sopenharmony_ci 49918c2ecf20Sopenharmony_ci/** 49928c2ecf20Sopenharmony_ci * lpfc_idiag_mbxacc_get_setup - idiag debugfs get mailbox access setup 49938c2ecf20Sopenharmony_ci * @phba: Pointer to HBA context object. 49948c2ecf20Sopenharmony_ci * @pbuffer: Pointer to data buffer. 49958c2ecf20Sopenharmony_ci * 49968c2ecf20Sopenharmony_ci * Description: 49978c2ecf20Sopenharmony_ci * This routine gets the driver mailbox access debugfs setup information. 49988c2ecf20Sopenharmony_ci * 49998c2ecf20Sopenharmony_ci * Returns: 50008c2ecf20Sopenharmony_ci * This function returns the amount of data that was read (this could be less 50018c2ecf20Sopenharmony_ci * than @nbytes if the end of the file was reached) or a negative error value. 50028c2ecf20Sopenharmony_ci **/ 50038c2ecf20Sopenharmony_cistatic int 50048c2ecf20Sopenharmony_cilpfc_idiag_mbxacc_get_setup(struct lpfc_hba *phba, char *pbuffer) 50058c2ecf20Sopenharmony_ci{ 50068c2ecf20Sopenharmony_ci uint32_t mbx_dump_map, mbx_dump_cnt, mbx_word_cnt, mbx_mbox_cmd; 50078c2ecf20Sopenharmony_ci int len = 0; 50088c2ecf20Sopenharmony_ci 50098c2ecf20Sopenharmony_ci mbx_mbox_cmd = idiag.cmd.data[IDIAG_MBXACC_MBCMD_INDX]; 50108c2ecf20Sopenharmony_ci mbx_dump_map = idiag.cmd.data[IDIAG_MBXACC_DPMAP_INDX]; 50118c2ecf20Sopenharmony_ci mbx_dump_cnt = idiag.cmd.data[IDIAG_MBXACC_DPCNT_INDX]; 50128c2ecf20Sopenharmony_ci mbx_word_cnt = idiag.cmd.data[IDIAG_MBXACC_WDCNT_INDX]; 50138c2ecf20Sopenharmony_ci 50148c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_MBX_ACC_BUF_SIZE-len, 50158c2ecf20Sopenharmony_ci "mbx_dump_map: 0x%08x\n", mbx_dump_map); 50168c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_MBX_ACC_BUF_SIZE-len, 50178c2ecf20Sopenharmony_ci "mbx_dump_cnt: %04d\n", mbx_dump_cnt); 50188c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_MBX_ACC_BUF_SIZE-len, 50198c2ecf20Sopenharmony_ci "mbx_word_cnt: %04d\n", mbx_word_cnt); 50208c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_MBX_ACC_BUF_SIZE-len, 50218c2ecf20Sopenharmony_ci "mbx_mbox_cmd: 0x%02x\n", mbx_mbox_cmd); 50228c2ecf20Sopenharmony_ci 50238c2ecf20Sopenharmony_ci return len; 50248c2ecf20Sopenharmony_ci} 50258c2ecf20Sopenharmony_ci 50268c2ecf20Sopenharmony_ci/** 50278c2ecf20Sopenharmony_ci * lpfc_idiag_mbxacc_read - idiag debugfs read on mailbox access 50288c2ecf20Sopenharmony_ci * @file: The file pointer to read from. 50298c2ecf20Sopenharmony_ci * @buf: The buffer to copy the data to. 50308c2ecf20Sopenharmony_ci * @nbytes: The number of bytes to read. 50318c2ecf20Sopenharmony_ci * @ppos: The position in the file to start reading from. 50328c2ecf20Sopenharmony_ci * 50338c2ecf20Sopenharmony_ci * Description: 50348c2ecf20Sopenharmony_ci * This routine reads data from the @phba driver mailbox access debugfs setup 50358c2ecf20Sopenharmony_ci * information. 50368c2ecf20Sopenharmony_ci * 50378c2ecf20Sopenharmony_ci * Returns: 50388c2ecf20Sopenharmony_ci * This function returns the amount of data that was read (this could be less 50398c2ecf20Sopenharmony_ci * than @nbytes if the end of the file was reached) or a negative error value. 50408c2ecf20Sopenharmony_ci **/ 50418c2ecf20Sopenharmony_cistatic ssize_t 50428c2ecf20Sopenharmony_cilpfc_idiag_mbxacc_read(struct file *file, char __user *buf, size_t nbytes, 50438c2ecf20Sopenharmony_ci loff_t *ppos) 50448c2ecf20Sopenharmony_ci{ 50458c2ecf20Sopenharmony_ci struct lpfc_debug *debug = file->private_data; 50468c2ecf20Sopenharmony_ci struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private; 50478c2ecf20Sopenharmony_ci char *pbuffer; 50488c2ecf20Sopenharmony_ci int len = 0; 50498c2ecf20Sopenharmony_ci 50508c2ecf20Sopenharmony_ci /* This is a user read operation */ 50518c2ecf20Sopenharmony_ci debug->op = LPFC_IDIAG_OP_RD; 50528c2ecf20Sopenharmony_ci 50538c2ecf20Sopenharmony_ci if (!debug->buffer) 50548c2ecf20Sopenharmony_ci debug->buffer = kmalloc(LPFC_MBX_ACC_BUF_SIZE, GFP_KERNEL); 50558c2ecf20Sopenharmony_ci if (!debug->buffer) 50568c2ecf20Sopenharmony_ci return 0; 50578c2ecf20Sopenharmony_ci pbuffer = debug->buffer; 50588c2ecf20Sopenharmony_ci 50598c2ecf20Sopenharmony_ci if (*ppos) 50608c2ecf20Sopenharmony_ci return 0; 50618c2ecf20Sopenharmony_ci 50628c2ecf20Sopenharmony_ci if ((idiag.cmd.opcode != LPFC_IDIAG_CMD_MBXACC_DP) && 50638c2ecf20Sopenharmony_ci (idiag.cmd.opcode != LPFC_IDIAG_BSG_MBXACC_DP)) 50648c2ecf20Sopenharmony_ci return 0; 50658c2ecf20Sopenharmony_ci 50668c2ecf20Sopenharmony_ci len = lpfc_idiag_mbxacc_get_setup(phba, pbuffer); 50678c2ecf20Sopenharmony_ci 50688c2ecf20Sopenharmony_ci return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len); 50698c2ecf20Sopenharmony_ci} 50708c2ecf20Sopenharmony_ci 50718c2ecf20Sopenharmony_ci/** 50728c2ecf20Sopenharmony_ci * lpfc_idiag_mbxacc_write - Syntax check and set up idiag mbxacc commands 50738c2ecf20Sopenharmony_ci * @file: The file pointer to read from. 50748c2ecf20Sopenharmony_ci * @buf: The buffer to copy the user data from. 50758c2ecf20Sopenharmony_ci * @nbytes: The number of bytes to get. 50768c2ecf20Sopenharmony_ci * @ppos: The position in the file to start reading from. 50778c2ecf20Sopenharmony_ci * 50788c2ecf20Sopenharmony_ci * This routine get the debugfs idiag command struct from user space and then 50798c2ecf20Sopenharmony_ci * perform the syntax check for driver mailbox command (dump) and sets up the 50808c2ecf20Sopenharmony_ci * necessary states in the idiag command struct accordingly. 50818c2ecf20Sopenharmony_ci * 50828c2ecf20Sopenharmony_ci * It returns the @nbytges passing in from debugfs user space when successful. 50838c2ecf20Sopenharmony_ci * In case of error conditions, it returns proper error code back to the user 50848c2ecf20Sopenharmony_ci * space. 50858c2ecf20Sopenharmony_ci **/ 50868c2ecf20Sopenharmony_cistatic ssize_t 50878c2ecf20Sopenharmony_cilpfc_idiag_mbxacc_write(struct file *file, const char __user *buf, 50888c2ecf20Sopenharmony_ci size_t nbytes, loff_t *ppos) 50898c2ecf20Sopenharmony_ci{ 50908c2ecf20Sopenharmony_ci struct lpfc_debug *debug = file->private_data; 50918c2ecf20Sopenharmony_ci uint32_t mbx_dump_map, mbx_dump_cnt, mbx_word_cnt, mbx_mbox_cmd; 50928c2ecf20Sopenharmony_ci int rc; 50938c2ecf20Sopenharmony_ci 50948c2ecf20Sopenharmony_ci /* This is a user write operation */ 50958c2ecf20Sopenharmony_ci debug->op = LPFC_IDIAG_OP_WR; 50968c2ecf20Sopenharmony_ci 50978c2ecf20Sopenharmony_ci rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd); 50988c2ecf20Sopenharmony_ci if (rc < 0) 50998c2ecf20Sopenharmony_ci return rc; 51008c2ecf20Sopenharmony_ci 51018c2ecf20Sopenharmony_ci /* Sanity check on command line arguments */ 51028c2ecf20Sopenharmony_ci mbx_mbox_cmd = idiag.cmd.data[IDIAG_MBXACC_MBCMD_INDX]; 51038c2ecf20Sopenharmony_ci mbx_dump_map = idiag.cmd.data[IDIAG_MBXACC_DPMAP_INDX]; 51048c2ecf20Sopenharmony_ci mbx_dump_cnt = idiag.cmd.data[IDIAG_MBXACC_DPCNT_INDX]; 51058c2ecf20Sopenharmony_ci mbx_word_cnt = idiag.cmd.data[IDIAG_MBXACC_WDCNT_INDX]; 51068c2ecf20Sopenharmony_ci 51078c2ecf20Sopenharmony_ci if (idiag.cmd.opcode == LPFC_IDIAG_CMD_MBXACC_DP) { 51088c2ecf20Sopenharmony_ci if (!(mbx_dump_map & LPFC_MBX_DMP_MBX_ALL)) 51098c2ecf20Sopenharmony_ci goto error_out; 51108c2ecf20Sopenharmony_ci if ((mbx_dump_map & ~LPFC_MBX_DMP_MBX_ALL) && 51118c2ecf20Sopenharmony_ci (mbx_dump_map != LPFC_MBX_DMP_ALL)) 51128c2ecf20Sopenharmony_ci goto error_out; 51138c2ecf20Sopenharmony_ci if (mbx_word_cnt > sizeof(MAILBOX_t)) 51148c2ecf20Sopenharmony_ci goto error_out; 51158c2ecf20Sopenharmony_ci } else if (idiag.cmd.opcode == LPFC_IDIAG_BSG_MBXACC_DP) { 51168c2ecf20Sopenharmony_ci if (!(mbx_dump_map & LPFC_BSG_DMP_MBX_ALL)) 51178c2ecf20Sopenharmony_ci goto error_out; 51188c2ecf20Sopenharmony_ci if ((mbx_dump_map & ~LPFC_BSG_DMP_MBX_ALL) && 51198c2ecf20Sopenharmony_ci (mbx_dump_map != LPFC_MBX_DMP_ALL)) 51208c2ecf20Sopenharmony_ci goto error_out; 51218c2ecf20Sopenharmony_ci if (mbx_word_cnt > (BSG_MBOX_SIZE)/4) 51228c2ecf20Sopenharmony_ci goto error_out; 51238c2ecf20Sopenharmony_ci if (mbx_mbox_cmd != 0x9b) 51248c2ecf20Sopenharmony_ci goto error_out; 51258c2ecf20Sopenharmony_ci } else 51268c2ecf20Sopenharmony_ci goto error_out; 51278c2ecf20Sopenharmony_ci 51288c2ecf20Sopenharmony_ci if (mbx_word_cnt == 0) 51298c2ecf20Sopenharmony_ci goto error_out; 51308c2ecf20Sopenharmony_ci if (rc != LPFC_MBX_DMP_ARG) 51318c2ecf20Sopenharmony_ci goto error_out; 51328c2ecf20Sopenharmony_ci if (mbx_mbox_cmd & ~0xff) 51338c2ecf20Sopenharmony_ci goto error_out; 51348c2ecf20Sopenharmony_ci 51358c2ecf20Sopenharmony_ci /* condition for stop mailbox dump */ 51368c2ecf20Sopenharmony_ci if (mbx_dump_cnt == 0) 51378c2ecf20Sopenharmony_ci goto reset_out; 51388c2ecf20Sopenharmony_ci 51398c2ecf20Sopenharmony_ci return nbytes; 51408c2ecf20Sopenharmony_ci 51418c2ecf20Sopenharmony_cireset_out: 51428c2ecf20Sopenharmony_ci /* Clean out command structure on command error out */ 51438c2ecf20Sopenharmony_ci memset(&idiag, 0, sizeof(idiag)); 51448c2ecf20Sopenharmony_ci return nbytes; 51458c2ecf20Sopenharmony_ci 51468c2ecf20Sopenharmony_cierror_out: 51478c2ecf20Sopenharmony_ci /* Clean out command structure on command error out */ 51488c2ecf20Sopenharmony_ci memset(&idiag, 0, sizeof(idiag)); 51498c2ecf20Sopenharmony_ci return -EINVAL; 51508c2ecf20Sopenharmony_ci} 51518c2ecf20Sopenharmony_ci 51528c2ecf20Sopenharmony_ci/** 51538c2ecf20Sopenharmony_ci * lpfc_idiag_extacc_avail_get - get the available extents information 51548c2ecf20Sopenharmony_ci * @phba: pointer to lpfc hba data structure. 51558c2ecf20Sopenharmony_ci * @pbuffer: pointer to internal buffer. 51568c2ecf20Sopenharmony_ci * @len: length into the internal buffer data has been copied. 51578c2ecf20Sopenharmony_ci * 51588c2ecf20Sopenharmony_ci * Description: 51598c2ecf20Sopenharmony_ci * This routine is to get the available extent information. 51608c2ecf20Sopenharmony_ci * 51618c2ecf20Sopenharmony_ci * Returns: 51628c2ecf20Sopenharmony_ci * overall lenth of the data read into the internal buffer. 51638c2ecf20Sopenharmony_ci **/ 51648c2ecf20Sopenharmony_cistatic int 51658c2ecf20Sopenharmony_cilpfc_idiag_extacc_avail_get(struct lpfc_hba *phba, char *pbuffer, int len) 51668c2ecf20Sopenharmony_ci{ 51678c2ecf20Sopenharmony_ci uint16_t ext_cnt, ext_size; 51688c2ecf20Sopenharmony_ci 51698c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, 51708c2ecf20Sopenharmony_ci "\nAvailable Extents Information:\n"); 51718c2ecf20Sopenharmony_ci 51728c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, 51738c2ecf20Sopenharmony_ci "\tPort Available VPI extents: "); 51748c2ecf20Sopenharmony_ci lpfc_sli4_get_avail_extnt_rsrc(phba, LPFC_RSC_TYPE_FCOE_VPI, 51758c2ecf20Sopenharmony_ci &ext_cnt, &ext_size); 51768c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, 51778c2ecf20Sopenharmony_ci "Count %3d, Size %3d\n", ext_cnt, ext_size); 51788c2ecf20Sopenharmony_ci 51798c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, 51808c2ecf20Sopenharmony_ci "\tPort Available VFI extents: "); 51818c2ecf20Sopenharmony_ci lpfc_sli4_get_avail_extnt_rsrc(phba, LPFC_RSC_TYPE_FCOE_VFI, 51828c2ecf20Sopenharmony_ci &ext_cnt, &ext_size); 51838c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, 51848c2ecf20Sopenharmony_ci "Count %3d, Size %3d\n", ext_cnt, ext_size); 51858c2ecf20Sopenharmony_ci 51868c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, 51878c2ecf20Sopenharmony_ci "\tPort Available RPI extents: "); 51888c2ecf20Sopenharmony_ci lpfc_sli4_get_avail_extnt_rsrc(phba, LPFC_RSC_TYPE_FCOE_RPI, 51898c2ecf20Sopenharmony_ci &ext_cnt, &ext_size); 51908c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, 51918c2ecf20Sopenharmony_ci "Count %3d, Size %3d\n", ext_cnt, ext_size); 51928c2ecf20Sopenharmony_ci 51938c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, 51948c2ecf20Sopenharmony_ci "\tPort Available XRI extents: "); 51958c2ecf20Sopenharmony_ci lpfc_sli4_get_avail_extnt_rsrc(phba, LPFC_RSC_TYPE_FCOE_XRI, 51968c2ecf20Sopenharmony_ci &ext_cnt, &ext_size); 51978c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, 51988c2ecf20Sopenharmony_ci "Count %3d, Size %3d\n", ext_cnt, ext_size); 51998c2ecf20Sopenharmony_ci 52008c2ecf20Sopenharmony_ci return len; 52018c2ecf20Sopenharmony_ci} 52028c2ecf20Sopenharmony_ci 52038c2ecf20Sopenharmony_ci/** 52048c2ecf20Sopenharmony_ci * lpfc_idiag_extacc_alloc_get - get the allocated extents information 52058c2ecf20Sopenharmony_ci * @phba: pointer to lpfc hba data structure. 52068c2ecf20Sopenharmony_ci * @pbuffer: pointer to internal buffer. 52078c2ecf20Sopenharmony_ci * @len: length into the internal buffer data has been copied. 52088c2ecf20Sopenharmony_ci * 52098c2ecf20Sopenharmony_ci * Description: 52108c2ecf20Sopenharmony_ci * This routine is to get the allocated extent information. 52118c2ecf20Sopenharmony_ci * 52128c2ecf20Sopenharmony_ci * Returns: 52138c2ecf20Sopenharmony_ci * overall lenth of the data read into the internal buffer. 52148c2ecf20Sopenharmony_ci **/ 52158c2ecf20Sopenharmony_cistatic int 52168c2ecf20Sopenharmony_cilpfc_idiag_extacc_alloc_get(struct lpfc_hba *phba, char *pbuffer, int len) 52178c2ecf20Sopenharmony_ci{ 52188c2ecf20Sopenharmony_ci uint16_t ext_cnt, ext_size; 52198c2ecf20Sopenharmony_ci int rc; 52208c2ecf20Sopenharmony_ci 52218c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, 52228c2ecf20Sopenharmony_ci "\nAllocated Extents Information:\n"); 52238c2ecf20Sopenharmony_ci 52248c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, 52258c2ecf20Sopenharmony_ci "\tHost Allocated VPI extents: "); 52268c2ecf20Sopenharmony_ci rc = lpfc_sli4_get_allocated_extnts(phba, LPFC_RSC_TYPE_FCOE_VPI, 52278c2ecf20Sopenharmony_ci &ext_cnt, &ext_size); 52288c2ecf20Sopenharmony_ci if (!rc) 52298c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, 52308c2ecf20Sopenharmony_ci "Port %d Extent %3d, Size %3d\n", 52318c2ecf20Sopenharmony_ci phba->brd_no, ext_cnt, ext_size); 52328c2ecf20Sopenharmony_ci else 52338c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, 52348c2ecf20Sopenharmony_ci "N/A\n"); 52358c2ecf20Sopenharmony_ci 52368c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, 52378c2ecf20Sopenharmony_ci "\tHost Allocated VFI extents: "); 52388c2ecf20Sopenharmony_ci rc = lpfc_sli4_get_allocated_extnts(phba, LPFC_RSC_TYPE_FCOE_VFI, 52398c2ecf20Sopenharmony_ci &ext_cnt, &ext_size); 52408c2ecf20Sopenharmony_ci if (!rc) 52418c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, 52428c2ecf20Sopenharmony_ci "Port %d Extent %3d, Size %3d\n", 52438c2ecf20Sopenharmony_ci phba->brd_no, ext_cnt, ext_size); 52448c2ecf20Sopenharmony_ci else 52458c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, 52468c2ecf20Sopenharmony_ci "N/A\n"); 52478c2ecf20Sopenharmony_ci 52488c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, 52498c2ecf20Sopenharmony_ci "\tHost Allocated RPI extents: "); 52508c2ecf20Sopenharmony_ci rc = lpfc_sli4_get_allocated_extnts(phba, LPFC_RSC_TYPE_FCOE_RPI, 52518c2ecf20Sopenharmony_ci &ext_cnt, &ext_size); 52528c2ecf20Sopenharmony_ci if (!rc) 52538c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, 52548c2ecf20Sopenharmony_ci "Port %d Extent %3d, Size %3d\n", 52558c2ecf20Sopenharmony_ci phba->brd_no, ext_cnt, ext_size); 52568c2ecf20Sopenharmony_ci else 52578c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, 52588c2ecf20Sopenharmony_ci "N/A\n"); 52598c2ecf20Sopenharmony_ci 52608c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, 52618c2ecf20Sopenharmony_ci "\tHost Allocated XRI extents: "); 52628c2ecf20Sopenharmony_ci rc = lpfc_sli4_get_allocated_extnts(phba, LPFC_RSC_TYPE_FCOE_XRI, 52638c2ecf20Sopenharmony_ci &ext_cnt, &ext_size); 52648c2ecf20Sopenharmony_ci if (!rc) 52658c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, 52668c2ecf20Sopenharmony_ci "Port %d Extent %3d, Size %3d\n", 52678c2ecf20Sopenharmony_ci phba->brd_no, ext_cnt, ext_size); 52688c2ecf20Sopenharmony_ci else 52698c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, 52708c2ecf20Sopenharmony_ci "N/A\n"); 52718c2ecf20Sopenharmony_ci 52728c2ecf20Sopenharmony_ci return len; 52738c2ecf20Sopenharmony_ci} 52748c2ecf20Sopenharmony_ci 52758c2ecf20Sopenharmony_ci/** 52768c2ecf20Sopenharmony_ci * lpfc_idiag_extacc_drivr_get - get driver extent information 52778c2ecf20Sopenharmony_ci * @phba: pointer to lpfc hba data structure. 52788c2ecf20Sopenharmony_ci * @pbuffer: pointer to internal buffer. 52798c2ecf20Sopenharmony_ci * @len: length into the internal buffer data has been copied. 52808c2ecf20Sopenharmony_ci * 52818c2ecf20Sopenharmony_ci * Description: 52828c2ecf20Sopenharmony_ci * This routine is to get the driver extent information. 52838c2ecf20Sopenharmony_ci * 52848c2ecf20Sopenharmony_ci * Returns: 52858c2ecf20Sopenharmony_ci * overall lenth of the data read into the internal buffer. 52868c2ecf20Sopenharmony_ci **/ 52878c2ecf20Sopenharmony_cistatic int 52888c2ecf20Sopenharmony_cilpfc_idiag_extacc_drivr_get(struct lpfc_hba *phba, char *pbuffer, int len) 52898c2ecf20Sopenharmony_ci{ 52908c2ecf20Sopenharmony_ci struct lpfc_rsrc_blks *rsrc_blks; 52918c2ecf20Sopenharmony_ci int index; 52928c2ecf20Sopenharmony_ci 52938c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, 52948c2ecf20Sopenharmony_ci "\nDriver Extents Information:\n"); 52958c2ecf20Sopenharmony_ci 52968c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, 52978c2ecf20Sopenharmony_ci "\tVPI extents:\n"); 52988c2ecf20Sopenharmony_ci index = 0; 52998c2ecf20Sopenharmony_ci list_for_each_entry(rsrc_blks, &phba->lpfc_vpi_blk_list, list) { 53008c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, 53018c2ecf20Sopenharmony_ci "\t\tBlock %3d: Start %4d, Count %4d\n", 53028c2ecf20Sopenharmony_ci index, rsrc_blks->rsrc_start, 53038c2ecf20Sopenharmony_ci rsrc_blks->rsrc_size); 53048c2ecf20Sopenharmony_ci index++; 53058c2ecf20Sopenharmony_ci } 53068c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, 53078c2ecf20Sopenharmony_ci "\tVFI extents:\n"); 53088c2ecf20Sopenharmony_ci index = 0; 53098c2ecf20Sopenharmony_ci list_for_each_entry(rsrc_blks, &phba->sli4_hba.lpfc_vfi_blk_list, 53108c2ecf20Sopenharmony_ci list) { 53118c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, 53128c2ecf20Sopenharmony_ci "\t\tBlock %3d: Start %4d, Count %4d\n", 53138c2ecf20Sopenharmony_ci index, rsrc_blks->rsrc_start, 53148c2ecf20Sopenharmony_ci rsrc_blks->rsrc_size); 53158c2ecf20Sopenharmony_ci index++; 53168c2ecf20Sopenharmony_ci } 53178c2ecf20Sopenharmony_ci 53188c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, 53198c2ecf20Sopenharmony_ci "\tRPI extents:\n"); 53208c2ecf20Sopenharmony_ci index = 0; 53218c2ecf20Sopenharmony_ci list_for_each_entry(rsrc_blks, &phba->sli4_hba.lpfc_rpi_blk_list, 53228c2ecf20Sopenharmony_ci list) { 53238c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, 53248c2ecf20Sopenharmony_ci "\t\tBlock %3d: Start %4d, Count %4d\n", 53258c2ecf20Sopenharmony_ci index, rsrc_blks->rsrc_start, 53268c2ecf20Sopenharmony_ci rsrc_blks->rsrc_size); 53278c2ecf20Sopenharmony_ci index++; 53288c2ecf20Sopenharmony_ci } 53298c2ecf20Sopenharmony_ci 53308c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, 53318c2ecf20Sopenharmony_ci "\tXRI extents:\n"); 53328c2ecf20Sopenharmony_ci index = 0; 53338c2ecf20Sopenharmony_ci list_for_each_entry(rsrc_blks, &phba->sli4_hba.lpfc_xri_blk_list, 53348c2ecf20Sopenharmony_ci list) { 53358c2ecf20Sopenharmony_ci len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, 53368c2ecf20Sopenharmony_ci "\t\tBlock %3d: Start %4d, Count %4d\n", 53378c2ecf20Sopenharmony_ci index, rsrc_blks->rsrc_start, 53388c2ecf20Sopenharmony_ci rsrc_blks->rsrc_size); 53398c2ecf20Sopenharmony_ci index++; 53408c2ecf20Sopenharmony_ci } 53418c2ecf20Sopenharmony_ci 53428c2ecf20Sopenharmony_ci return len; 53438c2ecf20Sopenharmony_ci} 53448c2ecf20Sopenharmony_ci 53458c2ecf20Sopenharmony_ci/** 53468c2ecf20Sopenharmony_ci * lpfc_idiag_extacc_write - Syntax check and set up idiag extacc commands 53478c2ecf20Sopenharmony_ci * @file: The file pointer to read from. 53488c2ecf20Sopenharmony_ci * @buf: The buffer to copy the user data from. 53498c2ecf20Sopenharmony_ci * @nbytes: The number of bytes to get. 53508c2ecf20Sopenharmony_ci * @ppos: The position in the file to start reading from. 53518c2ecf20Sopenharmony_ci * 53528c2ecf20Sopenharmony_ci * This routine get the debugfs idiag command struct from user space and then 53538c2ecf20Sopenharmony_ci * perform the syntax check for extent information access commands and sets 53548c2ecf20Sopenharmony_ci * up the necessary states in the idiag command struct accordingly. 53558c2ecf20Sopenharmony_ci * 53568c2ecf20Sopenharmony_ci * It returns the @nbytges passing in from debugfs user space when successful. 53578c2ecf20Sopenharmony_ci * In case of error conditions, it returns proper error code back to the user 53588c2ecf20Sopenharmony_ci * space. 53598c2ecf20Sopenharmony_ci **/ 53608c2ecf20Sopenharmony_cistatic ssize_t 53618c2ecf20Sopenharmony_cilpfc_idiag_extacc_write(struct file *file, const char __user *buf, 53628c2ecf20Sopenharmony_ci size_t nbytes, loff_t *ppos) 53638c2ecf20Sopenharmony_ci{ 53648c2ecf20Sopenharmony_ci struct lpfc_debug *debug = file->private_data; 53658c2ecf20Sopenharmony_ci uint32_t ext_map; 53668c2ecf20Sopenharmony_ci int rc; 53678c2ecf20Sopenharmony_ci 53688c2ecf20Sopenharmony_ci /* This is a user write operation */ 53698c2ecf20Sopenharmony_ci debug->op = LPFC_IDIAG_OP_WR; 53708c2ecf20Sopenharmony_ci 53718c2ecf20Sopenharmony_ci rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd); 53728c2ecf20Sopenharmony_ci if (rc < 0) 53738c2ecf20Sopenharmony_ci return rc; 53748c2ecf20Sopenharmony_ci 53758c2ecf20Sopenharmony_ci ext_map = idiag.cmd.data[IDIAG_EXTACC_EXMAP_INDX]; 53768c2ecf20Sopenharmony_ci 53778c2ecf20Sopenharmony_ci if (idiag.cmd.opcode != LPFC_IDIAG_CMD_EXTACC_RD) 53788c2ecf20Sopenharmony_ci goto error_out; 53798c2ecf20Sopenharmony_ci if (rc != LPFC_EXT_ACC_CMD_ARG) 53808c2ecf20Sopenharmony_ci goto error_out; 53818c2ecf20Sopenharmony_ci if (!(ext_map & LPFC_EXT_ACC_ALL)) 53828c2ecf20Sopenharmony_ci goto error_out; 53838c2ecf20Sopenharmony_ci 53848c2ecf20Sopenharmony_ci return nbytes; 53858c2ecf20Sopenharmony_cierror_out: 53868c2ecf20Sopenharmony_ci /* Clean out command structure on command error out */ 53878c2ecf20Sopenharmony_ci memset(&idiag, 0, sizeof(idiag)); 53888c2ecf20Sopenharmony_ci return -EINVAL; 53898c2ecf20Sopenharmony_ci} 53908c2ecf20Sopenharmony_ci 53918c2ecf20Sopenharmony_ci/** 53928c2ecf20Sopenharmony_ci * lpfc_idiag_extacc_read - idiag debugfs read access to extent information 53938c2ecf20Sopenharmony_ci * @file: The file pointer to read from. 53948c2ecf20Sopenharmony_ci * @buf: The buffer to copy the data to. 53958c2ecf20Sopenharmony_ci * @nbytes: The number of bytes to read. 53968c2ecf20Sopenharmony_ci * @ppos: The position in the file to start reading from. 53978c2ecf20Sopenharmony_ci * 53988c2ecf20Sopenharmony_ci * Description: 53998c2ecf20Sopenharmony_ci * This routine reads data from the proper extent information according to 54008c2ecf20Sopenharmony_ci * the idiag command, and copies to user @buf. 54018c2ecf20Sopenharmony_ci * 54028c2ecf20Sopenharmony_ci * Returns: 54038c2ecf20Sopenharmony_ci * This function returns the amount of data that was read (this could be less 54048c2ecf20Sopenharmony_ci * than @nbytes if the end of the file was reached) or a negative error value. 54058c2ecf20Sopenharmony_ci **/ 54068c2ecf20Sopenharmony_cistatic ssize_t 54078c2ecf20Sopenharmony_cilpfc_idiag_extacc_read(struct file *file, char __user *buf, size_t nbytes, 54088c2ecf20Sopenharmony_ci loff_t *ppos) 54098c2ecf20Sopenharmony_ci{ 54108c2ecf20Sopenharmony_ci struct lpfc_debug *debug = file->private_data; 54118c2ecf20Sopenharmony_ci struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private; 54128c2ecf20Sopenharmony_ci char *pbuffer; 54138c2ecf20Sopenharmony_ci uint32_t ext_map; 54148c2ecf20Sopenharmony_ci int len = 0; 54158c2ecf20Sopenharmony_ci 54168c2ecf20Sopenharmony_ci /* This is a user read operation */ 54178c2ecf20Sopenharmony_ci debug->op = LPFC_IDIAG_OP_RD; 54188c2ecf20Sopenharmony_ci 54198c2ecf20Sopenharmony_ci if (!debug->buffer) 54208c2ecf20Sopenharmony_ci debug->buffer = kmalloc(LPFC_EXT_ACC_BUF_SIZE, GFP_KERNEL); 54218c2ecf20Sopenharmony_ci if (!debug->buffer) 54228c2ecf20Sopenharmony_ci return 0; 54238c2ecf20Sopenharmony_ci pbuffer = debug->buffer; 54248c2ecf20Sopenharmony_ci if (*ppos) 54258c2ecf20Sopenharmony_ci return 0; 54268c2ecf20Sopenharmony_ci if (idiag.cmd.opcode != LPFC_IDIAG_CMD_EXTACC_RD) 54278c2ecf20Sopenharmony_ci return 0; 54288c2ecf20Sopenharmony_ci 54298c2ecf20Sopenharmony_ci ext_map = idiag.cmd.data[IDIAG_EXTACC_EXMAP_INDX]; 54308c2ecf20Sopenharmony_ci if (ext_map & LPFC_EXT_ACC_AVAIL) 54318c2ecf20Sopenharmony_ci len = lpfc_idiag_extacc_avail_get(phba, pbuffer, len); 54328c2ecf20Sopenharmony_ci if (ext_map & LPFC_EXT_ACC_ALLOC) 54338c2ecf20Sopenharmony_ci len = lpfc_idiag_extacc_alloc_get(phba, pbuffer, len); 54348c2ecf20Sopenharmony_ci if (ext_map & LPFC_EXT_ACC_DRIVR) 54358c2ecf20Sopenharmony_ci len = lpfc_idiag_extacc_drivr_get(phba, pbuffer, len); 54368c2ecf20Sopenharmony_ci 54378c2ecf20Sopenharmony_ci return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len); 54388c2ecf20Sopenharmony_ci} 54398c2ecf20Sopenharmony_ci 54408c2ecf20Sopenharmony_ci#undef lpfc_debugfs_op_disc_trc 54418c2ecf20Sopenharmony_cistatic const struct file_operations lpfc_debugfs_op_disc_trc = { 54428c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 54438c2ecf20Sopenharmony_ci .open = lpfc_debugfs_disc_trc_open, 54448c2ecf20Sopenharmony_ci .llseek = lpfc_debugfs_lseek, 54458c2ecf20Sopenharmony_ci .read = lpfc_debugfs_read, 54468c2ecf20Sopenharmony_ci .release = lpfc_debugfs_release, 54478c2ecf20Sopenharmony_ci}; 54488c2ecf20Sopenharmony_ci 54498c2ecf20Sopenharmony_ci#undef lpfc_debugfs_op_nodelist 54508c2ecf20Sopenharmony_cistatic const struct file_operations lpfc_debugfs_op_nodelist = { 54518c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 54528c2ecf20Sopenharmony_ci .open = lpfc_debugfs_nodelist_open, 54538c2ecf20Sopenharmony_ci .llseek = lpfc_debugfs_lseek, 54548c2ecf20Sopenharmony_ci .read = lpfc_debugfs_read, 54558c2ecf20Sopenharmony_ci .release = lpfc_debugfs_release, 54568c2ecf20Sopenharmony_ci}; 54578c2ecf20Sopenharmony_ci 54588c2ecf20Sopenharmony_ci#undef lpfc_debugfs_op_multixripools 54598c2ecf20Sopenharmony_cistatic const struct file_operations lpfc_debugfs_op_multixripools = { 54608c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 54618c2ecf20Sopenharmony_ci .open = lpfc_debugfs_multixripools_open, 54628c2ecf20Sopenharmony_ci .llseek = lpfc_debugfs_lseek, 54638c2ecf20Sopenharmony_ci .read = lpfc_debugfs_read, 54648c2ecf20Sopenharmony_ci .write = lpfc_debugfs_multixripools_write, 54658c2ecf20Sopenharmony_ci .release = lpfc_debugfs_release, 54668c2ecf20Sopenharmony_ci}; 54678c2ecf20Sopenharmony_ci 54688c2ecf20Sopenharmony_ci#undef lpfc_debugfs_op_hbqinfo 54698c2ecf20Sopenharmony_cistatic const struct file_operations lpfc_debugfs_op_hbqinfo = { 54708c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 54718c2ecf20Sopenharmony_ci .open = lpfc_debugfs_hbqinfo_open, 54728c2ecf20Sopenharmony_ci .llseek = lpfc_debugfs_lseek, 54738c2ecf20Sopenharmony_ci .read = lpfc_debugfs_read, 54748c2ecf20Sopenharmony_ci .release = lpfc_debugfs_release, 54758c2ecf20Sopenharmony_ci}; 54768c2ecf20Sopenharmony_ci 54778c2ecf20Sopenharmony_ci#ifdef LPFC_HDWQ_LOCK_STAT 54788c2ecf20Sopenharmony_ci#undef lpfc_debugfs_op_lockstat 54798c2ecf20Sopenharmony_cistatic const struct file_operations lpfc_debugfs_op_lockstat = { 54808c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 54818c2ecf20Sopenharmony_ci .open = lpfc_debugfs_lockstat_open, 54828c2ecf20Sopenharmony_ci .llseek = lpfc_debugfs_lseek, 54838c2ecf20Sopenharmony_ci .read = lpfc_debugfs_read, 54848c2ecf20Sopenharmony_ci .write = lpfc_debugfs_lockstat_write, 54858c2ecf20Sopenharmony_ci .release = lpfc_debugfs_release, 54868c2ecf20Sopenharmony_ci}; 54878c2ecf20Sopenharmony_ci#endif 54888c2ecf20Sopenharmony_ci 54898c2ecf20Sopenharmony_ci#undef lpfc_debugfs_ras_log 54908c2ecf20Sopenharmony_cistatic const struct file_operations lpfc_debugfs_ras_log = { 54918c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 54928c2ecf20Sopenharmony_ci .open = lpfc_debugfs_ras_log_open, 54938c2ecf20Sopenharmony_ci .llseek = lpfc_debugfs_lseek, 54948c2ecf20Sopenharmony_ci .read = lpfc_debugfs_read, 54958c2ecf20Sopenharmony_ci .release = lpfc_debugfs_ras_log_release, 54968c2ecf20Sopenharmony_ci}; 54978c2ecf20Sopenharmony_ci 54988c2ecf20Sopenharmony_ci#undef lpfc_debugfs_op_dumpHBASlim 54998c2ecf20Sopenharmony_cistatic const struct file_operations lpfc_debugfs_op_dumpHBASlim = { 55008c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 55018c2ecf20Sopenharmony_ci .open = lpfc_debugfs_dumpHBASlim_open, 55028c2ecf20Sopenharmony_ci .llseek = lpfc_debugfs_lseek, 55038c2ecf20Sopenharmony_ci .read = lpfc_debugfs_read, 55048c2ecf20Sopenharmony_ci .release = lpfc_debugfs_release, 55058c2ecf20Sopenharmony_ci}; 55068c2ecf20Sopenharmony_ci 55078c2ecf20Sopenharmony_ci#undef lpfc_debugfs_op_dumpHostSlim 55088c2ecf20Sopenharmony_cistatic const struct file_operations lpfc_debugfs_op_dumpHostSlim = { 55098c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 55108c2ecf20Sopenharmony_ci .open = lpfc_debugfs_dumpHostSlim_open, 55118c2ecf20Sopenharmony_ci .llseek = lpfc_debugfs_lseek, 55128c2ecf20Sopenharmony_ci .read = lpfc_debugfs_read, 55138c2ecf20Sopenharmony_ci .release = lpfc_debugfs_release, 55148c2ecf20Sopenharmony_ci}; 55158c2ecf20Sopenharmony_ci 55168c2ecf20Sopenharmony_ci#undef lpfc_debugfs_op_nvmestat 55178c2ecf20Sopenharmony_cistatic const struct file_operations lpfc_debugfs_op_nvmestat = { 55188c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 55198c2ecf20Sopenharmony_ci .open = lpfc_debugfs_nvmestat_open, 55208c2ecf20Sopenharmony_ci .llseek = lpfc_debugfs_lseek, 55218c2ecf20Sopenharmony_ci .read = lpfc_debugfs_read, 55228c2ecf20Sopenharmony_ci .write = lpfc_debugfs_nvmestat_write, 55238c2ecf20Sopenharmony_ci .release = lpfc_debugfs_release, 55248c2ecf20Sopenharmony_ci}; 55258c2ecf20Sopenharmony_ci 55268c2ecf20Sopenharmony_ci#undef lpfc_debugfs_op_scsistat 55278c2ecf20Sopenharmony_cistatic const struct file_operations lpfc_debugfs_op_scsistat = { 55288c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 55298c2ecf20Sopenharmony_ci .open = lpfc_debugfs_scsistat_open, 55308c2ecf20Sopenharmony_ci .llseek = lpfc_debugfs_lseek, 55318c2ecf20Sopenharmony_ci .read = lpfc_debugfs_read, 55328c2ecf20Sopenharmony_ci .write = lpfc_debugfs_scsistat_write, 55338c2ecf20Sopenharmony_ci .release = lpfc_debugfs_release, 55348c2ecf20Sopenharmony_ci}; 55358c2ecf20Sopenharmony_ci 55368c2ecf20Sopenharmony_ci#undef lpfc_debugfs_op_ioktime 55378c2ecf20Sopenharmony_cistatic const struct file_operations lpfc_debugfs_op_ioktime = { 55388c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 55398c2ecf20Sopenharmony_ci .open = lpfc_debugfs_ioktime_open, 55408c2ecf20Sopenharmony_ci .llseek = lpfc_debugfs_lseek, 55418c2ecf20Sopenharmony_ci .read = lpfc_debugfs_read, 55428c2ecf20Sopenharmony_ci .write = lpfc_debugfs_ioktime_write, 55438c2ecf20Sopenharmony_ci .release = lpfc_debugfs_release, 55448c2ecf20Sopenharmony_ci}; 55458c2ecf20Sopenharmony_ci 55468c2ecf20Sopenharmony_ci#undef lpfc_debugfs_op_nvmeio_trc 55478c2ecf20Sopenharmony_cistatic const struct file_operations lpfc_debugfs_op_nvmeio_trc = { 55488c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 55498c2ecf20Sopenharmony_ci .open = lpfc_debugfs_nvmeio_trc_open, 55508c2ecf20Sopenharmony_ci .llseek = lpfc_debugfs_lseek, 55518c2ecf20Sopenharmony_ci .read = lpfc_debugfs_read, 55528c2ecf20Sopenharmony_ci .write = lpfc_debugfs_nvmeio_trc_write, 55538c2ecf20Sopenharmony_ci .release = lpfc_debugfs_release, 55548c2ecf20Sopenharmony_ci}; 55558c2ecf20Sopenharmony_ci 55568c2ecf20Sopenharmony_ci#undef lpfc_debugfs_op_hdwqstat 55578c2ecf20Sopenharmony_cistatic const struct file_operations lpfc_debugfs_op_hdwqstat = { 55588c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 55598c2ecf20Sopenharmony_ci .open = lpfc_debugfs_hdwqstat_open, 55608c2ecf20Sopenharmony_ci .llseek = lpfc_debugfs_lseek, 55618c2ecf20Sopenharmony_ci .read = lpfc_debugfs_read, 55628c2ecf20Sopenharmony_ci .write = lpfc_debugfs_hdwqstat_write, 55638c2ecf20Sopenharmony_ci .release = lpfc_debugfs_release, 55648c2ecf20Sopenharmony_ci}; 55658c2ecf20Sopenharmony_ci 55668c2ecf20Sopenharmony_ci#undef lpfc_debugfs_op_dif_err 55678c2ecf20Sopenharmony_cistatic const struct file_operations lpfc_debugfs_op_dif_err = { 55688c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 55698c2ecf20Sopenharmony_ci .open = simple_open, 55708c2ecf20Sopenharmony_ci .llseek = lpfc_debugfs_lseek, 55718c2ecf20Sopenharmony_ci .read = lpfc_debugfs_dif_err_read, 55728c2ecf20Sopenharmony_ci .write = lpfc_debugfs_dif_err_write, 55738c2ecf20Sopenharmony_ci .release = lpfc_debugfs_dif_err_release, 55748c2ecf20Sopenharmony_ci}; 55758c2ecf20Sopenharmony_ci 55768c2ecf20Sopenharmony_ci#undef lpfc_debugfs_op_slow_ring_trc 55778c2ecf20Sopenharmony_cistatic const struct file_operations lpfc_debugfs_op_slow_ring_trc = { 55788c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 55798c2ecf20Sopenharmony_ci .open = lpfc_debugfs_slow_ring_trc_open, 55808c2ecf20Sopenharmony_ci .llseek = lpfc_debugfs_lseek, 55818c2ecf20Sopenharmony_ci .read = lpfc_debugfs_read, 55828c2ecf20Sopenharmony_ci .release = lpfc_debugfs_release, 55838c2ecf20Sopenharmony_ci}; 55848c2ecf20Sopenharmony_ci 55858c2ecf20Sopenharmony_cistatic struct dentry *lpfc_debugfs_root = NULL; 55868c2ecf20Sopenharmony_cistatic atomic_t lpfc_debugfs_hba_count; 55878c2ecf20Sopenharmony_ci 55888c2ecf20Sopenharmony_ci/* 55898c2ecf20Sopenharmony_ci * File operations for the iDiag debugfs 55908c2ecf20Sopenharmony_ci */ 55918c2ecf20Sopenharmony_ci#undef lpfc_idiag_op_pciCfg 55928c2ecf20Sopenharmony_cistatic const struct file_operations lpfc_idiag_op_pciCfg = { 55938c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 55948c2ecf20Sopenharmony_ci .open = lpfc_idiag_open, 55958c2ecf20Sopenharmony_ci .llseek = lpfc_debugfs_lseek, 55968c2ecf20Sopenharmony_ci .read = lpfc_idiag_pcicfg_read, 55978c2ecf20Sopenharmony_ci .write = lpfc_idiag_pcicfg_write, 55988c2ecf20Sopenharmony_ci .release = lpfc_idiag_cmd_release, 55998c2ecf20Sopenharmony_ci}; 56008c2ecf20Sopenharmony_ci 56018c2ecf20Sopenharmony_ci#undef lpfc_idiag_op_barAcc 56028c2ecf20Sopenharmony_cistatic const struct file_operations lpfc_idiag_op_barAcc = { 56038c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 56048c2ecf20Sopenharmony_ci .open = lpfc_idiag_open, 56058c2ecf20Sopenharmony_ci .llseek = lpfc_debugfs_lseek, 56068c2ecf20Sopenharmony_ci .read = lpfc_idiag_baracc_read, 56078c2ecf20Sopenharmony_ci .write = lpfc_idiag_baracc_write, 56088c2ecf20Sopenharmony_ci .release = lpfc_idiag_cmd_release, 56098c2ecf20Sopenharmony_ci}; 56108c2ecf20Sopenharmony_ci 56118c2ecf20Sopenharmony_ci#undef lpfc_idiag_op_queInfo 56128c2ecf20Sopenharmony_cistatic const struct file_operations lpfc_idiag_op_queInfo = { 56138c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 56148c2ecf20Sopenharmony_ci .open = lpfc_idiag_open, 56158c2ecf20Sopenharmony_ci .read = lpfc_idiag_queinfo_read, 56168c2ecf20Sopenharmony_ci .release = lpfc_idiag_release, 56178c2ecf20Sopenharmony_ci}; 56188c2ecf20Sopenharmony_ci 56198c2ecf20Sopenharmony_ci#undef lpfc_idiag_op_queAcc 56208c2ecf20Sopenharmony_cistatic const struct file_operations lpfc_idiag_op_queAcc = { 56218c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 56228c2ecf20Sopenharmony_ci .open = lpfc_idiag_open, 56238c2ecf20Sopenharmony_ci .llseek = lpfc_debugfs_lseek, 56248c2ecf20Sopenharmony_ci .read = lpfc_idiag_queacc_read, 56258c2ecf20Sopenharmony_ci .write = lpfc_idiag_queacc_write, 56268c2ecf20Sopenharmony_ci .release = lpfc_idiag_cmd_release, 56278c2ecf20Sopenharmony_ci}; 56288c2ecf20Sopenharmony_ci 56298c2ecf20Sopenharmony_ci#undef lpfc_idiag_op_drbAcc 56308c2ecf20Sopenharmony_cistatic const struct file_operations lpfc_idiag_op_drbAcc = { 56318c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 56328c2ecf20Sopenharmony_ci .open = lpfc_idiag_open, 56338c2ecf20Sopenharmony_ci .llseek = lpfc_debugfs_lseek, 56348c2ecf20Sopenharmony_ci .read = lpfc_idiag_drbacc_read, 56358c2ecf20Sopenharmony_ci .write = lpfc_idiag_drbacc_write, 56368c2ecf20Sopenharmony_ci .release = lpfc_idiag_cmd_release, 56378c2ecf20Sopenharmony_ci}; 56388c2ecf20Sopenharmony_ci 56398c2ecf20Sopenharmony_ci#undef lpfc_idiag_op_ctlAcc 56408c2ecf20Sopenharmony_cistatic const struct file_operations lpfc_idiag_op_ctlAcc = { 56418c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 56428c2ecf20Sopenharmony_ci .open = lpfc_idiag_open, 56438c2ecf20Sopenharmony_ci .llseek = lpfc_debugfs_lseek, 56448c2ecf20Sopenharmony_ci .read = lpfc_idiag_ctlacc_read, 56458c2ecf20Sopenharmony_ci .write = lpfc_idiag_ctlacc_write, 56468c2ecf20Sopenharmony_ci .release = lpfc_idiag_cmd_release, 56478c2ecf20Sopenharmony_ci}; 56488c2ecf20Sopenharmony_ci 56498c2ecf20Sopenharmony_ci#undef lpfc_idiag_op_mbxAcc 56508c2ecf20Sopenharmony_cistatic const struct file_operations lpfc_idiag_op_mbxAcc = { 56518c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 56528c2ecf20Sopenharmony_ci .open = lpfc_idiag_open, 56538c2ecf20Sopenharmony_ci .llseek = lpfc_debugfs_lseek, 56548c2ecf20Sopenharmony_ci .read = lpfc_idiag_mbxacc_read, 56558c2ecf20Sopenharmony_ci .write = lpfc_idiag_mbxacc_write, 56568c2ecf20Sopenharmony_ci .release = lpfc_idiag_cmd_release, 56578c2ecf20Sopenharmony_ci}; 56588c2ecf20Sopenharmony_ci 56598c2ecf20Sopenharmony_ci#undef lpfc_idiag_op_extAcc 56608c2ecf20Sopenharmony_cistatic const struct file_operations lpfc_idiag_op_extAcc = { 56618c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 56628c2ecf20Sopenharmony_ci .open = lpfc_idiag_open, 56638c2ecf20Sopenharmony_ci .llseek = lpfc_debugfs_lseek, 56648c2ecf20Sopenharmony_ci .read = lpfc_idiag_extacc_read, 56658c2ecf20Sopenharmony_ci .write = lpfc_idiag_extacc_write, 56668c2ecf20Sopenharmony_ci .release = lpfc_idiag_cmd_release, 56678c2ecf20Sopenharmony_ci}; 56688c2ecf20Sopenharmony_ci#endif 56698c2ecf20Sopenharmony_ci 56708c2ecf20Sopenharmony_ci/* lpfc_idiag_mbxacc_dump_bsg_mbox - idiag debugfs dump bsg mailbox command 56718c2ecf20Sopenharmony_ci * @phba: Pointer to HBA context object. 56728c2ecf20Sopenharmony_ci * @dmabuf: Pointer to a DMA buffer descriptor. 56738c2ecf20Sopenharmony_ci * 56748c2ecf20Sopenharmony_ci * Description: 56758c2ecf20Sopenharmony_ci * This routine dump a bsg pass-through non-embedded mailbox command with 56768c2ecf20Sopenharmony_ci * external buffer. 56778c2ecf20Sopenharmony_ci **/ 56788c2ecf20Sopenharmony_civoid 56798c2ecf20Sopenharmony_cilpfc_idiag_mbxacc_dump_bsg_mbox(struct lpfc_hba *phba, enum nemb_type nemb_tp, 56808c2ecf20Sopenharmony_ci enum mbox_type mbox_tp, enum dma_type dma_tp, 56818c2ecf20Sopenharmony_ci enum sta_type sta_tp, 56828c2ecf20Sopenharmony_ci struct lpfc_dmabuf *dmabuf, uint32_t ext_buf) 56838c2ecf20Sopenharmony_ci{ 56848c2ecf20Sopenharmony_ci#ifdef CONFIG_SCSI_LPFC_DEBUG_FS 56858c2ecf20Sopenharmony_ci uint32_t *mbx_mbox_cmd, *mbx_dump_map, *mbx_dump_cnt, *mbx_word_cnt; 56868c2ecf20Sopenharmony_ci char line_buf[LPFC_MBX_ACC_LBUF_SZ]; 56878c2ecf20Sopenharmony_ci int len = 0; 56888c2ecf20Sopenharmony_ci uint32_t do_dump = 0; 56898c2ecf20Sopenharmony_ci uint32_t *pword; 56908c2ecf20Sopenharmony_ci uint32_t i; 56918c2ecf20Sopenharmony_ci 56928c2ecf20Sopenharmony_ci if (idiag.cmd.opcode != LPFC_IDIAG_BSG_MBXACC_DP) 56938c2ecf20Sopenharmony_ci return; 56948c2ecf20Sopenharmony_ci 56958c2ecf20Sopenharmony_ci mbx_mbox_cmd = &idiag.cmd.data[IDIAG_MBXACC_MBCMD_INDX]; 56968c2ecf20Sopenharmony_ci mbx_dump_map = &idiag.cmd.data[IDIAG_MBXACC_DPMAP_INDX]; 56978c2ecf20Sopenharmony_ci mbx_dump_cnt = &idiag.cmd.data[IDIAG_MBXACC_DPCNT_INDX]; 56988c2ecf20Sopenharmony_ci mbx_word_cnt = &idiag.cmd.data[IDIAG_MBXACC_WDCNT_INDX]; 56998c2ecf20Sopenharmony_ci 57008c2ecf20Sopenharmony_ci if (!(*mbx_dump_map & LPFC_MBX_DMP_ALL) || 57018c2ecf20Sopenharmony_ci (*mbx_dump_cnt == 0) || 57028c2ecf20Sopenharmony_ci (*mbx_word_cnt == 0)) 57038c2ecf20Sopenharmony_ci return; 57048c2ecf20Sopenharmony_ci 57058c2ecf20Sopenharmony_ci if (*mbx_mbox_cmd != 0x9B) 57068c2ecf20Sopenharmony_ci return; 57078c2ecf20Sopenharmony_ci 57088c2ecf20Sopenharmony_ci if ((mbox_tp == mbox_rd) && (dma_tp == dma_mbox)) { 57098c2ecf20Sopenharmony_ci if (*mbx_dump_map & LPFC_BSG_DMP_MBX_RD_MBX) { 57108c2ecf20Sopenharmony_ci do_dump |= LPFC_BSG_DMP_MBX_RD_MBX; 57118c2ecf20Sopenharmony_ci pr_err("\nRead mbox command (x%x), " 57128c2ecf20Sopenharmony_ci "nemb:0x%x, extbuf_cnt:%d:\n", 57138c2ecf20Sopenharmony_ci sta_tp, nemb_tp, ext_buf); 57148c2ecf20Sopenharmony_ci } 57158c2ecf20Sopenharmony_ci } 57168c2ecf20Sopenharmony_ci if ((mbox_tp == mbox_rd) && (dma_tp == dma_ebuf)) { 57178c2ecf20Sopenharmony_ci if (*mbx_dump_map & LPFC_BSG_DMP_MBX_RD_BUF) { 57188c2ecf20Sopenharmony_ci do_dump |= LPFC_BSG_DMP_MBX_RD_BUF; 57198c2ecf20Sopenharmony_ci pr_err("\nRead mbox buffer (x%x), " 57208c2ecf20Sopenharmony_ci "nemb:0x%x, extbuf_seq:%d:\n", 57218c2ecf20Sopenharmony_ci sta_tp, nemb_tp, ext_buf); 57228c2ecf20Sopenharmony_ci } 57238c2ecf20Sopenharmony_ci } 57248c2ecf20Sopenharmony_ci if ((mbox_tp == mbox_wr) && (dma_tp == dma_mbox)) { 57258c2ecf20Sopenharmony_ci if (*mbx_dump_map & LPFC_BSG_DMP_MBX_WR_MBX) { 57268c2ecf20Sopenharmony_ci do_dump |= LPFC_BSG_DMP_MBX_WR_MBX; 57278c2ecf20Sopenharmony_ci pr_err("\nWrite mbox command (x%x), " 57288c2ecf20Sopenharmony_ci "nemb:0x%x, extbuf_cnt:%d:\n", 57298c2ecf20Sopenharmony_ci sta_tp, nemb_tp, ext_buf); 57308c2ecf20Sopenharmony_ci } 57318c2ecf20Sopenharmony_ci } 57328c2ecf20Sopenharmony_ci if ((mbox_tp == mbox_wr) && (dma_tp == dma_ebuf)) { 57338c2ecf20Sopenharmony_ci if (*mbx_dump_map & LPFC_BSG_DMP_MBX_WR_BUF) { 57348c2ecf20Sopenharmony_ci do_dump |= LPFC_BSG_DMP_MBX_WR_BUF; 57358c2ecf20Sopenharmony_ci pr_err("\nWrite mbox buffer (x%x), " 57368c2ecf20Sopenharmony_ci "nemb:0x%x, extbuf_seq:%d:\n", 57378c2ecf20Sopenharmony_ci sta_tp, nemb_tp, ext_buf); 57388c2ecf20Sopenharmony_ci } 57398c2ecf20Sopenharmony_ci } 57408c2ecf20Sopenharmony_ci 57418c2ecf20Sopenharmony_ci /* dump buffer content */ 57428c2ecf20Sopenharmony_ci if (do_dump) { 57438c2ecf20Sopenharmony_ci pword = (uint32_t *)dmabuf->virt; 57448c2ecf20Sopenharmony_ci for (i = 0; i < *mbx_word_cnt; i++) { 57458c2ecf20Sopenharmony_ci if (!(i % 8)) { 57468c2ecf20Sopenharmony_ci if (i != 0) 57478c2ecf20Sopenharmony_ci pr_err("%s\n", line_buf); 57488c2ecf20Sopenharmony_ci len = 0; 57498c2ecf20Sopenharmony_ci len += scnprintf(line_buf+len, 57508c2ecf20Sopenharmony_ci LPFC_MBX_ACC_LBUF_SZ-len, 57518c2ecf20Sopenharmony_ci "%03d: ", i); 57528c2ecf20Sopenharmony_ci } 57538c2ecf20Sopenharmony_ci len += scnprintf(line_buf+len, LPFC_MBX_ACC_LBUF_SZ-len, 57548c2ecf20Sopenharmony_ci "%08x ", (uint32_t)*pword); 57558c2ecf20Sopenharmony_ci pword++; 57568c2ecf20Sopenharmony_ci } 57578c2ecf20Sopenharmony_ci if ((i - 1) % 8) 57588c2ecf20Sopenharmony_ci pr_err("%s\n", line_buf); 57598c2ecf20Sopenharmony_ci (*mbx_dump_cnt)--; 57608c2ecf20Sopenharmony_ci } 57618c2ecf20Sopenharmony_ci 57628c2ecf20Sopenharmony_ci /* Clean out command structure on reaching dump count */ 57638c2ecf20Sopenharmony_ci if (*mbx_dump_cnt == 0) 57648c2ecf20Sopenharmony_ci memset(&idiag, 0, sizeof(idiag)); 57658c2ecf20Sopenharmony_ci return; 57668c2ecf20Sopenharmony_ci#endif 57678c2ecf20Sopenharmony_ci} 57688c2ecf20Sopenharmony_ci 57698c2ecf20Sopenharmony_ci/* lpfc_idiag_mbxacc_dump_issue_mbox - idiag debugfs dump issue mailbox command 57708c2ecf20Sopenharmony_ci * @phba: Pointer to HBA context object. 57718c2ecf20Sopenharmony_ci * @dmabuf: Pointer to a DMA buffer descriptor. 57728c2ecf20Sopenharmony_ci * 57738c2ecf20Sopenharmony_ci * Description: 57748c2ecf20Sopenharmony_ci * This routine dump a pass-through non-embedded mailbox command from issue 57758c2ecf20Sopenharmony_ci * mailbox command. 57768c2ecf20Sopenharmony_ci **/ 57778c2ecf20Sopenharmony_civoid 57788c2ecf20Sopenharmony_cilpfc_idiag_mbxacc_dump_issue_mbox(struct lpfc_hba *phba, MAILBOX_t *pmbox) 57798c2ecf20Sopenharmony_ci{ 57808c2ecf20Sopenharmony_ci#ifdef CONFIG_SCSI_LPFC_DEBUG_FS 57818c2ecf20Sopenharmony_ci uint32_t *mbx_dump_map, *mbx_dump_cnt, *mbx_word_cnt, *mbx_mbox_cmd; 57828c2ecf20Sopenharmony_ci char line_buf[LPFC_MBX_ACC_LBUF_SZ]; 57838c2ecf20Sopenharmony_ci int len = 0; 57848c2ecf20Sopenharmony_ci uint32_t *pword; 57858c2ecf20Sopenharmony_ci uint8_t *pbyte; 57868c2ecf20Sopenharmony_ci uint32_t i, j; 57878c2ecf20Sopenharmony_ci 57888c2ecf20Sopenharmony_ci if (idiag.cmd.opcode != LPFC_IDIAG_CMD_MBXACC_DP) 57898c2ecf20Sopenharmony_ci return; 57908c2ecf20Sopenharmony_ci 57918c2ecf20Sopenharmony_ci mbx_mbox_cmd = &idiag.cmd.data[IDIAG_MBXACC_MBCMD_INDX]; 57928c2ecf20Sopenharmony_ci mbx_dump_map = &idiag.cmd.data[IDIAG_MBXACC_DPMAP_INDX]; 57938c2ecf20Sopenharmony_ci mbx_dump_cnt = &idiag.cmd.data[IDIAG_MBXACC_DPCNT_INDX]; 57948c2ecf20Sopenharmony_ci mbx_word_cnt = &idiag.cmd.data[IDIAG_MBXACC_WDCNT_INDX]; 57958c2ecf20Sopenharmony_ci 57968c2ecf20Sopenharmony_ci if (!(*mbx_dump_map & LPFC_MBX_DMP_MBX_ALL) || 57978c2ecf20Sopenharmony_ci (*mbx_dump_cnt == 0) || 57988c2ecf20Sopenharmony_ci (*mbx_word_cnt == 0)) 57998c2ecf20Sopenharmony_ci return; 58008c2ecf20Sopenharmony_ci 58018c2ecf20Sopenharmony_ci if ((*mbx_mbox_cmd != LPFC_MBX_ALL_CMD) && 58028c2ecf20Sopenharmony_ci (*mbx_mbox_cmd != pmbox->mbxCommand)) 58038c2ecf20Sopenharmony_ci return; 58048c2ecf20Sopenharmony_ci 58058c2ecf20Sopenharmony_ci /* dump buffer content */ 58068c2ecf20Sopenharmony_ci if (*mbx_dump_map & LPFC_MBX_DMP_MBX_WORD) { 58078c2ecf20Sopenharmony_ci pr_err("Mailbox command:0x%x dump by word:\n", 58088c2ecf20Sopenharmony_ci pmbox->mbxCommand); 58098c2ecf20Sopenharmony_ci pword = (uint32_t *)pmbox; 58108c2ecf20Sopenharmony_ci for (i = 0; i < *mbx_word_cnt; i++) { 58118c2ecf20Sopenharmony_ci if (!(i % 8)) { 58128c2ecf20Sopenharmony_ci if (i != 0) 58138c2ecf20Sopenharmony_ci pr_err("%s\n", line_buf); 58148c2ecf20Sopenharmony_ci len = 0; 58158c2ecf20Sopenharmony_ci memset(line_buf, 0, LPFC_MBX_ACC_LBUF_SZ); 58168c2ecf20Sopenharmony_ci len += scnprintf(line_buf+len, 58178c2ecf20Sopenharmony_ci LPFC_MBX_ACC_LBUF_SZ-len, 58188c2ecf20Sopenharmony_ci "%03d: ", i); 58198c2ecf20Sopenharmony_ci } 58208c2ecf20Sopenharmony_ci len += scnprintf(line_buf+len, LPFC_MBX_ACC_LBUF_SZ-len, 58218c2ecf20Sopenharmony_ci "%08x ", 58228c2ecf20Sopenharmony_ci ((uint32_t)*pword) & 0xffffffff); 58238c2ecf20Sopenharmony_ci pword++; 58248c2ecf20Sopenharmony_ci } 58258c2ecf20Sopenharmony_ci if ((i - 1) % 8) 58268c2ecf20Sopenharmony_ci pr_err("%s\n", line_buf); 58278c2ecf20Sopenharmony_ci pr_err("\n"); 58288c2ecf20Sopenharmony_ci } 58298c2ecf20Sopenharmony_ci if (*mbx_dump_map & LPFC_MBX_DMP_MBX_BYTE) { 58308c2ecf20Sopenharmony_ci pr_err("Mailbox command:0x%x dump by byte:\n", 58318c2ecf20Sopenharmony_ci pmbox->mbxCommand); 58328c2ecf20Sopenharmony_ci pbyte = (uint8_t *)pmbox; 58338c2ecf20Sopenharmony_ci for (i = 0; i < *mbx_word_cnt; i++) { 58348c2ecf20Sopenharmony_ci if (!(i % 8)) { 58358c2ecf20Sopenharmony_ci if (i != 0) 58368c2ecf20Sopenharmony_ci pr_err("%s\n", line_buf); 58378c2ecf20Sopenharmony_ci len = 0; 58388c2ecf20Sopenharmony_ci memset(line_buf, 0, LPFC_MBX_ACC_LBUF_SZ); 58398c2ecf20Sopenharmony_ci len += scnprintf(line_buf+len, 58408c2ecf20Sopenharmony_ci LPFC_MBX_ACC_LBUF_SZ-len, 58418c2ecf20Sopenharmony_ci "%03d: ", i); 58428c2ecf20Sopenharmony_ci } 58438c2ecf20Sopenharmony_ci for (j = 0; j < 4; j++) { 58448c2ecf20Sopenharmony_ci len += scnprintf(line_buf+len, 58458c2ecf20Sopenharmony_ci LPFC_MBX_ACC_LBUF_SZ-len, 58468c2ecf20Sopenharmony_ci "%02x", 58478c2ecf20Sopenharmony_ci ((uint8_t)*pbyte) & 0xff); 58488c2ecf20Sopenharmony_ci pbyte++; 58498c2ecf20Sopenharmony_ci } 58508c2ecf20Sopenharmony_ci len += scnprintf(line_buf+len, 58518c2ecf20Sopenharmony_ci LPFC_MBX_ACC_LBUF_SZ-len, " "); 58528c2ecf20Sopenharmony_ci } 58538c2ecf20Sopenharmony_ci if ((i - 1) % 8) 58548c2ecf20Sopenharmony_ci pr_err("%s\n", line_buf); 58558c2ecf20Sopenharmony_ci pr_err("\n"); 58568c2ecf20Sopenharmony_ci } 58578c2ecf20Sopenharmony_ci (*mbx_dump_cnt)--; 58588c2ecf20Sopenharmony_ci 58598c2ecf20Sopenharmony_ci /* Clean out command structure on reaching dump count */ 58608c2ecf20Sopenharmony_ci if (*mbx_dump_cnt == 0) 58618c2ecf20Sopenharmony_ci memset(&idiag, 0, sizeof(idiag)); 58628c2ecf20Sopenharmony_ci return; 58638c2ecf20Sopenharmony_ci#endif 58648c2ecf20Sopenharmony_ci} 58658c2ecf20Sopenharmony_ci 58668c2ecf20Sopenharmony_ci/** 58678c2ecf20Sopenharmony_ci * lpfc_debugfs_initialize - Initialize debugfs for a vport 58688c2ecf20Sopenharmony_ci * @vport: The vport pointer to initialize. 58698c2ecf20Sopenharmony_ci * 58708c2ecf20Sopenharmony_ci * Description: 58718c2ecf20Sopenharmony_ci * When Debugfs is configured this routine sets up the lpfc debugfs file system. 58728c2ecf20Sopenharmony_ci * If not already created, this routine will create the lpfc directory, and 58738c2ecf20Sopenharmony_ci * lpfcX directory (for this HBA), and vportX directory for this vport. It will 58748c2ecf20Sopenharmony_ci * also create each file used to access lpfc specific debugfs information. 58758c2ecf20Sopenharmony_ci **/ 58768c2ecf20Sopenharmony_ciinline void 58778c2ecf20Sopenharmony_cilpfc_debugfs_initialize(struct lpfc_vport *vport) 58788c2ecf20Sopenharmony_ci{ 58798c2ecf20Sopenharmony_ci#ifdef CONFIG_SCSI_LPFC_DEBUG_FS 58808c2ecf20Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 58818c2ecf20Sopenharmony_ci char name[64]; 58828c2ecf20Sopenharmony_ci uint32_t num, i; 58838c2ecf20Sopenharmony_ci bool pport_setup = false; 58848c2ecf20Sopenharmony_ci 58858c2ecf20Sopenharmony_ci if (!lpfc_debugfs_enable) 58868c2ecf20Sopenharmony_ci return; 58878c2ecf20Sopenharmony_ci 58888c2ecf20Sopenharmony_ci /* Setup lpfc root directory */ 58898c2ecf20Sopenharmony_ci if (!lpfc_debugfs_root) { 58908c2ecf20Sopenharmony_ci lpfc_debugfs_root = debugfs_create_dir("lpfc", NULL); 58918c2ecf20Sopenharmony_ci atomic_set(&lpfc_debugfs_hba_count, 0); 58928c2ecf20Sopenharmony_ci } 58938c2ecf20Sopenharmony_ci if (!lpfc_debugfs_start_time) 58948c2ecf20Sopenharmony_ci lpfc_debugfs_start_time = jiffies; 58958c2ecf20Sopenharmony_ci 58968c2ecf20Sopenharmony_ci /* Setup funcX directory for specific HBA PCI function */ 58978c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "fn%d", phba->brd_no); 58988c2ecf20Sopenharmony_ci if (!phba->hba_debugfs_root) { 58998c2ecf20Sopenharmony_ci pport_setup = true; 59008c2ecf20Sopenharmony_ci phba->hba_debugfs_root = 59018c2ecf20Sopenharmony_ci debugfs_create_dir(name, lpfc_debugfs_root); 59028c2ecf20Sopenharmony_ci atomic_inc(&lpfc_debugfs_hba_count); 59038c2ecf20Sopenharmony_ci atomic_set(&phba->debugfs_vport_count, 0); 59048c2ecf20Sopenharmony_ci 59058c2ecf20Sopenharmony_ci /* Multi-XRI pools */ 59068c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "multixripools"); 59078c2ecf20Sopenharmony_ci phba->debug_multixri_pools = 59088c2ecf20Sopenharmony_ci debugfs_create_file(name, S_IFREG | 0644, 59098c2ecf20Sopenharmony_ci phba->hba_debugfs_root, 59108c2ecf20Sopenharmony_ci phba, 59118c2ecf20Sopenharmony_ci &lpfc_debugfs_op_multixripools); 59128c2ecf20Sopenharmony_ci if (IS_ERR(phba->debug_multixri_pools)) { 59138c2ecf20Sopenharmony_ci lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, 59148c2ecf20Sopenharmony_ci "0527 Cannot create debugfs multixripools\n"); 59158c2ecf20Sopenharmony_ci goto debug_failed; 59168c2ecf20Sopenharmony_ci } 59178c2ecf20Sopenharmony_ci 59188c2ecf20Sopenharmony_ci /* RAS log */ 59198c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "ras_log"); 59208c2ecf20Sopenharmony_ci phba->debug_ras_log = 59218c2ecf20Sopenharmony_ci debugfs_create_file(name, 0644, 59228c2ecf20Sopenharmony_ci phba->hba_debugfs_root, 59238c2ecf20Sopenharmony_ci phba, &lpfc_debugfs_ras_log); 59248c2ecf20Sopenharmony_ci if (IS_ERR(phba->debug_ras_log)) { 59258c2ecf20Sopenharmony_ci lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, 59268c2ecf20Sopenharmony_ci "6148 Cannot create debugfs" 59278c2ecf20Sopenharmony_ci " ras_log\n"); 59288c2ecf20Sopenharmony_ci goto debug_failed; 59298c2ecf20Sopenharmony_ci } 59308c2ecf20Sopenharmony_ci 59318c2ecf20Sopenharmony_ci /* Setup hbqinfo */ 59328c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "hbqinfo"); 59338c2ecf20Sopenharmony_ci phba->debug_hbqinfo = 59348c2ecf20Sopenharmony_ci debugfs_create_file(name, S_IFREG | 0644, 59358c2ecf20Sopenharmony_ci phba->hba_debugfs_root, 59368c2ecf20Sopenharmony_ci phba, &lpfc_debugfs_op_hbqinfo); 59378c2ecf20Sopenharmony_ci 59388c2ecf20Sopenharmony_ci#ifdef LPFC_HDWQ_LOCK_STAT 59398c2ecf20Sopenharmony_ci /* Setup lockstat */ 59408c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "lockstat"); 59418c2ecf20Sopenharmony_ci phba->debug_lockstat = 59428c2ecf20Sopenharmony_ci debugfs_create_file(name, S_IFREG | 0644, 59438c2ecf20Sopenharmony_ci phba->hba_debugfs_root, 59448c2ecf20Sopenharmony_ci phba, &lpfc_debugfs_op_lockstat); 59458c2ecf20Sopenharmony_ci if (IS_ERR(phba->debug_lockstat)) { 59468c2ecf20Sopenharmony_ci lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, 59478c2ecf20Sopenharmony_ci "4610 Can't create debugfs lockstat\n"); 59488c2ecf20Sopenharmony_ci goto debug_failed; 59498c2ecf20Sopenharmony_ci } 59508c2ecf20Sopenharmony_ci#endif 59518c2ecf20Sopenharmony_ci 59528c2ecf20Sopenharmony_ci /* Setup dumpHBASlim */ 59538c2ecf20Sopenharmony_ci if (phba->sli_rev < LPFC_SLI_REV4) { 59548c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "dumpHBASlim"); 59558c2ecf20Sopenharmony_ci phba->debug_dumpHBASlim = 59568c2ecf20Sopenharmony_ci debugfs_create_file(name, 59578c2ecf20Sopenharmony_ci S_IFREG|S_IRUGO|S_IWUSR, 59588c2ecf20Sopenharmony_ci phba->hba_debugfs_root, 59598c2ecf20Sopenharmony_ci phba, &lpfc_debugfs_op_dumpHBASlim); 59608c2ecf20Sopenharmony_ci } else 59618c2ecf20Sopenharmony_ci phba->debug_dumpHBASlim = NULL; 59628c2ecf20Sopenharmony_ci 59638c2ecf20Sopenharmony_ci /* Setup dumpHostSlim */ 59648c2ecf20Sopenharmony_ci if (phba->sli_rev < LPFC_SLI_REV4) { 59658c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "dumpHostSlim"); 59668c2ecf20Sopenharmony_ci phba->debug_dumpHostSlim = 59678c2ecf20Sopenharmony_ci debugfs_create_file(name, 59688c2ecf20Sopenharmony_ci S_IFREG|S_IRUGO|S_IWUSR, 59698c2ecf20Sopenharmony_ci phba->hba_debugfs_root, 59708c2ecf20Sopenharmony_ci phba, &lpfc_debugfs_op_dumpHostSlim); 59718c2ecf20Sopenharmony_ci } else 59728c2ecf20Sopenharmony_ci phba->debug_dumpHostSlim = NULL; 59738c2ecf20Sopenharmony_ci 59748c2ecf20Sopenharmony_ci /* Setup DIF Error Injections */ 59758c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "InjErrLBA"); 59768c2ecf20Sopenharmony_ci phba->debug_InjErrLBA = 59778c2ecf20Sopenharmony_ci debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, 59788c2ecf20Sopenharmony_ci phba->hba_debugfs_root, 59798c2ecf20Sopenharmony_ci phba, &lpfc_debugfs_op_dif_err); 59808c2ecf20Sopenharmony_ci phba->lpfc_injerr_lba = LPFC_INJERR_LBA_OFF; 59818c2ecf20Sopenharmony_ci 59828c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "InjErrNPortID"); 59838c2ecf20Sopenharmony_ci phba->debug_InjErrNPortID = 59848c2ecf20Sopenharmony_ci debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, 59858c2ecf20Sopenharmony_ci phba->hba_debugfs_root, 59868c2ecf20Sopenharmony_ci phba, &lpfc_debugfs_op_dif_err); 59878c2ecf20Sopenharmony_ci 59888c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "InjErrWWPN"); 59898c2ecf20Sopenharmony_ci phba->debug_InjErrWWPN = 59908c2ecf20Sopenharmony_ci debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, 59918c2ecf20Sopenharmony_ci phba->hba_debugfs_root, 59928c2ecf20Sopenharmony_ci phba, &lpfc_debugfs_op_dif_err); 59938c2ecf20Sopenharmony_ci 59948c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "writeGuardInjErr"); 59958c2ecf20Sopenharmony_ci phba->debug_writeGuard = 59968c2ecf20Sopenharmony_ci debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, 59978c2ecf20Sopenharmony_ci phba->hba_debugfs_root, 59988c2ecf20Sopenharmony_ci phba, &lpfc_debugfs_op_dif_err); 59998c2ecf20Sopenharmony_ci 60008c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "writeAppInjErr"); 60018c2ecf20Sopenharmony_ci phba->debug_writeApp = 60028c2ecf20Sopenharmony_ci debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, 60038c2ecf20Sopenharmony_ci phba->hba_debugfs_root, 60048c2ecf20Sopenharmony_ci phba, &lpfc_debugfs_op_dif_err); 60058c2ecf20Sopenharmony_ci 60068c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "writeRefInjErr"); 60078c2ecf20Sopenharmony_ci phba->debug_writeRef = 60088c2ecf20Sopenharmony_ci debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, 60098c2ecf20Sopenharmony_ci phba->hba_debugfs_root, 60108c2ecf20Sopenharmony_ci phba, &lpfc_debugfs_op_dif_err); 60118c2ecf20Sopenharmony_ci 60128c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "readGuardInjErr"); 60138c2ecf20Sopenharmony_ci phba->debug_readGuard = 60148c2ecf20Sopenharmony_ci debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, 60158c2ecf20Sopenharmony_ci phba->hba_debugfs_root, 60168c2ecf20Sopenharmony_ci phba, &lpfc_debugfs_op_dif_err); 60178c2ecf20Sopenharmony_ci 60188c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "readAppInjErr"); 60198c2ecf20Sopenharmony_ci phba->debug_readApp = 60208c2ecf20Sopenharmony_ci debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, 60218c2ecf20Sopenharmony_ci phba->hba_debugfs_root, 60228c2ecf20Sopenharmony_ci phba, &lpfc_debugfs_op_dif_err); 60238c2ecf20Sopenharmony_ci 60248c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "readRefInjErr"); 60258c2ecf20Sopenharmony_ci phba->debug_readRef = 60268c2ecf20Sopenharmony_ci debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, 60278c2ecf20Sopenharmony_ci phba->hba_debugfs_root, 60288c2ecf20Sopenharmony_ci phba, &lpfc_debugfs_op_dif_err); 60298c2ecf20Sopenharmony_ci 60308c2ecf20Sopenharmony_ci /* Setup slow ring trace */ 60318c2ecf20Sopenharmony_ci if (lpfc_debugfs_max_slow_ring_trc) { 60328c2ecf20Sopenharmony_ci num = lpfc_debugfs_max_slow_ring_trc - 1; 60338c2ecf20Sopenharmony_ci if (num & lpfc_debugfs_max_slow_ring_trc) { 60348c2ecf20Sopenharmony_ci /* Change to be a power of 2 */ 60358c2ecf20Sopenharmony_ci num = lpfc_debugfs_max_slow_ring_trc; 60368c2ecf20Sopenharmony_ci i = 0; 60378c2ecf20Sopenharmony_ci while (num > 1) { 60388c2ecf20Sopenharmony_ci num = num >> 1; 60398c2ecf20Sopenharmony_ci i++; 60408c2ecf20Sopenharmony_ci } 60418c2ecf20Sopenharmony_ci lpfc_debugfs_max_slow_ring_trc = (1 << i); 60428c2ecf20Sopenharmony_ci pr_err("lpfc_debugfs_max_disc_trc changed to " 60438c2ecf20Sopenharmony_ci "%d\n", lpfc_debugfs_max_disc_trc); 60448c2ecf20Sopenharmony_ci } 60458c2ecf20Sopenharmony_ci } 60468c2ecf20Sopenharmony_ci 60478c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "slow_ring_trace"); 60488c2ecf20Sopenharmony_ci phba->debug_slow_ring_trc = 60498c2ecf20Sopenharmony_ci debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, 60508c2ecf20Sopenharmony_ci phba->hba_debugfs_root, 60518c2ecf20Sopenharmony_ci phba, &lpfc_debugfs_op_slow_ring_trc); 60528c2ecf20Sopenharmony_ci if (!phba->slow_ring_trc) { 60538c2ecf20Sopenharmony_ci phba->slow_ring_trc = kmalloc( 60548c2ecf20Sopenharmony_ci (sizeof(struct lpfc_debugfs_trc) * 60558c2ecf20Sopenharmony_ci lpfc_debugfs_max_slow_ring_trc), 60568c2ecf20Sopenharmony_ci GFP_KERNEL); 60578c2ecf20Sopenharmony_ci if (!phba->slow_ring_trc) { 60588c2ecf20Sopenharmony_ci lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, 60598c2ecf20Sopenharmony_ci "0416 Cannot create debugfs " 60608c2ecf20Sopenharmony_ci "slow_ring buffer\n"); 60618c2ecf20Sopenharmony_ci goto debug_failed; 60628c2ecf20Sopenharmony_ci } 60638c2ecf20Sopenharmony_ci atomic_set(&phba->slow_ring_trc_cnt, 0); 60648c2ecf20Sopenharmony_ci memset(phba->slow_ring_trc, 0, 60658c2ecf20Sopenharmony_ci (sizeof(struct lpfc_debugfs_trc) * 60668c2ecf20Sopenharmony_ci lpfc_debugfs_max_slow_ring_trc)); 60678c2ecf20Sopenharmony_ci } 60688c2ecf20Sopenharmony_ci 60698c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "nvmeio_trc"); 60708c2ecf20Sopenharmony_ci phba->debug_nvmeio_trc = 60718c2ecf20Sopenharmony_ci debugfs_create_file(name, 0644, 60728c2ecf20Sopenharmony_ci phba->hba_debugfs_root, 60738c2ecf20Sopenharmony_ci phba, &lpfc_debugfs_op_nvmeio_trc); 60748c2ecf20Sopenharmony_ci 60758c2ecf20Sopenharmony_ci atomic_set(&phba->nvmeio_trc_cnt, 0); 60768c2ecf20Sopenharmony_ci if (lpfc_debugfs_max_nvmeio_trc) { 60778c2ecf20Sopenharmony_ci num = lpfc_debugfs_max_nvmeio_trc - 1; 60788c2ecf20Sopenharmony_ci if (num & lpfc_debugfs_max_disc_trc) { 60798c2ecf20Sopenharmony_ci /* Change to be a power of 2 */ 60808c2ecf20Sopenharmony_ci num = lpfc_debugfs_max_nvmeio_trc; 60818c2ecf20Sopenharmony_ci i = 0; 60828c2ecf20Sopenharmony_ci while (num > 1) { 60838c2ecf20Sopenharmony_ci num = num >> 1; 60848c2ecf20Sopenharmony_ci i++; 60858c2ecf20Sopenharmony_ci } 60868c2ecf20Sopenharmony_ci lpfc_debugfs_max_nvmeio_trc = (1 << i); 60878c2ecf20Sopenharmony_ci lpfc_printf_log(phba, KERN_ERR, LOG_INIT, 60888c2ecf20Sopenharmony_ci "0575 lpfc_debugfs_max_nvmeio_trc " 60898c2ecf20Sopenharmony_ci "changed to %d\n", 60908c2ecf20Sopenharmony_ci lpfc_debugfs_max_nvmeio_trc); 60918c2ecf20Sopenharmony_ci } 60928c2ecf20Sopenharmony_ci phba->nvmeio_trc_size = lpfc_debugfs_max_nvmeio_trc; 60938c2ecf20Sopenharmony_ci 60948c2ecf20Sopenharmony_ci /* Allocate trace buffer and initialize */ 60958c2ecf20Sopenharmony_ci phba->nvmeio_trc = kzalloc( 60968c2ecf20Sopenharmony_ci (sizeof(struct lpfc_debugfs_nvmeio_trc) * 60978c2ecf20Sopenharmony_ci phba->nvmeio_trc_size), GFP_KERNEL); 60988c2ecf20Sopenharmony_ci 60998c2ecf20Sopenharmony_ci if (!phba->nvmeio_trc) { 61008c2ecf20Sopenharmony_ci lpfc_printf_log(phba, KERN_ERR, LOG_INIT, 61018c2ecf20Sopenharmony_ci "0576 Cannot create debugfs " 61028c2ecf20Sopenharmony_ci "nvmeio_trc buffer\n"); 61038c2ecf20Sopenharmony_ci goto nvmeio_off; 61048c2ecf20Sopenharmony_ci } 61058c2ecf20Sopenharmony_ci phba->nvmeio_trc_on = 1; 61068c2ecf20Sopenharmony_ci phba->nvmeio_trc_output_idx = 0; 61078c2ecf20Sopenharmony_ci phba->nvmeio_trc = NULL; 61088c2ecf20Sopenharmony_ci } else { 61098c2ecf20Sopenharmony_cinvmeio_off: 61108c2ecf20Sopenharmony_ci phba->nvmeio_trc_size = 0; 61118c2ecf20Sopenharmony_ci phba->nvmeio_trc_on = 0; 61128c2ecf20Sopenharmony_ci phba->nvmeio_trc_output_idx = 0; 61138c2ecf20Sopenharmony_ci phba->nvmeio_trc = NULL; 61148c2ecf20Sopenharmony_ci } 61158c2ecf20Sopenharmony_ci } 61168c2ecf20Sopenharmony_ci 61178c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "vport%d", vport->vpi); 61188c2ecf20Sopenharmony_ci if (!vport->vport_debugfs_root) { 61198c2ecf20Sopenharmony_ci vport->vport_debugfs_root = 61208c2ecf20Sopenharmony_ci debugfs_create_dir(name, phba->hba_debugfs_root); 61218c2ecf20Sopenharmony_ci atomic_inc(&phba->debugfs_vport_count); 61228c2ecf20Sopenharmony_ci } 61238c2ecf20Sopenharmony_ci 61248c2ecf20Sopenharmony_ci if (lpfc_debugfs_max_disc_trc) { 61258c2ecf20Sopenharmony_ci num = lpfc_debugfs_max_disc_trc - 1; 61268c2ecf20Sopenharmony_ci if (num & lpfc_debugfs_max_disc_trc) { 61278c2ecf20Sopenharmony_ci /* Change to be a power of 2 */ 61288c2ecf20Sopenharmony_ci num = lpfc_debugfs_max_disc_trc; 61298c2ecf20Sopenharmony_ci i = 0; 61308c2ecf20Sopenharmony_ci while (num > 1) { 61318c2ecf20Sopenharmony_ci num = num >> 1; 61328c2ecf20Sopenharmony_ci i++; 61338c2ecf20Sopenharmony_ci } 61348c2ecf20Sopenharmony_ci lpfc_debugfs_max_disc_trc = (1 << i); 61358c2ecf20Sopenharmony_ci pr_err("lpfc_debugfs_max_disc_trc changed to %d\n", 61368c2ecf20Sopenharmony_ci lpfc_debugfs_max_disc_trc); 61378c2ecf20Sopenharmony_ci } 61388c2ecf20Sopenharmony_ci } 61398c2ecf20Sopenharmony_ci 61408c2ecf20Sopenharmony_ci vport->disc_trc = kzalloc( 61418c2ecf20Sopenharmony_ci (sizeof(struct lpfc_debugfs_trc) * lpfc_debugfs_max_disc_trc), 61428c2ecf20Sopenharmony_ci GFP_KERNEL); 61438c2ecf20Sopenharmony_ci 61448c2ecf20Sopenharmony_ci if (!vport->disc_trc) { 61458c2ecf20Sopenharmony_ci lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, 61468c2ecf20Sopenharmony_ci "0418 Cannot create debugfs disc trace " 61478c2ecf20Sopenharmony_ci "buffer\n"); 61488c2ecf20Sopenharmony_ci goto debug_failed; 61498c2ecf20Sopenharmony_ci } 61508c2ecf20Sopenharmony_ci atomic_set(&vport->disc_trc_cnt, 0); 61518c2ecf20Sopenharmony_ci 61528c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "discovery_trace"); 61538c2ecf20Sopenharmony_ci vport->debug_disc_trc = 61548c2ecf20Sopenharmony_ci debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, 61558c2ecf20Sopenharmony_ci vport->vport_debugfs_root, 61568c2ecf20Sopenharmony_ci vport, &lpfc_debugfs_op_disc_trc); 61578c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "nodelist"); 61588c2ecf20Sopenharmony_ci vport->debug_nodelist = 61598c2ecf20Sopenharmony_ci debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, 61608c2ecf20Sopenharmony_ci vport->vport_debugfs_root, 61618c2ecf20Sopenharmony_ci vport, &lpfc_debugfs_op_nodelist); 61628c2ecf20Sopenharmony_ci 61638c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "nvmestat"); 61648c2ecf20Sopenharmony_ci vport->debug_nvmestat = 61658c2ecf20Sopenharmony_ci debugfs_create_file(name, 0644, 61668c2ecf20Sopenharmony_ci vport->vport_debugfs_root, 61678c2ecf20Sopenharmony_ci vport, &lpfc_debugfs_op_nvmestat); 61688c2ecf20Sopenharmony_ci 61698c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "scsistat"); 61708c2ecf20Sopenharmony_ci vport->debug_scsistat = 61718c2ecf20Sopenharmony_ci debugfs_create_file(name, 0644, 61728c2ecf20Sopenharmony_ci vport->vport_debugfs_root, 61738c2ecf20Sopenharmony_ci vport, &lpfc_debugfs_op_scsistat); 61748c2ecf20Sopenharmony_ci if (IS_ERR(vport->debug_scsistat)) { 61758c2ecf20Sopenharmony_ci lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, 61768c2ecf20Sopenharmony_ci "4611 Cannot create debugfs scsistat\n"); 61778c2ecf20Sopenharmony_ci goto debug_failed; 61788c2ecf20Sopenharmony_ci } 61798c2ecf20Sopenharmony_ci 61808c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "ioktime"); 61818c2ecf20Sopenharmony_ci vport->debug_ioktime = 61828c2ecf20Sopenharmony_ci debugfs_create_file(name, 0644, 61838c2ecf20Sopenharmony_ci vport->vport_debugfs_root, 61848c2ecf20Sopenharmony_ci vport, &lpfc_debugfs_op_ioktime); 61858c2ecf20Sopenharmony_ci if (IS_ERR(vport->debug_ioktime)) { 61868c2ecf20Sopenharmony_ci lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, 61878c2ecf20Sopenharmony_ci "0815 Cannot create debugfs ioktime\n"); 61888c2ecf20Sopenharmony_ci goto debug_failed; 61898c2ecf20Sopenharmony_ci } 61908c2ecf20Sopenharmony_ci 61918c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "hdwqstat"); 61928c2ecf20Sopenharmony_ci vport->debug_hdwqstat = 61938c2ecf20Sopenharmony_ci debugfs_create_file(name, 0644, 61948c2ecf20Sopenharmony_ci vport->vport_debugfs_root, 61958c2ecf20Sopenharmony_ci vport, &lpfc_debugfs_op_hdwqstat); 61968c2ecf20Sopenharmony_ci 61978c2ecf20Sopenharmony_ci /* 61988c2ecf20Sopenharmony_ci * The following section is for additional directories/files for the 61998c2ecf20Sopenharmony_ci * physical port. 62008c2ecf20Sopenharmony_ci */ 62018c2ecf20Sopenharmony_ci 62028c2ecf20Sopenharmony_ci if (!pport_setup) 62038c2ecf20Sopenharmony_ci goto debug_failed; 62048c2ecf20Sopenharmony_ci 62058c2ecf20Sopenharmony_ci /* 62068c2ecf20Sopenharmony_ci * iDiag debugfs root entry points for SLI4 device only 62078c2ecf20Sopenharmony_ci */ 62088c2ecf20Sopenharmony_ci if (phba->sli_rev < LPFC_SLI_REV4) 62098c2ecf20Sopenharmony_ci goto debug_failed; 62108c2ecf20Sopenharmony_ci 62118c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "iDiag"); 62128c2ecf20Sopenharmony_ci if (!phba->idiag_root) { 62138c2ecf20Sopenharmony_ci phba->idiag_root = 62148c2ecf20Sopenharmony_ci debugfs_create_dir(name, phba->hba_debugfs_root); 62158c2ecf20Sopenharmony_ci /* Initialize iDiag data structure */ 62168c2ecf20Sopenharmony_ci memset(&idiag, 0, sizeof(idiag)); 62178c2ecf20Sopenharmony_ci } 62188c2ecf20Sopenharmony_ci 62198c2ecf20Sopenharmony_ci /* iDiag read PCI config space */ 62208c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "pciCfg"); 62218c2ecf20Sopenharmony_ci if (!phba->idiag_pci_cfg) { 62228c2ecf20Sopenharmony_ci phba->idiag_pci_cfg = 62238c2ecf20Sopenharmony_ci debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, 62248c2ecf20Sopenharmony_ci phba->idiag_root, phba, &lpfc_idiag_op_pciCfg); 62258c2ecf20Sopenharmony_ci idiag.offset.last_rd = 0; 62268c2ecf20Sopenharmony_ci } 62278c2ecf20Sopenharmony_ci 62288c2ecf20Sopenharmony_ci /* iDiag PCI BAR access */ 62298c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "barAcc"); 62308c2ecf20Sopenharmony_ci if (!phba->idiag_bar_acc) { 62318c2ecf20Sopenharmony_ci phba->idiag_bar_acc = 62328c2ecf20Sopenharmony_ci debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, 62338c2ecf20Sopenharmony_ci phba->idiag_root, phba, &lpfc_idiag_op_barAcc); 62348c2ecf20Sopenharmony_ci idiag.offset.last_rd = 0; 62358c2ecf20Sopenharmony_ci } 62368c2ecf20Sopenharmony_ci 62378c2ecf20Sopenharmony_ci /* iDiag get PCI function queue information */ 62388c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "queInfo"); 62398c2ecf20Sopenharmony_ci if (!phba->idiag_que_info) { 62408c2ecf20Sopenharmony_ci phba->idiag_que_info = 62418c2ecf20Sopenharmony_ci debugfs_create_file(name, S_IFREG|S_IRUGO, 62428c2ecf20Sopenharmony_ci phba->idiag_root, phba, &lpfc_idiag_op_queInfo); 62438c2ecf20Sopenharmony_ci } 62448c2ecf20Sopenharmony_ci 62458c2ecf20Sopenharmony_ci /* iDiag access PCI function queue */ 62468c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "queAcc"); 62478c2ecf20Sopenharmony_ci if (!phba->idiag_que_acc) { 62488c2ecf20Sopenharmony_ci phba->idiag_que_acc = 62498c2ecf20Sopenharmony_ci debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, 62508c2ecf20Sopenharmony_ci phba->idiag_root, phba, &lpfc_idiag_op_queAcc); 62518c2ecf20Sopenharmony_ci } 62528c2ecf20Sopenharmony_ci 62538c2ecf20Sopenharmony_ci /* iDiag access PCI function doorbell registers */ 62548c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "drbAcc"); 62558c2ecf20Sopenharmony_ci if (!phba->idiag_drb_acc) { 62568c2ecf20Sopenharmony_ci phba->idiag_drb_acc = 62578c2ecf20Sopenharmony_ci debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, 62588c2ecf20Sopenharmony_ci phba->idiag_root, phba, &lpfc_idiag_op_drbAcc); 62598c2ecf20Sopenharmony_ci } 62608c2ecf20Sopenharmony_ci 62618c2ecf20Sopenharmony_ci /* iDiag access PCI function control registers */ 62628c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "ctlAcc"); 62638c2ecf20Sopenharmony_ci if (!phba->idiag_ctl_acc) { 62648c2ecf20Sopenharmony_ci phba->idiag_ctl_acc = 62658c2ecf20Sopenharmony_ci debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, 62668c2ecf20Sopenharmony_ci phba->idiag_root, phba, &lpfc_idiag_op_ctlAcc); 62678c2ecf20Sopenharmony_ci } 62688c2ecf20Sopenharmony_ci 62698c2ecf20Sopenharmony_ci /* iDiag access mbox commands */ 62708c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "mbxAcc"); 62718c2ecf20Sopenharmony_ci if (!phba->idiag_mbx_acc) { 62728c2ecf20Sopenharmony_ci phba->idiag_mbx_acc = 62738c2ecf20Sopenharmony_ci debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, 62748c2ecf20Sopenharmony_ci phba->idiag_root, phba, &lpfc_idiag_op_mbxAcc); 62758c2ecf20Sopenharmony_ci } 62768c2ecf20Sopenharmony_ci 62778c2ecf20Sopenharmony_ci /* iDiag extents access commands */ 62788c2ecf20Sopenharmony_ci if (phba->sli4_hba.extents_in_use) { 62798c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "extAcc"); 62808c2ecf20Sopenharmony_ci if (!phba->idiag_ext_acc) { 62818c2ecf20Sopenharmony_ci phba->idiag_ext_acc = 62828c2ecf20Sopenharmony_ci debugfs_create_file(name, 62838c2ecf20Sopenharmony_ci S_IFREG|S_IRUGO|S_IWUSR, 62848c2ecf20Sopenharmony_ci phba->idiag_root, phba, 62858c2ecf20Sopenharmony_ci &lpfc_idiag_op_extAcc); 62868c2ecf20Sopenharmony_ci } 62878c2ecf20Sopenharmony_ci } 62888c2ecf20Sopenharmony_ci 62898c2ecf20Sopenharmony_cidebug_failed: 62908c2ecf20Sopenharmony_ci return; 62918c2ecf20Sopenharmony_ci#endif 62928c2ecf20Sopenharmony_ci} 62938c2ecf20Sopenharmony_ci 62948c2ecf20Sopenharmony_ci/** 62958c2ecf20Sopenharmony_ci * lpfc_debugfs_terminate - Tear down debugfs infrastructure for this vport 62968c2ecf20Sopenharmony_ci * @vport: The vport pointer to remove from debugfs. 62978c2ecf20Sopenharmony_ci * 62988c2ecf20Sopenharmony_ci * Description: 62998c2ecf20Sopenharmony_ci * When Debugfs is configured this routine removes debugfs file system elements 63008c2ecf20Sopenharmony_ci * that are specific to this vport. It also checks to see if there are any 63018c2ecf20Sopenharmony_ci * users left for the debugfs directories associated with the HBA and driver. If 63028c2ecf20Sopenharmony_ci * this is the last user of the HBA directory or driver directory then it will 63038c2ecf20Sopenharmony_ci * remove those from the debugfs infrastructure as well. 63048c2ecf20Sopenharmony_ci **/ 63058c2ecf20Sopenharmony_ciinline void 63068c2ecf20Sopenharmony_cilpfc_debugfs_terminate(struct lpfc_vport *vport) 63078c2ecf20Sopenharmony_ci{ 63088c2ecf20Sopenharmony_ci#ifdef CONFIG_SCSI_LPFC_DEBUG_FS 63098c2ecf20Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 63108c2ecf20Sopenharmony_ci 63118c2ecf20Sopenharmony_ci kfree(vport->disc_trc); 63128c2ecf20Sopenharmony_ci vport->disc_trc = NULL; 63138c2ecf20Sopenharmony_ci 63148c2ecf20Sopenharmony_ci debugfs_remove(vport->debug_disc_trc); /* discovery_trace */ 63158c2ecf20Sopenharmony_ci vport->debug_disc_trc = NULL; 63168c2ecf20Sopenharmony_ci 63178c2ecf20Sopenharmony_ci debugfs_remove(vport->debug_nodelist); /* nodelist */ 63188c2ecf20Sopenharmony_ci vport->debug_nodelist = NULL; 63198c2ecf20Sopenharmony_ci 63208c2ecf20Sopenharmony_ci debugfs_remove(vport->debug_nvmestat); /* nvmestat */ 63218c2ecf20Sopenharmony_ci vport->debug_nvmestat = NULL; 63228c2ecf20Sopenharmony_ci 63238c2ecf20Sopenharmony_ci debugfs_remove(vport->debug_scsistat); /* scsistat */ 63248c2ecf20Sopenharmony_ci vport->debug_scsistat = NULL; 63258c2ecf20Sopenharmony_ci 63268c2ecf20Sopenharmony_ci debugfs_remove(vport->debug_ioktime); /* ioktime */ 63278c2ecf20Sopenharmony_ci vport->debug_ioktime = NULL; 63288c2ecf20Sopenharmony_ci 63298c2ecf20Sopenharmony_ci debugfs_remove(vport->debug_hdwqstat); /* hdwqstat */ 63308c2ecf20Sopenharmony_ci vport->debug_hdwqstat = NULL; 63318c2ecf20Sopenharmony_ci 63328c2ecf20Sopenharmony_ci if (vport->vport_debugfs_root) { 63338c2ecf20Sopenharmony_ci debugfs_remove(vport->vport_debugfs_root); /* vportX */ 63348c2ecf20Sopenharmony_ci vport->vport_debugfs_root = NULL; 63358c2ecf20Sopenharmony_ci atomic_dec(&phba->debugfs_vport_count); 63368c2ecf20Sopenharmony_ci } 63378c2ecf20Sopenharmony_ci 63388c2ecf20Sopenharmony_ci if (atomic_read(&phba->debugfs_vport_count) == 0) { 63398c2ecf20Sopenharmony_ci 63408c2ecf20Sopenharmony_ci debugfs_remove(phba->debug_multixri_pools); /* multixripools*/ 63418c2ecf20Sopenharmony_ci phba->debug_multixri_pools = NULL; 63428c2ecf20Sopenharmony_ci 63438c2ecf20Sopenharmony_ci debugfs_remove(phba->debug_hbqinfo); /* hbqinfo */ 63448c2ecf20Sopenharmony_ci phba->debug_hbqinfo = NULL; 63458c2ecf20Sopenharmony_ci 63468c2ecf20Sopenharmony_ci debugfs_remove(phba->debug_ras_log); 63478c2ecf20Sopenharmony_ci phba->debug_ras_log = NULL; 63488c2ecf20Sopenharmony_ci 63498c2ecf20Sopenharmony_ci#ifdef LPFC_HDWQ_LOCK_STAT 63508c2ecf20Sopenharmony_ci debugfs_remove(phba->debug_lockstat); /* lockstat */ 63518c2ecf20Sopenharmony_ci phba->debug_lockstat = NULL; 63528c2ecf20Sopenharmony_ci#endif 63538c2ecf20Sopenharmony_ci debugfs_remove(phba->debug_dumpHBASlim); /* HBASlim */ 63548c2ecf20Sopenharmony_ci phba->debug_dumpHBASlim = NULL; 63558c2ecf20Sopenharmony_ci 63568c2ecf20Sopenharmony_ci debugfs_remove(phba->debug_dumpHostSlim); /* HostSlim */ 63578c2ecf20Sopenharmony_ci phba->debug_dumpHostSlim = NULL; 63588c2ecf20Sopenharmony_ci 63598c2ecf20Sopenharmony_ci debugfs_remove(phba->debug_InjErrLBA); /* InjErrLBA */ 63608c2ecf20Sopenharmony_ci phba->debug_InjErrLBA = NULL; 63618c2ecf20Sopenharmony_ci 63628c2ecf20Sopenharmony_ci debugfs_remove(phba->debug_InjErrNPortID); 63638c2ecf20Sopenharmony_ci phba->debug_InjErrNPortID = NULL; 63648c2ecf20Sopenharmony_ci 63658c2ecf20Sopenharmony_ci debugfs_remove(phba->debug_InjErrWWPN); /* InjErrWWPN */ 63668c2ecf20Sopenharmony_ci phba->debug_InjErrWWPN = NULL; 63678c2ecf20Sopenharmony_ci 63688c2ecf20Sopenharmony_ci debugfs_remove(phba->debug_writeGuard); /* writeGuard */ 63698c2ecf20Sopenharmony_ci phba->debug_writeGuard = NULL; 63708c2ecf20Sopenharmony_ci 63718c2ecf20Sopenharmony_ci debugfs_remove(phba->debug_writeApp); /* writeApp */ 63728c2ecf20Sopenharmony_ci phba->debug_writeApp = NULL; 63738c2ecf20Sopenharmony_ci 63748c2ecf20Sopenharmony_ci debugfs_remove(phba->debug_writeRef); /* writeRef */ 63758c2ecf20Sopenharmony_ci phba->debug_writeRef = NULL; 63768c2ecf20Sopenharmony_ci 63778c2ecf20Sopenharmony_ci debugfs_remove(phba->debug_readGuard); /* readGuard */ 63788c2ecf20Sopenharmony_ci phba->debug_readGuard = NULL; 63798c2ecf20Sopenharmony_ci 63808c2ecf20Sopenharmony_ci debugfs_remove(phba->debug_readApp); /* readApp */ 63818c2ecf20Sopenharmony_ci phba->debug_readApp = NULL; 63828c2ecf20Sopenharmony_ci 63838c2ecf20Sopenharmony_ci debugfs_remove(phba->debug_readRef); /* readRef */ 63848c2ecf20Sopenharmony_ci phba->debug_readRef = NULL; 63858c2ecf20Sopenharmony_ci 63868c2ecf20Sopenharmony_ci kfree(phba->slow_ring_trc); 63878c2ecf20Sopenharmony_ci phba->slow_ring_trc = NULL; 63888c2ecf20Sopenharmony_ci 63898c2ecf20Sopenharmony_ci /* slow_ring_trace */ 63908c2ecf20Sopenharmony_ci debugfs_remove(phba->debug_slow_ring_trc); 63918c2ecf20Sopenharmony_ci phba->debug_slow_ring_trc = NULL; 63928c2ecf20Sopenharmony_ci 63938c2ecf20Sopenharmony_ci debugfs_remove(phba->debug_nvmeio_trc); 63948c2ecf20Sopenharmony_ci phba->debug_nvmeio_trc = NULL; 63958c2ecf20Sopenharmony_ci 63968c2ecf20Sopenharmony_ci kfree(phba->nvmeio_trc); 63978c2ecf20Sopenharmony_ci phba->nvmeio_trc = NULL; 63988c2ecf20Sopenharmony_ci 63998c2ecf20Sopenharmony_ci /* 64008c2ecf20Sopenharmony_ci * iDiag release 64018c2ecf20Sopenharmony_ci */ 64028c2ecf20Sopenharmony_ci if (phba->sli_rev == LPFC_SLI_REV4) { 64038c2ecf20Sopenharmony_ci /* iDiag extAcc */ 64048c2ecf20Sopenharmony_ci debugfs_remove(phba->idiag_ext_acc); 64058c2ecf20Sopenharmony_ci phba->idiag_ext_acc = NULL; 64068c2ecf20Sopenharmony_ci 64078c2ecf20Sopenharmony_ci /* iDiag mbxAcc */ 64088c2ecf20Sopenharmony_ci debugfs_remove(phba->idiag_mbx_acc); 64098c2ecf20Sopenharmony_ci phba->idiag_mbx_acc = NULL; 64108c2ecf20Sopenharmony_ci 64118c2ecf20Sopenharmony_ci /* iDiag ctlAcc */ 64128c2ecf20Sopenharmony_ci debugfs_remove(phba->idiag_ctl_acc); 64138c2ecf20Sopenharmony_ci phba->idiag_ctl_acc = NULL; 64148c2ecf20Sopenharmony_ci 64158c2ecf20Sopenharmony_ci /* iDiag drbAcc */ 64168c2ecf20Sopenharmony_ci debugfs_remove(phba->idiag_drb_acc); 64178c2ecf20Sopenharmony_ci phba->idiag_drb_acc = NULL; 64188c2ecf20Sopenharmony_ci 64198c2ecf20Sopenharmony_ci /* iDiag queAcc */ 64208c2ecf20Sopenharmony_ci debugfs_remove(phba->idiag_que_acc); 64218c2ecf20Sopenharmony_ci phba->idiag_que_acc = NULL; 64228c2ecf20Sopenharmony_ci 64238c2ecf20Sopenharmony_ci /* iDiag queInfo */ 64248c2ecf20Sopenharmony_ci debugfs_remove(phba->idiag_que_info); 64258c2ecf20Sopenharmony_ci phba->idiag_que_info = NULL; 64268c2ecf20Sopenharmony_ci 64278c2ecf20Sopenharmony_ci /* iDiag barAcc */ 64288c2ecf20Sopenharmony_ci debugfs_remove(phba->idiag_bar_acc); 64298c2ecf20Sopenharmony_ci phba->idiag_bar_acc = NULL; 64308c2ecf20Sopenharmony_ci 64318c2ecf20Sopenharmony_ci /* iDiag pciCfg */ 64328c2ecf20Sopenharmony_ci debugfs_remove(phba->idiag_pci_cfg); 64338c2ecf20Sopenharmony_ci phba->idiag_pci_cfg = NULL; 64348c2ecf20Sopenharmony_ci 64358c2ecf20Sopenharmony_ci /* Finally remove the iDiag debugfs root */ 64368c2ecf20Sopenharmony_ci debugfs_remove(phba->idiag_root); 64378c2ecf20Sopenharmony_ci phba->idiag_root = NULL; 64388c2ecf20Sopenharmony_ci } 64398c2ecf20Sopenharmony_ci 64408c2ecf20Sopenharmony_ci if (phba->hba_debugfs_root) { 64418c2ecf20Sopenharmony_ci debugfs_remove(phba->hba_debugfs_root); /* fnX */ 64428c2ecf20Sopenharmony_ci phba->hba_debugfs_root = NULL; 64438c2ecf20Sopenharmony_ci atomic_dec(&lpfc_debugfs_hba_count); 64448c2ecf20Sopenharmony_ci } 64458c2ecf20Sopenharmony_ci 64468c2ecf20Sopenharmony_ci if (atomic_read(&lpfc_debugfs_hba_count) == 0) { 64478c2ecf20Sopenharmony_ci debugfs_remove(lpfc_debugfs_root); /* lpfc */ 64488c2ecf20Sopenharmony_ci lpfc_debugfs_root = NULL; 64498c2ecf20Sopenharmony_ci } 64508c2ecf20Sopenharmony_ci } 64518c2ecf20Sopenharmony_ci#endif 64528c2ecf20Sopenharmony_ci return; 64538c2ecf20Sopenharmony_ci} 64548c2ecf20Sopenharmony_ci 64558c2ecf20Sopenharmony_ci/* 64568c2ecf20Sopenharmony_ci * Driver debug utility routines outside of debugfs. The debug utility 64578c2ecf20Sopenharmony_ci * routines implemented here is intended to be used in the instrumented 64588c2ecf20Sopenharmony_ci * debug driver for debugging host or port issues. 64598c2ecf20Sopenharmony_ci */ 64608c2ecf20Sopenharmony_ci 64618c2ecf20Sopenharmony_ci/** 64628c2ecf20Sopenharmony_ci * lpfc_debug_dump_all_queues - dump all the queues with a hba 64638c2ecf20Sopenharmony_ci * @phba: Pointer to HBA context object. 64648c2ecf20Sopenharmony_ci * 64658c2ecf20Sopenharmony_ci * This function dumps entries of all the queues asociated with the @phba. 64668c2ecf20Sopenharmony_ci **/ 64678c2ecf20Sopenharmony_civoid 64688c2ecf20Sopenharmony_cilpfc_debug_dump_all_queues(struct lpfc_hba *phba) 64698c2ecf20Sopenharmony_ci{ 64708c2ecf20Sopenharmony_ci int idx; 64718c2ecf20Sopenharmony_ci 64728c2ecf20Sopenharmony_ci /* 64738c2ecf20Sopenharmony_ci * Dump Work Queues (WQs) 64748c2ecf20Sopenharmony_ci */ 64758c2ecf20Sopenharmony_ci lpfc_debug_dump_wq(phba, DUMP_MBX, 0); 64768c2ecf20Sopenharmony_ci lpfc_debug_dump_wq(phba, DUMP_ELS, 0); 64778c2ecf20Sopenharmony_ci lpfc_debug_dump_wq(phba, DUMP_NVMELS, 0); 64788c2ecf20Sopenharmony_ci 64798c2ecf20Sopenharmony_ci for (idx = 0; idx < phba->cfg_hdw_queue; idx++) 64808c2ecf20Sopenharmony_ci lpfc_debug_dump_wq(phba, DUMP_IO, idx); 64818c2ecf20Sopenharmony_ci 64828c2ecf20Sopenharmony_ci lpfc_debug_dump_hdr_rq(phba); 64838c2ecf20Sopenharmony_ci lpfc_debug_dump_dat_rq(phba); 64848c2ecf20Sopenharmony_ci /* 64858c2ecf20Sopenharmony_ci * Dump Complete Queues (CQs) 64868c2ecf20Sopenharmony_ci */ 64878c2ecf20Sopenharmony_ci lpfc_debug_dump_cq(phba, DUMP_MBX, 0); 64888c2ecf20Sopenharmony_ci lpfc_debug_dump_cq(phba, DUMP_ELS, 0); 64898c2ecf20Sopenharmony_ci lpfc_debug_dump_cq(phba, DUMP_NVMELS, 0); 64908c2ecf20Sopenharmony_ci 64918c2ecf20Sopenharmony_ci for (idx = 0; idx < phba->cfg_hdw_queue; idx++) 64928c2ecf20Sopenharmony_ci lpfc_debug_dump_cq(phba, DUMP_IO, idx); 64938c2ecf20Sopenharmony_ci 64948c2ecf20Sopenharmony_ci /* 64958c2ecf20Sopenharmony_ci * Dump Event Queues (EQs) 64968c2ecf20Sopenharmony_ci */ 64978c2ecf20Sopenharmony_ci for (idx = 0; idx < phba->cfg_hdw_queue; idx++) 64988c2ecf20Sopenharmony_ci lpfc_debug_dump_hba_eq(phba, idx); 64998c2ecf20Sopenharmony_ci} 6500