162306a36Sopenharmony_ci/******************************************************************* 262306a36Sopenharmony_ci * This file is part of the Emulex Linux Device Driver for * 362306a36Sopenharmony_ci * Fibre Channel Host Bus Adapters. * 462306a36Sopenharmony_ci * Copyright (C) 2017-2023 Broadcom. All Rights Reserved. The term * 562306a36Sopenharmony_ci * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * 662306a36Sopenharmony_ci * Copyright (C) 2004-2016 Emulex. All rights reserved. * 762306a36Sopenharmony_ci * EMULEX and SLI are trademarks of Emulex. * 862306a36Sopenharmony_ci * www.broadcom.com * 962306a36Sopenharmony_ci * Portions Copyright (C) 2004-2005 Christoph Hellwig * 1062306a36Sopenharmony_ci * * 1162306a36Sopenharmony_ci * This program is free software; you can redistribute it and/or * 1262306a36Sopenharmony_ci * modify it under the terms of version 2 of the GNU General * 1362306a36Sopenharmony_ci * Public License as published by the Free Software Foundation. * 1462306a36Sopenharmony_ci * This program is distributed in the hope that it will be useful. * 1562306a36Sopenharmony_ci * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * 1662306a36Sopenharmony_ci * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * 1762306a36Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE * 1862306a36Sopenharmony_ci * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD * 1962306a36Sopenharmony_ci * TO BE LEGALLY INVALID. See the GNU General Public License for * 2062306a36Sopenharmony_ci * more details, a copy of which can be found in the file COPYING * 2162306a36Sopenharmony_ci * included with this package. * 2262306a36Sopenharmony_ci *******************************************************************/ 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#include <linux/ctype.h> 2562306a36Sopenharmony_ci#include <linux/delay.h> 2662306a36Sopenharmony_ci#include <linux/pci.h> 2762306a36Sopenharmony_ci#include <linux/interrupt.h> 2862306a36Sopenharmony_ci#include <linux/module.h> 2962306a36Sopenharmony_ci#include <linux/aer.h> 3062306a36Sopenharmony_ci#include <linux/gfp.h> 3162306a36Sopenharmony_ci#include <linux/kernel.h> 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci#include <scsi/scsi.h> 3462306a36Sopenharmony_ci#include <scsi/scsi_device.h> 3562306a36Sopenharmony_ci#include <scsi/scsi_host.h> 3662306a36Sopenharmony_ci#include <scsi/scsi_tcq.h> 3762306a36Sopenharmony_ci#include <scsi/scsi_transport_fc.h> 3862306a36Sopenharmony_ci#include <scsi/fc/fc_fs.h> 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci#include "lpfc_hw4.h" 4162306a36Sopenharmony_ci#include "lpfc_hw.h" 4262306a36Sopenharmony_ci#include "lpfc_sli.h" 4362306a36Sopenharmony_ci#include "lpfc_sli4.h" 4462306a36Sopenharmony_ci#include "lpfc_nl.h" 4562306a36Sopenharmony_ci#include "lpfc_disc.h" 4662306a36Sopenharmony_ci#include "lpfc.h" 4762306a36Sopenharmony_ci#include "lpfc_scsi.h" 4862306a36Sopenharmony_ci#include "lpfc_nvme.h" 4962306a36Sopenharmony_ci#include "lpfc_logmsg.h" 5062306a36Sopenharmony_ci#include "lpfc_version.h" 5162306a36Sopenharmony_ci#include "lpfc_compat.h" 5262306a36Sopenharmony_ci#include "lpfc_crtn.h" 5362306a36Sopenharmony_ci#include "lpfc_vport.h" 5462306a36Sopenharmony_ci#include "lpfc_attr.h" 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci#define LPFC_DEF_DEVLOSS_TMO 30 5762306a36Sopenharmony_ci#define LPFC_MIN_DEVLOSS_TMO 1 5862306a36Sopenharmony_ci#define LPFC_MAX_DEVLOSS_TMO 255 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci#define LPFC_MAX_INFO_TMP_LEN 100 6162306a36Sopenharmony_ci#define LPFC_INFO_MORE_STR "\nCould be more info...\n" 6262306a36Sopenharmony_ci/* 6362306a36Sopenharmony_ci * Write key size should be multiple of 4. If write key is changed 6462306a36Sopenharmony_ci * make sure that library write key is also changed. 6562306a36Sopenharmony_ci */ 6662306a36Sopenharmony_ci#define LPFC_REG_WRITE_KEY_SIZE 4 6762306a36Sopenharmony_ci#define LPFC_REG_WRITE_KEY "EMLX" 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ciconst char *const trunk_errmsg[] = { /* map errcode */ 7062306a36Sopenharmony_ci "", /* There is no such error code at index 0*/ 7162306a36Sopenharmony_ci "link negotiated speed does not match existing" 7262306a36Sopenharmony_ci " trunk - link was \"low\" speed", 7362306a36Sopenharmony_ci "link negotiated speed does not match" 7462306a36Sopenharmony_ci " existing trunk - link was \"middle\" speed", 7562306a36Sopenharmony_ci "link negotiated speed does not match existing" 7662306a36Sopenharmony_ci " trunk - link was \"high\" speed", 7762306a36Sopenharmony_ci "Attached to non-trunking port - F_Port", 7862306a36Sopenharmony_ci "Attached to non-trunking port - N_Port", 7962306a36Sopenharmony_ci "FLOGI response timeout", 8062306a36Sopenharmony_ci "non-FLOGI frame received", 8162306a36Sopenharmony_ci "Invalid FLOGI response", 8262306a36Sopenharmony_ci "Trunking initialization protocol", 8362306a36Sopenharmony_ci "Trunk peer device mismatch", 8462306a36Sopenharmony_ci}; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci/** 8762306a36Sopenharmony_ci * lpfc_jedec_to_ascii - Hex to ascii convertor according to JEDEC rules 8862306a36Sopenharmony_ci * @incr: integer to convert. 8962306a36Sopenharmony_ci * @hdw: ascii string holding converted integer plus a string terminator. 9062306a36Sopenharmony_ci * 9162306a36Sopenharmony_ci * Description: 9262306a36Sopenharmony_ci * JEDEC Joint Electron Device Engineering Council. 9362306a36Sopenharmony_ci * Convert a 32 bit integer composed of 8 nibbles into an 8 byte ascii 9462306a36Sopenharmony_ci * character string. The string is then terminated with a NULL in byte 9. 9562306a36Sopenharmony_ci * Hex 0-9 becomes ascii '0' to '9'. 9662306a36Sopenharmony_ci * Hex a-f becomes ascii '=' to 'B' capital B. 9762306a36Sopenharmony_ci * 9862306a36Sopenharmony_ci * Notes: 9962306a36Sopenharmony_ci * Coded for 32 bit integers only. 10062306a36Sopenharmony_ci **/ 10162306a36Sopenharmony_cistatic void 10262306a36Sopenharmony_cilpfc_jedec_to_ascii(int incr, char hdw[]) 10362306a36Sopenharmony_ci{ 10462306a36Sopenharmony_ci int i, j; 10562306a36Sopenharmony_ci for (i = 0; i < 8; i++) { 10662306a36Sopenharmony_ci j = (incr & 0xf); 10762306a36Sopenharmony_ci if (j <= 9) 10862306a36Sopenharmony_ci hdw[7 - i] = 0x30 + j; 10962306a36Sopenharmony_ci else 11062306a36Sopenharmony_ci hdw[7 - i] = 0x61 + j - 10; 11162306a36Sopenharmony_ci incr = (incr >> 4); 11262306a36Sopenharmony_ci } 11362306a36Sopenharmony_ci hdw[8] = 0; 11462306a36Sopenharmony_ci return; 11562306a36Sopenharmony_ci} 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_cistatic ssize_t 11862306a36Sopenharmony_cilpfc_cmf_info_show(struct device *dev, struct device_attribute *attr, 11962306a36Sopenharmony_ci char *buf) 12062306a36Sopenharmony_ci{ 12162306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 12262306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata; 12362306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 12462306a36Sopenharmony_ci struct lpfc_cgn_info *cp = NULL; 12562306a36Sopenharmony_ci struct lpfc_cgn_stat *cgs; 12662306a36Sopenharmony_ci int len = 0; 12762306a36Sopenharmony_ci int cpu; 12862306a36Sopenharmony_ci u64 rcv, total; 12962306a36Sopenharmony_ci char tmp[LPFC_MAX_INFO_TMP_LEN] = {0}; 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci if (phba->cgn_i) 13262306a36Sopenharmony_ci cp = (struct lpfc_cgn_info *)phba->cgn_i->virt; 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 13562306a36Sopenharmony_ci "Congestion Mgmt Info: E2Eattr %d Ver %d " 13662306a36Sopenharmony_ci "CMF %d cnt %d\n", 13762306a36Sopenharmony_ci phba->sli4_hba.pc_sli4_params.mi_cap, 13862306a36Sopenharmony_ci cp ? cp->cgn_info_version : 0, 13962306a36Sopenharmony_ci phba->sli4_hba.pc_sli4_params.cmf, phba->cmf_timer_cnt); 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) 14262306a36Sopenharmony_ci goto buffer_done; 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci if (!phba->sli4_hba.pc_sli4_params.cmf) 14562306a36Sopenharmony_ci goto buffer_done; 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci switch (phba->cgn_init_reg_signal) { 14862306a36Sopenharmony_ci case EDC_CG_SIG_WARN_ONLY: 14962306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 15062306a36Sopenharmony_ci "Register: Init: Signal:WARN "); 15162306a36Sopenharmony_ci break; 15262306a36Sopenharmony_ci case EDC_CG_SIG_WARN_ALARM: 15362306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 15462306a36Sopenharmony_ci "Register: Init: Signal:WARN|ALARM "); 15562306a36Sopenharmony_ci break; 15662306a36Sopenharmony_ci default: 15762306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 15862306a36Sopenharmony_ci "Register: Init: Signal:NONE "); 15962306a36Sopenharmony_ci break; 16062306a36Sopenharmony_ci } 16162306a36Sopenharmony_ci if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) 16262306a36Sopenharmony_ci goto buffer_done; 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci switch (phba->cgn_init_reg_fpin) { 16562306a36Sopenharmony_ci case LPFC_CGN_FPIN_WARN: 16662306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 16762306a36Sopenharmony_ci "FPIN:WARN\n"); 16862306a36Sopenharmony_ci break; 16962306a36Sopenharmony_ci case LPFC_CGN_FPIN_ALARM: 17062306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 17162306a36Sopenharmony_ci "FPIN:ALARM\n"); 17262306a36Sopenharmony_ci break; 17362306a36Sopenharmony_ci case LPFC_CGN_FPIN_BOTH: 17462306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 17562306a36Sopenharmony_ci "FPIN:WARN|ALARM\n"); 17662306a36Sopenharmony_ci break; 17762306a36Sopenharmony_ci default: 17862306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 17962306a36Sopenharmony_ci "FPIN:NONE\n"); 18062306a36Sopenharmony_ci break; 18162306a36Sopenharmony_ci } 18262306a36Sopenharmony_ci if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) 18362306a36Sopenharmony_ci goto buffer_done; 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci switch (phba->cgn_reg_signal) { 18662306a36Sopenharmony_ci case EDC_CG_SIG_WARN_ONLY: 18762306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 18862306a36Sopenharmony_ci " Current: Signal:WARN "); 18962306a36Sopenharmony_ci break; 19062306a36Sopenharmony_ci case EDC_CG_SIG_WARN_ALARM: 19162306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 19262306a36Sopenharmony_ci " Current: Signal:WARN|ALARM "); 19362306a36Sopenharmony_ci break; 19462306a36Sopenharmony_ci default: 19562306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 19662306a36Sopenharmony_ci " Current: Signal:NONE "); 19762306a36Sopenharmony_ci break; 19862306a36Sopenharmony_ci } 19962306a36Sopenharmony_ci if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) 20062306a36Sopenharmony_ci goto buffer_done; 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci switch (phba->cgn_reg_fpin) { 20362306a36Sopenharmony_ci case LPFC_CGN_FPIN_WARN: 20462306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 20562306a36Sopenharmony_ci "FPIN:WARN ACQEcnt:%d\n", phba->cgn_acqe_cnt); 20662306a36Sopenharmony_ci break; 20762306a36Sopenharmony_ci case LPFC_CGN_FPIN_ALARM: 20862306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 20962306a36Sopenharmony_ci "FPIN:ALARM ACQEcnt:%d\n", phba->cgn_acqe_cnt); 21062306a36Sopenharmony_ci break; 21162306a36Sopenharmony_ci case LPFC_CGN_FPIN_BOTH: 21262306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 21362306a36Sopenharmony_ci "FPIN:WARN|ALARM ACQEcnt:%d\n", phba->cgn_acqe_cnt); 21462306a36Sopenharmony_ci break; 21562306a36Sopenharmony_ci default: 21662306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 21762306a36Sopenharmony_ci "FPIN:NONE ACQEcnt:%d\n", phba->cgn_acqe_cnt); 21862306a36Sopenharmony_ci break; 21962306a36Sopenharmony_ci } 22062306a36Sopenharmony_ci if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) 22162306a36Sopenharmony_ci goto buffer_done; 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci if (phba->cmf_active_mode != phba->cgn_p.cgn_param_mode) { 22462306a36Sopenharmony_ci switch (phba->cmf_active_mode) { 22562306a36Sopenharmony_ci case LPFC_CFG_OFF: 22662306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), "Active: Mode:Off\n"); 22762306a36Sopenharmony_ci break; 22862306a36Sopenharmony_ci case LPFC_CFG_MANAGED: 22962306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), "Active: Mode:Managed\n"); 23062306a36Sopenharmony_ci break; 23162306a36Sopenharmony_ci case LPFC_CFG_MONITOR: 23262306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), "Active: Mode:Monitor\n"); 23362306a36Sopenharmony_ci break; 23462306a36Sopenharmony_ci default: 23562306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), "Active: Mode:Unknown\n"); 23662306a36Sopenharmony_ci } 23762306a36Sopenharmony_ci if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) 23862306a36Sopenharmony_ci goto buffer_done; 23962306a36Sopenharmony_ci } 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci switch (phba->cgn_p.cgn_param_mode) { 24262306a36Sopenharmony_ci case LPFC_CFG_OFF: 24362306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), "Config: Mode:Off "); 24462306a36Sopenharmony_ci break; 24562306a36Sopenharmony_ci case LPFC_CFG_MANAGED: 24662306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), "Config: Mode:Managed "); 24762306a36Sopenharmony_ci break; 24862306a36Sopenharmony_ci case LPFC_CFG_MONITOR: 24962306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), "Config: Mode:Monitor "); 25062306a36Sopenharmony_ci break; 25162306a36Sopenharmony_ci default: 25262306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), "Config: Mode:Unknown "); 25362306a36Sopenharmony_ci } 25462306a36Sopenharmony_ci if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) 25562306a36Sopenharmony_ci goto buffer_done; 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci total = 0; 25862306a36Sopenharmony_ci rcv = 0; 25962306a36Sopenharmony_ci for_each_present_cpu(cpu) { 26062306a36Sopenharmony_ci cgs = per_cpu_ptr(phba->cmf_stat, cpu); 26162306a36Sopenharmony_ci total += atomic64_read(&cgs->total_bytes); 26262306a36Sopenharmony_ci rcv += atomic64_read(&cgs->rcv_bytes); 26362306a36Sopenharmony_ci } 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 26662306a36Sopenharmony_ci "IObusy:%d Info:%d Bytes: Rcv:x%llx Total:x%llx\n", 26762306a36Sopenharmony_ci atomic_read(&phba->cmf_busy), 26862306a36Sopenharmony_ci phba->cmf_active_info, rcv, total); 26962306a36Sopenharmony_ci if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) 27062306a36Sopenharmony_ci goto buffer_done; 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 27362306a36Sopenharmony_ci "Port_speed:%d Link_byte_cnt:%ld " 27462306a36Sopenharmony_ci "Max_byte_per_interval:%ld\n", 27562306a36Sopenharmony_ci lpfc_sli_port_speed_get(phba), 27662306a36Sopenharmony_ci (unsigned long)phba->cmf_link_byte_count, 27762306a36Sopenharmony_ci (unsigned long)phba->cmf_max_bytes_per_interval); 27862306a36Sopenharmony_ci strlcat(buf, tmp, PAGE_SIZE); 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_cibuffer_done: 28162306a36Sopenharmony_ci len = strnlen(buf, PAGE_SIZE); 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci if (unlikely(len >= (PAGE_SIZE - 1))) { 28462306a36Sopenharmony_ci lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT, 28562306a36Sopenharmony_ci "6312 Catching potential buffer " 28662306a36Sopenharmony_ci "overflow > PAGE_SIZE = %lu bytes\n", 28762306a36Sopenharmony_ci PAGE_SIZE); 28862306a36Sopenharmony_ci strscpy(buf + PAGE_SIZE - 1 - sizeof(LPFC_INFO_MORE_STR), 28962306a36Sopenharmony_ci LPFC_INFO_MORE_STR, sizeof(LPFC_INFO_MORE_STR) + 1); 29062306a36Sopenharmony_ci } 29162306a36Sopenharmony_ci return len; 29262306a36Sopenharmony_ci} 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci/** 29562306a36Sopenharmony_ci * lpfc_drvr_version_show - Return the Emulex driver string with version number 29662306a36Sopenharmony_ci * @dev: class unused variable. 29762306a36Sopenharmony_ci * @attr: device attribute, not used. 29862306a36Sopenharmony_ci * @buf: on return contains the module description text. 29962306a36Sopenharmony_ci * 30062306a36Sopenharmony_ci * Returns: size of formatted string. 30162306a36Sopenharmony_ci **/ 30262306a36Sopenharmony_cistatic ssize_t 30362306a36Sopenharmony_cilpfc_drvr_version_show(struct device *dev, struct device_attribute *attr, 30462306a36Sopenharmony_ci char *buf) 30562306a36Sopenharmony_ci{ 30662306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, LPFC_MODULE_DESC "\n"); 30762306a36Sopenharmony_ci} 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci/** 31062306a36Sopenharmony_ci * lpfc_enable_fip_show - Return the fip mode of the HBA 31162306a36Sopenharmony_ci * @dev: class unused variable. 31262306a36Sopenharmony_ci * @attr: device attribute, not used. 31362306a36Sopenharmony_ci * @buf: on return contains the module description text. 31462306a36Sopenharmony_ci * 31562306a36Sopenharmony_ci * Returns: size of formatted string. 31662306a36Sopenharmony_ci **/ 31762306a36Sopenharmony_cistatic ssize_t 31862306a36Sopenharmony_cilpfc_enable_fip_show(struct device *dev, struct device_attribute *attr, 31962306a36Sopenharmony_ci char *buf) 32062306a36Sopenharmony_ci{ 32162306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 32262306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 32362306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci if (phba->hba_flag & HBA_FIP_SUPPORT) 32662306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "1\n"); 32762306a36Sopenharmony_ci else 32862306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "0\n"); 32962306a36Sopenharmony_ci} 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_cistatic ssize_t 33262306a36Sopenharmony_cilpfc_nvme_info_show(struct device *dev, struct device_attribute *attr, 33362306a36Sopenharmony_ci char *buf) 33462306a36Sopenharmony_ci{ 33562306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 33662306a36Sopenharmony_ci struct lpfc_vport *vport = shost_priv(shost); 33762306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 33862306a36Sopenharmony_ci struct lpfc_nvmet_tgtport *tgtp; 33962306a36Sopenharmony_ci struct nvme_fc_local_port *localport; 34062306a36Sopenharmony_ci struct lpfc_nvme_lport *lport; 34162306a36Sopenharmony_ci struct lpfc_nvme_rport *rport; 34262306a36Sopenharmony_ci struct lpfc_nodelist *ndlp; 34362306a36Sopenharmony_ci struct nvme_fc_remote_port *nrport; 34462306a36Sopenharmony_ci struct lpfc_fc4_ctrl_stat *cstat; 34562306a36Sopenharmony_ci uint64_t data1, data2, data3; 34662306a36Sopenharmony_ci uint64_t totin, totout, tot; 34762306a36Sopenharmony_ci char *statep; 34862306a36Sopenharmony_ci int i; 34962306a36Sopenharmony_ci int len = 0; 35062306a36Sopenharmony_ci char tmp[LPFC_MAX_INFO_TMP_LEN] = {0}; 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci if (!(vport->cfg_enable_fc4_type & LPFC_ENABLE_NVME)) { 35362306a36Sopenharmony_ci len = scnprintf(buf, PAGE_SIZE, "NVME Disabled\n"); 35462306a36Sopenharmony_ci return len; 35562306a36Sopenharmony_ci } 35662306a36Sopenharmony_ci if (phba->nvmet_support) { 35762306a36Sopenharmony_ci if (!phba->targetport) { 35862306a36Sopenharmony_ci len = scnprintf(buf, PAGE_SIZE, 35962306a36Sopenharmony_ci "NVME Target: x%llx is not allocated\n", 36062306a36Sopenharmony_ci wwn_to_u64(vport->fc_portname.u.wwn)); 36162306a36Sopenharmony_ci return len; 36262306a36Sopenharmony_ci } 36362306a36Sopenharmony_ci /* Port state is only one of two values for now. */ 36462306a36Sopenharmony_ci if (phba->targetport->port_id) 36562306a36Sopenharmony_ci statep = "REGISTERED"; 36662306a36Sopenharmony_ci else 36762306a36Sopenharmony_ci statep = "INIT"; 36862306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 36962306a36Sopenharmony_ci "NVME Target Enabled State %s\n", 37062306a36Sopenharmony_ci statep); 37162306a36Sopenharmony_ci if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) 37262306a36Sopenharmony_ci goto buffer_done; 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 37562306a36Sopenharmony_ci "%s%d WWPN x%llx WWNN x%llx DID x%06x\n", 37662306a36Sopenharmony_ci "NVME Target: lpfc", 37762306a36Sopenharmony_ci phba->brd_no, 37862306a36Sopenharmony_ci wwn_to_u64(vport->fc_portname.u.wwn), 37962306a36Sopenharmony_ci wwn_to_u64(vport->fc_nodename.u.wwn), 38062306a36Sopenharmony_ci phba->targetport->port_id); 38162306a36Sopenharmony_ci if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) 38262306a36Sopenharmony_ci goto buffer_done; 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci if (strlcat(buf, "\nNVME Target: Statistics\n", PAGE_SIZE) 38562306a36Sopenharmony_ci >= PAGE_SIZE) 38662306a36Sopenharmony_ci goto buffer_done; 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private; 38962306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 39062306a36Sopenharmony_ci "LS: Rcv %08x Drop %08x Abort %08x\n", 39162306a36Sopenharmony_ci atomic_read(&tgtp->rcv_ls_req_in), 39262306a36Sopenharmony_ci atomic_read(&tgtp->rcv_ls_req_drop), 39362306a36Sopenharmony_ci atomic_read(&tgtp->xmt_ls_abort)); 39462306a36Sopenharmony_ci if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) 39562306a36Sopenharmony_ci goto buffer_done; 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci if (atomic_read(&tgtp->rcv_ls_req_in) != 39862306a36Sopenharmony_ci atomic_read(&tgtp->rcv_ls_req_out)) { 39962306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 40062306a36Sopenharmony_ci "Rcv LS: in %08x != out %08x\n", 40162306a36Sopenharmony_ci atomic_read(&tgtp->rcv_ls_req_in), 40262306a36Sopenharmony_ci atomic_read(&tgtp->rcv_ls_req_out)); 40362306a36Sopenharmony_ci if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) 40462306a36Sopenharmony_ci goto buffer_done; 40562306a36Sopenharmony_ci } 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 40862306a36Sopenharmony_ci "LS: Xmt %08x Drop %08x Cmpl %08x\n", 40962306a36Sopenharmony_ci atomic_read(&tgtp->xmt_ls_rsp), 41062306a36Sopenharmony_ci atomic_read(&tgtp->xmt_ls_drop), 41162306a36Sopenharmony_ci atomic_read(&tgtp->xmt_ls_rsp_cmpl)); 41262306a36Sopenharmony_ci if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) 41362306a36Sopenharmony_ci goto buffer_done; 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 41662306a36Sopenharmony_ci "LS: RSP Abort %08x xb %08x Err %08x\n", 41762306a36Sopenharmony_ci atomic_read(&tgtp->xmt_ls_rsp_aborted), 41862306a36Sopenharmony_ci atomic_read(&tgtp->xmt_ls_rsp_xb_set), 41962306a36Sopenharmony_ci atomic_read(&tgtp->xmt_ls_rsp_error)); 42062306a36Sopenharmony_ci if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) 42162306a36Sopenharmony_ci goto buffer_done; 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 42462306a36Sopenharmony_ci "FCP: Rcv %08x Defer %08x Release %08x " 42562306a36Sopenharmony_ci "Drop %08x\n", 42662306a36Sopenharmony_ci atomic_read(&tgtp->rcv_fcp_cmd_in), 42762306a36Sopenharmony_ci atomic_read(&tgtp->rcv_fcp_cmd_defer), 42862306a36Sopenharmony_ci atomic_read(&tgtp->xmt_fcp_release), 42962306a36Sopenharmony_ci atomic_read(&tgtp->rcv_fcp_cmd_drop)); 43062306a36Sopenharmony_ci if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) 43162306a36Sopenharmony_ci goto buffer_done; 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci if (atomic_read(&tgtp->rcv_fcp_cmd_in) != 43462306a36Sopenharmony_ci atomic_read(&tgtp->rcv_fcp_cmd_out)) { 43562306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 43662306a36Sopenharmony_ci "Rcv FCP: in %08x != out %08x\n", 43762306a36Sopenharmony_ci atomic_read(&tgtp->rcv_fcp_cmd_in), 43862306a36Sopenharmony_ci atomic_read(&tgtp->rcv_fcp_cmd_out)); 43962306a36Sopenharmony_ci if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) 44062306a36Sopenharmony_ci goto buffer_done; 44162306a36Sopenharmony_ci } 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 44462306a36Sopenharmony_ci "FCP Rsp: RD %08x rsp %08x WR %08x rsp %08x " 44562306a36Sopenharmony_ci "drop %08x\n", 44662306a36Sopenharmony_ci atomic_read(&tgtp->xmt_fcp_read), 44762306a36Sopenharmony_ci atomic_read(&tgtp->xmt_fcp_read_rsp), 44862306a36Sopenharmony_ci atomic_read(&tgtp->xmt_fcp_write), 44962306a36Sopenharmony_ci atomic_read(&tgtp->xmt_fcp_rsp), 45062306a36Sopenharmony_ci atomic_read(&tgtp->xmt_fcp_drop)); 45162306a36Sopenharmony_ci if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) 45262306a36Sopenharmony_ci goto buffer_done; 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 45562306a36Sopenharmony_ci "FCP Rsp Cmpl: %08x err %08x drop %08x\n", 45662306a36Sopenharmony_ci atomic_read(&tgtp->xmt_fcp_rsp_cmpl), 45762306a36Sopenharmony_ci atomic_read(&tgtp->xmt_fcp_rsp_error), 45862306a36Sopenharmony_ci atomic_read(&tgtp->xmt_fcp_rsp_drop)); 45962306a36Sopenharmony_ci if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) 46062306a36Sopenharmony_ci goto buffer_done; 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 46362306a36Sopenharmony_ci "FCP Rsp Abort: %08x xb %08x xricqe %08x\n", 46462306a36Sopenharmony_ci atomic_read(&tgtp->xmt_fcp_rsp_aborted), 46562306a36Sopenharmony_ci atomic_read(&tgtp->xmt_fcp_rsp_xb_set), 46662306a36Sopenharmony_ci atomic_read(&tgtp->xmt_fcp_xri_abort_cqe)); 46762306a36Sopenharmony_ci if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) 46862306a36Sopenharmony_ci goto buffer_done; 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 47162306a36Sopenharmony_ci "ABORT: Xmt %08x Cmpl %08x\n", 47262306a36Sopenharmony_ci atomic_read(&tgtp->xmt_fcp_abort), 47362306a36Sopenharmony_ci atomic_read(&tgtp->xmt_fcp_abort_cmpl)); 47462306a36Sopenharmony_ci if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) 47562306a36Sopenharmony_ci goto buffer_done; 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 47862306a36Sopenharmony_ci "ABORT: Sol %08x Usol %08x Err %08x Cmpl %08x\n", 47962306a36Sopenharmony_ci atomic_read(&tgtp->xmt_abort_sol), 48062306a36Sopenharmony_ci atomic_read(&tgtp->xmt_abort_unsol), 48162306a36Sopenharmony_ci atomic_read(&tgtp->xmt_abort_rsp), 48262306a36Sopenharmony_ci atomic_read(&tgtp->xmt_abort_rsp_error)); 48362306a36Sopenharmony_ci if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) 48462306a36Sopenharmony_ci goto buffer_done; 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 48762306a36Sopenharmony_ci "DELAY: ctx %08x fod %08x wqfull %08x\n", 48862306a36Sopenharmony_ci atomic_read(&tgtp->defer_ctx), 48962306a36Sopenharmony_ci atomic_read(&tgtp->defer_fod), 49062306a36Sopenharmony_ci atomic_read(&tgtp->defer_wqfull)); 49162306a36Sopenharmony_ci if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) 49262306a36Sopenharmony_ci goto buffer_done; 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci /* Calculate outstanding IOs */ 49562306a36Sopenharmony_ci tot = atomic_read(&tgtp->rcv_fcp_cmd_drop); 49662306a36Sopenharmony_ci tot += atomic_read(&tgtp->xmt_fcp_release); 49762306a36Sopenharmony_ci tot = atomic_read(&tgtp->rcv_fcp_cmd_in) - tot; 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 50062306a36Sopenharmony_ci "IO_CTX: %08x WAIT: cur %08x tot %08x\n" 50162306a36Sopenharmony_ci "CTX Outstanding %08llx\n\n", 50262306a36Sopenharmony_ci phba->sli4_hba.nvmet_xri_cnt, 50362306a36Sopenharmony_ci phba->sli4_hba.nvmet_io_wait_cnt, 50462306a36Sopenharmony_ci phba->sli4_hba.nvmet_io_wait_total, 50562306a36Sopenharmony_ci tot); 50662306a36Sopenharmony_ci strlcat(buf, tmp, PAGE_SIZE); 50762306a36Sopenharmony_ci goto buffer_done; 50862306a36Sopenharmony_ci } 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_ci localport = vport->localport; 51162306a36Sopenharmony_ci if (!localport) { 51262306a36Sopenharmony_ci len = scnprintf(buf, PAGE_SIZE, 51362306a36Sopenharmony_ci "NVME Initiator x%llx is not allocated\n", 51462306a36Sopenharmony_ci wwn_to_u64(vport->fc_portname.u.wwn)); 51562306a36Sopenharmony_ci return len; 51662306a36Sopenharmony_ci } 51762306a36Sopenharmony_ci lport = (struct lpfc_nvme_lport *)localport->private; 51862306a36Sopenharmony_ci if (strlcat(buf, "\nNVME Initiator Enabled\n", PAGE_SIZE) >= PAGE_SIZE) 51962306a36Sopenharmony_ci goto buffer_done; 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 52262306a36Sopenharmony_ci "XRI Dist lpfc%d Total %d IO %d ELS %d\n", 52362306a36Sopenharmony_ci phba->brd_no, 52462306a36Sopenharmony_ci phba->sli4_hba.max_cfg_param.max_xri, 52562306a36Sopenharmony_ci phba->sli4_hba.io_xri_max, 52662306a36Sopenharmony_ci lpfc_sli4_get_els_iocb_cnt(phba)); 52762306a36Sopenharmony_ci if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) 52862306a36Sopenharmony_ci goto buffer_done; 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci /* Port state is only one of two values for now. */ 53162306a36Sopenharmony_ci if (localport->port_id) 53262306a36Sopenharmony_ci statep = "ONLINE"; 53362306a36Sopenharmony_ci else 53462306a36Sopenharmony_ci statep = "UNKNOWN "; 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 53762306a36Sopenharmony_ci "%s%d WWPN x%llx WWNN x%llx DID x%06x %s\n", 53862306a36Sopenharmony_ci "NVME LPORT lpfc", 53962306a36Sopenharmony_ci phba->brd_no, 54062306a36Sopenharmony_ci wwn_to_u64(vport->fc_portname.u.wwn), 54162306a36Sopenharmony_ci wwn_to_u64(vport->fc_nodename.u.wwn), 54262306a36Sopenharmony_ci localport->port_id, statep); 54362306a36Sopenharmony_ci if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) 54462306a36Sopenharmony_ci goto buffer_done; 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci spin_lock_irq(shost->host_lock); 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) { 54962306a36Sopenharmony_ci nrport = NULL; 55062306a36Sopenharmony_ci spin_lock(&ndlp->lock); 55162306a36Sopenharmony_ci rport = lpfc_ndlp_get_nrport(ndlp); 55262306a36Sopenharmony_ci if (rport) 55362306a36Sopenharmony_ci nrport = rport->remoteport; 55462306a36Sopenharmony_ci spin_unlock(&ndlp->lock); 55562306a36Sopenharmony_ci if (!nrport) 55662306a36Sopenharmony_ci continue; 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ci /* Port state is only one of two values for now. */ 55962306a36Sopenharmony_ci switch (nrport->port_state) { 56062306a36Sopenharmony_ci case FC_OBJSTATE_ONLINE: 56162306a36Sopenharmony_ci statep = "ONLINE"; 56262306a36Sopenharmony_ci break; 56362306a36Sopenharmony_ci case FC_OBJSTATE_UNKNOWN: 56462306a36Sopenharmony_ci statep = "UNKNOWN "; 56562306a36Sopenharmony_ci break; 56662306a36Sopenharmony_ci default: 56762306a36Sopenharmony_ci statep = "UNSUPPORTED"; 56862306a36Sopenharmony_ci break; 56962306a36Sopenharmony_ci } 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_ci /* Tab in to show lport ownership. */ 57262306a36Sopenharmony_ci if (strlcat(buf, "NVME RPORT ", PAGE_SIZE) >= PAGE_SIZE) 57362306a36Sopenharmony_ci goto unlock_buf_done; 57462306a36Sopenharmony_ci if (phba->brd_no >= 10) { 57562306a36Sopenharmony_ci if (strlcat(buf, " ", PAGE_SIZE) >= PAGE_SIZE) 57662306a36Sopenharmony_ci goto unlock_buf_done; 57762306a36Sopenharmony_ci } 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), "WWPN x%llx ", 58062306a36Sopenharmony_ci nrport->port_name); 58162306a36Sopenharmony_ci if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) 58262306a36Sopenharmony_ci goto unlock_buf_done; 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), "WWNN x%llx ", 58562306a36Sopenharmony_ci nrport->node_name); 58662306a36Sopenharmony_ci if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) 58762306a36Sopenharmony_ci goto unlock_buf_done; 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), "DID x%06x ", 59062306a36Sopenharmony_ci nrport->port_id); 59162306a36Sopenharmony_ci if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) 59262306a36Sopenharmony_ci goto unlock_buf_done; 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_ci /* An NVME rport can have multiple roles. */ 59562306a36Sopenharmony_ci if (nrport->port_role & FC_PORT_ROLE_NVME_INITIATOR) { 59662306a36Sopenharmony_ci if (strlcat(buf, "INITIATOR ", PAGE_SIZE) >= PAGE_SIZE) 59762306a36Sopenharmony_ci goto unlock_buf_done; 59862306a36Sopenharmony_ci } 59962306a36Sopenharmony_ci if (nrport->port_role & FC_PORT_ROLE_NVME_TARGET) { 60062306a36Sopenharmony_ci if (strlcat(buf, "TARGET ", PAGE_SIZE) >= PAGE_SIZE) 60162306a36Sopenharmony_ci goto unlock_buf_done; 60262306a36Sopenharmony_ci } 60362306a36Sopenharmony_ci if (nrport->port_role & FC_PORT_ROLE_NVME_DISCOVERY) { 60462306a36Sopenharmony_ci if (strlcat(buf, "DISCSRVC ", PAGE_SIZE) >= PAGE_SIZE) 60562306a36Sopenharmony_ci goto unlock_buf_done; 60662306a36Sopenharmony_ci } 60762306a36Sopenharmony_ci if (nrport->port_role & ~(FC_PORT_ROLE_NVME_INITIATOR | 60862306a36Sopenharmony_ci FC_PORT_ROLE_NVME_TARGET | 60962306a36Sopenharmony_ci FC_PORT_ROLE_NVME_DISCOVERY)) { 61062306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), "UNKNOWN ROLE x%x", 61162306a36Sopenharmony_ci nrport->port_role); 61262306a36Sopenharmony_ci if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) 61362306a36Sopenharmony_ci goto unlock_buf_done; 61462306a36Sopenharmony_ci } 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), "%s\n", statep); 61762306a36Sopenharmony_ci if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) 61862306a36Sopenharmony_ci goto unlock_buf_done; 61962306a36Sopenharmony_ci } 62062306a36Sopenharmony_ci spin_unlock_irq(shost->host_lock); 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci if (!lport) 62362306a36Sopenharmony_ci goto buffer_done; 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_ci if (strlcat(buf, "\nNVME Statistics\n", PAGE_SIZE) >= PAGE_SIZE) 62662306a36Sopenharmony_ci goto buffer_done; 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 62962306a36Sopenharmony_ci "LS: Xmt %010x Cmpl %010x Abort %08x\n", 63062306a36Sopenharmony_ci atomic_read(&lport->fc4NvmeLsRequests), 63162306a36Sopenharmony_ci atomic_read(&lport->fc4NvmeLsCmpls), 63262306a36Sopenharmony_ci atomic_read(&lport->xmt_ls_abort)); 63362306a36Sopenharmony_ci if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) 63462306a36Sopenharmony_ci goto buffer_done; 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 63762306a36Sopenharmony_ci "LS XMIT: Err %08x CMPL: xb %08x Err %08x\n", 63862306a36Sopenharmony_ci atomic_read(&lport->xmt_ls_err), 63962306a36Sopenharmony_ci atomic_read(&lport->cmpl_ls_xb), 64062306a36Sopenharmony_ci atomic_read(&lport->cmpl_ls_err)); 64162306a36Sopenharmony_ci if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) 64262306a36Sopenharmony_ci goto buffer_done; 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_ci totin = 0; 64562306a36Sopenharmony_ci totout = 0; 64662306a36Sopenharmony_ci for (i = 0; i < phba->cfg_hdw_queue; i++) { 64762306a36Sopenharmony_ci cstat = &phba->sli4_hba.hdwq[i].nvme_cstat; 64862306a36Sopenharmony_ci tot = cstat->io_cmpls; 64962306a36Sopenharmony_ci totin += tot; 65062306a36Sopenharmony_ci data1 = cstat->input_requests; 65162306a36Sopenharmony_ci data2 = cstat->output_requests; 65262306a36Sopenharmony_ci data3 = cstat->control_requests; 65362306a36Sopenharmony_ci totout += (data1 + data2 + data3); 65462306a36Sopenharmony_ci } 65562306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 65662306a36Sopenharmony_ci "Total FCP Cmpl %016llx Issue %016llx " 65762306a36Sopenharmony_ci "OutIO %016llx\n", 65862306a36Sopenharmony_ci totin, totout, totout - totin); 65962306a36Sopenharmony_ci if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) 66062306a36Sopenharmony_ci goto buffer_done; 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 66362306a36Sopenharmony_ci "\tabort %08x noxri %08x nondlp %08x qdepth %08x " 66462306a36Sopenharmony_ci "wqerr %08x err %08x\n", 66562306a36Sopenharmony_ci atomic_read(&lport->xmt_fcp_abort), 66662306a36Sopenharmony_ci atomic_read(&lport->xmt_fcp_noxri), 66762306a36Sopenharmony_ci atomic_read(&lport->xmt_fcp_bad_ndlp), 66862306a36Sopenharmony_ci atomic_read(&lport->xmt_fcp_qdepth), 66962306a36Sopenharmony_ci atomic_read(&lport->xmt_fcp_wqerr), 67062306a36Sopenharmony_ci atomic_read(&lport->xmt_fcp_err)); 67162306a36Sopenharmony_ci if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) 67262306a36Sopenharmony_ci goto buffer_done; 67362306a36Sopenharmony_ci 67462306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), 67562306a36Sopenharmony_ci "FCP CMPL: xb %08x Err %08x\n", 67662306a36Sopenharmony_ci atomic_read(&lport->cmpl_fcp_xb), 67762306a36Sopenharmony_ci atomic_read(&lport->cmpl_fcp_err)); 67862306a36Sopenharmony_ci strlcat(buf, tmp, PAGE_SIZE); 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ci /* host_lock is already unlocked. */ 68162306a36Sopenharmony_ci goto buffer_done; 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_ci unlock_buf_done: 68462306a36Sopenharmony_ci spin_unlock_irq(shost->host_lock); 68562306a36Sopenharmony_ci 68662306a36Sopenharmony_ci buffer_done: 68762306a36Sopenharmony_ci len = strnlen(buf, PAGE_SIZE); 68862306a36Sopenharmony_ci 68962306a36Sopenharmony_ci if (unlikely(len >= (PAGE_SIZE - 1))) { 69062306a36Sopenharmony_ci lpfc_printf_log(phba, KERN_INFO, LOG_NVME, 69162306a36Sopenharmony_ci "6314 Catching potential buffer " 69262306a36Sopenharmony_ci "overflow > PAGE_SIZE = %lu bytes\n", 69362306a36Sopenharmony_ci PAGE_SIZE); 69462306a36Sopenharmony_ci strscpy(buf + PAGE_SIZE - 1 - sizeof(LPFC_INFO_MORE_STR), 69562306a36Sopenharmony_ci LPFC_INFO_MORE_STR, 69662306a36Sopenharmony_ci sizeof(LPFC_INFO_MORE_STR) + 1); 69762306a36Sopenharmony_ci } 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_ci return len; 70062306a36Sopenharmony_ci} 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_cistatic ssize_t 70362306a36Sopenharmony_cilpfc_scsi_stat_show(struct device *dev, struct device_attribute *attr, 70462306a36Sopenharmony_ci char *buf) 70562306a36Sopenharmony_ci{ 70662306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 70762306a36Sopenharmony_ci struct lpfc_vport *vport = shost_priv(shost); 70862306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 70962306a36Sopenharmony_ci int len; 71062306a36Sopenharmony_ci struct lpfc_fc4_ctrl_stat *cstat; 71162306a36Sopenharmony_ci u64 data1, data2, data3; 71262306a36Sopenharmony_ci u64 tot, totin, totout; 71362306a36Sopenharmony_ci int i; 71462306a36Sopenharmony_ci char tmp[LPFC_MAX_SCSI_INFO_TMP_LEN] = {0}; 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_ci if (!(vport->cfg_enable_fc4_type & LPFC_ENABLE_FCP) || 71762306a36Sopenharmony_ci (phba->sli_rev != LPFC_SLI_REV4)) 71862306a36Sopenharmony_ci return 0; 71962306a36Sopenharmony_ci 72062306a36Sopenharmony_ci scnprintf(buf, PAGE_SIZE, "SCSI HDWQ Statistics\n"); 72162306a36Sopenharmony_ci 72262306a36Sopenharmony_ci totin = 0; 72362306a36Sopenharmony_ci totout = 0; 72462306a36Sopenharmony_ci for (i = 0; i < phba->cfg_hdw_queue; i++) { 72562306a36Sopenharmony_ci cstat = &phba->sli4_hba.hdwq[i].scsi_cstat; 72662306a36Sopenharmony_ci tot = cstat->io_cmpls; 72762306a36Sopenharmony_ci totin += tot; 72862306a36Sopenharmony_ci data1 = cstat->input_requests; 72962306a36Sopenharmony_ci data2 = cstat->output_requests; 73062306a36Sopenharmony_ci data3 = cstat->control_requests; 73162306a36Sopenharmony_ci totout += (data1 + data2 + data3); 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), "HDWQ (%d): Rd %016llx Wr %016llx " 73462306a36Sopenharmony_ci "IO %016llx ", i, data1, data2, data3); 73562306a36Sopenharmony_ci if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) 73662306a36Sopenharmony_ci goto buffer_done; 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), "Cmpl %016llx OutIO %016llx\n", 73962306a36Sopenharmony_ci tot, ((data1 + data2 + data3) - tot)); 74062306a36Sopenharmony_ci if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE) 74162306a36Sopenharmony_ci goto buffer_done; 74262306a36Sopenharmony_ci } 74362306a36Sopenharmony_ci scnprintf(tmp, sizeof(tmp), "Total FCP Cmpl %016llx Issue %016llx " 74462306a36Sopenharmony_ci "OutIO %016llx\n", totin, totout, totout - totin); 74562306a36Sopenharmony_ci strlcat(buf, tmp, PAGE_SIZE); 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_cibuffer_done: 74862306a36Sopenharmony_ci len = strnlen(buf, PAGE_SIZE); 74962306a36Sopenharmony_ci 75062306a36Sopenharmony_ci return len; 75162306a36Sopenharmony_ci} 75262306a36Sopenharmony_ci 75362306a36Sopenharmony_cistatic ssize_t 75462306a36Sopenharmony_cilpfc_bg_info_show(struct device *dev, struct device_attribute *attr, 75562306a36Sopenharmony_ci char *buf) 75662306a36Sopenharmony_ci{ 75762306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 75862306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 75962306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 76062306a36Sopenharmony_ci 76162306a36Sopenharmony_ci if (phba->cfg_enable_bg) { 76262306a36Sopenharmony_ci if (phba->sli3_options & LPFC_SLI3_BG_ENABLED) 76362306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, 76462306a36Sopenharmony_ci "BlockGuard Enabled\n"); 76562306a36Sopenharmony_ci else 76662306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, 76762306a36Sopenharmony_ci "BlockGuard Not Supported\n"); 76862306a36Sopenharmony_ci } else 76962306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, 77062306a36Sopenharmony_ci "BlockGuard Disabled\n"); 77162306a36Sopenharmony_ci} 77262306a36Sopenharmony_ci 77362306a36Sopenharmony_cistatic ssize_t 77462306a36Sopenharmony_cilpfc_bg_guard_err_show(struct device *dev, struct device_attribute *attr, 77562306a36Sopenharmony_ci char *buf) 77662306a36Sopenharmony_ci{ 77762306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 77862306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 77962306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 78062306a36Sopenharmony_ci 78162306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%llu\n", 78262306a36Sopenharmony_ci (unsigned long long)phba->bg_guard_err_cnt); 78362306a36Sopenharmony_ci} 78462306a36Sopenharmony_ci 78562306a36Sopenharmony_cistatic ssize_t 78662306a36Sopenharmony_cilpfc_bg_apptag_err_show(struct device *dev, struct device_attribute *attr, 78762306a36Sopenharmony_ci char *buf) 78862306a36Sopenharmony_ci{ 78962306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 79062306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 79162306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 79262306a36Sopenharmony_ci 79362306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%llu\n", 79462306a36Sopenharmony_ci (unsigned long long)phba->bg_apptag_err_cnt); 79562306a36Sopenharmony_ci} 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_cistatic ssize_t 79862306a36Sopenharmony_cilpfc_bg_reftag_err_show(struct device *dev, struct device_attribute *attr, 79962306a36Sopenharmony_ci char *buf) 80062306a36Sopenharmony_ci{ 80162306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 80262306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 80362306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 80462306a36Sopenharmony_ci 80562306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%llu\n", 80662306a36Sopenharmony_ci (unsigned long long)phba->bg_reftag_err_cnt); 80762306a36Sopenharmony_ci} 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci/** 81062306a36Sopenharmony_ci * lpfc_info_show - Return some pci info about the host in ascii 81162306a36Sopenharmony_ci * @dev: class converted to a Scsi_host structure. 81262306a36Sopenharmony_ci * @attr: device attribute, not used. 81362306a36Sopenharmony_ci * @buf: on return contains the formatted text from lpfc_info(). 81462306a36Sopenharmony_ci * 81562306a36Sopenharmony_ci * Returns: size of formatted string. 81662306a36Sopenharmony_ci **/ 81762306a36Sopenharmony_cistatic ssize_t 81862306a36Sopenharmony_cilpfc_info_show(struct device *dev, struct device_attribute *attr, 81962306a36Sopenharmony_ci char *buf) 82062306a36Sopenharmony_ci{ 82162306a36Sopenharmony_ci struct Scsi_Host *host = class_to_shost(dev); 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%s\n", lpfc_info(host)); 82462306a36Sopenharmony_ci} 82562306a36Sopenharmony_ci 82662306a36Sopenharmony_ci/** 82762306a36Sopenharmony_ci * lpfc_serialnum_show - Return the hba serial number in ascii 82862306a36Sopenharmony_ci * @dev: class converted to a Scsi_host structure. 82962306a36Sopenharmony_ci * @attr: device attribute, not used. 83062306a36Sopenharmony_ci * @buf: on return contains the formatted text serial number. 83162306a36Sopenharmony_ci * 83262306a36Sopenharmony_ci * Returns: size of formatted string. 83362306a36Sopenharmony_ci **/ 83462306a36Sopenharmony_cistatic ssize_t 83562306a36Sopenharmony_cilpfc_serialnum_show(struct device *dev, struct device_attribute *attr, 83662306a36Sopenharmony_ci char *buf) 83762306a36Sopenharmony_ci{ 83862306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 83962306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 84062306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 84162306a36Sopenharmony_ci 84262306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%s\n", phba->SerialNumber); 84362306a36Sopenharmony_ci} 84462306a36Sopenharmony_ci 84562306a36Sopenharmony_ci/** 84662306a36Sopenharmony_ci * lpfc_temp_sensor_show - Return the temperature sensor level 84762306a36Sopenharmony_ci * @dev: class converted to a Scsi_host structure. 84862306a36Sopenharmony_ci * @attr: device attribute, not used. 84962306a36Sopenharmony_ci * @buf: on return contains the formatted support level. 85062306a36Sopenharmony_ci * 85162306a36Sopenharmony_ci * Description: 85262306a36Sopenharmony_ci * Returns a number indicating the temperature sensor level currently 85362306a36Sopenharmony_ci * supported, zero or one in ascii. 85462306a36Sopenharmony_ci * 85562306a36Sopenharmony_ci * Returns: size of formatted string. 85662306a36Sopenharmony_ci **/ 85762306a36Sopenharmony_cistatic ssize_t 85862306a36Sopenharmony_cilpfc_temp_sensor_show(struct device *dev, struct device_attribute *attr, 85962306a36Sopenharmony_ci char *buf) 86062306a36Sopenharmony_ci{ 86162306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 86262306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 86362306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 86462306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d\n", phba->temp_sensor_support); 86562306a36Sopenharmony_ci} 86662306a36Sopenharmony_ci 86762306a36Sopenharmony_ci/** 86862306a36Sopenharmony_ci * lpfc_modeldesc_show - Return the model description of the hba 86962306a36Sopenharmony_ci * @dev: class converted to a Scsi_host structure. 87062306a36Sopenharmony_ci * @attr: device attribute, not used. 87162306a36Sopenharmony_ci * @buf: on return contains the scsi vpd model description. 87262306a36Sopenharmony_ci * 87362306a36Sopenharmony_ci * Returns: size of formatted string. 87462306a36Sopenharmony_ci **/ 87562306a36Sopenharmony_cistatic ssize_t 87662306a36Sopenharmony_cilpfc_modeldesc_show(struct device *dev, struct device_attribute *attr, 87762306a36Sopenharmony_ci char *buf) 87862306a36Sopenharmony_ci{ 87962306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 88062306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 88162306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 88262306a36Sopenharmony_ci 88362306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%s\n", phba->ModelDesc); 88462306a36Sopenharmony_ci} 88562306a36Sopenharmony_ci 88662306a36Sopenharmony_ci/** 88762306a36Sopenharmony_ci * lpfc_modelname_show - Return the model name of the hba 88862306a36Sopenharmony_ci * @dev: class converted to a Scsi_host structure. 88962306a36Sopenharmony_ci * @attr: device attribute, not used. 89062306a36Sopenharmony_ci * @buf: on return contains the scsi vpd model name. 89162306a36Sopenharmony_ci * 89262306a36Sopenharmony_ci * Returns: size of formatted string. 89362306a36Sopenharmony_ci **/ 89462306a36Sopenharmony_cistatic ssize_t 89562306a36Sopenharmony_cilpfc_modelname_show(struct device *dev, struct device_attribute *attr, 89662306a36Sopenharmony_ci char *buf) 89762306a36Sopenharmony_ci{ 89862306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 89962306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 90062306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 90162306a36Sopenharmony_ci 90262306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%s\n", phba->ModelName); 90362306a36Sopenharmony_ci} 90462306a36Sopenharmony_ci 90562306a36Sopenharmony_ci/** 90662306a36Sopenharmony_ci * lpfc_programtype_show - Return the program type of the hba 90762306a36Sopenharmony_ci * @dev: class converted to a Scsi_host structure. 90862306a36Sopenharmony_ci * @attr: device attribute, not used. 90962306a36Sopenharmony_ci * @buf: on return contains the scsi vpd program type. 91062306a36Sopenharmony_ci * 91162306a36Sopenharmony_ci * Returns: size of formatted string. 91262306a36Sopenharmony_ci **/ 91362306a36Sopenharmony_cistatic ssize_t 91462306a36Sopenharmony_cilpfc_programtype_show(struct device *dev, struct device_attribute *attr, 91562306a36Sopenharmony_ci char *buf) 91662306a36Sopenharmony_ci{ 91762306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 91862306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 91962306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 92062306a36Sopenharmony_ci 92162306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%s\n", phba->ProgramType); 92262306a36Sopenharmony_ci} 92362306a36Sopenharmony_ci 92462306a36Sopenharmony_ci/** 92562306a36Sopenharmony_ci * lpfc_vportnum_show - Return the port number in ascii of the hba 92662306a36Sopenharmony_ci * @dev: class converted to a Scsi_host structure. 92762306a36Sopenharmony_ci * @attr: device attribute, not used. 92862306a36Sopenharmony_ci * @buf: on return contains scsi vpd program type. 92962306a36Sopenharmony_ci * 93062306a36Sopenharmony_ci * Returns: size of formatted string. 93162306a36Sopenharmony_ci **/ 93262306a36Sopenharmony_cistatic ssize_t 93362306a36Sopenharmony_cilpfc_vportnum_show(struct device *dev, struct device_attribute *attr, 93462306a36Sopenharmony_ci char *buf) 93562306a36Sopenharmony_ci{ 93662306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 93762306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 93862306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 93962306a36Sopenharmony_ci 94062306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%s\n", phba->Port); 94162306a36Sopenharmony_ci} 94262306a36Sopenharmony_ci 94362306a36Sopenharmony_ci/** 94462306a36Sopenharmony_ci * lpfc_fwrev_show - Return the firmware rev running in the hba 94562306a36Sopenharmony_ci * @dev: class converted to a Scsi_host structure. 94662306a36Sopenharmony_ci * @attr: device attribute, not used. 94762306a36Sopenharmony_ci * @buf: on return contains the scsi vpd program type. 94862306a36Sopenharmony_ci * 94962306a36Sopenharmony_ci * Returns: size of formatted string. 95062306a36Sopenharmony_ci **/ 95162306a36Sopenharmony_cistatic ssize_t 95262306a36Sopenharmony_cilpfc_fwrev_show(struct device *dev, struct device_attribute *attr, 95362306a36Sopenharmony_ci char *buf) 95462306a36Sopenharmony_ci{ 95562306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 95662306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 95762306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 95862306a36Sopenharmony_ci uint32_t if_type; 95962306a36Sopenharmony_ci uint8_t sli_family; 96062306a36Sopenharmony_ci char fwrev[FW_REV_STR_SIZE]; 96162306a36Sopenharmony_ci int len; 96262306a36Sopenharmony_ci 96362306a36Sopenharmony_ci lpfc_decode_firmware_rev(phba, fwrev, 1); 96462306a36Sopenharmony_ci if_type = phba->sli4_hba.pc_sli4_params.if_type; 96562306a36Sopenharmony_ci sli_family = phba->sli4_hba.pc_sli4_params.sli_family; 96662306a36Sopenharmony_ci 96762306a36Sopenharmony_ci if (phba->sli_rev < LPFC_SLI_REV4) 96862306a36Sopenharmony_ci len = scnprintf(buf, PAGE_SIZE, "%s, sli-%d\n", 96962306a36Sopenharmony_ci fwrev, phba->sli_rev); 97062306a36Sopenharmony_ci else 97162306a36Sopenharmony_ci len = scnprintf(buf, PAGE_SIZE, "%s, sli-%d:%d:%x\n", 97262306a36Sopenharmony_ci fwrev, phba->sli_rev, if_type, sli_family); 97362306a36Sopenharmony_ci 97462306a36Sopenharmony_ci return len; 97562306a36Sopenharmony_ci} 97662306a36Sopenharmony_ci 97762306a36Sopenharmony_ci/** 97862306a36Sopenharmony_ci * lpfc_hdw_show - Return the jedec information about the hba 97962306a36Sopenharmony_ci * @dev: class converted to a Scsi_host structure. 98062306a36Sopenharmony_ci * @attr: device attribute, not used. 98162306a36Sopenharmony_ci * @buf: on return contains the scsi vpd program type. 98262306a36Sopenharmony_ci * 98362306a36Sopenharmony_ci * Returns: size of formatted string. 98462306a36Sopenharmony_ci **/ 98562306a36Sopenharmony_cistatic ssize_t 98662306a36Sopenharmony_cilpfc_hdw_show(struct device *dev, struct device_attribute *attr, char *buf) 98762306a36Sopenharmony_ci{ 98862306a36Sopenharmony_ci char hdw[9]; 98962306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 99062306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 99162306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 99262306a36Sopenharmony_ci lpfc_vpd_t *vp = &phba->vpd; 99362306a36Sopenharmony_ci 99462306a36Sopenharmony_ci lpfc_jedec_to_ascii(vp->rev.biuRev, hdw); 99562306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%s %08x %08x\n", hdw, 99662306a36Sopenharmony_ci vp->rev.smRev, vp->rev.smFwRev); 99762306a36Sopenharmony_ci} 99862306a36Sopenharmony_ci 99962306a36Sopenharmony_ci/** 100062306a36Sopenharmony_ci * lpfc_option_rom_version_show - Return the adapter ROM FCode version 100162306a36Sopenharmony_ci * @dev: class converted to a Scsi_host structure. 100262306a36Sopenharmony_ci * @attr: device attribute, not used. 100362306a36Sopenharmony_ci * @buf: on return contains the ROM and FCode ascii strings. 100462306a36Sopenharmony_ci * 100562306a36Sopenharmony_ci * Returns: size of formatted string. 100662306a36Sopenharmony_ci **/ 100762306a36Sopenharmony_cistatic ssize_t 100862306a36Sopenharmony_cilpfc_option_rom_version_show(struct device *dev, struct device_attribute *attr, 100962306a36Sopenharmony_ci char *buf) 101062306a36Sopenharmony_ci{ 101162306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 101262306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 101362306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 101462306a36Sopenharmony_ci char fwrev[FW_REV_STR_SIZE]; 101562306a36Sopenharmony_ci 101662306a36Sopenharmony_ci if (phba->sli_rev < LPFC_SLI_REV4) 101762306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%s\n", 101862306a36Sopenharmony_ci phba->OptionROMVersion); 101962306a36Sopenharmony_ci 102062306a36Sopenharmony_ci lpfc_decode_firmware_rev(phba, fwrev, 1); 102162306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%s\n", fwrev); 102262306a36Sopenharmony_ci} 102362306a36Sopenharmony_ci 102462306a36Sopenharmony_ci/** 102562306a36Sopenharmony_ci * lpfc_link_state_show - Return the link state of the port 102662306a36Sopenharmony_ci * @dev: class converted to a Scsi_host structure. 102762306a36Sopenharmony_ci * @attr: device attribute, not used. 102862306a36Sopenharmony_ci * @buf: on return contains text describing the state of the link. 102962306a36Sopenharmony_ci * 103062306a36Sopenharmony_ci * Notes: 103162306a36Sopenharmony_ci * The switch statement has no default so zero will be returned. 103262306a36Sopenharmony_ci * 103362306a36Sopenharmony_ci * Returns: size of formatted string. 103462306a36Sopenharmony_ci **/ 103562306a36Sopenharmony_cistatic ssize_t 103662306a36Sopenharmony_cilpfc_link_state_show(struct device *dev, struct device_attribute *attr, 103762306a36Sopenharmony_ci char *buf) 103862306a36Sopenharmony_ci{ 103962306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 104062306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 104162306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 104262306a36Sopenharmony_ci int len = 0; 104362306a36Sopenharmony_ci 104462306a36Sopenharmony_ci switch (phba->link_state) { 104562306a36Sopenharmony_ci case LPFC_LINK_UNKNOWN: 104662306a36Sopenharmony_ci case LPFC_WARM_START: 104762306a36Sopenharmony_ci case LPFC_INIT_START: 104862306a36Sopenharmony_ci case LPFC_INIT_MBX_CMDS: 104962306a36Sopenharmony_ci case LPFC_LINK_DOWN: 105062306a36Sopenharmony_ci case LPFC_HBA_ERROR: 105162306a36Sopenharmony_ci if (phba->hba_flag & LINK_DISABLED) 105262306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, 105362306a36Sopenharmony_ci "Link Down - User disabled\n"); 105462306a36Sopenharmony_ci else 105562306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, 105662306a36Sopenharmony_ci "Link Down\n"); 105762306a36Sopenharmony_ci break; 105862306a36Sopenharmony_ci case LPFC_LINK_UP: 105962306a36Sopenharmony_ci case LPFC_CLEAR_LA: 106062306a36Sopenharmony_ci case LPFC_HBA_READY: 106162306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, "Link Up - "); 106262306a36Sopenharmony_ci 106362306a36Sopenharmony_ci switch (vport->port_state) { 106462306a36Sopenharmony_ci case LPFC_LOCAL_CFG_LINK: 106562306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, 106662306a36Sopenharmony_ci "Configuring Link\n"); 106762306a36Sopenharmony_ci break; 106862306a36Sopenharmony_ci case LPFC_FDISC: 106962306a36Sopenharmony_ci case LPFC_FLOGI: 107062306a36Sopenharmony_ci case LPFC_FABRIC_CFG_LINK: 107162306a36Sopenharmony_ci case LPFC_NS_REG: 107262306a36Sopenharmony_ci case LPFC_NS_QRY: 107362306a36Sopenharmony_ci case LPFC_BUILD_DISC_LIST: 107462306a36Sopenharmony_ci case LPFC_DISC_AUTH: 107562306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, 107662306a36Sopenharmony_ci "Discovery\n"); 107762306a36Sopenharmony_ci break; 107862306a36Sopenharmony_ci case LPFC_VPORT_READY: 107962306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, 108062306a36Sopenharmony_ci "Ready\n"); 108162306a36Sopenharmony_ci break; 108262306a36Sopenharmony_ci 108362306a36Sopenharmony_ci case LPFC_VPORT_FAILED: 108462306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, 108562306a36Sopenharmony_ci "Failed\n"); 108662306a36Sopenharmony_ci break; 108762306a36Sopenharmony_ci 108862306a36Sopenharmony_ci case LPFC_VPORT_UNKNOWN: 108962306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, 109062306a36Sopenharmony_ci "Unknown\n"); 109162306a36Sopenharmony_ci break; 109262306a36Sopenharmony_ci } 109362306a36Sopenharmony_ci if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) { 109462306a36Sopenharmony_ci if (vport->fc_flag & FC_PUBLIC_LOOP) 109562306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, 109662306a36Sopenharmony_ci " Public Loop\n"); 109762306a36Sopenharmony_ci else 109862306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, 109962306a36Sopenharmony_ci " Private Loop\n"); 110062306a36Sopenharmony_ci } else { 110162306a36Sopenharmony_ci if (vport->fc_flag & FC_FABRIC) { 110262306a36Sopenharmony_ci if (phba->sli_rev == LPFC_SLI_REV4 && 110362306a36Sopenharmony_ci vport->port_type == LPFC_PHYSICAL_PORT && 110462306a36Sopenharmony_ci phba->sli4_hba.fawwpn_flag & 110562306a36Sopenharmony_ci LPFC_FAWWPN_FABRIC) 110662306a36Sopenharmony_ci len += scnprintf(buf + len, 110762306a36Sopenharmony_ci PAGE_SIZE - len, 110862306a36Sopenharmony_ci " Fabric FA-PWWN\n"); 110962306a36Sopenharmony_ci else 111062306a36Sopenharmony_ci len += scnprintf(buf + len, 111162306a36Sopenharmony_ci PAGE_SIZE - len, 111262306a36Sopenharmony_ci " Fabric\n"); 111362306a36Sopenharmony_ci } else { 111462306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, 111562306a36Sopenharmony_ci " Point-2-Point\n"); 111662306a36Sopenharmony_ci } 111762306a36Sopenharmony_ci } 111862306a36Sopenharmony_ci } 111962306a36Sopenharmony_ci 112062306a36Sopenharmony_ci if ((phba->sli_rev == LPFC_SLI_REV4) && 112162306a36Sopenharmony_ci ((bf_get(lpfc_sli_intf_if_type, 112262306a36Sopenharmony_ci &phba->sli4_hba.sli_intf) == 112362306a36Sopenharmony_ci LPFC_SLI_INTF_IF_TYPE_6))) { 112462306a36Sopenharmony_ci struct lpfc_trunk_link link = phba->trunk_link; 112562306a36Sopenharmony_ci 112662306a36Sopenharmony_ci if (bf_get(lpfc_conf_trunk_port0, &phba->sli4_hba)) 112762306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, 112862306a36Sopenharmony_ci "Trunk port 0: Link %s %s\n", 112962306a36Sopenharmony_ci (link.link0.state == LPFC_LINK_UP) ? 113062306a36Sopenharmony_ci "Up" : "Down. ", 113162306a36Sopenharmony_ci trunk_errmsg[link.link0.fault]); 113262306a36Sopenharmony_ci 113362306a36Sopenharmony_ci if (bf_get(lpfc_conf_trunk_port1, &phba->sli4_hba)) 113462306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, 113562306a36Sopenharmony_ci "Trunk port 1: Link %s %s\n", 113662306a36Sopenharmony_ci (link.link1.state == LPFC_LINK_UP) ? 113762306a36Sopenharmony_ci "Up" : "Down. ", 113862306a36Sopenharmony_ci trunk_errmsg[link.link1.fault]); 113962306a36Sopenharmony_ci 114062306a36Sopenharmony_ci if (bf_get(lpfc_conf_trunk_port2, &phba->sli4_hba)) 114162306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, 114262306a36Sopenharmony_ci "Trunk port 2: Link %s %s\n", 114362306a36Sopenharmony_ci (link.link2.state == LPFC_LINK_UP) ? 114462306a36Sopenharmony_ci "Up" : "Down. ", 114562306a36Sopenharmony_ci trunk_errmsg[link.link2.fault]); 114662306a36Sopenharmony_ci 114762306a36Sopenharmony_ci if (bf_get(lpfc_conf_trunk_port3, &phba->sli4_hba)) 114862306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, 114962306a36Sopenharmony_ci "Trunk port 3: Link %s %s\n", 115062306a36Sopenharmony_ci (link.link3.state == LPFC_LINK_UP) ? 115162306a36Sopenharmony_ci "Up" : "Down. ", 115262306a36Sopenharmony_ci trunk_errmsg[link.link3.fault]); 115362306a36Sopenharmony_ci 115462306a36Sopenharmony_ci } 115562306a36Sopenharmony_ci 115662306a36Sopenharmony_ci return len; 115762306a36Sopenharmony_ci} 115862306a36Sopenharmony_ci 115962306a36Sopenharmony_ci/** 116062306a36Sopenharmony_ci * lpfc_sli4_protocol_show - Return the fip mode of the HBA 116162306a36Sopenharmony_ci * @dev: class unused variable. 116262306a36Sopenharmony_ci * @attr: device attribute, not used. 116362306a36Sopenharmony_ci * @buf: on return contains the module description text. 116462306a36Sopenharmony_ci * 116562306a36Sopenharmony_ci * Returns: size of formatted string. 116662306a36Sopenharmony_ci **/ 116762306a36Sopenharmony_cistatic ssize_t 116862306a36Sopenharmony_cilpfc_sli4_protocol_show(struct device *dev, struct device_attribute *attr, 116962306a36Sopenharmony_ci char *buf) 117062306a36Sopenharmony_ci{ 117162306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 117262306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 117362306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 117462306a36Sopenharmony_ci 117562306a36Sopenharmony_ci if (phba->sli_rev < LPFC_SLI_REV4) 117662306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "fc\n"); 117762306a36Sopenharmony_ci 117862306a36Sopenharmony_ci if (phba->sli4_hba.lnk_info.lnk_dv == LPFC_LNK_DAT_VAL) { 117962306a36Sopenharmony_ci if (phba->sli4_hba.lnk_info.lnk_tp == LPFC_LNK_TYPE_GE) 118062306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "fcoe\n"); 118162306a36Sopenharmony_ci if (phba->sli4_hba.lnk_info.lnk_tp == LPFC_LNK_TYPE_FC) 118262306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "fc\n"); 118362306a36Sopenharmony_ci } 118462306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "unknown\n"); 118562306a36Sopenharmony_ci} 118662306a36Sopenharmony_ci 118762306a36Sopenharmony_ci/** 118862306a36Sopenharmony_ci * lpfc_oas_supported_show - Return whether or not Optimized Access Storage 118962306a36Sopenharmony_ci * (OAS) is supported. 119062306a36Sopenharmony_ci * @dev: class unused variable. 119162306a36Sopenharmony_ci * @attr: device attribute, not used. 119262306a36Sopenharmony_ci * @buf: on return contains the module description text. 119362306a36Sopenharmony_ci * 119462306a36Sopenharmony_ci * Returns: size of formatted string. 119562306a36Sopenharmony_ci **/ 119662306a36Sopenharmony_cistatic ssize_t 119762306a36Sopenharmony_cilpfc_oas_supported_show(struct device *dev, struct device_attribute *attr, 119862306a36Sopenharmony_ci char *buf) 119962306a36Sopenharmony_ci{ 120062306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 120162306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata; 120262306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 120362306a36Sopenharmony_ci 120462306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d\n", 120562306a36Sopenharmony_ci phba->sli4_hba.pc_sli4_params.oas_supported); 120662306a36Sopenharmony_ci} 120762306a36Sopenharmony_ci 120862306a36Sopenharmony_ci/** 120962306a36Sopenharmony_ci * lpfc_link_state_store - Transition the link_state on an HBA port 121062306a36Sopenharmony_ci * @dev: class device that is converted into a Scsi_host. 121162306a36Sopenharmony_ci * @attr: device attribute, not used. 121262306a36Sopenharmony_ci * @buf: one or more lpfc_polling_flags values. 121362306a36Sopenharmony_ci * @count: not used. 121462306a36Sopenharmony_ci * 121562306a36Sopenharmony_ci * Returns: 121662306a36Sopenharmony_ci * -EINVAL if the buffer is not "up" or "down" 121762306a36Sopenharmony_ci * return from link state change function if non-zero 121862306a36Sopenharmony_ci * length of the buf on success 121962306a36Sopenharmony_ci **/ 122062306a36Sopenharmony_cistatic ssize_t 122162306a36Sopenharmony_cilpfc_link_state_store(struct device *dev, struct device_attribute *attr, 122262306a36Sopenharmony_ci const char *buf, size_t count) 122362306a36Sopenharmony_ci{ 122462306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 122562306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 122662306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 122762306a36Sopenharmony_ci 122862306a36Sopenharmony_ci int status = -EINVAL; 122962306a36Sopenharmony_ci 123062306a36Sopenharmony_ci if ((strncmp(buf, "up", sizeof("up") - 1) == 0) && 123162306a36Sopenharmony_ci (phba->link_state == LPFC_LINK_DOWN)) 123262306a36Sopenharmony_ci status = phba->lpfc_hba_init_link(phba, MBX_NOWAIT); 123362306a36Sopenharmony_ci else if ((strncmp(buf, "down", sizeof("down") - 1) == 0) && 123462306a36Sopenharmony_ci (phba->link_state >= LPFC_LINK_UP)) 123562306a36Sopenharmony_ci status = phba->lpfc_hba_down_link(phba, MBX_NOWAIT); 123662306a36Sopenharmony_ci 123762306a36Sopenharmony_ci if (status == 0) 123862306a36Sopenharmony_ci return strlen(buf); 123962306a36Sopenharmony_ci else 124062306a36Sopenharmony_ci return status; 124162306a36Sopenharmony_ci} 124262306a36Sopenharmony_ci 124362306a36Sopenharmony_ci/** 124462306a36Sopenharmony_ci * lpfc_num_discovered_ports_show - Return sum of mapped and unmapped vports 124562306a36Sopenharmony_ci * @dev: class device that is converted into a Scsi_host. 124662306a36Sopenharmony_ci * @attr: device attribute, not used. 124762306a36Sopenharmony_ci * @buf: on return contains the sum of fc mapped and unmapped. 124862306a36Sopenharmony_ci * 124962306a36Sopenharmony_ci * Description: 125062306a36Sopenharmony_ci * Returns the ascii text number of the sum of the fc mapped and unmapped 125162306a36Sopenharmony_ci * vport counts. 125262306a36Sopenharmony_ci * 125362306a36Sopenharmony_ci * Returns: size of formatted string. 125462306a36Sopenharmony_ci **/ 125562306a36Sopenharmony_cistatic ssize_t 125662306a36Sopenharmony_cilpfc_num_discovered_ports_show(struct device *dev, 125762306a36Sopenharmony_ci struct device_attribute *attr, char *buf) 125862306a36Sopenharmony_ci{ 125962306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 126062306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 126162306a36Sopenharmony_ci 126262306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d\n", 126362306a36Sopenharmony_ci vport->fc_map_cnt + vport->fc_unmap_cnt); 126462306a36Sopenharmony_ci} 126562306a36Sopenharmony_ci 126662306a36Sopenharmony_ci/** 126762306a36Sopenharmony_ci * lpfc_issue_lip - Misnomer, name carried over from long ago 126862306a36Sopenharmony_ci * @shost: Scsi_Host pointer. 126962306a36Sopenharmony_ci * 127062306a36Sopenharmony_ci * Description: 127162306a36Sopenharmony_ci * Bring the link down gracefully then re-init the link. The firmware will 127262306a36Sopenharmony_ci * re-init the fiber channel interface as required. Does not issue a LIP. 127362306a36Sopenharmony_ci * 127462306a36Sopenharmony_ci * Returns: 127562306a36Sopenharmony_ci * -EPERM port offline or management commands are being blocked 127662306a36Sopenharmony_ci * -ENOMEM cannot allocate memory for the mailbox command 127762306a36Sopenharmony_ci * -EIO error sending the mailbox command 127862306a36Sopenharmony_ci * zero for success 127962306a36Sopenharmony_ci **/ 128062306a36Sopenharmony_cistatic int 128162306a36Sopenharmony_cilpfc_issue_lip(struct Scsi_Host *shost) 128262306a36Sopenharmony_ci{ 128362306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 128462306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 128562306a36Sopenharmony_ci LPFC_MBOXQ_t *pmboxq; 128662306a36Sopenharmony_ci int mbxstatus = MBXERR_ERROR; 128762306a36Sopenharmony_ci 128862306a36Sopenharmony_ci /* 128962306a36Sopenharmony_ci * If the link is offline, disabled or BLOCK_MGMT_IO 129062306a36Sopenharmony_ci * it doesn't make any sense to allow issue_lip 129162306a36Sopenharmony_ci */ 129262306a36Sopenharmony_ci if ((vport->fc_flag & FC_OFFLINE_MODE) || 129362306a36Sopenharmony_ci (phba->hba_flag & LINK_DISABLED) || 129462306a36Sopenharmony_ci (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO)) 129562306a36Sopenharmony_ci return -EPERM; 129662306a36Sopenharmony_ci 129762306a36Sopenharmony_ci pmboxq = mempool_alloc(phba->mbox_mem_pool,GFP_KERNEL); 129862306a36Sopenharmony_ci 129962306a36Sopenharmony_ci if (!pmboxq) 130062306a36Sopenharmony_ci return -ENOMEM; 130162306a36Sopenharmony_ci 130262306a36Sopenharmony_ci memset((void *)pmboxq, 0, sizeof (LPFC_MBOXQ_t)); 130362306a36Sopenharmony_ci pmboxq->u.mb.mbxCommand = MBX_DOWN_LINK; 130462306a36Sopenharmony_ci pmboxq->u.mb.mbxOwner = OWN_HOST; 130562306a36Sopenharmony_ci 130662306a36Sopenharmony_ci if ((vport->fc_flag & FC_PT2PT) && (vport->fc_flag & FC_PT2PT_NO_NVME)) 130762306a36Sopenharmony_ci vport->fc_flag &= ~FC_PT2PT_NO_NVME; 130862306a36Sopenharmony_ci 130962306a36Sopenharmony_ci mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq, LPFC_MBOX_TMO * 2); 131062306a36Sopenharmony_ci 131162306a36Sopenharmony_ci if ((mbxstatus == MBX_SUCCESS) && 131262306a36Sopenharmony_ci (pmboxq->u.mb.mbxStatus == 0 || 131362306a36Sopenharmony_ci pmboxq->u.mb.mbxStatus == MBXERR_LINK_DOWN)) { 131462306a36Sopenharmony_ci memset((void *)pmboxq, 0, sizeof (LPFC_MBOXQ_t)); 131562306a36Sopenharmony_ci lpfc_init_link(phba, pmboxq, phba->cfg_topology, 131662306a36Sopenharmony_ci phba->cfg_link_speed); 131762306a36Sopenharmony_ci mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq, 131862306a36Sopenharmony_ci phba->fc_ratov * 2); 131962306a36Sopenharmony_ci if ((mbxstatus == MBX_SUCCESS) && 132062306a36Sopenharmony_ci (pmboxq->u.mb.mbxStatus == MBXERR_SEC_NO_PERMISSION)) 132162306a36Sopenharmony_ci lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, 132262306a36Sopenharmony_ci "2859 SLI authentication is required " 132362306a36Sopenharmony_ci "for INIT_LINK but has not done yet\n"); 132462306a36Sopenharmony_ci } 132562306a36Sopenharmony_ci 132662306a36Sopenharmony_ci lpfc_set_loopback_flag(phba); 132762306a36Sopenharmony_ci if (mbxstatus != MBX_TIMEOUT) 132862306a36Sopenharmony_ci mempool_free(pmboxq, phba->mbox_mem_pool); 132962306a36Sopenharmony_ci 133062306a36Sopenharmony_ci if (mbxstatus == MBXERR_ERROR) 133162306a36Sopenharmony_ci return -EIO; 133262306a36Sopenharmony_ci 133362306a36Sopenharmony_ci return 0; 133462306a36Sopenharmony_ci} 133562306a36Sopenharmony_ci 133662306a36Sopenharmony_ciint 133762306a36Sopenharmony_cilpfc_emptyq_wait(struct lpfc_hba *phba, struct list_head *q, spinlock_t *lock) 133862306a36Sopenharmony_ci{ 133962306a36Sopenharmony_ci int cnt = 0; 134062306a36Sopenharmony_ci 134162306a36Sopenharmony_ci spin_lock_irq(lock); 134262306a36Sopenharmony_ci while (!list_empty(q)) { 134362306a36Sopenharmony_ci spin_unlock_irq(lock); 134462306a36Sopenharmony_ci msleep(20); 134562306a36Sopenharmony_ci if (cnt++ > 250) { /* 5 secs */ 134662306a36Sopenharmony_ci lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, 134762306a36Sopenharmony_ci "0466 Outstanding IO when " 134862306a36Sopenharmony_ci "bringing Adapter offline\n"); 134962306a36Sopenharmony_ci return 0; 135062306a36Sopenharmony_ci } 135162306a36Sopenharmony_ci spin_lock_irq(lock); 135262306a36Sopenharmony_ci } 135362306a36Sopenharmony_ci spin_unlock_irq(lock); 135462306a36Sopenharmony_ci return 1; 135562306a36Sopenharmony_ci} 135662306a36Sopenharmony_ci 135762306a36Sopenharmony_ci/** 135862306a36Sopenharmony_ci * lpfc_do_offline - Issues a mailbox command to bring the link down 135962306a36Sopenharmony_ci * @phba: lpfc_hba pointer. 136062306a36Sopenharmony_ci * @type: LPFC_EVT_OFFLINE, LPFC_EVT_WARM_START, LPFC_EVT_KILL. 136162306a36Sopenharmony_ci * 136262306a36Sopenharmony_ci * Notes: 136362306a36Sopenharmony_ci * Assumes any error from lpfc_do_offline() will be negative. 136462306a36Sopenharmony_ci * Can wait up to 5 seconds for the port ring buffers count 136562306a36Sopenharmony_ci * to reach zero, prints a warning if it is not zero and continues. 136662306a36Sopenharmony_ci * lpfc_workq_post_event() returns a non-zero return code if call fails. 136762306a36Sopenharmony_ci * 136862306a36Sopenharmony_ci * Returns: 136962306a36Sopenharmony_ci * -EIO error posting the event 137062306a36Sopenharmony_ci * zero for success 137162306a36Sopenharmony_ci **/ 137262306a36Sopenharmony_cistatic int 137362306a36Sopenharmony_cilpfc_do_offline(struct lpfc_hba *phba, uint32_t type) 137462306a36Sopenharmony_ci{ 137562306a36Sopenharmony_ci struct completion online_compl; 137662306a36Sopenharmony_ci struct lpfc_queue *qp = NULL; 137762306a36Sopenharmony_ci struct lpfc_sli_ring *pring; 137862306a36Sopenharmony_ci struct lpfc_sli *psli; 137962306a36Sopenharmony_ci int status = 0; 138062306a36Sopenharmony_ci int i; 138162306a36Sopenharmony_ci int rc; 138262306a36Sopenharmony_ci 138362306a36Sopenharmony_ci init_completion(&online_compl); 138462306a36Sopenharmony_ci rc = lpfc_workq_post_event(phba, &status, &online_compl, 138562306a36Sopenharmony_ci LPFC_EVT_OFFLINE_PREP); 138662306a36Sopenharmony_ci if (rc == 0) 138762306a36Sopenharmony_ci return -ENOMEM; 138862306a36Sopenharmony_ci 138962306a36Sopenharmony_ci wait_for_completion(&online_compl); 139062306a36Sopenharmony_ci 139162306a36Sopenharmony_ci if (status != 0) 139262306a36Sopenharmony_ci return -EIO; 139362306a36Sopenharmony_ci 139462306a36Sopenharmony_ci psli = &phba->sli; 139562306a36Sopenharmony_ci 139662306a36Sopenharmony_ci /* 139762306a36Sopenharmony_ci * If freeing the queues have already started, don't access them. 139862306a36Sopenharmony_ci * Otherwise set FREE_WAIT to indicate that queues are being used 139962306a36Sopenharmony_ci * to hold the freeing process until we finish. 140062306a36Sopenharmony_ci */ 140162306a36Sopenharmony_ci spin_lock_irq(&phba->hbalock); 140262306a36Sopenharmony_ci if (!(psli->sli_flag & LPFC_QUEUE_FREE_INIT)) { 140362306a36Sopenharmony_ci psli->sli_flag |= LPFC_QUEUE_FREE_WAIT; 140462306a36Sopenharmony_ci } else { 140562306a36Sopenharmony_ci spin_unlock_irq(&phba->hbalock); 140662306a36Sopenharmony_ci goto skip_wait; 140762306a36Sopenharmony_ci } 140862306a36Sopenharmony_ci spin_unlock_irq(&phba->hbalock); 140962306a36Sopenharmony_ci 141062306a36Sopenharmony_ci /* Wait a little for things to settle down, but not 141162306a36Sopenharmony_ci * long enough for dev loss timeout to expire. 141262306a36Sopenharmony_ci */ 141362306a36Sopenharmony_ci if (phba->sli_rev != LPFC_SLI_REV4) { 141462306a36Sopenharmony_ci for (i = 0; i < psli->num_rings; i++) { 141562306a36Sopenharmony_ci pring = &psli->sli3_ring[i]; 141662306a36Sopenharmony_ci if (!lpfc_emptyq_wait(phba, &pring->txcmplq, 141762306a36Sopenharmony_ci &phba->hbalock)) 141862306a36Sopenharmony_ci goto out; 141962306a36Sopenharmony_ci } 142062306a36Sopenharmony_ci } else { 142162306a36Sopenharmony_ci list_for_each_entry(qp, &phba->sli4_hba.lpfc_wq_list, wq_list) { 142262306a36Sopenharmony_ci pring = qp->pring; 142362306a36Sopenharmony_ci if (!pring) 142462306a36Sopenharmony_ci continue; 142562306a36Sopenharmony_ci if (!lpfc_emptyq_wait(phba, &pring->txcmplq, 142662306a36Sopenharmony_ci &pring->ring_lock)) 142762306a36Sopenharmony_ci goto out; 142862306a36Sopenharmony_ci } 142962306a36Sopenharmony_ci } 143062306a36Sopenharmony_ciout: 143162306a36Sopenharmony_ci spin_lock_irq(&phba->hbalock); 143262306a36Sopenharmony_ci psli->sli_flag &= ~LPFC_QUEUE_FREE_WAIT; 143362306a36Sopenharmony_ci spin_unlock_irq(&phba->hbalock); 143462306a36Sopenharmony_ci 143562306a36Sopenharmony_ciskip_wait: 143662306a36Sopenharmony_ci init_completion(&online_compl); 143762306a36Sopenharmony_ci rc = lpfc_workq_post_event(phba, &status, &online_compl, type); 143862306a36Sopenharmony_ci if (rc == 0) 143962306a36Sopenharmony_ci return -ENOMEM; 144062306a36Sopenharmony_ci 144162306a36Sopenharmony_ci wait_for_completion(&online_compl); 144262306a36Sopenharmony_ci 144362306a36Sopenharmony_ci if (status != 0) 144462306a36Sopenharmony_ci return -EIO; 144562306a36Sopenharmony_ci 144662306a36Sopenharmony_ci return 0; 144762306a36Sopenharmony_ci} 144862306a36Sopenharmony_ci 144962306a36Sopenharmony_ci/** 145062306a36Sopenharmony_ci * lpfc_reset_pci_bus - resets PCI bridge controller's secondary bus of an HBA 145162306a36Sopenharmony_ci * @phba: lpfc_hba pointer. 145262306a36Sopenharmony_ci * 145362306a36Sopenharmony_ci * Description: 145462306a36Sopenharmony_ci * Issues a PCI secondary bus reset for the phba->pcidev. 145562306a36Sopenharmony_ci * 145662306a36Sopenharmony_ci * Notes: 145762306a36Sopenharmony_ci * First walks the bus_list to ensure only PCI devices with Emulex 145862306a36Sopenharmony_ci * vendor id, device ids that support hot reset, only one occurrence 145962306a36Sopenharmony_ci * of function 0, and all ports on the bus are in offline mode to ensure the 146062306a36Sopenharmony_ci * hot reset only affects one valid HBA. 146162306a36Sopenharmony_ci * 146262306a36Sopenharmony_ci * Returns: 146362306a36Sopenharmony_ci * -ENOTSUPP, cfg_enable_hba_reset must be of value 2 146462306a36Sopenharmony_ci * -ENODEV, NULL ptr to pcidev 146562306a36Sopenharmony_ci * -EBADSLT, detected invalid device 146662306a36Sopenharmony_ci * -EBUSY, port is not in offline state 146762306a36Sopenharmony_ci * 0, successful 146862306a36Sopenharmony_ci */ 146962306a36Sopenharmony_cistatic int 147062306a36Sopenharmony_cilpfc_reset_pci_bus(struct lpfc_hba *phba) 147162306a36Sopenharmony_ci{ 147262306a36Sopenharmony_ci struct pci_dev *pdev = phba->pcidev; 147362306a36Sopenharmony_ci struct Scsi_Host *shost = NULL; 147462306a36Sopenharmony_ci struct lpfc_hba *phba_other = NULL; 147562306a36Sopenharmony_ci struct pci_dev *ptr = NULL; 147662306a36Sopenharmony_ci int res; 147762306a36Sopenharmony_ci 147862306a36Sopenharmony_ci if (phba->cfg_enable_hba_reset != 2) 147962306a36Sopenharmony_ci return -ENOTSUPP; 148062306a36Sopenharmony_ci 148162306a36Sopenharmony_ci if (!pdev) { 148262306a36Sopenharmony_ci lpfc_printf_log(phba, KERN_INFO, LOG_INIT, "8345 pdev NULL!\n"); 148362306a36Sopenharmony_ci return -ENODEV; 148462306a36Sopenharmony_ci } 148562306a36Sopenharmony_ci 148662306a36Sopenharmony_ci res = lpfc_check_pci_resettable(phba); 148762306a36Sopenharmony_ci if (res) 148862306a36Sopenharmony_ci return res; 148962306a36Sopenharmony_ci 149062306a36Sopenharmony_ci /* Walk the list of devices on the pci_dev's bus */ 149162306a36Sopenharmony_ci list_for_each_entry(ptr, &pdev->bus->devices, bus_list) { 149262306a36Sopenharmony_ci /* Check port is offline */ 149362306a36Sopenharmony_ci shost = pci_get_drvdata(ptr); 149462306a36Sopenharmony_ci if (shost) { 149562306a36Sopenharmony_ci phba_other = 149662306a36Sopenharmony_ci ((struct lpfc_vport *)shost->hostdata)->phba; 149762306a36Sopenharmony_ci if (!(phba_other->pport->fc_flag & FC_OFFLINE_MODE)) { 149862306a36Sopenharmony_ci lpfc_printf_log(phba_other, KERN_INFO, LOG_INIT, 149962306a36Sopenharmony_ci "8349 WWPN = 0x%02x%02x%02x%02x" 150062306a36Sopenharmony_ci "%02x%02x%02x%02x is not " 150162306a36Sopenharmony_ci "offline!\n", 150262306a36Sopenharmony_ci phba_other->wwpn[0], 150362306a36Sopenharmony_ci phba_other->wwpn[1], 150462306a36Sopenharmony_ci phba_other->wwpn[2], 150562306a36Sopenharmony_ci phba_other->wwpn[3], 150662306a36Sopenharmony_ci phba_other->wwpn[4], 150762306a36Sopenharmony_ci phba_other->wwpn[5], 150862306a36Sopenharmony_ci phba_other->wwpn[6], 150962306a36Sopenharmony_ci phba_other->wwpn[7]); 151062306a36Sopenharmony_ci return -EBUSY; 151162306a36Sopenharmony_ci } 151262306a36Sopenharmony_ci } 151362306a36Sopenharmony_ci } 151462306a36Sopenharmony_ci 151562306a36Sopenharmony_ci /* Issue PCI bus reset */ 151662306a36Sopenharmony_ci res = pci_reset_bus(pdev); 151762306a36Sopenharmony_ci if (res) { 151862306a36Sopenharmony_ci lpfc_printf_log(phba, KERN_ERR, LOG_INIT, 151962306a36Sopenharmony_ci "8350 PCI reset bus failed: %d\n", res); 152062306a36Sopenharmony_ci } 152162306a36Sopenharmony_ci 152262306a36Sopenharmony_ci return res; 152362306a36Sopenharmony_ci} 152462306a36Sopenharmony_ci 152562306a36Sopenharmony_ci/** 152662306a36Sopenharmony_ci * lpfc_selective_reset - Offline then onlines the port 152762306a36Sopenharmony_ci * @phba: lpfc_hba pointer. 152862306a36Sopenharmony_ci * 152962306a36Sopenharmony_ci * Description: 153062306a36Sopenharmony_ci * If the port is configured to allow a reset then the hba is brought 153162306a36Sopenharmony_ci * offline then online. 153262306a36Sopenharmony_ci * 153362306a36Sopenharmony_ci * Notes: 153462306a36Sopenharmony_ci * Assumes any error from lpfc_do_offline() will be negative. 153562306a36Sopenharmony_ci * Do not make this function static. 153662306a36Sopenharmony_ci * 153762306a36Sopenharmony_ci * Returns: 153862306a36Sopenharmony_ci * lpfc_do_offline() return code if not zero 153962306a36Sopenharmony_ci * -EIO reset not configured or error posting the event 154062306a36Sopenharmony_ci * zero for success 154162306a36Sopenharmony_ci **/ 154262306a36Sopenharmony_ciint 154362306a36Sopenharmony_cilpfc_selective_reset(struct lpfc_hba *phba) 154462306a36Sopenharmony_ci{ 154562306a36Sopenharmony_ci struct completion online_compl; 154662306a36Sopenharmony_ci int status = 0; 154762306a36Sopenharmony_ci int rc; 154862306a36Sopenharmony_ci 154962306a36Sopenharmony_ci if (!phba->cfg_enable_hba_reset) 155062306a36Sopenharmony_ci return -EACCES; 155162306a36Sopenharmony_ci 155262306a36Sopenharmony_ci if (!(phba->pport->fc_flag & FC_OFFLINE_MODE)) { 155362306a36Sopenharmony_ci status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE); 155462306a36Sopenharmony_ci 155562306a36Sopenharmony_ci if (status != 0) 155662306a36Sopenharmony_ci return status; 155762306a36Sopenharmony_ci } 155862306a36Sopenharmony_ci 155962306a36Sopenharmony_ci init_completion(&online_compl); 156062306a36Sopenharmony_ci rc = lpfc_workq_post_event(phba, &status, &online_compl, 156162306a36Sopenharmony_ci LPFC_EVT_ONLINE); 156262306a36Sopenharmony_ci if (rc == 0) 156362306a36Sopenharmony_ci return -ENOMEM; 156462306a36Sopenharmony_ci 156562306a36Sopenharmony_ci wait_for_completion(&online_compl); 156662306a36Sopenharmony_ci 156762306a36Sopenharmony_ci if (status != 0) 156862306a36Sopenharmony_ci return -EIO; 156962306a36Sopenharmony_ci 157062306a36Sopenharmony_ci return 0; 157162306a36Sopenharmony_ci} 157262306a36Sopenharmony_ci 157362306a36Sopenharmony_ci/** 157462306a36Sopenharmony_ci * lpfc_issue_reset - Selectively resets an adapter 157562306a36Sopenharmony_ci * @dev: class device that is converted into a Scsi_host. 157662306a36Sopenharmony_ci * @attr: device attribute, not used. 157762306a36Sopenharmony_ci * @buf: containing the string "selective". 157862306a36Sopenharmony_ci * @count: unused variable. 157962306a36Sopenharmony_ci * 158062306a36Sopenharmony_ci * Description: 158162306a36Sopenharmony_ci * If the buf contains the string "selective" then lpfc_selective_reset() 158262306a36Sopenharmony_ci * is called to perform the reset. 158362306a36Sopenharmony_ci * 158462306a36Sopenharmony_ci * Notes: 158562306a36Sopenharmony_ci * Assumes any error from lpfc_selective_reset() will be negative. 158662306a36Sopenharmony_ci * If lpfc_selective_reset() returns zero then the length of the buffer 158762306a36Sopenharmony_ci * is returned which indicates success 158862306a36Sopenharmony_ci * 158962306a36Sopenharmony_ci * Returns: 159062306a36Sopenharmony_ci * -EINVAL if the buffer does not contain the string "selective" 159162306a36Sopenharmony_ci * length of buf if lpfc-selective_reset() if the call succeeds 159262306a36Sopenharmony_ci * return value of lpfc_selective_reset() if the call fails 159362306a36Sopenharmony_ci**/ 159462306a36Sopenharmony_cistatic ssize_t 159562306a36Sopenharmony_cilpfc_issue_reset(struct device *dev, struct device_attribute *attr, 159662306a36Sopenharmony_ci const char *buf, size_t count) 159762306a36Sopenharmony_ci{ 159862306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 159962306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 160062306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 160162306a36Sopenharmony_ci int status = -EINVAL; 160262306a36Sopenharmony_ci 160362306a36Sopenharmony_ci if (!phba->cfg_enable_hba_reset) 160462306a36Sopenharmony_ci return -EACCES; 160562306a36Sopenharmony_ci 160662306a36Sopenharmony_ci if (strncmp(buf, "selective", sizeof("selective") - 1) == 0) 160762306a36Sopenharmony_ci status = phba->lpfc_selective_reset(phba); 160862306a36Sopenharmony_ci 160962306a36Sopenharmony_ci if (status == 0) 161062306a36Sopenharmony_ci return strlen(buf); 161162306a36Sopenharmony_ci else 161262306a36Sopenharmony_ci return status; 161362306a36Sopenharmony_ci} 161462306a36Sopenharmony_ci 161562306a36Sopenharmony_ci/** 161662306a36Sopenharmony_ci * lpfc_sli4_pdev_status_reg_wait - Wait for pdev status register for readyness 161762306a36Sopenharmony_ci * @phba: lpfc_hba pointer. 161862306a36Sopenharmony_ci * 161962306a36Sopenharmony_ci * Description: 162062306a36Sopenharmony_ci * SLI4 interface type-2 device to wait on the sliport status register for 162162306a36Sopenharmony_ci * the readyness after performing a firmware reset. 162262306a36Sopenharmony_ci * 162362306a36Sopenharmony_ci * Returns: 162462306a36Sopenharmony_ci * zero for success, -EPERM when port does not have privilege to perform the 162562306a36Sopenharmony_ci * reset, -EIO when port timeout from recovering from the reset. 162662306a36Sopenharmony_ci * 162762306a36Sopenharmony_ci * Note: 162862306a36Sopenharmony_ci * As the caller will interpret the return code by value, be careful in making 162962306a36Sopenharmony_ci * change or addition to return codes. 163062306a36Sopenharmony_ci **/ 163162306a36Sopenharmony_ciint 163262306a36Sopenharmony_cilpfc_sli4_pdev_status_reg_wait(struct lpfc_hba *phba) 163362306a36Sopenharmony_ci{ 163462306a36Sopenharmony_ci struct lpfc_register portstat_reg = {0}; 163562306a36Sopenharmony_ci int i; 163662306a36Sopenharmony_ci 163762306a36Sopenharmony_ci msleep(100); 163862306a36Sopenharmony_ci if (lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr, 163962306a36Sopenharmony_ci &portstat_reg.word0)) 164062306a36Sopenharmony_ci return -EIO; 164162306a36Sopenharmony_ci 164262306a36Sopenharmony_ci /* verify if privileged for the request operation */ 164362306a36Sopenharmony_ci if (!bf_get(lpfc_sliport_status_rn, &portstat_reg) && 164462306a36Sopenharmony_ci !bf_get(lpfc_sliport_status_err, &portstat_reg)) 164562306a36Sopenharmony_ci return -EPERM; 164662306a36Sopenharmony_ci 164762306a36Sopenharmony_ci /* There is no point to wait if the port is in an unrecoverable 164862306a36Sopenharmony_ci * state. 164962306a36Sopenharmony_ci */ 165062306a36Sopenharmony_ci if (lpfc_sli4_unrecoverable_port(&portstat_reg)) 165162306a36Sopenharmony_ci return -EIO; 165262306a36Sopenharmony_ci 165362306a36Sopenharmony_ci /* wait for the SLI port firmware ready after firmware reset */ 165462306a36Sopenharmony_ci for (i = 0; i < LPFC_FW_RESET_MAXIMUM_WAIT_10MS_CNT; i++) { 165562306a36Sopenharmony_ci msleep(10); 165662306a36Sopenharmony_ci if (lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr, 165762306a36Sopenharmony_ci &portstat_reg.word0)) 165862306a36Sopenharmony_ci continue; 165962306a36Sopenharmony_ci if (!bf_get(lpfc_sliport_status_err, &portstat_reg)) 166062306a36Sopenharmony_ci continue; 166162306a36Sopenharmony_ci if (!bf_get(lpfc_sliport_status_rn, &portstat_reg)) 166262306a36Sopenharmony_ci continue; 166362306a36Sopenharmony_ci if (!bf_get(lpfc_sliport_status_rdy, &portstat_reg)) 166462306a36Sopenharmony_ci continue; 166562306a36Sopenharmony_ci break; 166662306a36Sopenharmony_ci } 166762306a36Sopenharmony_ci 166862306a36Sopenharmony_ci if (i < LPFC_FW_RESET_MAXIMUM_WAIT_10MS_CNT) 166962306a36Sopenharmony_ci return 0; 167062306a36Sopenharmony_ci else 167162306a36Sopenharmony_ci return -EIO; 167262306a36Sopenharmony_ci} 167362306a36Sopenharmony_ci 167462306a36Sopenharmony_ci/** 167562306a36Sopenharmony_ci * lpfc_sli4_pdev_reg_request - Request physical dev to perform a register acc 167662306a36Sopenharmony_ci * @phba: lpfc_hba pointer. 167762306a36Sopenharmony_ci * @opcode: The sli4 config command opcode. 167862306a36Sopenharmony_ci * 167962306a36Sopenharmony_ci * Description: 168062306a36Sopenharmony_ci * Request SLI4 interface type-2 device to perform a physical register set 168162306a36Sopenharmony_ci * access. 168262306a36Sopenharmony_ci * 168362306a36Sopenharmony_ci * Returns: 168462306a36Sopenharmony_ci * zero for success 168562306a36Sopenharmony_ci **/ 168662306a36Sopenharmony_cistatic ssize_t 168762306a36Sopenharmony_cilpfc_sli4_pdev_reg_request(struct lpfc_hba *phba, uint32_t opcode) 168862306a36Sopenharmony_ci{ 168962306a36Sopenharmony_ci struct completion online_compl; 169062306a36Sopenharmony_ci struct pci_dev *pdev = phba->pcidev; 169162306a36Sopenharmony_ci uint32_t before_fc_flag; 169262306a36Sopenharmony_ci uint32_t sriov_nr_virtfn; 169362306a36Sopenharmony_ci uint32_t reg_val; 169462306a36Sopenharmony_ci int status = 0, rc = 0; 169562306a36Sopenharmony_ci int job_posted = 1, sriov_err; 169662306a36Sopenharmony_ci 169762306a36Sopenharmony_ci if (!phba->cfg_enable_hba_reset) 169862306a36Sopenharmony_ci return -EACCES; 169962306a36Sopenharmony_ci 170062306a36Sopenharmony_ci if ((phba->sli_rev < LPFC_SLI_REV4) || 170162306a36Sopenharmony_ci (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) < 170262306a36Sopenharmony_ci LPFC_SLI_INTF_IF_TYPE_2)) 170362306a36Sopenharmony_ci return -EPERM; 170462306a36Sopenharmony_ci 170562306a36Sopenharmony_ci /* Keep state if we need to restore back */ 170662306a36Sopenharmony_ci before_fc_flag = phba->pport->fc_flag; 170762306a36Sopenharmony_ci sriov_nr_virtfn = phba->cfg_sriov_nr_virtfn; 170862306a36Sopenharmony_ci 170962306a36Sopenharmony_ci if (opcode == LPFC_FW_DUMP) { 171062306a36Sopenharmony_ci init_completion(&online_compl); 171162306a36Sopenharmony_ci phba->fw_dump_cmpl = &online_compl; 171262306a36Sopenharmony_ci } else { 171362306a36Sopenharmony_ci /* Disable SR-IOV virtual functions if enabled */ 171462306a36Sopenharmony_ci if (phba->cfg_sriov_nr_virtfn) { 171562306a36Sopenharmony_ci pci_disable_sriov(pdev); 171662306a36Sopenharmony_ci phba->cfg_sriov_nr_virtfn = 0; 171762306a36Sopenharmony_ci } 171862306a36Sopenharmony_ci 171962306a36Sopenharmony_ci status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE); 172062306a36Sopenharmony_ci 172162306a36Sopenharmony_ci if (status != 0) 172262306a36Sopenharmony_ci return status; 172362306a36Sopenharmony_ci 172462306a36Sopenharmony_ci /* wait for the device to be quiesced before firmware reset */ 172562306a36Sopenharmony_ci msleep(100); 172662306a36Sopenharmony_ci } 172762306a36Sopenharmony_ci 172862306a36Sopenharmony_ci reg_val = readl(phba->sli4_hba.conf_regs_memmap_p + 172962306a36Sopenharmony_ci LPFC_CTL_PDEV_CTL_OFFSET); 173062306a36Sopenharmony_ci 173162306a36Sopenharmony_ci if (opcode == LPFC_FW_DUMP) 173262306a36Sopenharmony_ci reg_val |= LPFC_FW_DUMP_REQUEST; 173362306a36Sopenharmony_ci else if (opcode == LPFC_FW_RESET) 173462306a36Sopenharmony_ci reg_val |= LPFC_CTL_PDEV_CTL_FRST; 173562306a36Sopenharmony_ci else if (opcode == LPFC_DV_RESET) 173662306a36Sopenharmony_ci reg_val |= LPFC_CTL_PDEV_CTL_DRST; 173762306a36Sopenharmony_ci 173862306a36Sopenharmony_ci writel(reg_val, phba->sli4_hba.conf_regs_memmap_p + 173962306a36Sopenharmony_ci LPFC_CTL_PDEV_CTL_OFFSET); 174062306a36Sopenharmony_ci /* flush */ 174162306a36Sopenharmony_ci readl(phba->sli4_hba.conf_regs_memmap_p + LPFC_CTL_PDEV_CTL_OFFSET); 174262306a36Sopenharmony_ci 174362306a36Sopenharmony_ci /* delay driver action following IF_TYPE_2 reset */ 174462306a36Sopenharmony_ci rc = lpfc_sli4_pdev_status_reg_wait(phba); 174562306a36Sopenharmony_ci 174662306a36Sopenharmony_ci if (rc == -EPERM) { 174762306a36Sopenharmony_ci /* no privilege for reset */ 174862306a36Sopenharmony_ci lpfc_printf_log(phba, KERN_ERR, LOG_SLI, 174962306a36Sopenharmony_ci "3150 No privilege to perform the requested " 175062306a36Sopenharmony_ci "access: x%x\n", reg_val); 175162306a36Sopenharmony_ci } else if (rc == -EIO) { 175262306a36Sopenharmony_ci /* reset failed, there is nothing more we can do */ 175362306a36Sopenharmony_ci lpfc_printf_log(phba, KERN_ERR, LOG_SLI, 175462306a36Sopenharmony_ci "3153 Fail to perform the requested " 175562306a36Sopenharmony_ci "access: x%x\n", reg_val); 175662306a36Sopenharmony_ci if (phba->fw_dump_cmpl) 175762306a36Sopenharmony_ci phba->fw_dump_cmpl = NULL; 175862306a36Sopenharmony_ci return rc; 175962306a36Sopenharmony_ci } 176062306a36Sopenharmony_ci 176162306a36Sopenharmony_ci /* keep the original port state */ 176262306a36Sopenharmony_ci if (before_fc_flag & FC_OFFLINE_MODE) { 176362306a36Sopenharmony_ci if (phba->fw_dump_cmpl) 176462306a36Sopenharmony_ci phba->fw_dump_cmpl = NULL; 176562306a36Sopenharmony_ci goto out; 176662306a36Sopenharmony_ci } 176762306a36Sopenharmony_ci 176862306a36Sopenharmony_ci /* Firmware dump will trigger an HA_ERATT event, and 176962306a36Sopenharmony_ci * lpfc_handle_eratt_s4 routine already handles bringing the port back 177062306a36Sopenharmony_ci * online. 177162306a36Sopenharmony_ci */ 177262306a36Sopenharmony_ci if (opcode == LPFC_FW_DUMP) { 177362306a36Sopenharmony_ci wait_for_completion(phba->fw_dump_cmpl); 177462306a36Sopenharmony_ci } else { 177562306a36Sopenharmony_ci init_completion(&online_compl); 177662306a36Sopenharmony_ci job_posted = lpfc_workq_post_event(phba, &status, &online_compl, 177762306a36Sopenharmony_ci LPFC_EVT_ONLINE); 177862306a36Sopenharmony_ci if (!job_posted) 177962306a36Sopenharmony_ci goto out; 178062306a36Sopenharmony_ci 178162306a36Sopenharmony_ci wait_for_completion(&online_compl); 178262306a36Sopenharmony_ci } 178362306a36Sopenharmony_ciout: 178462306a36Sopenharmony_ci /* in any case, restore the virtual functions enabled as before */ 178562306a36Sopenharmony_ci if (sriov_nr_virtfn) { 178662306a36Sopenharmony_ci /* If fw_dump was performed, first disable to clean up */ 178762306a36Sopenharmony_ci if (opcode == LPFC_FW_DUMP) { 178862306a36Sopenharmony_ci pci_disable_sriov(pdev); 178962306a36Sopenharmony_ci phba->cfg_sriov_nr_virtfn = 0; 179062306a36Sopenharmony_ci } 179162306a36Sopenharmony_ci 179262306a36Sopenharmony_ci sriov_err = 179362306a36Sopenharmony_ci lpfc_sli_probe_sriov_nr_virtfn(phba, sriov_nr_virtfn); 179462306a36Sopenharmony_ci if (!sriov_err) 179562306a36Sopenharmony_ci phba->cfg_sriov_nr_virtfn = sriov_nr_virtfn; 179662306a36Sopenharmony_ci } 179762306a36Sopenharmony_ci 179862306a36Sopenharmony_ci /* return proper error code */ 179962306a36Sopenharmony_ci if (!rc) { 180062306a36Sopenharmony_ci if (!job_posted) 180162306a36Sopenharmony_ci rc = -ENOMEM; 180262306a36Sopenharmony_ci else if (status) 180362306a36Sopenharmony_ci rc = -EIO; 180462306a36Sopenharmony_ci } 180562306a36Sopenharmony_ci return rc; 180662306a36Sopenharmony_ci} 180762306a36Sopenharmony_ci 180862306a36Sopenharmony_ci/** 180962306a36Sopenharmony_ci * lpfc_nport_evt_cnt_show - Return the number of nport events 181062306a36Sopenharmony_ci * @dev: class device that is converted into a Scsi_host. 181162306a36Sopenharmony_ci * @attr: device attribute, not used. 181262306a36Sopenharmony_ci * @buf: on return contains the ascii number of nport events. 181362306a36Sopenharmony_ci * 181462306a36Sopenharmony_ci * Returns: size of formatted string. 181562306a36Sopenharmony_ci **/ 181662306a36Sopenharmony_cistatic ssize_t 181762306a36Sopenharmony_cilpfc_nport_evt_cnt_show(struct device *dev, struct device_attribute *attr, 181862306a36Sopenharmony_ci char *buf) 181962306a36Sopenharmony_ci{ 182062306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 182162306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 182262306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 182362306a36Sopenharmony_ci 182462306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d\n", phba->nport_event_cnt); 182562306a36Sopenharmony_ci} 182662306a36Sopenharmony_ci 182762306a36Sopenharmony_cistatic int 182862306a36Sopenharmony_cilpfc_set_trunking(struct lpfc_hba *phba, char *buff_out) 182962306a36Sopenharmony_ci{ 183062306a36Sopenharmony_ci LPFC_MBOXQ_t *mbox = NULL; 183162306a36Sopenharmony_ci unsigned long val = 0; 183262306a36Sopenharmony_ci char *pval = NULL; 183362306a36Sopenharmony_ci int rc = 0; 183462306a36Sopenharmony_ci 183562306a36Sopenharmony_ci if (!strncmp("enable", buff_out, 183662306a36Sopenharmony_ci strlen("enable"))) { 183762306a36Sopenharmony_ci pval = buff_out + strlen("enable") + 1; 183862306a36Sopenharmony_ci rc = kstrtoul(pval, 0, &val); 183962306a36Sopenharmony_ci if (rc) 184062306a36Sopenharmony_ci return rc; /* Invalid number */ 184162306a36Sopenharmony_ci } else if (!strncmp("disable", buff_out, 184262306a36Sopenharmony_ci strlen("disable"))) { 184362306a36Sopenharmony_ci val = 0; 184462306a36Sopenharmony_ci } else { 184562306a36Sopenharmony_ci return -EINVAL; /* Invalid command */ 184662306a36Sopenharmony_ci } 184762306a36Sopenharmony_ci 184862306a36Sopenharmony_ci switch (val) { 184962306a36Sopenharmony_ci case 0: 185062306a36Sopenharmony_ci val = 0x0; /* Disable */ 185162306a36Sopenharmony_ci break; 185262306a36Sopenharmony_ci case 2: 185362306a36Sopenharmony_ci val = 0x1; /* Enable two port trunk */ 185462306a36Sopenharmony_ci break; 185562306a36Sopenharmony_ci case 4: 185662306a36Sopenharmony_ci val = 0x2; /* Enable four port trunk */ 185762306a36Sopenharmony_ci break; 185862306a36Sopenharmony_ci default: 185962306a36Sopenharmony_ci return -EINVAL; 186062306a36Sopenharmony_ci } 186162306a36Sopenharmony_ci 186262306a36Sopenharmony_ci lpfc_printf_log(phba, KERN_ERR, LOG_MBOX, 186362306a36Sopenharmony_ci "0070 Set trunk mode with val %ld ", val); 186462306a36Sopenharmony_ci 186562306a36Sopenharmony_ci mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); 186662306a36Sopenharmony_ci if (!mbox) 186762306a36Sopenharmony_ci return -ENOMEM; 186862306a36Sopenharmony_ci 186962306a36Sopenharmony_ci lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_FCOE, 187062306a36Sopenharmony_ci LPFC_MBOX_OPCODE_FCOE_FC_SET_TRUNK_MODE, 187162306a36Sopenharmony_ci 12, LPFC_SLI4_MBX_EMBED); 187262306a36Sopenharmony_ci 187362306a36Sopenharmony_ci bf_set(lpfc_mbx_set_trunk_mode, 187462306a36Sopenharmony_ci &mbox->u.mqe.un.set_trunk_mode, 187562306a36Sopenharmony_ci val); 187662306a36Sopenharmony_ci rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL); 187762306a36Sopenharmony_ci if (rc) 187862306a36Sopenharmony_ci lpfc_printf_log(phba, KERN_ERR, LOG_MBOX, 187962306a36Sopenharmony_ci "0071 Set trunk mode failed with status: %d", 188062306a36Sopenharmony_ci rc); 188162306a36Sopenharmony_ci mempool_free(mbox, phba->mbox_mem_pool); 188262306a36Sopenharmony_ci 188362306a36Sopenharmony_ci return 0; 188462306a36Sopenharmony_ci} 188562306a36Sopenharmony_ci 188662306a36Sopenharmony_cistatic ssize_t 188762306a36Sopenharmony_cilpfc_xcvr_data_show(struct device *dev, struct device_attribute *attr, 188862306a36Sopenharmony_ci char *buf) 188962306a36Sopenharmony_ci{ 189062306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 189162306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata; 189262306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 189362306a36Sopenharmony_ci int rc; 189462306a36Sopenharmony_ci int len = 0; 189562306a36Sopenharmony_ci struct lpfc_rdp_context *rdp_context; 189662306a36Sopenharmony_ci u16 temperature; 189762306a36Sopenharmony_ci u16 rx_power; 189862306a36Sopenharmony_ci u16 tx_bias; 189962306a36Sopenharmony_ci u16 tx_power; 190062306a36Sopenharmony_ci u16 vcc; 190162306a36Sopenharmony_ci char chbuf[128]; 190262306a36Sopenharmony_ci u16 wavelength = 0; 190362306a36Sopenharmony_ci struct sff_trasnceiver_codes_byte7 *trasn_code_byte7; 190462306a36Sopenharmony_ci 190562306a36Sopenharmony_ci /* Get transceiver information */ 190662306a36Sopenharmony_ci rdp_context = kmalloc(sizeof(*rdp_context), GFP_KERNEL); 190762306a36Sopenharmony_ci 190862306a36Sopenharmony_ci rc = lpfc_get_sfp_info_wait(phba, rdp_context); 190962306a36Sopenharmony_ci if (rc) { 191062306a36Sopenharmony_ci len = scnprintf(buf, PAGE_SIZE - len, "SFP info NA:\n"); 191162306a36Sopenharmony_ci goto out_free_rdp; 191262306a36Sopenharmony_ci } 191362306a36Sopenharmony_ci 191462306a36Sopenharmony_ci strscpy(chbuf, &rdp_context->page_a0[SSF_VENDOR_NAME], 16); 191562306a36Sopenharmony_ci 191662306a36Sopenharmony_ci len = scnprintf(buf, PAGE_SIZE - len, "VendorName:\t%s\n", chbuf); 191762306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, 191862306a36Sopenharmony_ci "VendorOUI:\t%02x-%02x-%02x\n", 191962306a36Sopenharmony_ci (uint8_t)rdp_context->page_a0[SSF_VENDOR_OUI], 192062306a36Sopenharmony_ci (uint8_t)rdp_context->page_a0[SSF_VENDOR_OUI + 1], 192162306a36Sopenharmony_ci (uint8_t)rdp_context->page_a0[SSF_VENDOR_OUI + 2]); 192262306a36Sopenharmony_ci strscpy(chbuf, &rdp_context->page_a0[SSF_VENDOR_PN], 16); 192362306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "VendorPN:\t%s\n", chbuf); 192462306a36Sopenharmony_ci strscpy(chbuf, &rdp_context->page_a0[SSF_VENDOR_SN], 16); 192562306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "VendorSN:\t%s\n", chbuf); 192662306a36Sopenharmony_ci strscpy(chbuf, &rdp_context->page_a0[SSF_VENDOR_REV], 4); 192762306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "VendorRev:\t%s\n", chbuf); 192862306a36Sopenharmony_ci strscpy(chbuf, &rdp_context->page_a0[SSF_DATE_CODE], 8); 192962306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "DateCode:\t%s\n", chbuf); 193062306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "Identifier:\t%xh\n", 193162306a36Sopenharmony_ci (uint8_t)rdp_context->page_a0[SSF_IDENTIFIER]); 193262306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "ExtIdentifier:\t%xh\n", 193362306a36Sopenharmony_ci (uint8_t)rdp_context->page_a0[SSF_EXT_IDENTIFIER]); 193462306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "Connector:\t%xh\n", 193562306a36Sopenharmony_ci (uint8_t)rdp_context->page_a0[SSF_CONNECTOR]); 193662306a36Sopenharmony_ci wavelength = (rdp_context->page_a0[SSF_WAVELENGTH_B1] << 8) | 193762306a36Sopenharmony_ci rdp_context->page_a0[SSF_WAVELENGTH_B0]; 193862306a36Sopenharmony_ci 193962306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "Wavelength:\t%d nm\n", 194062306a36Sopenharmony_ci wavelength); 194162306a36Sopenharmony_ci trasn_code_byte7 = (struct sff_trasnceiver_codes_byte7 *) 194262306a36Sopenharmony_ci &rdp_context->page_a0[SSF_TRANSCEIVER_CODE_B7]; 194362306a36Sopenharmony_ci 194462306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "Speeds: \t"); 194562306a36Sopenharmony_ci if (*(uint8_t *)trasn_code_byte7 == 0) { 194662306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "Unknown\n"); 194762306a36Sopenharmony_ci } else { 194862306a36Sopenharmony_ci if (trasn_code_byte7->fc_sp_100MB) 194962306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "1 "); 195062306a36Sopenharmony_ci if (trasn_code_byte7->fc_sp_200mb) 195162306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "2 "); 195262306a36Sopenharmony_ci if (trasn_code_byte7->fc_sp_400MB) 195362306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "4 "); 195462306a36Sopenharmony_ci if (trasn_code_byte7->fc_sp_800MB) 195562306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "8 "); 195662306a36Sopenharmony_ci if (trasn_code_byte7->fc_sp_1600MB) 195762306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "16 "); 195862306a36Sopenharmony_ci if (trasn_code_byte7->fc_sp_3200MB) 195962306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "32 "); 196062306a36Sopenharmony_ci if (trasn_code_byte7->speed_chk_ecc) 196162306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "64 "); 196262306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "GB\n"); 196362306a36Sopenharmony_ci } 196462306a36Sopenharmony_ci temperature = (rdp_context->page_a2[SFF_TEMPERATURE_B1] << 8 | 196562306a36Sopenharmony_ci rdp_context->page_a2[SFF_TEMPERATURE_B0]); 196662306a36Sopenharmony_ci vcc = (rdp_context->page_a2[SFF_VCC_B1] << 8 | 196762306a36Sopenharmony_ci rdp_context->page_a2[SFF_VCC_B0]); 196862306a36Sopenharmony_ci tx_power = (rdp_context->page_a2[SFF_TXPOWER_B1] << 8 | 196962306a36Sopenharmony_ci rdp_context->page_a2[SFF_TXPOWER_B0]); 197062306a36Sopenharmony_ci tx_bias = (rdp_context->page_a2[SFF_TX_BIAS_CURRENT_B1] << 8 | 197162306a36Sopenharmony_ci rdp_context->page_a2[SFF_TX_BIAS_CURRENT_B0]); 197262306a36Sopenharmony_ci rx_power = (rdp_context->page_a2[SFF_RXPOWER_B1] << 8 | 197362306a36Sopenharmony_ci rdp_context->page_a2[SFF_RXPOWER_B0]); 197462306a36Sopenharmony_ci 197562306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, 197662306a36Sopenharmony_ci "Temperature:\tx%04x C\n", temperature); 197762306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "Vcc:\t\tx%04x V\n", vcc); 197862306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, 197962306a36Sopenharmony_ci "TxBiasCurrent:\tx%04x mA\n", tx_bias); 198062306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "TxPower:\tx%04x mW\n", 198162306a36Sopenharmony_ci tx_power); 198262306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "RxPower:\tx%04x mW\n", 198362306a36Sopenharmony_ci rx_power); 198462306a36Sopenharmony_ciout_free_rdp: 198562306a36Sopenharmony_ci kfree(rdp_context); 198662306a36Sopenharmony_ci return len; 198762306a36Sopenharmony_ci} 198862306a36Sopenharmony_ci 198962306a36Sopenharmony_ci/** 199062306a36Sopenharmony_ci * lpfc_board_mode_show - Return the state of the board 199162306a36Sopenharmony_ci * @dev: class device that is converted into a Scsi_host. 199262306a36Sopenharmony_ci * @attr: device attribute, not used. 199362306a36Sopenharmony_ci * @buf: on return contains the state of the adapter. 199462306a36Sopenharmony_ci * 199562306a36Sopenharmony_ci * Returns: size of formatted string. 199662306a36Sopenharmony_ci **/ 199762306a36Sopenharmony_cistatic ssize_t 199862306a36Sopenharmony_cilpfc_board_mode_show(struct device *dev, struct device_attribute *attr, 199962306a36Sopenharmony_ci char *buf) 200062306a36Sopenharmony_ci{ 200162306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 200262306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 200362306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 200462306a36Sopenharmony_ci char * state; 200562306a36Sopenharmony_ci 200662306a36Sopenharmony_ci if (phba->link_state == LPFC_HBA_ERROR) 200762306a36Sopenharmony_ci state = "error"; 200862306a36Sopenharmony_ci else if (phba->link_state == LPFC_WARM_START) 200962306a36Sopenharmony_ci state = "warm start"; 201062306a36Sopenharmony_ci else if (phba->link_state == LPFC_INIT_START) 201162306a36Sopenharmony_ci state = "offline"; 201262306a36Sopenharmony_ci else 201362306a36Sopenharmony_ci state = "online"; 201462306a36Sopenharmony_ci 201562306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%s\n", state); 201662306a36Sopenharmony_ci} 201762306a36Sopenharmony_ci 201862306a36Sopenharmony_ci/** 201962306a36Sopenharmony_ci * lpfc_board_mode_store - Puts the hba in online, offline, warm or error state 202062306a36Sopenharmony_ci * @dev: class device that is converted into a Scsi_host. 202162306a36Sopenharmony_ci * @attr: device attribute, not used. 202262306a36Sopenharmony_ci * @buf: containing one of the strings "online", "offline", "warm" or "error". 202362306a36Sopenharmony_ci * @count: unused variable. 202462306a36Sopenharmony_ci * 202562306a36Sopenharmony_ci * Returns: 202662306a36Sopenharmony_ci * -EACCES if enable hba reset not enabled 202762306a36Sopenharmony_ci * -EINVAL if the buffer does not contain a valid string (see above) 202862306a36Sopenharmony_ci * -EIO if lpfc_workq_post_event() or lpfc_do_offline() fails 202962306a36Sopenharmony_ci * buf length greater than zero indicates success 203062306a36Sopenharmony_ci **/ 203162306a36Sopenharmony_cistatic ssize_t 203262306a36Sopenharmony_cilpfc_board_mode_store(struct device *dev, struct device_attribute *attr, 203362306a36Sopenharmony_ci const char *buf, size_t count) 203462306a36Sopenharmony_ci{ 203562306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 203662306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 203762306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 203862306a36Sopenharmony_ci struct completion online_compl; 203962306a36Sopenharmony_ci char *board_mode_str = NULL; 204062306a36Sopenharmony_ci int status = 0; 204162306a36Sopenharmony_ci int rc; 204262306a36Sopenharmony_ci 204362306a36Sopenharmony_ci if (!phba->cfg_enable_hba_reset) { 204462306a36Sopenharmony_ci status = -EACCES; 204562306a36Sopenharmony_ci goto board_mode_out; 204662306a36Sopenharmony_ci } 204762306a36Sopenharmony_ci 204862306a36Sopenharmony_ci lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, 204962306a36Sopenharmony_ci "3050 lpfc_board_mode set to %s\n", buf); 205062306a36Sopenharmony_ci 205162306a36Sopenharmony_ci init_completion(&online_compl); 205262306a36Sopenharmony_ci 205362306a36Sopenharmony_ci if(strncmp(buf, "online", sizeof("online") - 1) == 0) { 205462306a36Sopenharmony_ci rc = lpfc_workq_post_event(phba, &status, &online_compl, 205562306a36Sopenharmony_ci LPFC_EVT_ONLINE); 205662306a36Sopenharmony_ci if (rc == 0) { 205762306a36Sopenharmony_ci status = -ENOMEM; 205862306a36Sopenharmony_ci goto board_mode_out; 205962306a36Sopenharmony_ci } 206062306a36Sopenharmony_ci wait_for_completion(&online_compl); 206162306a36Sopenharmony_ci if (status) 206262306a36Sopenharmony_ci status = -EIO; 206362306a36Sopenharmony_ci } else if (strncmp(buf, "offline", sizeof("offline") - 1) == 0) 206462306a36Sopenharmony_ci status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE); 206562306a36Sopenharmony_ci else if (strncmp(buf, "warm", sizeof("warm") - 1) == 0) 206662306a36Sopenharmony_ci if (phba->sli_rev == LPFC_SLI_REV4) 206762306a36Sopenharmony_ci status = -EINVAL; 206862306a36Sopenharmony_ci else 206962306a36Sopenharmony_ci status = lpfc_do_offline(phba, LPFC_EVT_WARM_START); 207062306a36Sopenharmony_ci else if (strncmp(buf, "error", sizeof("error") - 1) == 0) 207162306a36Sopenharmony_ci if (phba->sli_rev == LPFC_SLI_REV4) 207262306a36Sopenharmony_ci status = -EINVAL; 207362306a36Sopenharmony_ci else 207462306a36Sopenharmony_ci status = lpfc_do_offline(phba, LPFC_EVT_KILL); 207562306a36Sopenharmony_ci else if (strncmp(buf, "dump", sizeof("dump") - 1) == 0) 207662306a36Sopenharmony_ci status = lpfc_sli4_pdev_reg_request(phba, LPFC_FW_DUMP); 207762306a36Sopenharmony_ci else if (strncmp(buf, "fw_reset", sizeof("fw_reset") - 1) == 0) 207862306a36Sopenharmony_ci status = lpfc_sli4_pdev_reg_request(phba, LPFC_FW_RESET); 207962306a36Sopenharmony_ci else if (strncmp(buf, "dv_reset", sizeof("dv_reset") - 1) == 0) 208062306a36Sopenharmony_ci status = lpfc_sli4_pdev_reg_request(phba, LPFC_DV_RESET); 208162306a36Sopenharmony_ci else if (strncmp(buf, "pci_bus_reset", sizeof("pci_bus_reset") - 1) 208262306a36Sopenharmony_ci == 0) 208362306a36Sopenharmony_ci status = lpfc_reset_pci_bus(phba); 208462306a36Sopenharmony_ci else if (strncmp(buf, "heartbeat", sizeof("heartbeat") - 1) == 0) 208562306a36Sopenharmony_ci lpfc_issue_hb_tmo(phba); 208662306a36Sopenharmony_ci else if (strncmp(buf, "trunk", sizeof("trunk") - 1) == 0) 208762306a36Sopenharmony_ci status = lpfc_set_trunking(phba, (char *)buf + sizeof("trunk")); 208862306a36Sopenharmony_ci else 208962306a36Sopenharmony_ci status = -EINVAL; 209062306a36Sopenharmony_ci 209162306a36Sopenharmony_ciboard_mode_out: 209262306a36Sopenharmony_ci if (!status) 209362306a36Sopenharmony_ci return strlen(buf); 209462306a36Sopenharmony_ci else { 209562306a36Sopenharmony_ci board_mode_str = strchr(buf, '\n'); 209662306a36Sopenharmony_ci if (board_mode_str) 209762306a36Sopenharmony_ci *board_mode_str = '\0'; 209862306a36Sopenharmony_ci lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, 209962306a36Sopenharmony_ci "3097 Failed \"%s\", status(%d), " 210062306a36Sopenharmony_ci "fc_flag(x%x)\n", 210162306a36Sopenharmony_ci buf, status, phba->pport->fc_flag); 210262306a36Sopenharmony_ci return status; 210362306a36Sopenharmony_ci } 210462306a36Sopenharmony_ci} 210562306a36Sopenharmony_ci 210662306a36Sopenharmony_ci/** 210762306a36Sopenharmony_ci * lpfc_get_hba_info - Return various bits of informaton about the adapter 210862306a36Sopenharmony_ci * @phba: pointer to the adapter structure. 210962306a36Sopenharmony_ci * @mxri: max xri count. 211062306a36Sopenharmony_ci * @axri: available xri count. 211162306a36Sopenharmony_ci * @mrpi: max rpi count. 211262306a36Sopenharmony_ci * @arpi: available rpi count. 211362306a36Sopenharmony_ci * @mvpi: max vpi count. 211462306a36Sopenharmony_ci * @avpi: available vpi count. 211562306a36Sopenharmony_ci * 211662306a36Sopenharmony_ci * Description: 211762306a36Sopenharmony_ci * If an integer pointer for an count is not null then the value for the 211862306a36Sopenharmony_ci * count is returned. 211962306a36Sopenharmony_ci * 212062306a36Sopenharmony_ci * Returns: 212162306a36Sopenharmony_ci * zero on error 212262306a36Sopenharmony_ci * one for success 212362306a36Sopenharmony_ci **/ 212462306a36Sopenharmony_cistatic int 212562306a36Sopenharmony_cilpfc_get_hba_info(struct lpfc_hba *phba, 212662306a36Sopenharmony_ci uint32_t *mxri, uint32_t *axri, 212762306a36Sopenharmony_ci uint32_t *mrpi, uint32_t *arpi, 212862306a36Sopenharmony_ci uint32_t *mvpi, uint32_t *avpi) 212962306a36Sopenharmony_ci{ 213062306a36Sopenharmony_ci LPFC_MBOXQ_t *pmboxq; 213162306a36Sopenharmony_ci MAILBOX_t *pmb; 213262306a36Sopenharmony_ci int rc = 0; 213362306a36Sopenharmony_ci struct lpfc_sli4_hba *sli4_hba; 213462306a36Sopenharmony_ci struct lpfc_max_cfg_param *max_cfg_param; 213562306a36Sopenharmony_ci u16 rsrc_ext_cnt, rsrc_ext_size, max_vpi; 213662306a36Sopenharmony_ci 213762306a36Sopenharmony_ci /* 213862306a36Sopenharmony_ci * prevent udev from issuing mailbox commands until the port is 213962306a36Sopenharmony_ci * configured. 214062306a36Sopenharmony_ci */ 214162306a36Sopenharmony_ci if (phba->link_state < LPFC_LINK_DOWN || 214262306a36Sopenharmony_ci !phba->mbox_mem_pool || 214362306a36Sopenharmony_ci (phba->sli.sli_flag & LPFC_SLI_ACTIVE) == 0) 214462306a36Sopenharmony_ci return 0; 214562306a36Sopenharmony_ci 214662306a36Sopenharmony_ci if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO) 214762306a36Sopenharmony_ci return 0; 214862306a36Sopenharmony_ci 214962306a36Sopenharmony_ci pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); 215062306a36Sopenharmony_ci if (!pmboxq) 215162306a36Sopenharmony_ci return 0; 215262306a36Sopenharmony_ci memset(pmboxq, 0, sizeof (LPFC_MBOXQ_t)); 215362306a36Sopenharmony_ci 215462306a36Sopenharmony_ci pmb = &pmboxq->u.mb; 215562306a36Sopenharmony_ci pmb->mbxCommand = MBX_READ_CONFIG; 215662306a36Sopenharmony_ci pmb->mbxOwner = OWN_HOST; 215762306a36Sopenharmony_ci pmboxq->ctx_buf = NULL; 215862306a36Sopenharmony_ci 215962306a36Sopenharmony_ci if (phba->pport->fc_flag & FC_OFFLINE_MODE) 216062306a36Sopenharmony_ci rc = MBX_NOT_FINISHED; 216162306a36Sopenharmony_ci else 216262306a36Sopenharmony_ci rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2); 216362306a36Sopenharmony_ci 216462306a36Sopenharmony_ci if (rc != MBX_SUCCESS) { 216562306a36Sopenharmony_ci if (rc != MBX_TIMEOUT) 216662306a36Sopenharmony_ci mempool_free(pmboxq, phba->mbox_mem_pool); 216762306a36Sopenharmony_ci return 0; 216862306a36Sopenharmony_ci } 216962306a36Sopenharmony_ci 217062306a36Sopenharmony_ci if (phba->sli_rev == LPFC_SLI_REV4) { 217162306a36Sopenharmony_ci sli4_hba = &phba->sli4_hba; 217262306a36Sopenharmony_ci max_cfg_param = &sli4_hba->max_cfg_param; 217362306a36Sopenharmony_ci 217462306a36Sopenharmony_ci /* Normally, extents are not used */ 217562306a36Sopenharmony_ci if (!phba->sli4_hba.extents_in_use) { 217662306a36Sopenharmony_ci if (mrpi) 217762306a36Sopenharmony_ci *mrpi = max_cfg_param->max_rpi; 217862306a36Sopenharmony_ci if (mxri) 217962306a36Sopenharmony_ci *mxri = max_cfg_param->max_xri; 218062306a36Sopenharmony_ci if (mvpi) { 218162306a36Sopenharmony_ci max_vpi = max_cfg_param->max_vpi; 218262306a36Sopenharmony_ci 218362306a36Sopenharmony_ci /* Limit the max we support */ 218462306a36Sopenharmony_ci if (max_vpi > LPFC_MAX_VPI) 218562306a36Sopenharmony_ci max_vpi = LPFC_MAX_VPI; 218662306a36Sopenharmony_ci *mvpi = max_vpi; 218762306a36Sopenharmony_ci } 218862306a36Sopenharmony_ci } else { /* Extents in use */ 218962306a36Sopenharmony_ci if (mrpi) { 219062306a36Sopenharmony_ci if (lpfc_sli4_get_avail_extnt_rsrc(phba, 219162306a36Sopenharmony_ci LPFC_RSC_TYPE_FCOE_RPI, 219262306a36Sopenharmony_ci &rsrc_ext_cnt, 219362306a36Sopenharmony_ci &rsrc_ext_size)) { 219462306a36Sopenharmony_ci rc = 0; 219562306a36Sopenharmony_ci goto free_pmboxq; 219662306a36Sopenharmony_ci } 219762306a36Sopenharmony_ci 219862306a36Sopenharmony_ci *mrpi = rsrc_ext_cnt * rsrc_ext_size; 219962306a36Sopenharmony_ci } 220062306a36Sopenharmony_ci 220162306a36Sopenharmony_ci if (mxri) { 220262306a36Sopenharmony_ci if (lpfc_sli4_get_avail_extnt_rsrc(phba, 220362306a36Sopenharmony_ci LPFC_RSC_TYPE_FCOE_XRI, 220462306a36Sopenharmony_ci &rsrc_ext_cnt, 220562306a36Sopenharmony_ci &rsrc_ext_size)) { 220662306a36Sopenharmony_ci rc = 0; 220762306a36Sopenharmony_ci goto free_pmboxq; 220862306a36Sopenharmony_ci } 220962306a36Sopenharmony_ci 221062306a36Sopenharmony_ci *mxri = rsrc_ext_cnt * rsrc_ext_size; 221162306a36Sopenharmony_ci } 221262306a36Sopenharmony_ci 221362306a36Sopenharmony_ci if (mvpi) { 221462306a36Sopenharmony_ci if (lpfc_sli4_get_avail_extnt_rsrc(phba, 221562306a36Sopenharmony_ci LPFC_RSC_TYPE_FCOE_VPI, 221662306a36Sopenharmony_ci &rsrc_ext_cnt, 221762306a36Sopenharmony_ci &rsrc_ext_size)) { 221862306a36Sopenharmony_ci rc = 0; 221962306a36Sopenharmony_ci goto free_pmboxq; 222062306a36Sopenharmony_ci } 222162306a36Sopenharmony_ci 222262306a36Sopenharmony_ci max_vpi = rsrc_ext_cnt * rsrc_ext_size; 222362306a36Sopenharmony_ci 222462306a36Sopenharmony_ci /* Limit the max we support */ 222562306a36Sopenharmony_ci if (max_vpi > LPFC_MAX_VPI) 222662306a36Sopenharmony_ci max_vpi = LPFC_MAX_VPI; 222762306a36Sopenharmony_ci *mvpi = max_vpi; 222862306a36Sopenharmony_ci } 222962306a36Sopenharmony_ci } 223062306a36Sopenharmony_ci } else { 223162306a36Sopenharmony_ci if (mrpi) 223262306a36Sopenharmony_ci *mrpi = pmb->un.varRdConfig.max_rpi; 223362306a36Sopenharmony_ci if (arpi) 223462306a36Sopenharmony_ci *arpi = pmb->un.varRdConfig.avail_rpi; 223562306a36Sopenharmony_ci if (mxri) 223662306a36Sopenharmony_ci *mxri = pmb->un.varRdConfig.max_xri; 223762306a36Sopenharmony_ci if (axri) 223862306a36Sopenharmony_ci *axri = pmb->un.varRdConfig.avail_xri; 223962306a36Sopenharmony_ci if (mvpi) 224062306a36Sopenharmony_ci *mvpi = pmb->un.varRdConfig.max_vpi; 224162306a36Sopenharmony_ci if (avpi) { 224262306a36Sopenharmony_ci /* avail_vpi is only valid if link is up and ready */ 224362306a36Sopenharmony_ci if (phba->link_state == LPFC_HBA_READY) 224462306a36Sopenharmony_ci *avpi = pmb->un.varRdConfig.avail_vpi; 224562306a36Sopenharmony_ci else 224662306a36Sopenharmony_ci *avpi = pmb->un.varRdConfig.max_vpi; 224762306a36Sopenharmony_ci } 224862306a36Sopenharmony_ci } 224962306a36Sopenharmony_ci 225062306a36Sopenharmony_ci /* Success */ 225162306a36Sopenharmony_ci rc = 1; 225262306a36Sopenharmony_ci 225362306a36Sopenharmony_cifree_pmboxq: 225462306a36Sopenharmony_ci mempool_free(pmboxq, phba->mbox_mem_pool); 225562306a36Sopenharmony_ci return rc; 225662306a36Sopenharmony_ci} 225762306a36Sopenharmony_ci 225862306a36Sopenharmony_ci/** 225962306a36Sopenharmony_ci * lpfc_max_rpi_show - Return maximum rpi 226062306a36Sopenharmony_ci * @dev: class device that is converted into a Scsi_host. 226162306a36Sopenharmony_ci * @attr: device attribute, not used. 226262306a36Sopenharmony_ci * @buf: on return contains the maximum rpi count in decimal or "Unknown". 226362306a36Sopenharmony_ci * 226462306a36Sopenharmony_ci * Description: 226562306a36Sopenharmony_ci * Calls lpfc_get_hba_info() asking for just the mrpi count. 226662306a36Sopenharmony_ci * If lpfc_get_hba_info() returns zero (failure) the buffer text is set 226762306a36Sopenharmony_ci * to "Unknown" and the buffer length is returned, therefore the caller 226862306a36Sopenharmony_ci * must check for "Unknown" in the buffer to detect a failure. 226962306a36Sopenharmony_ci * 227062306a36Sopenharmony_ci * Returns: size of formatted string. 227162306a36Sopenharmony_ci **/ 227262306a36Sopenharmony_cistatic ssize_t 227362306a36Sopenharmony_cilpfc_max_rpi_show(struct device *dev, struct device_attribute *attr, 227462306a36Sopenharmony_ci char *buf) 227562306a36Sopenharmony_ci{ 227662306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 227762306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 227862306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 227962306a36Sopenharmony_ci uint32_t cnt; 228062306a36Sopenharmony_ci 228162306a36Sopenharmony_ci if (lpfc_get_hba_info(phba, NULL, NULL, &cnt, NULL, NULL, NULL)) 228262306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d\n", cnt); 228362306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "Unknown\n"); 228462306a36Sopenharmony_ci} 228562306a36Sopenharmony_ci 228662306a36Sopenharmony_ci/** 228762306a36Sopenharmony_ci * lpfc_used_rpi_show - Return maximum rpi minus available rpi 228862306a36Sopenharmony_ci * @dev: class device that is converted into a Scsi_host. 228962306a36Sopenharmony_ci * @attr: device attribute, not used. 229062306a36Sopenharmony_ci * @buf: containing the used rpi count in decimal or "Unknown". 229162306a36Sopenharmony_ci * 229262306a36Sopenharmony_ci * Description: 229362306a36Sopenharmony_ci * Calls lpfc_get_hba_info() asking for just the mrpi and arpi counts. 229462306a36Sopenharmony_ci * If lpfc_get_hba_info() returns zero (failure) the buffer text is set 229562306a36Sopenharmony_ci * to "Unknown" and the buffer length is returned, therefore the caller 229662306a36Sopenharmony_ci * must check for "Unknown" in the buffer to detect a failure. 229762306a36Sopenharmony_ci * 229862306a36Sopenharmony_ci * Returns: size of formatted string. 229962306a36Sopenharmony_ci **/ 230062306a36Sopenharmony_cistatic ssize_t 230162306a36Sopenharmony_cilpfc_used_rpi_show(struct device *dev, struct device_attribute *attr, 230262306a36Sopenharmony_ci char *buf) 230362306a36Sopenharmony_ci{ 230462306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 230562306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 230662306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 230762306a36Sopenharmony_ci struct lpfc_sli4_hba *sli4_hba; 230862306a36Sopenharmony_ci struct lpfc_max_cfg_param *max_cfg_param; 230962306a36Sopenharmony_ci u32 cnt = 0, acnt = 0; 231062306a36Sopenharmony_ci 231162306a36Sopenharmony_ci if (phba->sli_rev == LPFC_SLI_REV4) { 231262306a36Sopenharmony_ci sli4_hba = &phba->sli4_hba; 231362306a36Sopenharmony_ci max_cfg_param = &sli4_hba->max_cfg_param; 231462306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d\n", 231562306a36Sopenharmony_ci max_cfg_param->rpi_used); 231662306a36Sopenharmony_ci } else { 231762306a36Sopenharmony_ci if (lpfc_get_hba_info(phba, NULL, NULL, &cnt, &acnt, NULL, NULL)) 231862306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d\n", (cnt - acnt)); 231962306a36Sopenharmony_ci } 232062306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "Unknown\n"); 232162306a36Sopenharmony_ci} 232262306a36Sopenharmony_ci 232362306a36Sopenharmony_ci/** 232462306a36Sopenharmony_ci * lpfc_max_xri_show - Return maximum xri 232562306a36Sopenharmony_ci * @dev: class device that is converted into a Scsi_host. 232662306a36Sopenharmony_ci * @attr: device attribute, not used. 232762306a36Sopenharmony_ci * @buf: on return contains the maximum xri count in decimal or "Unknown". 232862306a36Sopenharmony_ci * 232962306a36Sopenharmony_ci * Description: 233062306a36Sopenharmony_ci * Calls lpfc_get_hba_info() asking for just the mrpi count. 233162306a36Sopenharmony_ci * If lpfc_get_hba_info() returns zero (failure) the buffer text is set 233262306a36Sopenharmony_ci * to "Unknown" and the buffer length is returned, therefore the caller 233362306a36Sopenharmony_ci * must check for "Unknown" in the buffer to detect a failure. 233462306a36Sopenharmony_ci * 233562306a36Sopenharmony_ci * Returns: size of formatted string. 233662306a36Sopenharmony_ci **/ 233762306a36Sopenharmony_cistatic ssize_t 233862306a36Sopenharmony_cilpfc_max_xri_show(struct device *dev, struct device_attribute *attr, 233962306a36Sopenharmony_ci char *buf) 234062306a36Sopenharmony_ci{ 234162306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 234262306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 234362306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 234462306a36Sopenharmony_ci uint32_t cnt; 234562306a36Sopenharmony_ci 234662306a36Sopenharmony_ci if (lpfc_get_hba_info(phba, &cnt, NULL, NULL, NULL, NULL, NULL)) 234762306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d\n", cnt); 234862306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "Unknown\n"); 234962306a36Sopenharmony_ci} 235062306a36Sopenharmony_ci 235162306a36Sopenharmony_ci/** 235262306a36Sopenharmony_ci * lpfc_used_xri_show - Return maximum xpi minus the available xpi 235362306a36Sopenharmony_ci * @dev: class device that is converted into a Scsi_host. 235462306a36Sopenharmony_ci * @attr: device attribute, not used. 235562306a36Sopenharmony_ci * @buf: on return contains the used xri count in decimal or "Unknown". 235662306a36Sopenharmony_ci * 235762306a36Sopenharmony_ci * Description: 235862306a36Sopenharmony_ci * Calls lpfc_get_hba_info() asking for just the mxri and axri counts. 235962306a36Sopenharmony_ci * If lpfc_get_hba_info() returns zero (failure) the buffer text is set 236062306a36Sopenharmony_ci * to "Unknown" and the buffer length is returned, therefore the caller 236162306a36Sopenharmony_ci * must check for "Unknown" in the buffer to detect a failure. 236262306a36Sopenharmony_ci * 236362306a36Sopenharmony_ci * Returns: size of formatted string. 236462306a36Sopenharmony_ci **/ 236562306a36Sopenharmony_cistatic ssize_t 236662306a36Sopenharmony_cilpfc_used_xri_show(struct device *dev, struct device_attribute *attr, 236762306a36Sopenharmony_ci char *buf) 236862306a36Sopenharmony_ci{ 236962306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 237062306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 237162306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 237262306a36Sopenharmony_ci struct lpfc_sli4_hba *sli4_hba; 237362306a36Sopenharmony_ci struct lpfc_max_cfg_param *max_cfg_param; 237462306a36Sopenharmony_ci u32 cnt = 0, acnt = 0; 237562306a36Sopenharmony_ci 237662306a36Sopenharmony_ci if (phba->sli_rev == LPFC_SLI_REV4) { 237762306a36Sopenharmony_ci sli4_hba = &phba->sli4_hba; 237862306a36Sopenharmony_ci max_cfg_param = &sli4_hba->max_cfg_param; 237962306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d\n", 238062306a36Sopenharmony_ci max_cfg_param->xri_used); 238162306a36Sopenharmony_ci } else { 238262306a36Sopenharmony_ci if (lpfc_get_hba_info(phba, &cnt, &acnt, NULL, NULL, NULL, NULL)) 238362306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d\n", (cnt - acnt)); 238462306a36Sopenharmony_ci } 238562306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "Unknown\n"); 238662306a36Sopenharmony_ci} 238762306a36Sopenharmony_ci 238862306a36Sopenharmony_ci/** 238962306a36Sopenharmony_ci * lpfc_max_vpi_show - Return maximum vpi 239062306a36Sopenharmony_ci * @dev: class device that is converted into a Scsi_host. 239162306a36Sopenharmony_ci * @attr: device attribute, not used. 239262306a36Sopenharmony_ci * @buf: on return contains the maximum vpi count in decimal or "Unknown". 239362306a36Sopenharmony_ci * 239462306a36Sopenharmony_ci * Description: 239562306a36Sopenharmony_ci * Calls lpfc_get_hba_info() asking for just the mvpi count. 239662306a36Sopenharmony_ci * If lpfc_get_hba_info() returns zero (failure) the buffer text is set 239762306a36Sopenharmony_ci * to "Unknown" and the buffer length is returned, therefore the caller 239862306a36Sopenharmony_ci * must check for "Unknown" in the buffer to detect a failure. 239962306a36Sopenharmony_ci * 240062306a36Sopenharmony_ci * Returns: size of formatted string. 240162306a36Sopenharmony_ci **/ 240262306a36Sopenharmony_cistatic ssize_t 240362306a36Sopenharmony_cilpfc_max_vpi_show(struct device *dev, struct device_attribute *attr, 240462306a36Sopenharmony_ci char *buf) 240562306a36Sopenharmony_ci{ 240662306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 240762306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 240862306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 240962306a36Sopenharmony_ci uint32_t cnt; 241062306a36Sopenharmony_ci 241162306a36Sopenharmony_ci if (lpfc_get_hba_info(phba, NULL, NULL, NULL, NULL, &cnt, NULL)) 241262306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d\n", cnt); 241362306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "Unknown\n"); 241462306a36Sopenharmony_ci} 241562306a36Sopenharmony_ci 241662306a36Sopenharmony_ci/** 241762306a36Sopenharmony_ci * lpfc_used_vpi_show - Return maximum vpi minus the available vpi 241862306a36Sopenharmony_ci * @dev: class device that is converted into a Scsi_host. 241962306a36Sopenharmony_ci * @attr: device attribute, not used. 242062306a36Sopenharmony_ci * @buf: on return contains the used vpi count in decimal or "Unknown". 242162306a36Sopenharmony_ci * 242262306a36Sopenharmony_ci * Description: 242362306a36Sopenharmony_ci * Calls lpfc_get_hba_info() asking for just the mvpi and avpi counts. 242462306a36Sopenharmony_ci * If lpfc_get_hba_info() returns zero (failure) the buffer text is set 242562306a36Sopenharmony_ci * to "Unknown" and the buffer length is returned, therefore the caller 242662306a36Sopenharmony_ci * must check for "Unknown" in the buffer to detect a failure. 242762306a36Sopenharmony_ci * 242862306a36Sopenharmony_ci * Returns: size of formatted string. 242962306a36Sopenharmony_ci **/ 243062306a36Sopenharmony_cistatic ssize_t 243162306a36Sopenharmony_cilpfc_used_vpi_show(struct device *dev, struct device_attribute *attr, 243262306a36Sopenharmony_ci char *buf) 243362306a36Sopenharmony_ci{ 243462306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 243562306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 243662306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 243762306a36Sopenharmony_ci struct lpfc_sli4_hba *sli4_hba; 243862306a36Sopenharmony_ci struct lpfc_max_cfg_param *max_cfg_param; 243962306a36Sopenharmony_ci u32 cnt = 0, acnt = 0; 244062306a36Sopenharmony_ci 244162306a36Sopenharmony_ci if (phba->sli_rev == LPFC_SLI_REV4) { 244262306a36Sopenharmony_ci sli4_hba = &phba->sli4_hba; 244362306a36Sopenharmony_ci max_cfg_param = &sli4_hba->max_cfg_param; 244462306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d\n", 244562306a36Sopenharmony_ci max_cfg_param->vpi_used); 244662306a36Sopenharmony_ci } else { 244762306a36Sopenharmony_ci if (lpfc_get_hba_info(phba, NULL, NULL, NULL, NULL, &cnt, &acnt)) 244862306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d\n", (cnt - acnt)); 244962306a36Sopenharmony_ci } 245062306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "Unknown\n"); 245162306a36Sopenharmony_ci} 245262306a36Sopenharmony_ci 245362306a36Sopenharmony_ci/** 245462306a36Sopenharmony_ci * lpfc_npiv_info_show - Return text about NPIV support for the adapter 245562306a36Sopenharmony_ci * @dev: class device that is converted into a Scsi_host. 245662306a36Sopenharmony_ci * @attr: device attribute, not used. 245762306a36Sopenharmony_ci * @buf: text that must be interpreted to determine if npiv is supported. 245862306a36Sopenharmony_ci * 245962306a36Sopenharmony_ci * Description: 246062306a36Sopenharmony_ci * Buffer will contain text indicating npiv is not suppoerted on the port, 246162306a36Sopenharmony_ci * the port is an NPIV physical port, or it is an npiv virtual port with 246262306a36Sopenharmony_ci * the id of the vport. 246362306a36Sopenharmony_ci * 246462306a36Sopenharmony_ci * Returns: size of formatted string. 246562306a36Sopenharmony_ci **/ 246662306a36Sopenharmony_cistatic ssize_t 246762306a36Sopenharmony_cilpfc_npiv_info_show(struct device *dev, struct device_attribute *attr, 246862306a36Sopenharmony_ci char *buf) 246962306a36Sopenharmony_ci{ 247062306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 247162306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 247262306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 247362306a36Sopenharmony_ci 247462306a36Sopenharmony_ci if (!(phba->max_vpi)) 247562306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "NPIV Not Supported\n"); 247662306a36Sopenharmony_ci if (vport->port_type == LPFC_PHYSICAL_PORT) 247762306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "NPIV Physical\n"); 247862306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "NPIV Virtual (VPI %d)\n", vport->vpi); 247962306a36Sopenharmony_ci} 248062306a36Sopenharmony_ci 248162306a36Sopenharmony_ci/** 248262306a36Sopenharmony_ci * lpfc_poll_show - Return text about poll support for the adapter 248362306a36Sopenharmony_ci * @dev: class device that is converted into a Scsi_host. 248462306a36Sopenharmony_ci * @attr: device attribute, not used. 248562306a36Sopenharmony_ci * @buf: on return contains the cfg_poll in hex. 248662306a36Sopenharmony_ci * 248762306a36Sopenharmony_ci * Notes: 248862306a36Sopenharmony_ci * cfg_poll should be a lpfc_polling_flags type. 248962306a36Sopenharmony_ci * 249062306a36Sopenharmony_ci * Returns: size of formatted string. 249162306a36Sopenharmony_ci **/ 249262306a36Sopenharmony_cistatic ssize_t 249362306a36Sopenharmony_cilpfc_poll_show(struct device *dev, struct device_attribute *attr, 249462306a36Sopenharmony_ci char *buf) 249562306a36Sopenharmony_ci{ 249662306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 249762306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 249862306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 249962306a36Sopenharmony_ci 250062306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%#x\n", phba->cfg_poll); 250162306a36Sopenharmony_ci} 250262306a36Sopenharmony_ci 250362306a36Sopenharmony_ci/** 250462306a36Sopenharmony_ci * lpfc_poll_store - Set the value of cfg_poll for the adapter 250562306a36Sopenharmony_ci * @dev: class device that is converted into a Scsi_host. 250662306a36Sopenharmony_ci * @attr: device attribute, not used. 250762306a36Sopenharmony_ci * @buf: one or more lpfc_polling_flags values. 250862306a36Sopenharmony_ci * @count: not used. 250962306a36Sopenharmony_ci * 251062306a36Sopenharmony_ci * Notes: 251162306a36Sopenharmony_ci * buf contents converted to integer and checked for a valid value. 251262306a36Sopenharmony_ci * 251362306a36Sopenharmony_ci * Returns: 251462306a36Sopenharmony_ci * -EINVAL if the buffer connot be converted or is out of range 251562306a36Sopenharmony_ci * length of the buf on success 251662306a36Sopenharmony_ci **/ 251762306a36Sopenharmony_cistatic ssize_t 251862306a36Sopenharmony_cilpfc_poll_store(struct device *dev, struct device_attribute *attr, 251962306a36Sopenharmony_ci const char *buf, size_t count) 252062306a36Sopenharmony_ci{ 252162306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 252262306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 252362306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 252462306a36Sopenharmony_ci uint32_t creg_val; 252562306a36Sopenharmony_ci uint32_t old_val; 252662306a36Sopenharmony_ci int val=0; 252762306a36Sopenharmony_ci 252862306a36Sopenharmony_ci if (!isdigit(buf[0])) 252962306a36Sopenharmony_ci return -EINVAL; 253062306a36Sopenharmony_ci 253162306a36Sopenharmony_ci if (sscanf(buf, "%i", &val) != 1) 253262306a36Sopenharmony_ci return -EINVAL; 253362306a36Sopenharmony_ci 253462306a36Sopenharmony_ci if ((val & 0x3) != val) 253562306a36Sopenharmony_ci return -EINVAL; 253662306a36Sopenharmony_ci 253762306a36Sopenharmony_ci if (phba->sli_rev == LPFC_SLI_REV4) 253862306a36Sopenharmony_ci val = 0; 253962306a36Sopenharmony_ci 254062306a36Sopenharmony_ci lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, 254162306a36Sopenharmony_ci "3051 lpfc_poll changed from %d to %d\n", 254262306a36Sopenharmony_ci phba->cfg_poll, val); 254362306a36Sopenharmony_ci 254462306a36Sopenharmony_ci spin_lock_irq(&phba->hbalock); 254562306a36Sopenharmony_ci 254662306a36Sopenharmony_ci old_val = phba->cfg_poll; 254762306a36Sopenharmony_ci 254862306a36Sopenharmony_ci if (val & ENABLE_FCP_RING_POLLING) { 254962306a36Sopenharmony_ci if ((val & DISABLE_FCP_RING_INT) && 255062306a36Sopenharmony_ci !(old_val & DISABLE_FCP_RING_INT)) { 255162306a36Sopenharmony_ci if (lpfc_readl(phba->HCregaddr, &creg_val)) { 255262306a36Sopenharmony_ci spin_unlock_irq(&phba->hbalock); 255362306a36Sopenharmony_ci return -EINVAL; 255462306a36Sopenharmony_ci } 255562306a36Sopenharmony_ci creg_val &= ~(HC_R0INT_ENA << LPFC_FCP_RING); 255662306a36Sopenharmony_ci writel(creg_val, phba->HCregaddr); 255762306a36Sopenharmony_ci readl(phba->HCregaddr); /* flush */ 255862306a36Sopenharmony_ci 255962306a36Sopenharmony_ci lpfc_poll_start_timer(phba); 256062306a36Sopenharmony_ci } 256162306a36Sopenharmony_ci } else if (val != 0x0) { 256262306a36Sopenharmony_ci spin_unlock_irq(&phba->hbalock); 256362306a36Sopenharmony_ci return -EINVAL; 256462306a36Sopenharmony_ci } 256562306a36Sopenharmony_ci 256662306a36Sopenharmony_ci if (!(val & DISABLE_FCP_RING_INT) && 256762306a36Sopenharmony_ci (old_val & DISABLE_FCP_RING_INT)) 256862306a36Sopenharmony_ci { 256962306a36Sopenharmony_ci spin_unlock_irq(&phba->hbalock); 257062306a36Sopenharmony_ci del_timer(&phba->fcp_poll_timer); 257162306a36Sopenharmony_ci spin_lock_irq(&phba->hbalock); 257262306a36Sopenharmony_ci if (lpfc_readl(phba->HCregaddr, &creg_val)) { 257362306a36Sopenharmony_ci spin_unlock_irq(&phba->hbalock); 257462306a36Sopenharmony_ci return -EINVAL; 257562306a36Sopenharmony_ci } 257662306a36Sopenharmony_ci creg_val |= (HC_R0INT_ENA << LPFC_FCP_RING); 257762306a36Sopenharmony_ci writel(creg_val, phba->HCregaddr); 257862306a36Sopenharmony_ci readl(phba->HCregaddr); /* flush */ 257962306a36Sopenharmony_ci } 258062306a36Sopenharmony_ci 258162306a36Sopenharmony_ci phba->cfg_poll = val; 258262306a36Sopenharmony_ci 258362306a36Sopenharmony_ci spin_unlock_irq(&phba->hbalock); 258462306a36Sopenharmony_ci 258562306a36Sopenharmony_ci return strlen(buf); 258662306a36Sopenharmony_ci} 258762306a36Sopenharmony_ci 258862306a36Sopenharmony_ci/** 258962306a36Sopenharmony_ci * lpfc_sriov_hw_max_virtfn_show - Return maximum number of virtual functions 259062306a36Sopenharmony_ci * @dev: class converted to a Scsi_host structure. 259162306a36Sopenharmony_ci * @attr: device attribute, not used. 259262306a36Sopenharmony_ci * @buf: on return contains the formatted support level. 259362306a36Sopenharmony_ci * 259462306a36Sopenharmony_ci * Description: 259562306a36Sopenharmony_ci * Returns the maximum number of virtual functions a physical function can 259662306a36Sopenharmony_ci * support, 0 will be returned if called on virtual function. 259762306a36Sopenharmony_ci * 259862306a36Sopenharmony_ci * Returns: size of formatted string. 259962306a36Sopenharmony_ci **/ 260062306a36Sopenharmony_cistatic ssize_t 260162306a36Sopenharmony_cilpfc_sriov_hw_max_virtfn_show(struct device *dev, 260262306a36Sopenharmony_ci struct device_attribute *attr, 260362306a36Sopenharmony_ci char *buf) 260462306a36Sopenharmony_ci{ 260562306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 260662306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 260762306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 260862306a36Sopenharmony_ci uint16_t max_nr_virtfn; 260962306a36Sopenharmony_ci 261062306a36Sopenharmony_ci max_nr_virtfn = lpfc_sli_sriov_nr_virtfn_get(phba); 261162306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d\n", max_nr_virtfn); 261262306a36Sopenharmony_ci} 261362306a36Sopenharmony_ci 261462306a36Sopenharmony_ci/** 261562306a36Sopenharmony_ci * lpfc_enable_bbcr_set: Sets an attribute value. 261662306a36Sopenharmony_ci * @phba: pointer to the adapter structure. 261762306a36Sopenharmony_ci * @val: integer attribute value. 261862306a36Sopenharmony_ci * 261962306a36Sopenharmony_ci * Description: 262062306a36Sopenharmony_ci * Validates the min and max values then sets the 262162306a36Sopenharmony_ci * adapter config field if in the valid range. prints error message 262262306a36Sopenharmony_ci * and does not set the parameter if invalid. 262362306a36Sopenharmony_ci * 262462306a36Sopenharmony_ci * Returns: 262562306a36Sopenharmony_ci * zero on success 262662306a36Sopenharmony_ci * -EINVAL if val is invalid 262762306a36Sopenharmony_ci */ 262862306a36Sopenharmony_cistatic ssize_t 262962306a36Sopenharmony_cilpfc_enable_bbcr_set(struct lpfc_hba *phba, uint val) 263062306a36Sopenharmony_ci{ 263162306a36Sopenharmony_ci if (lpfc_rangecheck(val, 0, 1) && phba->sli_rev == LPFC_SLI_REV4) { 263262306a36Sopenharmony_ci lpfc_printf_log(phba, KERN_ERR, LOG_INIT, 263362306a36Sopenharmony_ci "3068 lpfc_enable_bbcr changed from %d to " 263462306a36Sopenharmony_ci "%d\n", phba->cfg_enable_bbcr, val); 263562306a36Sopenharmony_ci phba->cfg_enable_bbcr = val; 263662306a36Sopenharmony_ci return 0; 263762306a36Sopenharmony_ci } 263862306a36Sopenharmony_ci lpfc_printf_log(phba, KERN_ERR, LOG_INIT, 263962306a36Sopenharmony_ci "0451 lpfc_enable_bbcr cannot set to %d, range is 0, " 264062306a36Sopenharmony_ci "1\n", val); 264162306a36Sopenharmony_ci return -EINVAL; 264262306a36Sopenharmony_ci} 264362306a36Sopenharmony_ci 264462306a36Sopenharmony_ci/* 264562306a36Sopenharmony_ci * lpfc_param_show - Return a cfg attribute value in decimal 264662306a36Sopenharmony_ci * 264762306a36Sopenharmony_ci * Description: 264862306a36Sopenharmony_ci * Macro that given an attr e.g. hba_queue_depth expands 264962306a36Sopenharmony_ci * into a function with the name lpfc_hba_queue_depth_show. 265062306a36Sopenharmony_ci * 265162306a36Sopenharmony_ci * lpfc_##attr##_show: Return the decimal value of an adapters cfg_xxx field. 265262306a36Sopenharmony_ci * @dev: class device that is converted into a Scsi_host. 265362306a36Sopenharmony_ci * @attr: device attribute, not used. 265462306a36Sopenharmony_ci * @buf: on return contains the attribute value in decimal. 265562306a36Sopenharmony_ci * 265662306a36Sopenharmony_ci * Returns: size of formatted string. 265762306a36Sopenharmony_ci **/ 265862306a36Sopenharmony_ci#define lpfc_param_show(attr) \ 265962306a36Sopenharmony_cistatic ssize_t \ 266062306a36Sopenharmony_cilpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \ 266162306a36Sopenharmony_ci char *buf) \ 266262306a36Sopenharmony_ci{ \ 266362306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev);\ 266462306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\ 266562306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba;\ 266662306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d\n",\ 266762306a36Sopenharmony_ci phba->cfg_##attr);\ 266862306a36Sopenharmony_ci} 266962306a36Sopenharmony_ci 267062306a36Sopenharmony_ci/* 267162306a36Sopenharmony_ci * lpfc_param_hex_show - Return a cfg attribute value in hex 267262306a36Sopenharmony_ci * 267362306a36Sopenharmony_ci * Description: 267462306a36Sopenharmony_ci * Macro that given an attr e.g. hba_queue_depth expands 267562306a36Sopenharmony_ci * into a function with the name lpfc_hba_queue_depth_show 267662306a36Sopenharmony_ci * 267762306a36Sopenharmony_ci * lpfc_##attr##_show: Return the hex value of an adapters cfg_xxx field. 267862306a36Sopenharmony_ci * @dev: class device that is converted into a Scsi_host. 267962306a36Sopenharmony_ci * @attr: device attribute, not used. 268062306a36Sopenharmony_ci * @buf: on return contains the attribute value in hexadecimal. 268162306a36Sopenharmony_ci * 268262306a36Sopenharmony_ci * Returns: size of formatted string. 268362306a36Sopenharmony_ci **/ 268462306a36Sopenharmony_ci#define lpfc_param_hex_show(attr) \ 268562306a36Sopenharmony_cistatic ssize_t \ 268662306a36Sopenharmony_cilpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \ 268762306a36Sopenharmony_ci char *buf) \ 268862306a36Sopenharmony_ci{ \ 268962306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev);\ 269062306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\ 269162306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba;\ 269262306a36Sopenharmony_ci uint val = 0;\ 269362306a36Sopenharmony_ci val = phba->cfg_##attr;\ 269462306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%#x\n",\ 269562306a36Sopenharmony_ci phba->cfg_##attr);\ 269662306a36Sopenharmony_ci} 269762306a36Sopenharmony_ci 269862306a36Sopenharmony_ci/* 269962306a36Sopenharmony_ci * lpfc_param_init - Initializes a cfg attribute 270062306a36Sopenharmony_ci * 270162306a36Sopenharmony_ci * Description: 270262306a36Sopenharmony_ci * Macro that given an attr e.g. hba_queue_depth expands 270362306a36Sopenharmony_ci * into a function with the name lpfc_hba_queue_depth_init. The macro also 270462306a36Sopenharmony_ci * takes a default argument, a minimum and maximum argument. 270562306a36Sopenharmony_ci * 270662306a36Sopenharmony_ci * lpfc_##attr##_init: Initializes an attribute. 270762306a36Sopenharmony_ci * @phba: pointer to the adapter structure. 270862306a36Sopenharmony_ci * @val: integer attribute value. 270962306a36Sopenharmony_ci * 271062306a36Sopenharmony_ci * Validates the min and max values then sets the adapter config field 271162306a36Sopenharmony_ci * accordingly, or uses the default if out of range and prints an error message. 271262306a36Sopenharmony_ci * 271362306a36Sopenharmony_ci * Returns: 271462306a36Sopenharmony_ci * zero on success 271562306a36Sopenharmony_ci * -EINVAL if default used 271662306a36Sopenharmony_ci **/ 271762306a36Sopenharmony_ci#define lpfc_param_init(attr, default, minval, maxval) \ 271862306a36Sopenharmony_cistatic int \ 271962306a36Sopenharmony_cilpfc_##attr##_init(struct lpfc_hba *phba, uint val) \ 272062306a36Sopenharmony_ci{ \ 272162306a36Sopenharmony_ci if (lpfc_rangecheck(val, minval, maxval)) {\ 272262306a36Sopenharmony_ci phba->cfg_##attr = val;\ 272362306a36Sopenharmony_ci return 0;\ 272462306a36Sopenharmony_ci }\ 272562306a36Sopenharmony_ci lpfc_printf_log(phba, KERN_ERR, LOG_INIT, \ 272662306a36Sopenharmony_ci "0449 lpfc_"#attr" attribute cannot be set to %d, "\ 272762306a36Sopenharmony_ci "allowed range is ["#minval", "#maxval"]\n", val); \ 272862306a36Sopenharmony_ci phba->cfg_##attr = default;\ 272962306a36Sopenharmony_ci return -EINVAL;\ 273062306a36Sopenharmony_ci} 273162306a36Sopenharmony_ci 273262306a36Sopenharmony_ci/* 273362306a36Sopenharmony_ci * lpfc_param_set - Set a cfg attribute value 273462306a36Sopenharmony_ci * 273562306a36Sopenharmony_ci * Description: 273662306a36Sopenharmony_ci * Macro that given an attr e.g. hba_queue_depth expands 273762306a36Sopenharmony_ci * into a function with the name lpfc_hba_queue_depth_set 273862306a36Sopenharmony_ci * 273962306a36Sopenharmony_ci * lpfc_##attr##_set: Sets an attribute value. 274062306a36Sopenharmony_ci * @phba: pointer to the adapter structure. 274162306a36Sopenharmony_ci * @val: integer attribute value. 274262306a36Sopenharmony_ci * 274362306a36Sopenharmony_ci * Description: 274462306a36Sopenharmony_ci * Validates the min and max values then sets the 274562306a36Sopenharmony_ci * adapter config field if in the valid range. prints error message 274662306a36Sopenharmony_ci * and does not set the parameter if invalid. 274762306a36Sopenharmony_ci * 274862306a36Sopenharmony_ci * Returns: 274962306a36Sopenharmony_ci * zero on success 275062306a36Sopenharmony_ci * -EINVAL if val is invalid 275162306a36Sopenharmony_ci **/ 275262306a36Sopenharmony_ci#define lpfc_param_set(attr, default, minval, maxval) \ 275362306a36Sopenharmony_cistatic int \ 275462306a36Sopenharmony_cilpfc_##attr##_set(struct lpfc_hba *phba, uint val) \ 275562306a36Sopenharmony_ci{ \ 275662306a36Sopenharmony_ci if (lpfc_rangecheck(val, minval, maxval)) {\ 275762306a36Sopenharmony_ci lpfc_printf_log(phba, KERN_ERR, LOG_INIT, \ 275862306a36Sopenharmony_ci "3052 lpfc_" #attr " changed from %d to %d\n", \ 275962306a36Sopenharmony_ci phba->cfg_##attr, val); \ 276062306a36Sopenharmony_ci phba->cfg_##attr = val;\ 276162306a36Sopenharmony_ci return 0;\ 276262306a36Sopenharmony_ci }\ 276362306a36Sopenharmony_ci lpfc_printf_log(phba, KERN_ERR, LOG_INIT, \ 276462306a36Sopenharmony_ci "0450 lpfc_"#attr" attribute cannot be set to %d, "\ 276562306a36Sopenharmony_ci "allowed range is ["#minval", "#maxval"]\n", val); \ 276662306a36Sopenharmony_ci return -EINVAL;\ 276762306a36Sopenharmony_ci} 276862306a36Sopenharmony_ci 276962306a36Sopenharmony_ci/* 277062306a36Sopenharmony_ci * lpfc_param_store - Set a vport attribute value 277162306a36Sopenharmony_ci * 277262306a36Sopenharmony_ci * Description: 277362306a36Sopenharmony_ci * Macro that given an attr e.g. hba_queue_depth expands 277462306a36Sopenharmony_ci * into a function with the name lpfc_hba_queue_depth_store. 277562306a36Sopenharmony_ci * 277662306a36Sopenharmony_ci * lpfc_##attr##_store: Set an sttribute value. 277762306a36Sopenharmony_ci * @dev: class device that is converted into a Scsi_host. 277862306a36Sopenharmony_ci * @attr: device attribute, not used. 277962306a36Sopenharmony_ci * @buf: contains the attribute value in ascii. 278062306a36Sopenharmony_ci * @count: not used. 278162306a36Sopenharmony_ci * 278262306a36Sopenharmony_ci * Description: 278362306a36Sopenharmony_ci * Convert the ascii text number to an integer, then 278462306a36Sopenharmony_ci * use the lpfc_##attr##_set function to set the value. 278562306a36Sopenharmony_ci * 278662306a36Sopenharmony_ci * Returns: 278762306a36Sopenharmony_ci * -EINVAL if val is invalid or lpfc_##attr##_set() fails 278862306a36Sopenharmony_ci * length of buffer upon success. 278962306a36Sopenharmony_ci **/ 279062306a36Sopenharmony_ci#define lpfc_param_store(attr) \ 279162306a36Sopenharmony_cistatic ssize_t \ 279262306a36Sopenharmony_cilpfc_##attr##_store(struct device *dev, struct device_attribute *attr, \ 279362306a36Sopenharmony_ci const char *buf, size_t count) \ 279462306a36Sopenharmony_ci{ \ 279562306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev);\ 279662306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\ 279762306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba;\ 279862306a36Sopenharmony_ci uint val = 0;\ 279962306a36Sopenharmony_ci if (!isdigit(buf[0]))\ 280062306a36Sopenharmony_ci return -EINVAL;\ 280162306a36Sopenharmony_ci if (sscanf(buf, "%i", &val) != 1)\ 280262306a36Sopenharmony_ci return -EINVAL;\ 280362306a36Sopenharmony_ci if (lpfc_##attr##_set(phba, val) == 0) \ 280462306a36Sopenharmony_ci return strlen(buf);\ 280562306a36Sopenharmony_ci else \ 280662306a36Sopenharmony_ci return -EINVAL;\ 280762306a36Sopenharmony_ci} 280862306a36Sopenharmony_ci 280962306a36Sopenharmony_ci/* 281062306a36Sopenharmony_ci * lpfc_vport_param_show - Return decimal formatted cfg attribute value 281162306a36Sopenharmony_ci * 281262306a36Sopenharmony_ci * Description: 281362306a36Sopenharmony_ci * Macro that given an attr e.g. hba_queue_depth expands 281462306a36Sopenharmony_ci * into a function with the name lpfc_hba_queue_depth_show 281562306a36Sopenharmony_ci * 281662306a36Sopenharmony_ci * lpfc_##attr##_show: prints the attribute value in decimal. 281762306a36Sopenharmony_ci * @dev: class device that is converted into a Scsi_host. 281862306a36Sopenharmony_ci * @attr: device attribute, not used. 281962306a36Sopenharmony_ci * @buf: on return contains the attribute value in decimal. 282062306a36Sopenharmony_ci * 282162306a36Sopenharmony_ci * Returns: length of formatted string. 282262306a36Sopenharmony_ci **/ 282362306a36Sopenharmony_ci#define lpfc_vport_param_show(attr) \ 282462306a36Sopenharmony_cistatic ssize_t \ 282562306a36Sopenharmony_cilpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \ 282662306a36Sopenharmony_ci char *buf) \ 282762306a36Sopenharmony_ci{ \ 282862306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev);\ 282962306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\ 283062306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d\n", vport->cfg_##attr);\ 283162306a36Sopenharmony_ci} 283262306a36Sopenharmony_ci 283362306a36Sopenharmony_ci/* 283462306a36Sopenharmony_ci * lpfc_vport_param_hex_show - Return hex formatted attribute value 283562306a36Sopenharmony_ci * 283662306a36Sopenharmony_ci * Description: 283762306a36Sopenharmony_ci * Macro that given an attr e.g. 283862306a36Sopenharmony_ci * hba_queue_depth expands into a function with the name 283962306a36Sopenharmony_ci * lpfc_hba_queue_depth_show 284062306a36Sopenharmony_ci * 284162306a36Sopenharmony_ci * lpfc_##attr##_show: prints the attribute value in hexadecimal. 284262306a36Sopenharmony_ci * @dev: class device that is converted into a Scsi_host. 284362306a36Sopenharmony_ci * @attr: device attribute, not used. 284462306a36Sopenharmony_ci * @buf: on return contains the attribute value in hexadecimal. 284562306a36Sopenharmony_ci * 284662306a36Sopenharmony_ci * Returns: length of formatted string. 284762306a36Sopenharmony_ci **/ 284862306a36Sopenharmony_ci#define lpfc_vport_param_hex_show(attr) \ 284962306a36Sopenharmony_cistatic ssize_t \ 285062306a36Sopenharmony_cilpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \ 285162306a36Sopenharmony_ci char *buf) \ 285262306a36Sopenharmony_ci{ \ 285362306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev);\ 285462306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\ 285562306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%#x\n", vport->cfg_##attr);\ 285662306a36Sopenharmony_ci} 285762306a36Sopenharmony_ci 285862306a36Sopenharmony_ci/* 285962306a36Sopenharmony_ci * lpfc_vport_param_init - Initialize a vport cfg attribute 286062306a36Sopenharmony_ci * 286162306a36Sopenharmony_ci * Description: 286262306a36Sopenharmony_ci * Macro that given an attr e.g. hba_queue_depth expands 286362306a36Sopenharmony_ci * into a function with the name lpfc_hba_queue_depth_init. The macro also 286462306a36Sopenharmony_ci * takes a default argument, a minimum and maximum argument. 286562306a36Sopenharmony_ci * 286662306a36Sopenharmony_ci * lpfc_##attr##_init: validates the min and max values then sets the 286762306a36Sopenharmony_ci * adapter config field accordingly, or uses the default if out of range 286862306a36Sopenharmony_ci * and prints an error message. 286962306a36Sopenharmony_ci * @phba: pointer to the adapter structure. 287062306a36Sopenharmony_ci * @val: integer attribute value. 287162306a36Sopenharmony_ci * 287262306a36Sopenharmony_ci * Returns: 287362306a36Sopenharmony_ci * zero on success 287462306a36Sopenharmony_ci * -EINVAL if default used 287562306a36Sopenharmony_ci **/ 287662306a36Sopenharmony_ci#define lpfc_vport_param_init(attr, default, minval, maxval) \ 287762306a36Sopenharmony_cistatic int \ 287862306a36Sopenharmony_cilpfc_##attr##_init(struct lpfc_vport *vport, uint val) \ 287962306a36Sopenharmony_ci{ \ 288062306a36Sopenharmony_ci if (lpfc_rangecheck(val, minval, maxval)) {\ 288162306a36Sopenharmony_ci vport->cfg_##attr = val;\ 288262306a36Sopenharmony_ci return 0;\ 288362306a36Sopenharmony_ci }\ 288462306a36Sopenharmony_ci lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, \ 288562306a36Sopenharmony_ci "0423 lpfc_"#attr" attribute cannot be set to %d, "\ 288662306a36Sopenharmony_ci "allowed range is ["#minval", "#maxval"]\n", val); \ 288762306a36Sopenharmony_ci vport->cfg_##attr = default;\ 288862306a36Sopenharmony_ci return -EINVAL;\ 288962306a36Sopenharmony_ci} 289062306a36Sopenharmony_ci 289162306a36Sopenharmony_ci/* 289262306a36Sopenharmony_ci * lpfc_vport_param_set - Set a vport cfg attribute 289362306a36Sopenharmony_ci * 289462306a36Sopenharmony_ci * Description: 289562306a36Sopenharmony_ci * Macro that given an attr e.g. hba_queue_depth expands 289662306a36Sopenharmony_ci * into a function with the name lpfc_hba_queue_depth_set 289762306a36Sopenharmony_ci * 289862306a36Sopenharmony_ci * lpfc_##attr##_set: validates the min and max values then sets the 289962306a36Sopenharmony_ci * adapter config field if in the valid range. prints error message 290062306a36Sopenharmony_ci * and does not set the parameter if invalid. 290162306a36Sopenharmony_ci * @phba: pointer to the adapter structure. 290262306a36Sopenharmony_ci * @val: integer attribute value. 290362306a36Sopenharmony_ci * 290462306a36Sopenharmony_ci * Returns: 290562306a36Sopenharmony_ci * zero on success 290662306a36Sopenharmony_ci * -EINVAL if val is invalid 290762306a36Sopenharmony_ci **/ 290862306a36Sopenharmony_ci#define lpfc_vport_param_set(attr, default, minval, maxval) \ 290962306a36Sopenharmony_cistatic int \ 291062306a36Sopenharmony_cilpfc_##attr##_set(struct lpfc_vport *vport, uint val) \ 291162306a36Sopenharmony_ci{ \ 291262306a36Sopenharmony_ci if (lpfc_rangecheck(val, minval, maxval)) {\ 291362306a36Sopenharmony_ci lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, \ 291462306a36Sopenharmony_ci "3053 lpfc_" #attr \ 291562306a36Sopenharmony_ci " changed from %d (x%x) to %d (x%x)\n", \ 291662306a36Sopenharmony_ci vport->cfg_##attr, vport->cfg_##attr, \ 291762306a36Sopenharmony_ci val, val); \ 291862306a36Sopenharmony_ci vport->cfg_##attr = val;\ 291962306a36Sopenharmony_ci return 0;\ 292062306a36Sopenharmony_ci }\ 292162306a36Sopenharmony_ci lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, \ 292262306a36Sopenharmony_ci "0424 lpfc_"#attr" attribute cannot be set to %d, "\ 292362306a36Sopenharmony_ci "allowed range is ["#minval", "#maxval"]\n", val); \ 292462306a36Sopenharmony_ci return -EINVAL;\ 292562306a36Sopenharmony_ci} 292662306a36Sopenharmony_ci 292762306a36Sopenharmony_ci/* 292862306a36Sopenharmony_ci * lpfc_vport_param_store - Set a vport attribute 292962306a36Sopenharmony_ci * 293062306a36Sopenharmony_ci * Description: 293162306a36Sopenharmony_ci * Macro that given an attr e.g. hba_queue_depth 293262306a36Sopenharmony_ci * expands into a function with the name lpfc_hba_queue_depth_store 293362306a36Sopenharmony_ci * 293462306a36Sopenharmony_ci * lpfc_##attr##_store: convert the ascii text number to an integer, then 293562306a36Sopenharmony_ci * use the lpfc_##attr##_set function to set the value. 293662306a36Sopenharmony_ci * @cdev: class device that is converted into a Scsi_host. 293762306a36Sopenharmony_ci * @buf: contains the attribute value in decimal. 293862306a36Sopenharmony_ci * @count: not used. 293962306a36Sopenharmony_ci * 294062306a36Sopenharmony_ci * Returns: 294162306a36Sopenharmony_ci * -EINVAL if val is invalid or lpfc_##attr##_set() fails 294262306a36Sopenharmony_ci * length of buffer upon success. 294362306a36Sopenharmony_ci **/ 294462306a36Sopenharmony_ci#define lpfc_vport_param_store(attr) \ 294562306a36Sopenharmony_cistatic ssize_t \ 294662306a36Sopenharmony_cilpfc_##attr##_store(struct device *dev, struct device_attribute *attr, \ 294762306a36Sopenharmony_ci const char *buf, size_t count) \ 294862306a36Sopenharmony_ci{ \ 294962306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev);\ 295062306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\ 295162306a36Sopenharmony_ci uint val = 0;\ 295262306a36Sopenharmony_ci if (!isdigit(buf[0]))\ 295362306a36Sopenharmony_ci return -EINVAL;\ 295462306a36Sopenharmony_ci if (sscanf(buf, "%i", &val) != 1)\ 295562306a36Sopenharmony_ci return -EINVAL;\ 295662306a36Sopenharmony_ci if (lpfc_##attr##_set(vport, val) == 0) \ 295762306a36Sopenharmony_ci return strlen(buf);\ 295862306a36Sopenharmony_ci else \ 295962306a36Sopenharmony_ci return -EINVAL;\ 296062306a36Sopenharmony_ci} 296162306a36Sopenharmony_ci 296262306a36Sopenharmony_ci 296362306a36Sopenharmony_cistatic DEVICE_ATTR(nvme_info, 0444, lpfc_nvme_info_show, NULL); 296462306a36Sopenharmony_cistatic DEVICE_ATTR(scsi_stat, 0444, lpfc_scsi_stat_show, NULL); 296562306a36Sopenharmony_cistatic DEVICE_ATTR(bg_info, S_IRUGO, lpfc_bg_info_show, NULL); 296662306a36Sopenharmony_cistatic DEVICE_ATTR(bg_guard_err, S_IRUGO, lpfc_bg_guard_err_show, NULL); 296762306a36Sopenharmony_cistatic DEVICE_ATTR(bg_apptag_err, S_IRUGO, lpfc_bg_apptag_err_show, NULL); 296862306a36Sopenharmony_cistatic DEVICE_ATTR(bg_reftag_err, S_IRUGO, lpfc_bg_reftag_err_show, NULL); 296962306a36Sopenharmony_cistatic DEVICE_ATTR(info, S_IRUGO, lpfc_info_show, NULL); 297062306a36Sopenharmony_cistatic DEVICE_ATTR(serialnum, S_IRUGO, lpfc_serialnum_show, NULL); 297162306a36Sopenharmony_cistatic DEVICE_ATTR(modeldesc, S_IRUGO, lpfc_modeldesc_show, NULL); 297262306a36Sopenharmony_cistatic DEVICE_ATTR(modelname, S_IRUGO, lpfc_modelname_show, NULL); 297362306a36Sopenharmony_cistatic DEVICE_ATTR(programtype, S_IRUGO, lpfc_programtype_show, NULL); 297462306a36Sopenharmony_cistatic DEVICE_ATTR(portnum, S_IRUGO, lpfc_vportnum_show, NULL); 297562306a36Sopenharmony_cistatic DEVICE_ATTR(fwrev, S_IRUGO, lpfc_fwrev_show, NULL); 297662306a36Sopenharmony_cistatic DEVICE_ATTR(hdw, S_IRUGO, lpfc_hdw_show, NULL); 297762306a36Sopenharmony_cistatic DEVICE_ATTR(link_state, S_IRUGO | S_IWUSR, lpfc_link_state_show, 297862306a36Sopenharmony_ci lpfc_link_state_store); 297962306a36Sopenharmony_cistatic DEVICE_ATTR(option_rom_version, S_IRUGO, 298062306a36Sopenharmony_ci lpfc_option_rom_version_show, NULL); 298162306a36Sopenharmony_cistatic DEVICE_ATTR(num_discovered_ports, S_IRUGO, 298262306a36Sopenharmony_ci lpfc_num_discovered_ports_show, NULL); 298362306a36Sopenharmony_cistatic DEVICE_ATTR(nport_evt_cnt, S_IRUGO, lpfc_nport_evt_cnt_show, NULL); 298462306a36Sopenharmony_cistatic DEVICE_ATTR_RO(lpfc_drvr_version); 298562306a36Sopenharmony_cistatic DEVICE_ATTR_RO(lpfc_enable_fip); 298662306a36Sopenharmony_cistatic DEVICE_ATTR(board_mode, S_IRUGO | S_IWUSR, 298762306a36Sopenharmony_ci lpfc_board_mode_show, lpfc_board_mode_store); 298862306a36Sopenharmony_cistatic DEVICE_ATTR_RO(lpfc_xcvr_data); 298962306a36Sopenharmony_cistatic DEVICE_ATTR(issue_reset, S_IWUSR, NULL, lpfc_issue_reset); 299062306a36Sopenharmony_cistatic DEVICE_ATTR(max_vpi, S_IRUGO, lpfc_max_vpi_show, NULL); 299162306a36Sopenharmony_cistatic DEVICE_ATTR(used_vpi, S_IRUGO, lpfc_used_vpi_show, NULL); 299262306a36Sopenharmony_cistatic DEVICE_ATTR(max_rpi, S_IRUGO, lpfc_max_rpi_show, NULL); 299362306a36Sopenharmony_cistatic DEVICE_ATTR(used_rpi, S_IRUGO, lpfc_used_rpi_show, NULL); 299462306a36Sopenharmony_cistatic DEVICE_ATTR(max_xri, S_IRUGO, lpfc_max_xri_show, NULL); 299562306a36Sopenharmony_cistatic DEVICE_ATTR(used_xri, S_IRUGO, lpfc_used_xri_show, NULL); 299662306a36Sopenharmony_cistatic DEVICE_ATTR(npiv_info, S_IRUGO, lpfc_npiv_info_show, NULL); 299762306a36Sopenharmony_cistatic DEVICE_ATTR_RO(lpfc_temp_sensor); 299862306a36Sopenharmony_cistatic DEVICE_ATTR_RO(lpfc_sriov_hw_max_virtfn); 299962306a36Sopenharmony_cistatic DEVICE_ATTR(protocol, S_IRUGO, lpfc_sli4_protocol_show, NULL); 300062306a36Sopenharmony_cistatic DEVICE_ATTR(lpfc_xlane_supported, S_IRUGO, lpfc_oas_supported_show, 300162306a36Sopenharmony_ci NULL); 300262306a36Sopenharmony_cistatic DEVICE_ATTR(cmf_info, 0444, lpfc_cmf_info_show, NULL); 300362306a36Sopenharmony_ci 300462306a36Sopenharmony_ci#define WWN_SZ 8 300562306a36Sopenharmony_ci/** 300662306a36Sopenharmony_ci * lpfc_wwn_set - Convert string to the 8 byte WWN value. 300762306a36Sopenharmony_ci * @buf: WWN string. 300862306a36Sopenharmony_ci * @cnt: Length of string. 300962306a36Sopenharmony_ci * @wwn: Array to receive converted wwn value. 301062306a36Sopenharmony_ci * 301162306a36Sopenharmony_ci * Returns: 301262306a36Sopenharmony_ci * -EINVAL if the buffer does not contain a valid wwn 301362306a36Sopenharmony_ci * 0 success 301462306a36Sopenharmony_ci **/ 301562306a36Sopenharmony_cistatic size_t 301662306a36Sopenharmony_cilpfc_wwn_set(const char *buf, size_t cnt, char wwn[]) 301762306a36Sopenharmony_ci{ 301862306a36Sopenharmony_ci unsigned int i, j; 301962306a36Sopenharmony_ci 302062306a36Sopenharmony_ci /* Count may include a LF at end of string */ 302162306a36Sopenharmony_ci if (buf[cnt-1] == '\n') 302262306a36Sopenharmony_ci cnt--; 302362306a36Sopenharmony_ci 302462306a36Sopenharmony_ci if ((cnt < 16) || (cnt > 18) || ((cnt == 17) && (*buf++ != 'x')) || 302562306a36Sopenharmony_ci ((cnt == 18) && ((*buf++ != '0') || (*buf++ != 'x')))) 302662306a36Sopenharmony_ci return -EINVAL; 302762306a36Sopenharmony_ci 302862306a36Sopenharmony_ci memset(wwn, 0, WWN_SZ); 302962306a36Sopenharmony_ci 303062306a36Sopenharmony_ci /* Validate and store the new name */ 303162306a36Sopenharmony_ci for (i = 0, j = 0; i < 16; i++) { 303262306a36Sopenharmony_ci if ((*buf >= 'a') && (*buf <= 'f')) 303362306a36Sopenharmony_ci j = ((j << 4) | ((*buf++ - 'a') + 10)); 303462306a36Sopenharmony_ci else if ((*buf >= 'A') && (*buf <= 'F')) 303562306a36Sopenharmony_ci j = ((j << 4) | ((*buf++ - 'A') + 10)); 303662306a36Sopenharmony_ci else if ((*buf >= '0') && (*buf <= '9')) 303762306a36Sopenharmony_ci j = ((j << 4) | (*buf++ - '0')); 303862306a36Sopenharmony_ci else 303962306a36Sopenharmony_ci return -EINVAL; 304062306a36Sopenharmony_ci if (i % 2) { 304162306a36Sopenharmony_ci wwn[i/2] = j & 0xff; 304262306a36Sopenharmony_ci j = 0; 304362306a36Sopenharmony_ci } 304462306a36Sopenharmony_ci } 304562306a36Sopenharmony_ci return 0; 304662306a36Sopenharmony_ci} 304762306a36Sopenharmony_ci 304862306a36Sopenharmony_ci 304962306a36Sopenharmony_ci/** 305062306a36Sopenharmony_ci * lpfc_oas_tgt_show - Return wwpn of target whose luns maybe enabled for 305162306a36Sopenharmony_ci * Optimized Access Storage (OAS) operations. 305262306a36Sopenharmony_ci * @dev: class device that is converted into a Scsi_host. 305362306a36Sopenharmony_ci * @attr: device attribute, not used. 305462306a36Sopenharmony_ci * @buf: buffer for passing information. 305562306a36Sopenharmony_ci * 305662306a36Sopenharmony_ci * Returns: 305762306a36Sopenharmony_ci * value of count 305862306a36Sopenharmony_ci **/ 305962306a36Sopenharmony_cistatic ssize_t 306062306a36Sopenharmony_cilpfc_oas_tgt_show(struct device *dev, struct device_attribute *attr, 306162306a36Sopenharmony_ci char *buf) 306262306a36Sopenharmony_ci{ 306362306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 306462306a36Sopenharmony_ci struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; 306562306a36Sopenharmony_ci 306662306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "0x%llx\n", 306762306a36Sopenharmony_ci wwn_to_u64(phba->cfg_oas_tgt_wwpn)); 306862306a36Sopenharmony_ci} 306962306a36Sopenharmony_ci 307062306a36Sopenharmony_ci/** 307162306a36Sopenharmony_ci * lpfc_oas_tgt_store - Store wwpn of target whose luns maybe enabled for 307262306a36Sopenharmony_ci * Optimized Access Storage (OAS) operations. 307362306a36Sopenharmony_ci * @dev: class device that is converted into a Scsi_host. 307462306a36Sopenharmony_ci * @attr: device attribute, not used. 307562306a36Sopenharmony_ci * @buf: buffer for passing information. 307662306a36Sopenharmony_ci * @count: Size of the data buffer. 307762306a36Sopenharmony_ci * 307862306a36Sopenharmony_ci * Returns: 307962306a36Sopenharmony_ci * -EINVAL count is invalid, invalid wwpn byte invalid 308062306a36Sopenharmony_ci * -EPERM oas is not supported by hba 308162306a36Sopenharmony_ci * value of count on success 308262306a36Sopenharmony_ci **/ 308362306a36Sopenharmony_cistatic ssize_t 308462306a36Sopenharmony_cilpfc_oas_tgt_store(struct device *dev, struct device_attribute *attr, 308562306a36Sopenharmony_ci const char *buf, size_t count) 308662306a36Sopenharmony_ci{ 308762306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 308862306a36Sopenharmony_ci struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; 308962306a36Sopenharmony_ci unsigned int cnt = count; 309062306a36Sopenharmony_ci uint8_t wwpn[WWN_SZ]; 309162306a36Sopenharmony_ci int rc; 309262306a36Sopenharmony_ci 309362306a36Sopenharmony_ci if (!phba->cfg_fof) 309462306a36Sopenharmony_ci return -EPERM; 309562306a36Sopenharmony_ci 309662306a36Sopenharmony_ci /* count may include a LF at end of string */ 309762306a36Sopenharmony_ci if (buf[cnt-1] == '\n') 309862306a36Sopenharmony_ci cnt--; 309962306a36Sopenharmony_ci 310062306a36Sopenharmony_ci rc = lpfc_wwn_set(buf, cnt, wwpn); 310162306a36Sopenharmony_ci if (rc) 310262306a36Sopenharmony_ci return rc; 310362306a36Sopenharmony_ci 310462306a36Sopenharmony_ci memcpy(phba->cfg_oas_tgt_wwpn, wwpn, (8 * sizeof(uint8_t))); 310562306a36Sopenharmony_ci memcpy(phba->sli4_hba.oas_next_tgt_wwpn, wwpn, (8 * sizeof(uint8_t))); 310662306a36Sopenharmony_ci if (wwn_to_u64(wwpn) == 0) 310762306a36Sopenharmony_ci phba->cfg_oas_flags |= OAS_FIND_ANY_TARGET; 310862306a36Sopenharmony_ci else 310962306a36Sopenharmony_ci phba->cfg_oas_flags &= ~OAS_FIND_ANY_TARGET; 311062306a36Sopenharmony_ci phba->cfg_oas_flags &= ~OAS_LUN_VALID; 311162306a36Sopenharmony_ci phba->sli4_hba.oas_next_lun = FIND_FIRST_OAS_LUN; 311262306a36Sopenharmony_ci return count; 311362306a36Sopenharmony_ci} 311462306a36Sopenharmony_cistatic DEVICE_ATTR(lpfc_xlane_tgt, S_IRUGO | S_IWUSR, 311562306a36Sopenharmony_ci lpfc_oas_tgt_show, lpfc_oas_tgt_store); 311662306a36Sopenharmony_ci 311762306a36Sopenharmony_ci/** 311862306a36Sopenharmony_ci * lpfc_oas_priority_show - Return wwpn of target whose luns maybe enabled for 311962306a36Sopenharmony_ci * Optimized Access Storage (OAS) operations. 312062306a36Sopenharmony_ci * @dev: class device that is converted into a Scsi_host. 312162306a36Sopenharmony_ci * @attr: device attribute, not used. 312262306a36Sopenharmony_ci * @buf: buffer for passing information. 312362306a36Sopenharmony_ci * 312462306a36Sopenharmony_ci * Returns: 312562306a36Sopenharmony_ci * value of count 312662306a36Sopenharmony_ci **/ 312762306a36Sopenharmony_cistatic ssize_t 312862306a36Sopenharmony_cilpfc_oas_priority_show(struct device *dev, struct device_attribute *attr, 312962306a36Sopenharmony_ci char *buf) 313062306a36Sopenharmony_ci{ 313162306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 313262306a36Sopenharmony_ci struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; 313362306a36Sopenharmony_ci 313462306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d\n", phba->cfg_oas_priority); 313562306a36Sopenharmony_ci} 313662306a36Sopenharmony_ci 313762306a36Sopenharmony_ci/** 313862306a36Sopenharmony_ci * lpfc_oas_priority_store - Store wwpn of target whose luns maybe enabled for 313962306a36Sopenharmony_ci * Optimized Access Storage (OAS) operations. 314062306a36Sopenharmony_ci * @dev: class device that is converted into a Scsi_host. 314162306a36Sopenharmony_ci * @attr: device attribute, not used. 314262306a36Sopenharmony_ci * @buf: buffer for passing information. 314362306a36Sopenharmony_ci * @count: Size of the data buffer. 314462306a36Sopenharmony_ci * 314562306a36Sopenharmony_ci * Returns: 314662306a36Sopenharmony_ci * -EINVAL count is invalid, invalid wwpn byte invalid 314762306a36Sopenharmony_ci * -EPERM oas is not supported by hba 314862306a36Sopenharmony_ci * value of count on success 314962306a36Sopenharmony_ci **/ 315062306a36Sopenharmony_cistatic ssize_t 315162306a36Sopenharmony_cilpfc_oas_priority_store(struct device *dev, struct device_attribute *attr, 315262306a36Sopenharmony_ci const char *buf, size_t count) 315362306a36Sopenharmony_ci{ 315462306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 315562306a36Sopenharmony_ci struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; 315662306a36Sopenharmony_ci unsigned int cnt = count; 315762306a36Sopenharmony_ci unsigned long val; 315862306a36Sopenharmony_ci int ret; 315962306a36Sopenharmony_ci 316062306a36Sopenharmony_ci if (!phba->cfg_fof) 316162306a36Sopenharmony_ci return -EPERM; 316262306a36Sopenharmony_ci 316362306a36Sopenharmony_ci /* count may include a LF at end of string */ 316462306a36Sopenharmony_ci if (buf[cnt-1] == '\n') 316562306a36Sopenharmony_ci cnt--; 316662306a36Sopenharmony_ci 316762306a36Sopenharmony_ci ret = kstrtoul(buf, 0, &val); 316862306a36Sopenharmony_ci if (ret || (val > 0x7f)) 316962306a36Sopenharmony_ci return -EINVAL; 317062306a36Sopenharmony_ci 317162306a36Sopenharmony_ci if (val) 317262306a36Sopenharmony_ci phba->cfg_oas_priority = (uint8_t)val; 317362306a36Sopenharmony_ci else 317462306a36Sopenharmony_ci phba->cfg_oas_priority = phba->cfg_XLanePriority; 317562306a36Sopenharmony_ci return count; 317662306a36Sopenharmony_ci} 317762306a36Sopenharmony_cistatic DEVICE_ATTR(lpfc_xlane_priority, S_IRUGO | S_IWUSR, 317862306a36Sopenharmony_ci lpfc_oas_priority_show, lpfc_oas_priority_store); 317962306a36Sopenharmony_ci 318062306a36Sopenharmony_ci/** 318162306a36Sopenharmony_ci * lpfc_oas_vpt_show - Return wwpn of vport whose targets maybe enabled 318262306a36Sopenharmony_ci * for Optimized Access Storage (OAS) operations. 318362306a36Sopenharmony_ci * @dev: class device that is converted into a Scsi_host. 318462306a36Sopenharmony_ci * @attr: device attribute, not used. 318562306a36Sopenharmony_ci * @buf: buffer for passing information. 318662306a36Sopenharmony_ci * 318762306a36Sopenharmony_ci * Returns: 318862306a36Sopenharmony_ci * value of count on success 318962306a36Sopenharmony_ci **/ 319062306a36Sopenharmony_cistatic ssize_t 319162306a36Sopenharmony_cilpfc_oas_vpt_show(struct device *dev, struct device_attribute *attr, 319262306a36Sopenharmony_ci char *buf) 319362306a36Sopenharmony_ci{ 319462306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 319562306a36Sopenharmony_ci struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; 319662306a36Sopenharmony_ci 319762306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "0x%llx\n", 319862306a36Sopenharmony_ci wwn_to_u64(phba->cfg_oas_vpt_wwpn)); 319962306a36Sopenharmony_ci} 320062306a36Sopenharmony_ci 320162306a36Sopenharmony_ci/** 320262306a36Sopenharmony_ci * lpfc_oas_vpt_store - Store wwpn of vport whose targets maybe enabled 320362306a36Sopenharmony_ci * for Optimized Access Storage (OAS) operations. 320462306a36Sopenharmony_ci * @dev: class device that is converted into a Scsi_host. 320562306a36Sopenharmony_ci * @attr: device attribute, not used. 320662306a36Sopenharmony_ci * @buf: buffer for passing information. 320762306a36Sopenharmony_ci * @count: Size of the data buffer. 320862306a36Sopenharmony_ci * 320962306a36Sopenharmony_ci * Returns: 321062306a36Sopenharmony_ci * -EINVAL count is invalid, invalid wwpn byte invalid 321162306a36Sopenharmony_ci * -EPERM oas is not supported by hba 321262306a36Sopenharmony_ci * value of count on success 321362306a36Sopenharmony_ci **/ 321462306a36Sopenharmony_cistatic ssize_t 321562306a36Sopenharmony_cilpfc_oas_vpt_store(struct device *dev, struct device_attribute *attr, 321662306a36Sopenharmony_ci const char *buf, size_t count) 321762306a36Sopenharmony_ci{ 321862306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 321962306a36Sopenharmony_ci struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; 322062306a36Sopenharmony_ci unsigned int cnt = count; 322162306a36Sopenharmony_ci uint8_t wwpn[WWN_SZ]; 322262306a36Sopenharmony_ci int rc; 322362306a36Sopenharmony_ci 322462306a36Sopenharmony_ci if (!phba->cfg_fof) 322562306a36Sopenharmony_ci return -EPERM; 322662306a36Sopenharmony_ci 322762306a36Sopenharmony_ci /* count may include a LF at end of string */ 322862306a36Sopenharmony_ci if (buf[cnt-1] == '\n') 322962306a36Sopenharmony_ci cnt--; 323062306a36Sopenharmony_ci 323162306a36Sopenharmony_ci rc = lpfc_wwn_set(buf, cnt, wwpn); 323262306a36Sopenharmony_ci if (rc) 323362306a36Sopenharmony_ci return rc; 323462306a36Sopenharmony_ci 323562306a36Sopenharmony_ci memcpy(phba->cfg_oas_vpt_wwpn, wwpn, (8 * sizeof(uint8_t))); 323662306a36Sopenharmony_ci memcpy(phba->sli4_hba.oas_next_vpt_wwpn, wwpn, (8 * sizeof(uint8_t))); 323762306a36Sopenharmony_ci if (wwn_to_u64(wwpn) == 0) 323862306a36Sopenharmony_ci phba->cfg_oas_flags |= OAS_FIND_ANY_VPORT; 323962306a36Sopenharmony_ci else 324062306a36Sopenharmony_ci phba->cfg_oas_flags &= ~OAS_FIND_ANY_VPORT; 324162306a36Sopenharmony_ci phba->cfg_oas_flags &= ~OAS_LUN_VALID; 324262306a36Sopenharmony_ci if (phba->cfg_oas_priority == 0) 324362306a36Sopenharmony_ci phba->cfg_oas_priority = phba->cfg_XLanePriority; 324462306a36Sopenharmony_ci phba->sli4_hba.oas_next_lun = FIND_FIRST_OAS_LUN; 324562306a36Sopenharmony_ci return count; 324662306a36Sopenharmony_ci} 324762306a36Sopenharmony_cistatic DEVICE_ATTR(lpfc_xlane_vpt, S_IRUGO | S_IWUSR, 324862306a36Sopenharmony_ci lpfc_oas_vpt_show, lpfc_oas_vpt_store); 324962306a36Sopenharmony_ci 325062306a36Sopenharmony_ci/** 325162306a36Sopenharmony_ci * lpfc_oas_lun_state_show - Return the current state (enabled or disabled) 325262306a36Sopenharmony_ci * of whether luns will be enabled or disabled 325362306a36Sopenharmony_ci * for Optimized Access Storage (OAS) operations. 325462306a36Sopenharmony_ci * @dev: class device that is converted into a Scsi_host. 325562306a36Sopenharmony_ci * @attr: device attribute, not used. 325662306a36Sopenharmony_ci * @buf: buffer for passing information. 325762306a36Sopenharmony_ci * 325862306a36Sopenharmony_ci * Returns: 325962306a36Sopenharmony_ci * size of formatted string. 326062306a36Sopenharmony_ci **/ 326162306a36Sopenharmony_cistatic ssize_t 326262306a36Sopenharmony_cilpfc_oas_lun_state_show(struct device *dev, struct device_attribute *attr, 326362306a36Sopenharmony_ci char *buf) 326462306a36Sopenharmony_ci{ 326562306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 326662306a36Sopenharmony_ci struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; 326762306a36Sopenharmony_ci 326862306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d\n", phba->cfg_oas_lun_state); 326962306a36Sopenharmony_ci} 327062306a36Sopenharmony_ci 327162306a36Sopenharmony_ci/** 327262306a36Sopenharmony_ci * lpfc_oas_lun_state_store - Store the state (enabled or disabled) 327362306a36Sopenharmony_ci * of whether luns will be enabled or disabled 327462306a36Sopenharmony_ci * for Optimized Access Storage (OAS) operations. 327562306a36Sopenharmony_ci * @dev: class device that is converted into a Scsi_host. 327662306a36Sopenharmony_ci * @attr: device attribute, not used. 327762306a36Sopenharmony_ci * @buf: buffer for passing information. 327862306a36Sopenharmony_ci * @count: Size of the data buffer. 327962306a36Sopenharmony_ci * 328062306a36Sopenharmony_ci * Returns: 328162306a36Sopenharmony_ci * -EINVAL count is invalid, invalid wwpn byte invalid 328262306a36Sopenharmony_ci * -EPERM oas is not supported by hba 328362306a36Sopenharmony_ci * value of count on success 328462306a36Sopenharmony_ci **/ 328562306a36Sopenharmony_cistatic ssize_t 328662306a36Sopenharmony_cilpfc_oas_lun_state_store(struct device *dev, struct device_attribute *attr, 328762306a36Sopenharmony_ci const char *buf, size_t count) 328862306a36Sopenharmony_ci{ 328962306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 329062306a36Sopenharmony_ci struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; 329162306a36Sopenharmony_ci int val = 0; 329262306a36Sopenharmony_ci 329362306a36Sopenharmony_ci if (!phba->cfg_fof) 329462306a36Sopenharmony_ci return -EPERM; 329562306a36Sopenharmony_ci 329662306a36Sopenharmony_ci if (!isdigit(buf[0])) 329762306a36Sopenharmony_ci return -EINVAL; 329862306a36Sopenharmony_ci 329962306a36Sopenharmony_ci if (sscanf(buf, "%i", &val) != 1) 330062306a36Sopenharmony_ci return -EINVAL; 330162306a36Sopenharmony_ci 330262306a36Sopenharmony_ci if ((val != 0) && (val != 1)) 330362306a36Sopenharmony_ci return -EINVAL; 330462306a36Sopenharmony_ci 330562306a36Sopenharmony_ci phba->cfg_oas_lun_state = val; 330662306a36Sopenharmony_ci return strlen(buf); 330762306a36Sopenharmony_ci} 330862306a36Sopenharmony_cistatic DEVICE_ATTR(lpfc_xlane_lun_state, S_IRUGO | S_IWUSR, 330962306a36Sopenharmony_ci lpfc_oas_lun_state_show, lpfc_oas_lun_state_store); 331062306a36Sopenharmony_ci 331162306a36Sopenharmony_ci/** 331262306a36Sopenharmony_ci * lpfc_oas_lun_status_show - Return the status of the Optimized Access 331362306a36Sopenharmony_ci * Storage (OAS) lun returned by the 331462306a36Sopenharmony_ci * lpfc_oas_lun_show function. 331562306a36Sopenharmony_ci * @dev: class device that is converted into a Scsi_host. 331662306a36Sopenharmony_ci * @attr: device attribute, not used. 331762306a36Sopenharmony_ci * @buf: buffer for passing information. 331862306a36Sopenharmony_ci * 331962306a36Sopenharmony_ci * Returns: 332062306a36Sopenharmony_ci * size of formatted string. 332162306a36Sopenharmony_ci **/ 332262306a36Sopenharmony_cistatic ssize_t 332362306a36Sopenharmony_cilpfc_oas_lun_status_show(struct device *dev, struct device_attribute *attr, 332462306a36Sopenharmony_ci char *buf) 332562306a36Sopenharmony_ci{ 332662306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 332762306a36Sopenharmony_ci struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; 332862306a36Sopenharmony_ci 332962306a36Sopenharmony_ci if (!(phba->cfg_oas_flags & OAS_LUN_VALID)) 333062306a36Sopenharmony_ci return -EFAULT; 333162306a36Sopenharmony_ci 333262306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d\n", phba->cfg_oas_lun_status); 333362306a36Sopenharmony_ci} 333462306a36Sopenharmony_cistatic DEVICE_ATTR(lpfc_xlane_lun_status, S_IRUGO, 333562306a36Sopenharmony_ci lpfc_oas_lun_status_show, NULL); 333662306a36Sopenharmony_ci 333762306a36Sopenharmony_ci 333862306a36Sopenharmony_ci/** 333962306a36Sopenharmony_ci * lpfc_oas_lun_state_set - enable or disable a lun for Optimized Access Storage 334062306a36Sopenharmony_ci * (OAS) operations. 334162306a36Sopenharmony_ci * @phba: lpfc_hba pointer. 334262306a36Sopenharmony_ci * @vpt_wwpn: wwpn of the vport associated with the returned lun 334362306a36Sopenharmony_ci * @tgt_wwpn: wwpn of the target associated with the returned lun 334462306a36Sopenharmony_ci * @lun: the fc lun for setting oas state. 334562306a36Sopenharmony_ci * @oas_state: the oas state to be set to the lun. 334662306a36Sopenharmony_ci * @pri: priority 334762306a36Sopenharmony_ci * 334862306a36Sopenharmony_ci * Returns: 334962306a36Sopenharmony_ci * SUCCESS : 0 335062306a36Sopenharmony_ci * -EPERM OAS is not enabled or not supported by this port. 335162306a36Sopenharmony_ci * 335262306a36Sopenharmony_ci */ 335362306a36Sopenharmony_cistatic size_t 335462306a36Sopenharmony_cilpfc_oas_lun_state_set(struct lpfc_hba *phba, uint8_t vpt_wwpn[], 335562306a36Sopenharmony_ci uint8_t tgt_wwpn[], uint64_t lun, 335662306a36Sopenharmony_ci uint32_t oas_state, uint8_t pri) 335762306a36Sopenharmony_ci{ 335862306a36Sopenharmony_ci 335962306a36Sopenharmony_ci int rc = 0; 336062306a36Sopenharmony_ci 336162306a36Sopenharmony_ci if (!phba->cfg_fof) 336262306a36Sopenharmony_ci return -EPERM; 336362306a36Sopenharmony_ci 336462306a36Sopenharmony_ci if (oas_state) { 336562306a36Sopenharmony_ci if (!lpfc_enable_oas_lun(phba, (struct lpfc_name *)vpt_wwpn, 336662306a36Sopenharmony_ci (struct lpfc_name *)tgt_wwpn, 336762306a36Sopenharmony_ci lun, pri)) 336862306a36Sopenharmony_ci rc = -ENOMEM; 336962306a36Sopenharmony_ci } else { 337062306a36Sopenharmony_ci lpfc_disable_oas_lun(phba, (struct lpfc_name *)vpt_wwpn, 337162306a36Sopenharmony_ci (struct lpfc_name *)tgt_wwpn, lun, pri); 337262306a36Sopenharmony_ci } 337362306a36Sopenharmony_ci return rc; 337462306a36Sopenharmony_ci 337562306a36Sopenharmony_ci} 337662306a36Sopenharmony_ci 337762306a36Sopenharmony_ci/** 337862306a36Sopenharmony_ci * lpfc_oas_lun_get_next - get the next lun that has been enabled for Optimized 337962306a36Sopenharmony_ci * Access Storage (OAS) operations. 338062306a36Sopenharmony_ci * @phba: lpfc_hba pointer. 338162306a36Sopenharmony_ci * @vpt_wwpn: wwpn of the vport associated with the returned lun 338262306a36Sopenharmony_ci * @tgt_wwpn: wwpn of the target associated with the returned lun 338362306a36Sopenharmony_ci * @lun_status: status of the lun returned lun 338462306a36Sopenharmony_ci * @lun_pri: priority of the lun returned lun 338562306a36Sopenharmony_ci * 338662306a36Sopenharmony_ci * Returns the first or next lun enabled for OAS operations for the vport/target 338762306a36Sopenharmony_ci * specified. If a lun is found, its vport wwpn, target wwpn and status is 338862306a36Sopenharmony_ci * returned. If the lun is not found, NOT_OAS_ENABLED_LUN is returned. 338962306a36Sopenharmony_ci * 339062306a36Sopenharmony_ci * Return: 339162306a36Sopenharmony_ci * lun that is OAS enabled for the vport/target 339262306a36Sopenharmony_ci * NOT_OAS_ENABLED_LUN when no oas enabled lun found. 339362306a36Sopenharmony_ci */ 339462306a36Sopenharmony_cistatic uint64_t 339562306a36Sopenharmony_cilpfc_oas_lun_get_next(struct lpfc_hba *phba, uint8_t vpt_wwpn[], 339662306a36Sopenharmony_ci uint8_t tgt_wwpn[], uint32_t *lun_status, 339762306a36Sopenharmony_ci uint32_t *lun_pri) 339862306a36Sopenharmony_ci{ 339962306a36Sopenharmony_ci uint64_t found_lun; 340062306a36Sopenharmony_ci 340162306a36Sopenharmony_ci if (unlikely(!phba) || !vpt_wwpn || !tgt_wwpn) 340262306a36Sopenharmony_ci return NOT_OAS_ENABLED_LUN; 340362306a36Sopenharmony_ci if (lpfc_find_next_oas_lun(phba, (struct lpfc_name *) 340462306a36Sopenharmony_ci phba->sli4_hba.oas_next_vpt_wwpn, 340562306a36Sopenharmony_ci (struct lpfc_name *) 340662306a36Sopenharmony_ci phba->sli4_hba.oas_next_tgt_wwpn, 340762306a36Sopenharmony_ci &phba->sli4_hba.oas_next_lun, 340862306a36Sopenharmony_ci (struct lpfc_name *)vpt_wwpn, 340962306a36Sopenharmony_ci (struct lpfc_name *)tgt_wwpn, 341062306a36Sopenharmony_ci &found_lun, lun_status, lun_pri)) 341162306a36Sopenharmony_ci return found_lun; 341262306a36Sopenharmony_ci else 341362306a36Sopenharmony_ci return NOT_OAS_ENABLED_LUN; 341462306a36Sopenharmony_ci} 341562306a36Sopenharmony_ci 341662306a36Sopenharmony_ci/** 341762306a36Sopenharmony_ci * lpfc_oas_lun_state_change - enable/disable a lun for OAS operations 341862306a36Sopenharmony_ci * @phba: lpfc_hba pointer. 341962306a36Sopenharmony_ci * @vpt_wwpn: vport wwpn by reference. 342062306a36Sopenharmony_ci * @tgt_wwpn: target wwpn by reference. 342162306a36Sopenharmony_ci * @lun: the fc lun for setting oas state. 342262306a36Sopenharmony_ci * @oas_state: the oas state to be set to the oas_lun. 342362306a36Sopenharmony_ci * @pri: priority 342462306a36Sopenharmony_ci * 342562306a36Sopenharmony_ci * This routine enables (OAS_LUN_ENABLE) or disables (OAS_LUN_DISABLE) 342662306a36Sopenharmony_ci * a lun for OAS operations. 342762306a36Sopenharmony_ci * 342862306a36Sopenharmony_ci * Return: 342962306a36Sopenharmony_ci * SUCCESS: 0 343062306a36Sopenharmony_ci * -ENOMEM: failed to enable an lun for OAS operations 343162306a36Sopenharmony_ci * -EPERM: OAS is not enabled 343262306a36Sopenharmony_ci */ 343362306a36Sopenharmony_cistatic ssize_t 343462306a36Sopenharmony_cilpfc_oas_lun_state_change(struct lpfc_hba *phba, uint8_t vpt_wwpn[], 343562306a36Sopenharmony_ci uint8_t tgt_wwpn[], uint64_t lun, 343662306a36Sopenharmony_ci uint32_t oas_state, uint8_t pri) 343762306a36Sopenharmony_ci{ 343862306a36Sopenharmony_ci 343962306a36Sopenharmony_ci int rc; 344062306a36Sopenharmony_ci 344162306a36Sopenharmony_ci rc = lpfc_oas_lun_state_set(phba, vpt_wwpn, tgt_wwpn, lun, 344262306a36Sopenharmony_ci oas_state, pri); 344362306a36Sopenharmony_ci return rc; 344462306a36Sopenharmony_ci} 344562306a36Sopenharmony_ci 344662306a36Sopenharmony_ci/** 344762306a36Sopenharmony_ci * lpfc_oas_lun_show - Return oas enabled luns from a chosen target 344862306a36Sopenharmony_ci * @dev: class device that is converted into a Scsi_host. 344962306a36Sopenharmony_ci * @attr: device attribute, not used. 345062306a36Sopenharmony_ci * @buf: buffer for passing information. 345162306a36Sopenharmony_ci * 345262306a36Sopenharmony_ci * This routine returns a lun enabled for OAS each time the function 345362306a36Sopenharmony_ci * is called. 345462306a36Sopenharmony_ci * 345562306a36Sopenharmony_ci * Returns: 345662306a36Sopenharmony_ci * SUCCESS: size of formatted string. 345762306a36Sopenharmony_ci * -EFAULT: target or vport wwpn was not set properly. 345862306a36Sopenharmony_ci * -EPERM: oas is not enabled. 345962306a36Sopenharmony_ci **/ 346062306a36Sopenharmony_cistatic ssize_t 346162306a36Sopenharmony_cilpfc_oas_lun_show(struct device *dev, struct device_attribute *attr, 346262306a36Sopenharmony_ci char *buf) 346362306a36Sopenharmony_ci{ 346462306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 346562306a36Sopenharmony_ci struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; 346662306a36Sopenharmony_ci 346762306a36Sopenharmony_ci uint64_t oas_lun; 346862306a36Sopenharmony_ci int len = 0; 346962306a36Sopenharmony_ci 347062306a36Sopenharmony_ci if (!phba->cfg_fof) 347162306a36Sopenharmony_ci return -EPERM; 347262306a36Sopenharmony_ci 347362306a36Sopenharmony_ci if (wwn_to_u64(phba->cfg_oas_vpt_wwpn) == 0) 347462306a36Sopenharmony_ci if (!(phba->cfg_oas_flags & OAS_FIND_ANY_VPORT)) 347562306a36Sopenharmony_ci return -EFAULT; 347662306a36Sopenharmony_ci 347762306a36Sopenharmony_ci if (wwn_to_u64(phba->cfg_oas_tgt_wwpn) == 0) 347862306a36Sopenharmony_ci if (!(phba->cfg_oas_flags & OAS_FIND_ANY_TARGET)) 347962306a36Sopenharmony_ci return -EFAULT; 348062306a36Sopenharmony_ci 348162306a36Sopenharmony_ci oas_lun = lpfc_oas_lun_get_next(phba, phba->cfg_oas_vpt_wwpn, 348262306a36Sopenharmony_ci phba->cfg_oas_tgt_wwpn, 348362306a36Sopenharmony_ci &phba->cfg_oas_lun_status, 348462306a36Sopenharmony_ci &phba->cfg_oas_priority); 348562306a36Sopenharmony_ci if (oas_lun != NOT_OAS_ENABLED_LUN) 348662306a36Sopenharmony_ci phba->cfg_oas_flags |= OAS_LUN_VALID; 348762306a36Sopenharmony_ci 348862306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, "0x%llx", oas_lun); 348962306a36Sopenharmony_ci 349062306a36Sopenharmony_ci return len; 349162306a36Sopenharmony_ci} 349262306a36Sopenharmony_ci 349362306a36Sopenharmony_ci/** 349462306a36Sopenharmony_ci * lpfc_oas_lun_store - Sets the OAS state for lun 349562306a36Sopenharmony_ci * @dev: class device that is converted into a Scsi_host. 349662306a36Sopenharmony_ci * @attr: device attribute, not used. 349762306a36Sopenharmony_ci * @buf: buffer for passing information. 349862306a36Sopenharmony_ci * @count: size of the formatting string 349962306a36Sopenharmony_ci * 350062306a36Sopenharmony_ci * This function sets the OAS state for lun. Before this function is called, 350162306a36Sopenharmony_ci * the vport wwpn, target wwpn, and oas state need to be set. 350262306a36Sopenharmony_ci * 350362306a36Sopenharmony_ci * Returns: 350462306a36Sopenharmony_ci * SUCCESS: size of formatted string. 350562306a36Sopenharmony_ci * -EFAULT: target or vport wwpn was not set properly. 350662306a36Sopenharmony_ci * -EPERM: oas is not enabled. 350762306a36Sopenharmony_ci * size of formatted string. 350862306a36Sopenharmony_ci **/ 350962306a36Sopenharmony_cistatic ssize_t 351062306a36Sopenharmony_cilpfc_oas_lun_store(struct device *dev, struct device_attribute *attr, 351162306a36Sopenharmony_ci const char *buf, size_t count) 351262306a36Sopenharmony_ci{ 351362306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 351462306a36Sopenharmony_ci struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; 351562306a36Sopenharmony_ci uint64_t scsi_lun; 351662306a36Sopenharmony_ci uint32_t pri; 351762306a36Sopenharmony_ci ssize_t rc; 351862306a36Sopenharmony_ci 351962306a36Sopenharmony_ci if (!phba->cfg_fof) 352062306a36Sopenharmony_ci return -EPERM; 352162306a36Sopenharmony_ci 352262306a36Sopenharmony_ci if (wwn_to_u64(phba->cfg_oas_vpt_wwpn) == 0) 352362306a36Sopenharmony_ci return -EFAULT; 352462306a36Sopenharmony_ci 352562306a36Sopenharmony_ci if (wwn_to_u64(phba->cfg_oas_tgt_wwpn) == 0) 352662306a36Sopenharmony_ci return -EFAULT; 352762306a36Sopenharmony_ci 352862306a36Sopenharmony_ci if (!isdigit(buf[0])) 352962306a36Sopenharmony_ci return -EINVAL; 353062306a36Sopenharmony_ci 353162306a36Sopenharmony_ci if (sscanf(buf, "0x%llx", &scsi_lun) != 1) 353262306a36Sopenharmony_ci return -EINVAL; 353362306a36Sopenharmony_ci 353462306a36Sopenharmony_ci pri = phba->cfg_oas_priority; 353562306a36Sopenharmony_ci if (pri == 0) 353662306a36Sopenharmony_ci pri = phba->cfg_XLanePriority; 353762306a36Sopenharmony_ci 353862306a36Sopenharmony_ci lpfc_printf_log(phba, KERN_INFO, LOG_INIT, 353962306a36Sopenharmony_ci "3372 Try to set vport 0x%llx target 0x%llx lun:0x%llx " 354062306a36Sopenharmony_ci "priority 0x%x with oas state %d\n", 354162306a36Sopenharmony_ci wwn_to_u64(phba->cfg_oas_vpt_wwpn), 354262306a36Sopenharmony_ci wwn_to_u64(phba->cfg_oas_tgt_wwpn), scsi_lun, 354362306a36Sopenharmony_ci pri, phba->cfg_oas_lun_state); 354462306a36Sopenharmony_ci 354562306a36Sopenharmony_ci rc = lpfc_oas_lun_state_change(phba, phba->cfg_oas_vpt_wwpn, 354662306a36Sopenharmony_ci phba->cfg_oas_tgt_wwpn, scsi_lun, 354762306a36Sopenharmony_ci phba->cfg_oas_lun_state, pri); 354862306a36Sopenharmony_ci if (rc) 354962306a36Sopenharmony_ci return rc; 355062306a36Sopenharmony_ci 355162306a36Sopenharmony_ci return count; 355262306a36Sopenharmony_ci} 355362306a36Sopenharmony_cistatic DEVICE_ATTR(lpfc_xlane_lun, S_IRUGO | S_IWUSR, 355462306a36Sopenharmony_ci lpfc_oas_lun_show, lpfc_oas_lun_store); 355562306a36Sopenharmony_ci 355662306a36Sopenharmony_ciint lpfc_enable_nvmet_cnt; 355762306a36Sopenharmony_ciunsigned long long lpfc_enable_nvmet[LPFC_NVMET_MAX_PORTS] = { 355862306a36Sopenharmony_ci 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 355962306a36Sopenharmony_ci 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 356062306a36Sopenharmony_cimodule_param_array(lpfc_enable_nvmet, ullong, &lpfc_enable_nvmet_cnt, 0444); 356162306a36Sopenharmony_ciMODULE_PARM_DESC(lpfc_enable_nvmet, "Enable HBA port(s) WWPN as a NVME Target"); 356262306a36Sopenharmony_ci 356362306a36Sopenharmony_cistatic int lpfc_poll = 0; 356462306a36Sopenharmony_cimodule_param(lpfc_poll, int, S_IRUGO); 356562306a36Sopenharmony_ciMODULE_PARM_DESC(lpfc_poll, "FCP ring polling mode control:" 356662306a36Sopenharmony_ci " 0 - none," 356762306a36Sopenharmony_ci " 1 - poll with interrupts enabled" 356862306a36Sopenharmony_ci " 3 - poll and disable FCP ring interrupts"); 356962306a36Sopenharmony_ci 357062306a36Sopenharmony_cistatic DEVICE_ATTR_RW(lpfc_poll); 357162306a36Sopenharmony_ci 357262306a36Sopenharmony_ciint lpfc_no_hba_reset_cnt; 357362306a36Sopenharmony_ciunsigned long lpfc_no_hba_reset[MAX_HBAS_NO_RESET] = { 357462306a36Sopenharmony_ci 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 357562306a36Sopenharmony_cimodule_param_array(lpfc_no_hba_reset, ulong, &lpfc_no_hba_reset_cnt, 0444); 357662306a36Sopenharmony_ciMODULE_PARM_DESC(lpfc_no_hba_reset, "WWPN of HBAs that should not be reset"); 357762306a36Sopenharmony_ci 357862306a36Sopenharmony_ciLPFC_ATTR(sli_mode, 3, 3, 3, 357962306a36Sopenharmony_ci "SLI mode selector: 3 - select SLI-3"); 358062306a36Sopenharmony_ci 358162306a36Sopenharmony_ciLPFC_ATTR_R(enable_npiv, 1, 0, 1, 358262306a36Sopenharmony_ci "Enable NPIV functionality"); 358362306a36Sopenharmony_ci 358462306a36Sopenharmony_ciLPFC_ATTR_R(fcf_failover_policy, 1, 1, 2, 358562306a36Sopenharmony_ci "FCF Fast failover=1 Priority failover=2"); 358662306a36Sopenharmony_ci 358762306a36Sopenharmony_ci/* 358862306a36Sopenharmony_ci * lpfc_fcp_wait_abts_rsp: Modifies criteria for reporting completion of 358962306a36Sopenharmony_ci * aborted IO. 359062306a36Sopenharmony_ci * The range is [0,1]. Default value is 0 359162306a36Sopenharmony_ci * 0, IO completes after ABTS issued (default). 359262306a36Sopenharmony_ci * 1, IO completes after receipt of ABTS response or timeout. 359362306a36Sopenharmony_ci */ 359462306a36Sopenharmony_ciLPFC_ATTR_R(fcp_wait_abts_rsp, 0, 0, 1, "Wait for FCP ABTS completion"); 359562306a36Sopenharmony_ci 359662306a36Sopenharmony_ci/* 359762306a36Sopenharmony_ci# lpfc_enable_rrq: Track XRI/OXID reuse after IO failures 359862306a36Sopenharmony_ci# 0x0 = disabled, XRI/OXID use not tracked. 359962306a36Sopenharmony_ci# 0x1 = XRI/OXID reuse is timed with ratov, RRQ sent. 360062306a36Sopenharmony_ci# 0x2 = XRI/OXID reuse is timed with ratov, No RRQ sent. 360162306a36Sopenharmony_ci*/ 360262306a36Sopenharmony_ciLPFC_ATTR_R(enable_rrq, 2, 0, 2, 360362306a36Sopenharmony_ci "Enable RRQ functionality"); 360462306a36Sopenharmony_ci 360562306a36Sopenharmony_ci/* 360662306a36Sopenharmony_ci# lpfc_suppress_link_up: Bring link up at initialization 360762306a36Sopenharmony_ci# 0x0 = bring link up (issue MBX_INIT_LINK) 360862306a36Sopenharmony_ci# 0x1 = do NOT bring link up at initialization(MBX_INIT_LINK) 360962306a36Sopenharmony_ci# 0x2 = never bring up link 361062306a36Sopenharmony_ci# Default value is 0. 361162306a36Sopenharmony_ci*/ 361262306a36Sopenharmony_ciLPFC_ATTR_R(suppress_link_up, LPFC_INITIALIZE_LINK, LPFC_INITIALIZE_LINK, 361362306a36Sopenharmony_ci LPFC_DELAY_INIT_LINK_INDEFINITELY, 361462306a36Sopenharmony_ci "Suppress Link Up at initialization"); 361562306a36Sopenharmony_ci 361662306a36Sopenharmony_cistatic ssize_t 361762306a36Sopenharmony_cilpfc_pls_show(struct device *dev, struct device_attribute *attr, char *buf) 361862306a36Sopenharmony_ci{ 361962306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 362062306a36Sopenharmony_ci struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; 362162306a36Sopenharmony_ci 362262306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d\n", 362362306a36Sopenharmony_ci phba->sli4_hba.pc_sli4_params.pls); 362462306a36Sopenharmony_ci} 362562306a36Sopenharmony_cistatic DEVICE_ATTR(pls, 0444, 362662306a36Sopenharmony_ci lpfc_pls_show, NULL); 362762306a36Sopenharmony_ci 362862306a36Sopenharmony_cistatic ssize_t 362962306a36Sopenharmony_cilpfc_pt_show(struct device *dev, struct device_attribute *attr, char *buf) 363062306a36Sopenharmony_ci{ 363162306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 363262306a36Sopenharmony_ci struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; 363362306a36Sopenharmony_ci 363462306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d\n", 363562306a36Sopenharmony_ci (phba->hba_flag & HBA_PERSISTENT_TOPO) ? 1 : 0); 363662306a36Sopenharmony_ci} 363762306a36Sopenharmony_cistatic DEVICE_ATTR(pt, 0444, 363862306a36Sopenharmony_ci lpfc_pt_show, NULL); 363962306a36Sopenharmony_ci 364062306a36Sopenharmony_ci/* 364162306a36Sopenharmony_ci# lpfc_cnt: Number of IOCBs allocated for ELS, CT, and ABTS 364262306a36Sopenharmony_ci# 1 - (1024) 364362306a36Sopenharmony_ci# 2 - (2048) 364462306a36Sopenharmony_ci# 3 - (3072) 364562306a36Sopenharmony_ci# 4 - (4096) 364662306a36Sopenharmony_ci# 5 - (5120) 364762306a36Sopenharmony_ci*/ 364862306a36Sopenharmony_cistatic ssize_t 364962306a36Sopenharmony_cilpfc_iocb_hw_show(struct device *dev, struct device_attribute *attr, char *buf) 365062306a36Sopenharmony_ci{ 365162306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 365262306a36Sopenharmony_ci struct lpfc_hba *phba = ((struct lpfc_vport *) shost->hostdata)->phba; 365362306a36Sopenharmony_ci 365462306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d\n", phba->iocb_max); 365562306a36Sopenharmony_ci} 365662306a36Sopenharmony_ci 365762306a36Sopenharmony_cistatic DEVICE_ATTR(iocb_hw, S_IRUGO, 365862306a36Sopenharmony_ci lpfc_iocb_hw_show, NULL); 365962306a36Sopenharmony_cistatic ssize_t 366062306a36Sopenharmony_cilpfc_txq_hw_show(struct device *dev, struct device_attribute *attr, char *buf) 366162306a36Sopenharmony_ci{ 366262306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 366362306a36Sopenharmony_ci struct lpfc_hba *phba = ((struct lpfc_vport *) shost->hostdata)->phba; 366462306a36Sopenharmony_ci struct lpfc_sli_ring *pring = lpfc_phba_elsring(phba); 366562306a36Sopenharmony_ci 366662306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d\n", 366762306a36Sopenharmony_ci pring ? pring->txq_max : 0); 366862306a36Sopenharmony_ci} 366962306a36Sopenharmony_ci 367062306a36Sopenharmony_cistatic DEVICE_ATTR(txq_hw, S_IRUGO, 367162306a36Sopenharmony_ci lpfc_txq_hw_show, NULL); 367262306a36Sopenharmony_cistatic ssize_t 367362306a36Sopenharmony_cilpfc_txcmplq_hw_show(struct device *dev, struct device_attribute *attr, 367462306a36Sopenharmony_ci char *buf) 367562306a36Sopenharmony_ci{ 367662306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 367762306a36Sopenharmony_ci struct lpfc_hba *phba = ((struct lpfc_vport *) shost->hostdata)->phba; 367862306a36Sopenharmony_ci struct lpfc_sli_ring *pring = lpfc_phba_elsring(phba); 367962306a36Sopenharmony_ci 368062306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d\n", 368162306a36Sopenharmony_ci pring ? pring->txcmplq_max : 0); 368262306a36Sopenharmony_ci} 368362306a36Sopenharmony_ci 368462306a36Sopenharmony_cistatic DEVICE_ATTR(txcmplq_hw, S_IRUGO, 368562306a36Sopenharmony_ci lpfc_txcmplq_hw_show, NULL); 368662306a36Sopenharmony_ci 368762306a36Sopenharmony_ci/* 368862306a36Sopenharmony_ci# lpfc_nodev_tmo: If set, it will hold all I/O errors on devices that disappear 368962306a36Sopenharmony_ci# until the timer expires. Value range is [0,255]. Default value is 30. 369062306a36Sopenharmony_ci*/ 369162306a36Sopenharmony_cistatic int lpfc_nodev_tmo = LPFC_DEF_DEVLOSS_TMO; 369262306a36Sopenharmony_cistatic int lpfc_devloss_tmo = LPFC_DEF_DEVLOSS_TMO; 369362306a36Sopenharmony_cimodule_param(lpfc_nodev_tmo, int, 0); 369462306a36Sopenharmony_ciMODULE_PARM_DESC(lpfc_nodev_tmo, 369562306a36Sopenharmony_ci "Seconds driver will hold I/O waiting " 369662306a36Sopenharmony_ci "for a device to come back"); 369762306a36Sopenharmony_ci 369862306a36Sopenharmony_ci/** 369962306a36Sopenharmony_ci * lpfc_nodev_tmo_show - Return the hba dev loss timeout value 370062306a36Sopenharmony_ci * @dev: class converted to a Scsi_host structure. 370162306a36Sopenharmony_ci * @attr: device attribute, not used. 370262306a36Sopenharmony_ci * @buf: on return contains the dev loss timeout in decimal. 370362306a36Sopenharmony_ci * 370462306a36Sopenharmony_ci * Returns: size of formatted string. 370562306a36Sopenharmony_ci **/ 370662306a36Sopenharmony_cistatic ssize_t 370762306a36Sopenharmony_cilpfc_nodev_tmo_show(struct device *dev, struct device_attribute *attr, 370862306a36Sopenharmony_ci char *buf) 370962306a36Sopenharmony_ci{ 371062306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 371162306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 371262306a36Sopenharmony_ci 371362306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d\n", vport->cfg_devloss_tmo); 371462306a36Sopenharmony_ci} 371562306a36Sopenharmony_ci 371662306a36Sopenharmony_ci/** 371762306a36Sopenharmony_ci * lpfc_nodev_tmo_init - Set the hba nodev timeout value 371862306a36Sopenharmony_ci * @vport: lpfc vport structure pointer. 371962306a36Sopenharmony_ci * @val: contains the nodev timeout value. 372062306a36Sopenharmony_ci * 372162306a36Sopenharmony_ci * Description: 372262306a36Sopenharmony_ci * If the devloss tmo is already set then nodev tmo is set to devloss tmo, 372362306a36Sopenharmony_ci * a kernel error message is printed and zero is returned. 372462306a36Sopenharmony_ci * Else if val is in range then nodev tmo and devloss tmo are set to val. 372562306a36Sopenharmony_ci * Otherwise nodev tmo is set to the default value. 372662306a36Sopenharmony_ci * 372762306a36Sopenharmony_ci * Returns: 372862306a36Sopenharmony_ci * zero if already set or if val is in range 372962306a36Sopenharmony_ci * -EINVAL val out of range 373062306a36Sopenharmony_ci **/ 373162306a36Sopenharmony_cistatic int 373262306a36Sopenharmony_cilpfc_nodev_tmo_init(struct lpfc_vport *vport, int val) 373362306a36Sopenharmony_ci{ 373462306a36Sopenharmony_ci if (vport->cfg_devloss_tmo != LPFC_DEF_DEVLOSS_TMO) { 373562306a36Sopenharmony_ci vport->cfg_nodev_tmo = vport->cfg_devloss_tmo; 373662306a36Sopenharmony_ci if (val != LPFC_DEF_DEVLOSS_TMO) 373762306a36Sopenharmony_ci lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, 373862306a36Sopenharmony_ci "0407 Ignoring lpfc_nodev_tmo module " 373962306a36Sopenharmony_ci "parameter because lpfc_devloss_tmo " 374062306a36Sopenharmony_ci "is set.\n"); 374162306a36Sopenharmony_ci return 0; 374262306a36Sopenharmony_ci } 374362306a36Sopenharmony_ci 374462306a36Sopenharmony_ci if (val >= LPFC_MIN_DEVLOSS_TMO && val <= LPFC_MAX_DEVLOSS_TMO) { 374562306a36Sopenharmony_ci vport->cfg_nodev_tmo = val; 374662306a36Sopenharmony_ci vport->cfg_devloss_tmo = val; 374762306a36Sopenharmony_ci return 0; 374862306a36Sopenharmony_ci } 374962306a36Sopenharmony_ci lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, 375062306a36Sopenharmony_ci "0400 lpfc_nodev_tmo attribute cannot be set to" 375162306a36Sopenharmony_ci " %d, allowed range is [%d, %d]\n", 375262306a36Sopenharmony_ci val, LPFC_MIN_DEVLOSS_TMO, LPFC_MAX_DEVLOSS_TMO); 375362306a36Sopenharmony_ci vport->cfg_nodev_tmo = LPFC_DEF_DEVLOSS_TMO; 375462306a36Sopenharmony_ci return -EINVAL; 375562306a36Sopenharmony_ci} 375662306a36Sopenharmony_ci 375762306a36Sopenharmony_ci/** 375862306a36Sopenharmony_ci * lpfc_update_rport_devloss_tmo - Update dev loss tmo value 375962306a36Sopenharmony_ci * @vport: lpfc vport structure pointer. 376062306a36Sopenharmony_ci * 376162306a36Sopenharmony_ci * Description: 376262306a36Sopenharmony_ci * Update all the ndlp's dev loss tmo with the vport devloss tmo value. 376362306a36Sopenharmony_ci **/ 376462306a36Sopenharmony_cistatic void 376562306a36Sopenharmony_cilpfc_update_rport_devloss_tmo(struct lpfc_vport *vport) 376662306a36Sopenharmony_ci{ 376762306a36Sopenharmony_ci struct Scsi_Host *shost; 376862306a36Sopenharmony_ci struct lpfc_nodelist *ndlp; 376962306a36Sopenharmony_ci#if (IS_ENABLED(CONFIG_NVME_FC)) 377062306a36Sopenharmony_ci struct lpfc_nvme_rport *rport; 377162306a36Sopenharmony_ci struct nvme_fc_remote_port *remoteport = NULL; 377262306a36Sopenharmony_ci#endif 377362306a36Sopenharmony_ci 377462306a36Sopenharmony_ci shost = lpfc_shost_from_vport(vport); 377562306a36Sopenharmony_ci spin_lock_irq(shost->host_lock); 377662306a36Sopenharmony_ci list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) { 377762306a36Sopenharmony_ci if (ndlp->rport) 377862306a36Sopenharmony_ci ndlp->rport->dev_loss_tmo = vport->cfg_devloss_tmo; 377962306a36Sopenharmony_ci#if (IS_ENABLED(CONFIG_NVME_FC)) 378062306a36Sopenharmony_ci spin_lock(&ndlp->lock); 378162306a36Sopenharmony_ci rport = lpfc_ndlp_get_nrport(ndlp); 378262306a36Sopenharmony_ci if (rport) 378362306a36Sopenharmony_ci remoteport = rport->remoteport; 378462306a36Sopenharmony_ci spin_unlock(&ndlp->lock); 378562306a36Sopenharmony_ci if (rport && remoteport) 378662306a36Sopenharmony_ci nvme_fc_set_remoteport_devloss(remoteport, 378762306a36Sopenharmony_ci vport->cfg_devloss_tmo); 378862306a36Sopenharmony_ci#endif 378962306a36Sopenharmony_ci } 379062306a36Sopenharmony_ci spin_unlock_irq(shost->host_lock); 379162306a36Sopenharmony_ci} 379262306a36Sopenharmony_ci 379362306a36Sopenharmony_ci/** 379462306a36Sopenharmony_ci * lpfc_nodev_tmo_set - Set the vport nodev tmo and devloss tmo values 379562306a36Sopenharmony_ci * @vport: lpfc vport structure pointer. 379662306a36Sopenharmony_ci * @val: contains the tmo value. 379762306a36Sopenharmony_ci * 379862306a36Sopenharmony_ci * Description: 379962306a36Sopenharmony_ci * If the devloss tmo is already set or the vport dev loss tmo has changed 380062306a36Sopenharmony_ci * then a kernel error message is printed and zero is returned. 380162306a36Sopenharmony_ci * Else if val is in range then nodev tmo and devloss tmo are set to val. 380262306a36Sopenharmony_ci * Otherwise nodev tmo is set to the default value. 380362306a36Sopenharmony_ci * 380462306a36Sopenharmony_ci * Returns: 380562306a36Sopenharmony_ci * zero if already set or if val is in range 380662306a36Sopenharmony_ci * -EINVAL val out of range 380762306a36Sopenharmony_ci **/ 380862306a36Sopenharmony_cistatic int 380962306a36Sopenharmony_cilpfc_nodev_tmo_set(struct lpfc_vport *vport, int val) 381062306a36Sopenharmony_ci{ 381162306a36Sopenharmony_ci if (vport->dev_loss_tmo_changed || 381262306a36Sopenharmony_ci (lpfc_devloss_tmo != LPFC_DEF_DEVLOSS_TMO)) { 381362306a36Sopenharmony_ci lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, 381462306a36Sopenharmony_ci "0401 Ignoring change to lpfc_nodev_tmo " 381562306a36Sopenharmony_ci "because lpfc_devloss_tmo is set.\n"); 381662306a36Sopenharmony_ci return 0; 381762306a36Sopenharmony_ci } 381862306a36Sopenharmony_ci if (val >= LPFC_MIN_DEVLOSS_TMO && val <= LPFC_MAX_DEVLOSS_TMO) { 381962306a36Sopenharmony_ci vport->cfg_nodev_tmo = val; 382062306a36Sopenharmony_ci vport->cfg_devloss_tmo = val; 382162306a36Sopenharmony_ci /* 382262306a36Sopenharmony_ci * For compat: set the fc_host dev loss so new rports 382362306a36Sopenharmony_ci * will get the value. 382462306a36Sopenharmony_ci */ 382562306a36Sopenharmony_ci fc_host_dev_loss_tmo(lpfc_shost_from_vport(vport)) = val; 382662306a36Sopenharmony_ci lpfc_update_rport_devloss_tmo(vport); 382762306a36Sopenharmony_ci return 0; 382862306a36Sopenharmony_ci } 382962306a36Sopenharmony_ci lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, 383062306a36Sopenharmony_ci "0403 lpfc_nodev_tmo attribute cannot be set to " 383162306a36Sopenharmony_ci "%d, allowed range is [%d, %d]\n", 383262306a36Sopenharmony_ci val, LPFC_MIN_DEVLOSS_TMO, LPFC_MAX_DEVLOSS_TMO); 383362306a36Sopenharmony_ci return -EINVAL; 383462306a36Sopenharmony_ci} 383562306a36Sopenharmony_ci 383662306a36Sopenharmony_cilpfc_vport_param_store(nodev_tmo) 383762306a36Sopenharmony_ci 383862306a36Sopenharmony_cistatic DEVICE_ATTR_RW(lpfc_nodev_tmo); 383962306a36Sopenharmony_ci 384062306a36Sopenharmony_ci/* 384162306a36Sopenharmony_ci# lpfc_devloss_tmo: If set, it will hold all I/O errors on devices that 384262306a36Sopenharmony_ci# disappear until the timer expires. Value range is [0,255]. Default 384362306a36Sopenharmony_ci# value is 30. 384462306a36Sopenharmony_ci*/ 384562306a36Sopenharmony_cimodule_param(lpfc_devloss_tmo, int, S_IRUGO); 384662306a36Sopenharmony_ciMODULE_PARM_DESC(lpfc_devloss_tmo, 384762306a36Sopenharmony_ci "Seconds driver will hold I/O waiting " 384862306a36Sopenharmony_ci "for a device to come back"); 384962306a36Sopenharmony_cilpfc_vport_param_init(devloss_tmo, LPFC_DEF_DEVLOSS_TMO, 385062306a36Sopenharmony_ci LPFC_MIN_DEVLOSS_TMO, LPFC_MAX_DEVLOSS_TMO) 385162306a36Sopenharmony_cilpfc_vport_param_show(devloss_tmo) 385262306a36Sopenharmony_ci 385362306a36Sopenharmony_ci/** 385462306a36Sopenharmony_ci * lpfc_devloss_tmo_set - Sets vport nodev tmo, devloss tmo values, changed bit 385562306a36Sopenharmony_ci * @vport: lpfc vport structure pointer. 385662306a36Sopenharmony_ci * @val: contains the tmo value. 385762306a36Sopenharmony_ci * 385862306a36Sopenharmony_ci * Description: 385962306a36Sopenharmony_ci * If val is in a valid range then set the vport nodev tmo, 386062306a36Sopenharmony_ci * devloss tmo, also set the vport dev loss tmo changed flag. 386162306a36Sopenharmony_ci * Else a kernel error message is printed. 386262306a36Sopenharmony_ci * 386362306a36Sopenharmony_ci * Returns: 386462306a36Sopenharmony_ci * zero if val is in range 386562306a36Sopenharmony_ci * -EINVAL val out of range 386662306a36Sopenharmony_ci **/ 386762306a36Sopenharmony_cistatic int 386862306a36Sopenharmony_cilpfc_devloss_tmo_set(struct lpfc_vport *vport, int val) 386962306a36Sopenharmony_ci{ 387062306a36Sopenharmony_ci if (val >= LPFC_MIN_DEVLOSS_TMO && val <= LPFC_MAX_DEVLOSS_TMO) { 387162306a36Sopenharmony_ci vport->cfg_nodev_tmo = val; 387262306a36Sopenharmony_ci vport->cfg_devloss_tmo = val; 387362306a36Sopenharmony_ci vport->dev_loss_tmo_changed = 1; 387462306a36Sopenharmony_ci fc_host_dev_loss_tmo(lpfc_shost_from_vport(vport)) = val; 387562306a36Sopenharmony_ci lpfc_update_rport_devloss_tmo(vport); 387662306a36Sopenharmony_ci return 0; 387762306a36Sopenharmony_ci } 387862306a36Sopenharmony_ci 387962306a36Sopenharmony_ci lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, 388062306a36Sopenharmony_ci "0404 lpfc_devloss_tmo attribute cannot be set to " 388162306a36Sopenharmony_ci "%d, allowed range is [%d, %d]\n", 388262306a36Sopenharmony_ci val, LPFC_MIN_DEVLOSS_TMO, LPFC_MAX_DEVLOSS_TMO); 388362306a36Sopenharmony_ci return -EINVAL; 388462306a36Sopenharmony_ci} 388562306a36Sopenharmony_ci 388662306a36Sopenharmony_cilpfc_vport_param_store(devloss_tmo) 388762306a36Sopenharmony_cistatic DEVICE_ATTR_RW(lpfc_devloss_tmo); 388862306a36Sopenharmony_ci 388962306a36Sopenharmony_ci/* 389062306a36Sopenharmony_ci * lpfc_suppress_rsp: Enable suppress rsp feature is firmware supports it 389162306a36Sopenharmony_ci * lpfc_suppress_rsp = 0 Disable 389262306a36Sopenharmony_ci * lpfc_suppress_rsp = 1 Enable (default) 389362306a36Sopenharmony_ci * 389462306a36Sopenharmony_ci */ 389562306a36Sopenharmony_ciLPFC_ATTR_R(suppress_rsp, 1, 0, 1, 389662306a36Sopenharmony_ci "Enable suppress rsp feature is firmware supports it"); 389762306a36Sopenharmony_ci 389862306a36Sopenharmony_ci/* 389962306a36Sopenharmony_ci * lpfc_nvmet_mrq: Specify number of RQ pairs for processing NVMET cmds 390062306a36Sopenharmony_ci * lpfc_nvmet_mrq = 0 driver will calcualte optimal number of RQ pairs 390162306a36Sopenharmony_ci * lpfc_nvmet_mrq = 1 use a single RQ pair 390262306a36Sopenharmony_ci * lpfc_nvmet_mrq >= 2 use specified RQ pairs for MRQ 390362306a36Sopenharmony_ci * 390462306a36Sopenharmony_ci */ 390562306a36Sopenharmony_ciLPFC_ATTR_R(nvmet_mrq, 390662306a36Sopenharmony_ci LPFC_NVMET_MRQ_AUTO, LPFC_NVMET_MRQ_AUTO, LPFC_NVMET_MRQ_MAX, 390762306a36Sopenharmony_ci "Specify number of RQ pairs for processing NVMET cmds"); 390862306a36Sopenharmony_ci 390962306a36Sopenharmony_ci/* 391062306a36Sopenharmony_ci * lpfc_nvmet_mrq_post: Specify number of RQ buffer to initially post 391162306a36Sopenharmony_ci * to each NVMET RQ. Range 64 to 2048, default is 512. 391262306a36Sopenharmony_ci */ 391362306a36Sopenharmony_ciLPFC_ATTR_R(nvmet_mrq_post, 391462306a36Sopenharmony_ci LPFC_NVMET_RQE_DEF_POST, LPFC_NVMET_RQE_MIN_POST, 391562306a36Sopenharmony_ci LPFC_NVMET_RQE_DEF_COUNT, 391662306a36Sopenharmony_ci "Specify number of RQ buffers to initially post"); 391762306a36Sopenharmony_ci 391862306a36Sopenharmony_ci/* 391962306a36Sopenharmony_ci * lpfc_enable_fc4_type: Defines what FC4 types are supported. 392062306a36Sopenharmony_ci * Supported Values: 1 - register just FCP 392162306a36Sopenharmony_ci * 3 - register both FCP and NVME 392262306a36Sopenharmony_ci * Supported values are [1,3]. Default value is 3 392362306a36Sopenharmony_ci */ 392462306a36Sopenharmony_ciLPFC_ATTR_R(enable_fc4_type, LPFC_DEF_ENBL_FC4_TYPE, 392562306a36Sopenharmony_ci LPFC_ENABLE_FCP, LPFC_MAX_ENBL_FC4_TYPE, 392662306a36Sopenharmony_ci "Enable FC4 Protocol support - FCP / NVME"); 392762306a36Sopenharmony_ci 392862306a36Sopenharmony_ci/* 392962306a36Sopenharmony_ci# lpfc_log_verbose: Only turn this flag on if you are willing to risk being 393062306a36Sopenharmony_ci# deluged with LOTS of information. 393162306a36Sopenharmony_ci# You can set a bit mask to record specific types of verbose messages: 393262306a36Sopenharmony_ci# See lpfc_logmsh.h for definitions. 393362306a36Sopenharmony_ci*/ 393462306a36Sopenharmony_ciLPFC_VPORT_ATTR_HEX_RW(log_verbose, 0x0, 0x0, 0xffffffff, 393562306a36Sopenharmony_ci "Verbose logging bit-mask"); 393662306a36Sopenharmony_ci 393762306a36Sopenharmony_ci/* 393862306a36Sopenharmony_ci# lpfc_enable_da_id: This turns on the DA_ID CT command that deregisters 393962306a36Sopenharmony_ci# objects that have been registered with the nameserver after login. 394062306a36Sopenharmony_ci*/ 394162306a36Sopenharmony_ciLPFC_VPORT_ATTR_R(enable_da_id, 1, 0, 1, 394262306a36Sopenharmony_ci "Deregister nameserver objects before LOGO"); 394362306a36Sopenharmony_ci 394462306a36Sopenharmony_ci/* 394562306a36Sopenharmony_ci# lun_queue_depth: This parameter is used to limit the number of outstanding 394662306a36Sopenharmony_ci# commands per FCP LUN. 394762306a36Sopenharmony_ci*/ 394862306a36Sopenharmony_ciLPFC_VPORT_ATTR_R(lun_queue_depth, 64, 1, 512, 394962306a36Sopenharmony_ci "Max number of FCP commands we can queue to a specific LUN"); 395062306a36Sopenharmony_ci 395162306a36Sopenharmony_ci/* 395262306a36Sopenharmony_ci# tgt_queue_depth: This parameter is used to limit the number of outstanding 395362306a36Sopenharmony_ci# commands per target port. Value range is [10,65535]. Default value is 65535. 395462306a36Sopenharmony_ci*/ 395562306a36Sopenharmony_cistatic uint lpfc_tgt_queue_depth = LPFC_MAX_TGT_QDEPTH; 395662306a36Sopenharmony_cimodule_param(lpfc_tgt_queue_depth, uint, 0444); 395762306a36Sopenharmony_ciMODULE_PARM_DESC(lpfc_tgt_queue_depth, "Set max Target queue depth"); 395862306a36Sopenharmony_cilpfc_vport_param_show(tgt_queue_depth); 395962306a36Sopenharmony_cilpfc_vport_param_init(tgt_queue_depth, LPFC_MAX_TGT_QDEPTH, 396062306a36Sopenharmony_ci LPFC_MIN_TGT_QDEPTH, LPFC_MAX_TGT_QDEPTH); 396162306a36Sopenharmony_ci 396262306a36Sopenharmony_ci/** 396362306a36Sopenharmony_ci * lpfc_tgt_queue_depth_set: Sets an attribute value. 396462306a36Sopenharmony_ci * @vport: lpfc vport structure pointer. 396562306a36Sopenharmony_ci * @val: integer attribute value. 396662306a36Sopenharmony_ci * 396762306a36Sopenharmony_ci * Description: Sets the parameter to the new value. 396862306a36Sopenharmony_ci * 396962306a36Sopenharmony_ci * Returns: 397062306a36Sopenharmony_ci * zero on success 397162306a36Sopenharmony_ci * -EINVAL if val is invalid 397262306a36Sopenharmony_ci */ 397362306a36Sopenharmony_cistatic int 397462306a36Sopenharmony_cilpfc_tgt_queue_depth_set(struct lpfc_vport *vport, uint val) 397562306a36Sopenharmony_ci{ 397662306a36Sopenharmony_ci struct Scsi_Host *shost = lpfc_shost_from_vport(vport); 397762306a36Sopenharmony_ci struct lpfc_nodelist *ndlp; 397862306a36Sopenharmony_ci 397962306a36Sopenharmony_ci if (!lpfc_rangecheck(val, LPFC_MIN_TGT_QDEPTH, LPFC_MAX_TGT_QDEPTH)) 398062306a36Sopenharmony_ci return -EINVAL; 398162306a36Sopenharmony_ci 398262306a36Sopenharmony_ci if (val == vport->cfg_tgt_queue_depth) 398362306a36Sopenharmony_ci return 0; 398462306a36Sopenharmony_ci 398562306a36Sopenharmony_ci spin_lock_irq(shost->host_lock); 398662306a36Sopenharmony_ci vport->cfg_tgt_queue_depth = val; 398762306a36Sopenharmony_ci 398862306a36Sopenharmony_ci /* Next loop thru nodelist and change cmd_qdepth */ 398962306a36Sopenharmony_ci list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) 399062306a36Sopenharmony_ci ndlp->cmd_qdepth = vport->cfg_tgt_queue_depth; 399162306a36Sopenharmony_ci 399262306a36Sopenharmony_ci spin_unlock_irq(shost->host_lock); 399362306a36Sopenharmony_ci return 0; 399462306a36Sopenharmony_ci} 399562306a36Sopenharmony_ci 399662306a36Sopenharmony_cilpfc_vport_param_store(tgt_queue_depth); 399762306a36Sopenharmony_cistatic DEVICE_ATTR_RW(lpfc_tgt_queue_depth); 399862306a36Sopenharmony_ci 399962306a36Sopenharmony_ci/* 400062306a36Sopenharmony_ci# hba_queue_depth: This parameter is used to limit the number of outstanding 400162306a36Sopenharmony_ci# commands per lpfc HBA. Value range is [32,8192]. If this parameter 400262306a36Sopenharmony_ci# value is greater than the maximum number of exchanges supported by the HBA, 400362306a36Sopenharmony_ci# then maximum number of exchanges supported by the HBA is used to determine 400462306a36Sopenharmony_ci# the hba_queue_depth. 400562306a36Sopenharmony_ci*/ 400662306a36Sopenharmony_ciLPFC_ATTR_R(hba_queue_depth, 8192, 32, 8192, 400762306a36Sopenharmony_ci "Max number of FCP commands we can queue to a lpfc HBA"); 400862306a36Sopenharmony_ci 400962306a36Sopenharmony_ci/* 401062306a36Sopenharmony_ci# peer_port_login: This parameter allows/prevents logins 401162306a36Sopenharmony_ci# between peer ports hosted on the same physical port. 401262306a36Sopenharmony_ci# When this parameter is set 0 peer ports of same physical port 401362306a36Sopenharmony_ci# are not allowed to login to each other. 401462306a36Sopenharmony_ci# When this parameter is set 1 peer ports of same physical port 401562306a36Sopenharmony_ci# are allowed to login to each other. 401662306a36Sopenharmony_ci# Default value of this parameter is 0. 401762306a36Sopenharmony_ci*/ 401862306a36Sopenharmony_ciLPFC_VPORT_ATTR_R(peer_port_login, 0, 0, 1, 401962306a36Sopenharmony_ci "Allow peer ports on the same physical port to login to each " 402062306a36Sopenharmony_ci "other."); 402162306a36Sopenharmony_ci 402262306a36Sopenharmony_ci/* 402362306a36Sopenharmony_ci# restrict_login: This parameter allows/prevents logins 402462306a36Sopenharmony_ci# between Virtual Ports and remote initiators. 402562306a36Sopenharmony_ci# When this parameter is not set (0) Virtual Ports will accept PLOGIs from 402662306a36Sopenharmony_ci# other initiators and will attempt to PLOGI all remote ports. 402762306a36Sopenharmony_ci# When this parameter is set (1) Virtual Ports will reject PLOGIs from 402862306a36Sopenharmony_ci# remote ports and will not attempt to PLOGI to other initiators. 402962306a36Sopenharmony_ci# This parameter does not restrict to the physical port. 403062306a36Sopenharmony_ci# This parameter does not restrict logins to Fabric resident remote ports. 403162306a36Sopenharmony_ci# Default value of this parameter is 1. 403262306a36Sopenharmony_ci*/ 403362306a36Sopenharmony_cistatic int lpfc_restrict_login = 1; 403462306a36Sopenharmony_cimodule_param(lpfc_restrict_login, int, S_IRUGO); 403562306a36Sopenharmony_ciMODULE_PARM_DESC(lpfc_restrict_login, 403662306a36Sopenharmony_ci "Restrict virtual ports login to remote initiators."); 403762306a36Sopenharmony_cilpfc_vport_param_show(restrict_login); 403862306a36Sopenharmony_ci 403962306a36Sopenharmony_ci/** 404062306a36Sopenharmony_ci * lpfc_restrict_login_init - Set the vport restrict login flag 404162306a36Sopenharmony_ci * @vport: lpfc vport structure pointer. 404262306a36Sopenharmony_ci * @val: contains the restrict login value. 404362306a36Sopenharmony_ci * 404462306a36Sopenharmony_ci * Description: 404562306a36Sopenharmony_ci * If val is not in a valid range then log a kernel error message and set 404662306a36Sopenharmony_ci * the vport restrict login to one. 404762306a36Sopenharmony_ci * If the port type is physical clear the restrict login flag and return. 404862306a36Sopenharmony_ci * Else set the restrict login flag to val. 404962306a36Sopenharmony_ci * 405062306a36Sopenharmony_ci * Returns: 405162306a36Sopenharmony_ci * zero if val is in range 405262306a36Sopenharmony_ci * -EINVAL val out of range 405362306a36Sopenharmony_ci **/ 405462306a36Sopenharmony_cistatic int 405562306a36Sopenharmony_cilpfc_restrict_login_init(struct lpfc_vport *vport, int val) 405662306a36Sopenharmony_ci{ 405762306a36Sopenharmony_ci if (val < 0 || val > 1) { 405862306a36Sopenharmony_ci lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, 405962306a36Sopenharmony_ci "0422 lpfc_restrict_login attribute cannot " 406062306a36Sopenharmony_ci "be set to %d, allowed range is [0, 1]\n", 406162306a36Sopenharmony_ci val); 406262306a36Sopenharmony_ci vport->cfg_restrict_login = 1; 406362306a36Sopenharmony_ci return -EINVAL; 406462306a36Sopenharmony_ci } 406562306a36Sopenharmony_ci if (vport->port_type == LPFC_PHYSICAL_PORT) { 406662306a36Sopenharmony_ci vport->cfg_restrict_login = 0; 406762306a36Sopenharmony_ci return 0; 406862306a36Sopenharmony_ci } 406962306a36Sopenharmony_ci vport->cfg_restrict_login = val; 407062306a36Sopenharmony_ci return 0; 407162306a36Sopenharmony_ci} 407262306a36Sopenharmony_ci 407362306a36Sopenharmony_ci/** 407462306a36Sopenharmony_ci * lpfc_restrict_login_set - Set the vport restrict login flag 407562306a36Sopenharmony_ci * @vport: lpfc vport structure pointer. 407662306a36Sopenharmony_ci * @val: contains the restrict login value. 407762306a36Sopenharmony_ci * 407862306a36Sopenharmony_ci * Description: 407962306a36Sopenharmony_ci * If val is not in a valid range then log a kernel error message and set 408062306a36Sopenharmony_ci * the vport restrict login to one. 408162306a36Sopenharmony_ci * If the port type is physical and the val is not zero log a kernel 408262306a36Sopenharmony_ci * error message, clear the restrict login flag and return zero. 408362306a36Sopenharmony_ci * Else set the restrict login flag to val. 408462306a36Sopenharmony_ci * 408562306a36Sopenharmony_ci * Returns: 408662306a36Sopenharmony_ci * zero if val is in range 408762306a36Sopenharmony_ci * -EINVAL val out of range 408862306a36Sopenharmony_ci **/ 408962306a36Sopenharmony_cistatic int 409062306a36Sopenharmony_cilpfc_restrict_login_set(struct lpfc_vport *vport, int val) 409162306a36Sopenharmony_ci{ 409262306a36Sopenharmony_ci if (val < 0 || val > 1) { 409362306a36Sopenharmony_ci lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, 409462306a36Sopenharmony_ci "0425 lpfc_restrict_login attribute cannot " 409562306a36Sopenharmony_ci "be set to %d, allowed range is [0, 1]\n", 409662306a36Sopenharmony_ci val); 409762306a36Sopenharmony_ci vport->cfg_restrict_login = 1; 409862306a36Sopenharmony_ci return -EINVAL; 409962306a36Sopenharmony_ci } 410062306a36Sopenharmony_ci if (vport->port_type == LPFC_PHYSICAL_PORT && val != 0) { 410162306a36Sopenharmony_ci lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, 410262306a36Sopenharmony_ci "0468 lpfc_restrict_login must be 0 for " 410362306a36Sopenharmony_ci "Physical ports.\n"); 410462306a36Sopenharmony_ci vport->cfg_restrict_login = 0; 410562306a36Sopenharmony_ci return 0; 410662306a36Sopenharmony_ci } 410762306a36Sopenharmony_ci vport->cfg_restrict_login = val; 410862306a36Sopenharmony_ci return 0; 410962306a36Sopenharmony_ci} 411062306a36Sopenharmony_cilpfc_vport_param_store(restrict_login); 411162306a36Sopenharmony_cistatic DEVICE_ATTR_RW(lpfc_restrict_login); 411262306a36Sopenharmony_ci 411362306a36Sopenharmony_ci/* 411462306a36Sopenharmony_ci# Some disk devices have a "select ID" or "select Target" capability. 411562306a36Sopenharmony_ci# From a protocol standpoint "select ID" usually means select the 411662306a36Sopenharmony_ci# Fibre channel "ALPA". In the FC-AL Profile there is an "informative 411762306a36Sopenharmony_ci# annex" which contains a table that maps a "select ID" (a number 411862306a36Sopenharmony_ci# between 0 and 7F) to an ALPA. By default, for compatibility with 411962306a36Sopenharmony_ci# older drivers, the lpfc driver scans this table from low ALPA to high 412062306a36Sopenharmony_ci# ALPA. 412162306a36Sopenharmony_ci# 412262306a36Sopenharmony_ci# Turning on the scan-down variable (on = 1, off = 0) will 412362306a36Sopenharmony_ci# cause the lpfc driver to use an inverted table, effectively 412462306a36Sopenharmony_ci# scanning ALPAs from high to low. Value range is [0,1]. Default value is 1. 412562306a36Sopenharmony_ci# 412662306a36Sopenharmony_ci# (Note: This "select ID" functionality is a LOOP ONLY characteristic 412762306a36Sopenharmony_ci# and will not work across a fabric. Also this parameter will take 412862306a36Sopenharmony_ci# effect only in the case when ALPA map is not available.) 412962306a36Sopenharmony_ci*/ 413062306a36Sopenharmony_ciLPFC_VPORT_ATTR_R(scan_down, 1, 0, 1, 413162306a36Sopenharmony_ci "Start scanning for devices from highest ALPA to lowest"); 413262306a36Sopenharmony_ci 413362306a36Sopenharmony_ci/* 413462306a36Sopenharmony_ci# lpfc_topology: link topology for init link 413562306a36Sopenharmony_ci# 0x0 = attempt loop mode then point-to-point 413662306a36Sopenharmony_ci# 0x01 = internal loopback mode 413762306a36Sopenharmony_ci# 0x02 = attempt point-to-point mode only 413862306a36Sopenharmony_ci# 0x04 = attempt loop mode only 413962306a36Sopenharmony_ci# 0x06 = attempt point-to-point mode then loop 414062306a36Sopenharmony_ci# Set point-to-point mode if you want to run as an N_Port. 414162306a36Sopenharmony_ci# Set loop mode if you want to run as an NL_Port. Value range is [0,0x6]. 414262306a36Sopenharmony_ci# Default value is 0. 414362306a36Sopenharmony_ci*/ 414462306a36Sopenharmony_ciLPFC_ATTR(topology, 0, 0, 6, 414562306a36Sopenharmony_ci "Select Fibre Channel topology"); 414662306a36Sopenharmony_ci 414762306a36Sopenharmony_ci/** 414862306a36Sopenharmony_ci * lpfc_topology_store - Set the adapters topology field 414962306a36Sopenharmony_ci * @dev: class device that is converted into a scsi_host. 415062306a36Sopenharmony_ci * @attr:device attribute, not used. 415162306a36Sopenharmony_ci * @buf: buffer for passing information. 415262306a36Sopenharmony_ci * @count: size of the data buffer. 415362306a36Sopenharmony_ci * 415462306a36Sopenharmony_ci * Description: 415562306a36Sopenharmony_ci * If val is in a valid range then set the adapter's topology field and 415662306a36Sopenharmony_ci * issue a lip; if the lip fails reset the topology to the old value. 415762306a36Sopenharmony_ci * 415862306a36Sopenharmony_ci * If the value is not in range log a kernel error message and return an error. 415962306a36Sopenharmony_ci * 416062306a36Sopenharmony_ci * Returns: 416162306a36Sopenharmony_ci * zero if val is in range and lip okay 416262306a36Sopenharmony_ci * non-zero return value from lpfc_issue_lip() 416362306a36Sopenharmony_ci * -EINVAL val out of range 416462306a36Sopenharmony_ci **/ 416562306a36Sopenharmony_cistatic ssize_t 416662306a36Sopenharmony_cilpfc_topology_store(struct device *dev, struct device_attribute *attr, 416762306a36Sopenharmony_ci const char *buf, size_t count) 416862306a36Sopenharmony_ci{ 416962306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 417062306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 417162306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 417262306a36Sopenharmony_ci int val = 0; 417362306a36Sopenharmony_ci int nolip = 0; 417462306a36Sopenharmony_ci const char *val_buf = buf; 417562306a36Sopenharmony_ci int err; 417662306a36Sopenharmony_ci uint32_t prev_val; 417762306a36Sopenharmony_ci u8 sli_family, if_type; 417862306a36Sopenharmony_ci 417962306a36Sopenharmony_ci if (!strncmp(buf, "nolip ", strlen("nolip "))) { 418062306a36Sopenharmony_ci nolip = 1; 418162306a36Sopenharmony_ci val_buf = &buf[strlen("nolip ")]; 418262306a36Sopenharmony_ci } 418362306a36Sopenharmony_ci 418462306a36Sopenharmony_ci if (!isdigit(val_buf[0])) 418562306a36Sopenharmony_ci return -EINVAL; 418662306a36Sopenharmony_ci if (sscanf(val_buf, "%i", &val) != 1) 418762306a36Sopenharmony_ci return -EINVAL; 418862306a36Sopenharmony_ci 418962306a36Sopenharmony_ci if (val >= 0 && val <= 6) { 419062306a36Sopenharmony_ci prev_val = phba->cfg_topology; 419162306a36Sopenharmony_ci if (phba->cfg_link_speed == LPFC_USER_LINK_SPEED_16G && 419262306a36Sopenharmony_ci val == 4) { 419362306a36Sopenharmony_ci lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, 419462306a36Sopenharmony_ci "3113 Loop mode not supported at speed %d\n", 419562306a36Sopenharmony_ci val); 419662306a36Sopenharmony_ci return -EINVAL; 419762306a36Sopenharmony_ci } 419862306a36Sopenharmony_ci /* 419962306a36Sopenharmony_ci * The 'topology' is not a configurable parameter if : 420062306a36Sopenharmony_ci * - persistent topology enabled 420162306a36Sopenharmony_ci * - ASIC_GEN_NUM >= 0xC, with no private loop support 420262306a36Sopenharmony_ci */ 420362306a36Sopenharmony_ci sli_family = bf_get(lpfc_sli_intf_sli_family, 420462306a36Sopenharmony_ci &phba->sli4_hba.sli_intf); 420562306a36Sopenharmony_ci if_type = bf_get(lpfc_sli_intf_if_type, 420662306a36Sopenharmony_ci &phba->sli4_hba.sli_intf); 420762306a36Sopenharmony_ci if ((phba->hba_flag & HBA_PERSISTENT_TOPO || 420862306a36Sopenharmony_ci (!phba->sli4_hba.pc_sli4_params.pls && 420962306a36Sopenharmony_ci (sli_family == LPFC_SLI_INTF_FAMILY_G6 || 421062306a36Sopenharmony_ci if_type == LPFC_SLI_INTF_IF_TYPE_6))) && 421162306a36Sopenharmony_ci val == 4) { 421262306a36Sopenharmony_ci lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, 421362306a36Sopenharmony_ci "3114 Loop mode not supported\n"); 421462306a36Sopenharmony_ci return -EINVAL; 421562306a36Sopenharmony_ci } 421662306a36Sopenharmony_ci phba->cfg_topology = val; 421762306a36Sopenharmony_ci if (nolip) 421862306a36Sopenharmony_ci return strlen(buf); 421962306a36Sopenharmony_ci 422062306a36Sopenharmony_ci lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, 422162306a36Sopenharmony_ci "3054 lpfc_topology changed from %d to %d\n", 422262306a36Sopenharmony_ci prev_val, val); 422362306a36Sopenharmony_ci if (prev_val != val && phba->sli_rev == LPFC_SLI_REV4) 422462306a36Sopenharmony_ci phba->fc_topology_changed = 1; 422562306a36Sopenharmony_ci err = lpfc_issue_lip(lpfc_shost_from_vport(phba->pport)); 422662306a36Sopenharmony_ci if (err) { 422762306a36Sopenharmony_ci phba->cfg_topology = prev_val; 422862306a36Sopenharmony_ci return -EINVAL; 422962306a36Sopenharmony_ci } else 423062306a36Sopenharmony_ci return strlen(buf); 423162306a36Sopenharmony_ci } 423262306a36Sopenharmony_ci lpfc_printf_log(phba, KERN_ERR, LOG_INIT, 423362306a36Sopenharmony_ci "%d:0467 lpfc_topology attribute cannot be set to %d, " 423462306a36Sopenharmony_ci "allowed range is [0, 6]\n", 423562306a36Sopenharmony_ci phba->brd_no, val); 423662306a36Sopenharmony_ci return -EINVAL; 423762306a36Sopenharmony_ci} 423862306a36Sopenharmony_ci 423962306a36Sopenharmony_cilpfc_param_show(topology) 424062306a36Sopenharmony_cistatic DEVICE_ATTR_RW(lpfc_topology); 424162306a36Sopenharmony_ci 424262306a36Sopenharmony_ci/** 424362306a36Sopenharmony_ci * lpfc_static_vport_show: Read callback function for 424462306a36Sopenharmony_ci * lpfc_static_vport sysfs file. 424562306a36Sopenharmony_ci * @dev: Pointer to class device object. 424662306a36Sopenharmony_ci * @attr: device attribute structure. 424762306a36Sopenharmony_ci * @buf: Data buffer. 424862306a36Sopenharmony_ci * 424962306a36Sopenharmony_ci * This function is the read call back function for 425062306a36Sopenharmony_ci * lpfc_static_vport sysfs file. The lpfc_static_vport 425162306a36Sopenharmony_ci * sysfs file report the mageability of the vport. 425262306a36Sopenharmony_ci **/ 425362306a36Sopenharmony_cistatic ssize_t 425462306a36Sopenharmony_cilpfc_static_vport_show(struct device *dev, struct device_attribute *attr, 425562306a36Sopenharmony_ci char *buf) 425662306a36Sopenharmony_ci{ 425762306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 425862306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 425962306a36Sopenharmony_ci if (vport->vport_flag & STATIC_VPORT) 426062306a36Sopenharmony_ci sprintf(buf, "1\n"); 426162306a36Sopenharmony_ci else 426262306a36Sopenharmony_ci sprintf(buf, "0\n"); 426362306a36Sopenharmony_ci 426462306a36Sopenharmony_ci return strlen(buf); 426562306a36Sopenharmony_ci} 426662306a36Sopenharmony_ci 426762306a36Sopenharmony_ci/* 426862306a36Sopenharmony_ci * Sysfs attribute to control the statistical data collection. 426962306a36Sopenharmony_ci */ 427062306a36Sopenharmony_cistatic DEVICE_ATTR_RO(lpfc_static_vport); 427162306a36Sopenharmony_ci 427262306a36Sopenharmony_ci/* 427362306a36Sopenharmony_ci# lpfc_link_speed: Link speed selection for initializing the Fibre Channel 427462306a36Sopenharmony_ci# connection. 427562306a36Sopenharmony_ci# Value range is [0,16]. Default value is 0. 427662306a36Sopenharmony_ci*/ 427762306a36Sopenharmony_ci/** 427862306a36Sopenharmony_ci * lpfc_link_speed_store - Set the adapters link speed 427962306a36Sopenharmony_ci * @dev: Pointer to class device. 428062306a36Sopenharmony_ci * @attr: Unused. 428162306a36Sopenharmony_ci * @buf: Data buffer. 428262306a36Sopenharmony_ci * @count: Size of the data buffer. 428362306a36Sopenharmony_ci * 428462306a36Sopenharmony_ci * Description: 428562306a36Sopenharmony_ci * If val is in a valid range then set the adapter's link speed field and 428662306a36Sopenharmony_ci * issue a lip; if the lip fails reset the link speed to the old value. 428762306a36Sopenharmony_ci * 428862306a36Sopenharmony_ci * Notes: 428962306a36Sopenharmony_ci * If the value is not in range log a kernel error message and return an error. 429062306a36Sopenharmony_ci * 429162306a36Sopenharmony_ci * Returns: 429262306a36Sopenharmony_ci * zero if val is in range and lip okay. 429362306a36Sopenharmony_ci * non-zero return value from lpfc_issue_lip() 429462306a36Sopenharmony_ci * -EINVAL val out of range 429562306a36Sopenharmony_ci **/ 429662306a36Sopenharmony_cistatic ssize_t 429762306a36Sopenharmony_cilpfc_link_speed_store(struct device *dev, struct device_attribute *attr, 429862306a36Sopenharmony_ci const char *buf, size_t count) 429962306a36Sopenharmony_ci{ 430062306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 430162306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 430262306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 430362306a36Sopenharmony_ci int val = LPFC_USER_LINK_SPEED_AUTO; 430462306a36Sopenharmony_ci int nolip = 0; 430562306a36Sopenharmony_ci const char *val_buf = buf; 430662306a36Sopenharmony_ci int err; 430762306a36Sopenharmony_ci uint32_t prev_val, if_type; 430862306a36Sopenharmony_ci 430962306a36Sopenharmony_ci if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf); 431062306a36Sopenharmony_ci if (if_type >= LPFC_SLI_INTF_IF_TYPE_2 && 431162306a36Sopenharmony_ci phba->hba_flag & HBA_FORCED_LINK_SPEED) 431262306a36Sopenharmony_ci return -EPERM; 431362306a36Sopenharmony_ci 431462306a36Sopenharmony_ci if (!strncmp(buf, "nolip ", strlen("nolip "))) { 431562306a36Sopenharmony_ci nolip = 1; 431662306a36Sopenharmony_ci val_buf = &buf[strlen("nolip ")]; 431762306a36Sopenharmony_ci } 431862306a36Sopenharmony_ci 431962306a36Sopenharmony_ci if (!isdigit(val_buf[0])) 432062306a36Sopenharmony_ci return -EINVAL; 432162306a36Sopenharmony_ci if (sscanf(val_buf, "%i", &val) != 1) 432262306a36Sopenharmony_ci return -EINVAL; 432362306a36Sopenharmony_ci 432462306a36Sopenharmony_ci lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, 432562306a36Sopenharmony_ci "3055 lpfc_link_speed changed from %d to %d %s\n", 432662306a36Sopenharmony_ci phba->cfg_link_speed, val, nolip ? "(nolip)" : "(lip)"); 432762306a36Sopenharmony_ci 432862306a36Sopenharmony_ci if (((val == LPFC_USER_LINK_SPEED_1G) && !(phba->lmt & LMT_1Gb)) || 432962306a36Sopenharmony_ci ((val == LPFC_USER_LINK_SPEED_2G) && !(phba->lmt & LMT_2Gb)) || 433062306a36Sopenharmony_ci ((val == LPFC_USER_LINK_SPEED_4G) && !(phba->lmt & LMT_4Gb)) || 433162306a36Sopenharmony_ci ((val == LPFC_USER_LINK_SPEED_8G) && !(phba->lmt & LMT_8Gb)) || 433262306a36Sopenharmony_ci ((val == LPFC_USER_LINK_SPEED_10G) && !(phba->lmt & LMT_10Gb)) || 433362306a36Sopenharmony_ci ((val == LPFC_USER_LINK_SPEED_16G) && !(phba->lmt & LMT_16Gb)) || 433462306a36Sopenharmony_ci ((val == LPFC_USER_LINK_SPEED_32G) && !(phba->lmt & LMT_32Gb)) || 433562306a36Sopenharmony_ci ((val == LPFC_USER_LINK_SPEED_64G) && !(phba->lmt & LMT_64Gb))) { 433662306a36Sopenharmony_ci lpfc_printf_log(phba, KERN_ERR, LOG_INIT, 433762306a36Sopenharmony_ci "2879 lpfc_link_speed attribute cannot be set " 433862306a36Sopenharmony_ci "to %d. Speed is not supported by this port.\n", 433962306a36Sopenharmony_ci val); 434062306a36Sopenharmony_ci return -EINVAL; 434162306a36Sopenharmony_ci } 434262306a36Sopenharmony_ci if (val >= LPFC_USER_LINK_SPEED_16G && 434362306a36Sopenharmony_ci phba->fc_topology == LPFC_TOPOLOGY_LOOP) { 434462306a36Sopenharmony_ci lpfc_printf_log(phba, KERN_ERR, LOG_INIT, 434562306a36Sopenharmony_ci "3112 lpfc_link_speed attribute cannot be set " 434662306a36Sopenharmony_ci "to %d. Speed is not supported in loop mode.\n", 434762306a36Sopenharmony_ci val); 434862306a36Sopenharmony_ci return -EINVAL; 434962306a36Sopenharmony_ci } 435062306a36Sopenharmony_ci 435162306a36Sopenharmony_ci switch (val) { 435262306a36Sopenharmony_ci case LPFC_USER_LINK_SPEED_AUTO: 435362306a36Sopenharmony_ci case LPFC_USER_LINK_SPEED_1G: 435462306a36Sopenharmony_ci case LPFC_USER_LINK_SPEED_2G: 435562306a36Sopenharmony_ci case LPFC_USER_LINK_SPEED_4G: 435662306a36Sopenharmony_ci case LPFC_USER_LINK_SPEED_8G: 435762306a36Sopenharmony_ci case LPFC_USER_LINK_SPEED_16G: 435862306a36Sopenharmony_ci case LPFC_USER_LINK_SPEED_32G: 435962306a36Sopenharmony_ci case LPFC_USER_LINK_SPEED_64G: 436062306a36Sopenharmony_ci prev_val = phba->cfg_link_speed; 436162306a36Sopenharmony_ci phba->cfg_link_speed = val; 436262306a36Sopenharmony_ci if (nolip) 436362306a36Sopenharmony_ci return strlen(buf); 436462306a36Sopenharmony_ci 436562306a36Sopenharmony_ci err = lpfc_issue_lip(lpfc_shost_from_vport(phba->pport)); 436662306a36Sopenharmony_ci if (err) { 436762306a36Sopenharmony_ci phba->cfg_link_speed = prev_val; 436862306a36Sopenharmony_ci return -EINVAL; 436962306a36Sopenharmony_ci } 437062306a36Sopenharmony_ci return strlen(buf); 437162306a36Sopenharmony_ci default: 437262306a36Sopenharmony_ci break; 437362306a36Sopenharmony_ci } 437462306a36Sopenharmony_ci 437562306a36Sopenharmony_ci lpfc_printf_log(phba, KERN_ERR, LOG_INIT, 437662306a36Sopenharmony_ci "0469 lpfc_link_speed attribute cannot be set to %d, " 437762306a36Sopenharmony_ci "allowed values are [%s]\n", 437862306a36Sopenharmony_ci val, LPFC_LINK_SPEED_STRING); 437962306a36Sopenharmony_ci return -EINVAL; 438062306a36Sopenharmony_ci 438162306a36Sopenharmony_ci} 438262306a36Sopenharmony_ci 438362306a36Sopenharmony_cistatic int lpfc_link_speed = 0; 438462306a36Sopenharmony_cimodule_param(lpfc_link_speed, int, S_IRUGO); 438562306a36Sopenharmony_ciMODULE_PARM_DESC(lpfc_link_speed, "Select link speed"); 438662306a36Sopenharmony_cilpfc_param_show(link_speed) 438762306a36Sopenharmony_ci 438862306a36Sopenharmony_ci/** 438962306a36Sopenharmony_ci * lpfc_link_speed_init - Set the adapters link speed 439062306a36Sopenharmony_ci * @phba: lpfc_hba pointer. 439162306a36Sopenharmony_ci * @val: link speed value. 439262306a36Sopenharmony_ci * 439362306a36Sopenharmony_ci * Description: 439462306a36Sopenharmony_ci * If val is in a valid range then set the adapter's link speed field. 439562306a36Sopenharmony_ci * 439662306a36Sopenharmony_ci * Notes: 439762306a36Sopenharmony_ci * If the value is not in range log a kernel error message, clear the link 439862306a36Sopenharmony_ci * speed and return an error. 439962306a36Sopenharmony_ci * 440062306a36Sopenharmony_ci * Returns: 440162306a36Sopenharmony_ci * zero if val saved. 440262306a36Sopenharmony_ci * -EINVAL val out of range 440362306a36Sopenharmony_ci **/ 440462306a36Sopenharmony_cistatic int 440562306a36Sopenharmony_cilpfc_link_speed_init(struct lpfc_hba *phba, int val) 440662306a36Sopenharmony_ci{ 440762306a36Sopenharmony_ci if (val >= LPFC_USER_LINK_SPEED_16G && phba->cfg_topology == 4) { 440862306a36Sopenharmony_ci lpfc_printf_log(phba, KERN_ERR, LOG_INIT, 440962306a36Sopenharmony_ci "3111 lpfc_link_speed of %d cannot " 441062306a36Sopenharmony_ci "support loop mode, setting topology to default.\n", 441162306a36Sopenharmony_ci val); 441262306a36Sopenharmony_ci phba->cfg_topology = 0; 441362306a36Sopenharmony_ci } 441462306a36Sopenharmony_ci 441562306a36Sopenharmony_ci switch (val) { 441662306a36Sopenharmony_ci case LPFC_USER_LINK_SPEED_AUTO: 441762306a36Sopenharmony_ci case LPFC_USER_LINK_SPEED_1G: 441862306a36Sopenharmony_ci case LPFC_USER_LINK_SPEED_2G: 441962306a36Sopenharmony_ci case LPFC_USER_LINK_SPEED_4G: 442062306a36Sopenharmony_ci case LPFC_USER_LINK_SPEED_8G: 442162306a36Sopenharmony_ci case LPFC_USER_LINK_SPEED_16G: 442262306a36Sopenharmony_ci case LPFC_USER_LINK_SPEED_32G: 442362306a36Sopenharmony_ci case LPFC_USER_LINK_SPEED_64G: 442462306a36Sopenharmony_ci phba->cfg_link_speed = val; 442562306a36Sopenharmony_ci return 0; 442662306a36Sopenharmony_ci default: 442762306a36Sopenharmony_ci lpfc_printf_log(phba, KERN_ERR, LOG_INIT, 442862306a36Sopenharmony_ci "0405 lpfc_link_speed attribute cannot " 442962306a36Sopenharmony_ci "be set to %d, allowed values are " 443062306a36Sopenharmony_ci "["LPFC_LINK_SPEED_STRING"]\n", val); 443162306a36Sopenharmony_ci phba->cfg_link_speed = LPFC_USER_LINK_SPEED_AUTO; 443262306a36Sopenharmony_ci return -EINVAL; 443362306a36Sopenharmony_ci } 443462306a36Sopenharmony_ci} 443562306a36Sopenharmony_ci 443662306a36Sopenharmony_cistatic DEVICE_ATTR_RW(lpfc_link_speed); 443762306a36Sopenharmony_ci 443862306a36Sopenharmony_ci/* 443962306a36Sopenharmony_ci# lpfc_aer_support: Support PCIe device Advanced Error Reporting (AER) 444062306a36Sopenharmony_ci# 1 = aer supported and enabled (default) 444162306a36Sopenharmony_ci# PCIe error reporting is always enabled by the PCI core, so this always 444262306a36Sopenharmony_ci# shows 1. 444362306a36Sopenharmony_ci# 444462306a36Sopenharmony_ci# N.B. Parts of LPFC_ATTR open-coded since some of the underlying 444562306a36Sopenharmony_ci# infrastructure (phba->cfg_aer_support) is gone. 444662306a36Sopenharmony_ci*/ 444762306a36Sopenharmony_cistatic uint lpfc_aer_support = 1; 444862306a36Sopenharmony_cimodule_param(lpfc_aer_support, uint, S_IRUGO); 444962306a36Sopenharmony_ciMODULE_PARM_DESC(lpfc_aer_support, "Enable PCIe device AER support"); 445062306a36Sopenharmony_cistatic ssize_t 445162306a36Sopenharmony_cilpfc_aer_support_show(struct device *dev, struct device_attribute *attr, 445262306a36Sopenharmony_ci char *buf) 445362306a36Sopenharmony_ci{ 445462306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d\n", lpfc_aer_support); 445562306a36Sopenharmony_ci} 445662306a36Sopenharmony_ci 445762306a36Sopenharmony_ci/** 445862306a36Sopenharmony_ci * lpfc_aer_support_store - Set the adapter for aer support 445962306a36Sopenharmony_ci * 446062306a36Sopenharmony_ci * @dev: class device that is converted into a Scsi_host. 446162306a36Sopenharmony_ci * @attr: device attribute, not used. 446262306a36Sopenharmony_ci * @buf: containing enable or disable aer flag. 446362306a36Sopenharmony_ci * @count: unused variable. 446462306a36Sopenharmony_ci * 446562306a36Sopenharmony_ci * Description: 446662306a36Sopenharmony_ci * PCIe error reporting is enabled by the PCI core, so drivers don't need 446762306a36Sopenharmony_ci * to do anything. Retain this interface for backwards compatibility, 446862306a36Sopenharmony_ci * but do nothing. 446962306a36Sopenharmony_ci * 447062306a36Sopenharmony_ci * Returns: 447162306a36Sopenharmony_ci * length of the buf on success 447262306a36Sopenharmony_ci * -EINVAL if val out of range 447362306a36Sopenharmony_ci **/ 447462306a36Sopenharmony_cistatic ssize_t 447562306a36Sopenharmony_cilpfc_aer_support_store(struct device *dev, struct device_attribute *attr, 447662306a36Sopenharmony_ci const char *buf, size_t count) 447762306a36Sopenharmony_ci{ 447862306a36Sopenharmony_ci int val = 0; 447962306a36Sopenharmony_ci 448062306a36Sopenharmony_ci if (!isdigit(buf[0])) 448162306a36Sopenharmony_ci return -EINVAL; 448262306a36Sopenharmony_ci if (sscanf(buf, "%i", &val) != 1) 448362306a36Sopenharmony_ci return -EINVAL; 448462306a36Sopenharmony_ci 448562306a36Sopenharmony_ci dev_info_once(dev, "PCIe error reporting automatically enabled by the PCI core; sysfs write ignored\n"); 448662306a36Sopenharmony_ci return strlen(buf); 448762306a36Sopenharmony_ci} 448862306a36Sopenharmony_ci 448962306a36Sopenharmony_cistatic DEVICE_ATTR_RW(lpfc_aer_support); 449062306a36Sopenharmony_ci 449162306a36Sopenharmony_ci/** 449262306a36Sopenharmony_ci * lpfc_aer_cleanup_state - Clean up aer state to the aer enabled device 449362306a36Sopenharmony_ci * @dev: class device that is converted into a Scsi_host. 449462306a36Sopenharmony_ci * @attr: device attribute, not used. 449562306a36Sopenharmony_ci * @buf: containing flag 1 for aer cleanup state. 449662306a36Sopenharmony_ci * @count: unused variable. 449762306a36Sopenharmony_ci * 449862306a36Sopenharmony_ci * Description: 449962306a36Sopenharmony_ci * If the @buf contains 1, invokes the kernel AER helper routine 450062306a36Sopenharmony_ci * pci_aer_clear_nonfatal_status() to clean up the uncorrectable 450162306a36Sopenharmony_ci * error status register. 450262306a36Sopenharmony_ci * 450362306a36Sopenharmony_ci * Notes: 450462306a36Sopenharmony_ci * 450562306a36Sopenharmony_ci * Returns: 450662306a36Sopenharmony_ci * -EINVAL if the buf does not contain 1 450762306a36Sopenharmony_ci * -EPERM if the OS cannot clear AER error status, i.e., when platform 450862306a36Sopenharmony_ci * firmware owns the AER Capability 450962306a36Sopenharmony_ci **/ 451062306a36Sopenharmony_cistatic ssize_t 451162306a36Sopenharmony_cilpfc_aer_cleanup_state(struct device *dev, struct device_attribute *attr, 451262306a36Sopenharmony_ci const char *buf, size_t count) 451362306a36Sopenharmony_ci{ 451462306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 451562306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 451662306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 451762306a36Sopenharmony_ci int val, rc = -1; 451862306a36Sopenharmony_ci 451962306a36Sopenharmony_ci if (!isdigit(buf[0])) 452062306a36Sopenharmony_ci return -EINVAL; 452162306a36Sopenharmony_ci if (sscanf(buf, "%i", &val) != 1) 452262306a36Sopenharmony_ci return -EINVAL; 452362306a36Sopenharmony_ci if (val != 1) 452462306a36Sopenharmony_ci return -EINVAL; 452562306a36Sopenharmony_ci 452662306a36Sopenharmony_ci rc = pci_aer_clear_nonfatal_status(phba->pcidev); 452762306a36Sopenharmony_ci 452862306a36Sopenharmony_ci if (rc == 0) 452962306a36Sopenharmony_ci return strlen(buf); 453062306a36Sopenharmony_ci else 453162306a36Sopenharmony_ci return -EPERM; 453262306a36Sopenharmony_ci} 453362306a36Sopenharmony_ci 453462306a36Sopenharmony_cistatic DEVICE_ATTR(lpfc_aer_state_cleanup, S_IWUSR, NULL, 453562306a36Sopenharmony_ci lpfc_aer_cleanup_state); 453662306a36Sopenharmony_ci 453762306a36Sopenharmony_ci/** 453862306a36Sopenharmony_ci * lpfc_sriov_nr_virtfn_store - Enable the adapter for sr-iov virtual functions 453962306a36Sopenharmony_ci * 454062306a36Sopenharmony_ci * @dev: class device that is converted into a Scsi_host. 454162306a36Sopenharmony_ci * @attr: device attribute, not used. 454262306a36Sopenharmony_ci * @buf: containing the string the number of vfs to be enabled. 454362306a36Sopenharmony_ci * @count: unused variable. 454462306a36Sopenharmony_ci * 454562306a36Sopenharmony_ci * Description: 454662306a36Sopenharmony_ci * When this api is called either through user sysfs, the driver shall 454762306a36Sopenharmony_ci * try to enable or disable SR-IOV virtual functions according to the 454862306a36Sopenharmony_ci * following: 454962306a36Sopenharmony_ci * 455062306a36Sopenharmony_ci * If zero virtual function has been enabled to the physical function, 455162306a36Sopenharmony_ci * the driver shall invoke the pci enable virtual function api trying 455262306a36Sopenharmony_ci * to enable the virtual functions. If the nr_vfn provided is greater 455362306a36Sopenharmony_ci * than the maximum supported, the maximum virtual function number will 455462306a36Sopenharmony_ci * be used for invoking the api; otherwise, the nr_vfn provided shall 455562306a36Sopenharmony_ci * be used for invoking the api. If the api call returned success, the 455662306a36Sopenharmony_ci * actual number of virtual functions enabled will be set to the driver 455762306a36Sopenharmony_ci * cfg_sriov_nr_virtfn; otherwise, -EINVAL shall be returned and driver 455862306a36Sopenharmony_ci * cfg_sriov_nr_virtfn remains zero. 455962306a36Sopenharmony_ci * 456062306a36Sopenharmony_ci * If none-zero virtual functions have already been enabled to the 456162306a36Sopenharmony_ci * physical function, as reflected by the driver's cfg_sriov_nr_virtfn, 456262306a36Sopenharmony_ci * -EINVAL will be returned and the driver does nothing; 456362306a36Sopenharmony_ci * 456462306a36Sopenharmony_ci * If the nr_vfn provided is zero and none-zero virtual functions have 456562306a36Sopenharmony_ci * been enabled, as indicated by the driver's cfg_sriov_nr_virtfn, the 456662306a36Sopenharmony_ci * disabling virtual function api shall be invoded to disable all the 456762306a36Sopenharmony_ci * virtual functions and driver's cfg_sriov_nr_virtfn shall be set to 456862306a36Sopenharmony_ci * zero. Otherwise, if zero virtual function has been enabled, do 456962306a36Sopenharmony_ci * nothing. 457062306a36Sopenharmony_ci * 457162306a36Sopenharmony_ci * Returns: 457262306a36Sopenharmony_ci * length of the buf on success if val is in range the intended mode 457362306a36Sopenharmony_ci * is supported. 457462306a36Sopenharmony_ci * -EINVAL if val out of range or intended mode is not supported. 457562306a36Sopenharmony_ci **/ 457662306a36Sopenharmony_cistatic ssize_t 457762306a36Sopenharmony_cilpfc_sriov_nr_virtfn_store(struct device *dev, struct device_attribute *attr, 457862306a36Sopenharmony_ci const char *buf, size_t count) 457962306a36Sopenharmony_ci{ 458062306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 458162306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata; 458262306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 458362306a36Sopenharmony_ci struct pci_dev *pdev = phba->pcidev; 458462306a36Sopenharmony_ci int val = 0, rc = -EINVAL; 458562306a36Sopenharmony_ci 458662306a36Sopenharmony_ci /* Sanity check on user data */ 458762306a36Sopenharmony_ci if (!isdigit(buf[0])) 458862306a36Sopenharmony_ci return -EINVAL; 458962306a36Sopenharmony_ci if (sscanf(buf, "%i", &val) != 1) 459062306a36Sopenharmony_ci return -EINVAL; 459162306a36Sopenharmony_ci if (val < 0) 459262306a36Sopenharmony_ci return -EINVAL; 459362306a36Sopenharmony_ci 459462306a36Sopenharmony_ci /* Request disabling virtual functions */ 459562306a36Sopenharmony_ci if (val == 0) { 459662306a36Sopenharmony_ci if (phba->cfg_sriov_nr_virtfn > 0) { 459762306a36Sopenharmony_ci pci_disable_sriov(pdev); 459862306a36Sopenharmony_ci phba->cfg_sriov_nr_virtfn = 0; 459962306a36Sopenharmony_ci } 460062306a36Sopenharmony_ci return strlen(buf); 460162306a36Sopenharmony_ci } 460262306a36Sopenharmony_ci 460362306a36Sopenharmony_ci /* Request enabling virtual functions */ 460462306a36Sopenharmony_ci if (phba->cfg_sriov_nr_virtfn > 0) { 460562306a36Sopenharmony_ci lpfc_printf_log(phba, KERN_ERR, LOG_INIT, 460662306a36Sopenharmony_ci "3018 There are %d virtual functions " 460762306a36Sopenharmony_ci "enabled on physical function.\n", 460862306a36Sopenharmony_ci phba->cfg_sriov_nr_virtfn); 460962306a36Sopenharmony_ci return -EEXIST; 461062306a36Sopenharmony_ci } 461162306a36Sopenharmony_ci 461262306a36Sopenharmony_ci if (val <= LPFC_MAX_VFN_PER_PFN) 461362306a36Sopenharmony_ci phba->cfg_sriov_nr_virtfn = val; 461462306a36Sopenharmony_ci else { 461562306a36Sopenharmony_ci lpfc_printf_log(phba, KERN_ERR, LOG_INIT, 461662306a36Sopenharmony_ci "3019 Enabling %d virtual functions is not " 461762306a36Sopenharmony_ci "allowed.\n", val); 461862306a36Sopenharmony_ci return -EINVAL; 461962306a36Sopenharmony_ci } 462062306a36Sopenharmony_ci 462162306a36Sopenharmony_ci rc = lpfc_sli_probe_sriov_nr_virtfn(phba, phba->cfg_sriov_nr_virtfn); 462262306a36Sopenharmony_ci if (rc) { 462362306a36Sopenharmony_ci phba->cfg_sriov_nr_virtfn = 0; 462462306a36Sopenharmony_ci rc = -EPERM; 462562306a36Sopenharmony_ci } else 462662306a36Sopenharmony_ci rc = strlen(buf); 462762306a36Sopenharmony_ci 462862306a36Sopenharmony_ci return rc; 462962306a36Sopenharmony_ci} 463062306a36Sopenharmony_ci 463162306a36Sopenharmony_ciLPFC_ATTR(sriov_nr_virtfn, LPFC_DEF_VFN_PER_PFN, 0, LPFC_MAX_VFN_PER_PFN, 463262306a36Sopenharmony_ci "Enable PCIe device SR-IOV virtual fn"); 463362306a36Sopenharmony_ci 463462306a36Sopenharmony_cilpfc_param_show(sriov_nr_virtfn) 463562306a36Sopenharmony_cistatic DEVICE_ATTR_RW(lpfc_sriov_nr_virtfn); 463662306a36Sopenharmony_ci 463762306a36Sopenharmony_ci/** 463862306a36Sopenharmony_ci * lpfc_request_firmware_upgrade_store - Request for Linux generic firmware upgrade 463962306a36Sopenharmony_ci * 464062306a36Sopenharmony_ci * @dev: class device that is converted into a Scsi_host. 464162306a36Sopenharmony_ci * @attr: device attribute, not used. 464262306a36Sopenharmony_ci * @buf: containing the string the number of vfs to be enabled. 464362306a36Sopenharmony_ci * @count: unused variable. 464462306a36Sopenharmony_ci * 464562306a36Sopenharmony_ci * Description: 464662306a36Sopenharmony_ci * 464762306a36Sopenharmony_ci * Returns: 464862306a36Sopenharmony_ci * length of the buf on success if val is in range the intended mode 464962306a36Sopenharmony_ci * is supported. 465062306a36Sopenharmony_ci * -EINVAL if val out of range or intended mode is not supported. 465162306a36Sopenharmony_ci **/ 465262306a36Sopenharmony_cistatic ssize_t 465362306a36Sopenharmony_cilpfc_request_firmware_upgrade_store(struct device *dev, 465462306a36Sopenharmony_ci struct device_attribute *attr, 465562306a36Sopenharmony_ci const char *buf, size_t count) 465662306a36Sopenharmony_ci{ 465762306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 465862306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata; 465962306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 466062306a36Sopenharmony_ci int val = 0, rc; 466162306a36Sopenharmony_ci 466262306a36Sopenharmony_ci /* Sanity check on user data */ 466362306a36Sopenharmony_ci if (!isdigit(buf[0])) 466462306a36Sopenharmony_ci return -EINVAL; 466562306a36Sopenharmony_ci if (sscanf(buf, "%i", &val) != 1) 466662306a36Sopenharmony_ci return -EINVAL; 466762306a36Sopenharmony_ci if (val != 1) 466862306a36Sopenharmony_ci return -EINVAL; 466962306a36Sopenharmony_ci 467062306a36Sopenharmony_ci rc = lpfc_sli4_request_firmware_update(phba, RUN_FW_UPGRADE); 467162306a36Sopenharmony_ci if (rc) 467262306a36Sopenharmony_ci rc = -EPERM; 467362306a36Sopenharmony_ci else 467462306a36Sopenharmony_ci rc = strlen(buf); 467562306a36Sopenharmony_ci return rc; 467662306a36Sopenharmony_ci} 467762306a36Sopenharmony_ci 467862306a36Sopenharmony_cistatic int lpfc_req_fw_upgrade; 467962306a36Sopenharmony_cimodule_param(lpfc_req_fw_upgrade, int, S_IRUGO|S_IWUSR); 468062306a36Sopenharmony_ciMODULE_PARM_DESC(lpfc_req_fw_upgrade, "Enable Linux generic firmware upgrade"); 468162306a36Sopenharmony_cilpfc_param_show(request_firmware_upgrade) 468262306a36Sopenharmony_ci 468362306a36Sopenharmony_ci/** 468462306a36Sopenharmony_ci * lpfc_request_firmware_upgrade_init - Enable initial linux generic fw upgrade 468562306a36Sopenharmony_ci * @phba: lpfc_hba pointer. 468662306a36Sopenharmony_ci * @val: 0 or 1. 468762306a36Sopenharmony_ci * 468862306a36Sopenharmony_ci * Description: 468962306a36Sopenharmony_ci * Set the initial Linux generic firmware upgrade enable or disable flag. 469062306a36Sopenharmony_ci * 469162306a36Sopenharmony_ci * Returns: 469262306a36Sopenharmony_ci * zero if val saved. 469362306a36Sopenharmony_ci * -EINVAL val out of range 469462306a36Sopenharmony_ci **/ 469562306a36Sopenharmony_cistatic int 469662306a36Sopenharmony_cilpfc_request_firmware_upgrade_init(struct lpfc_hba *phba, int val) 469762306a36Sopenharmony_ci{ 469862306a36Sopenharmony_ci if (val >= 0 && val <= 1) { 469962306a36Sopenharmony_ci phba->cfg_request_firmware_upgrade = val; 470062306a36Sopenharmony_ci return 0; 470162306a36Sopenharmony_ci } 470262306a36Sopenharmony_ci return -EINVAL; 470362306a36Sopenharmony_ci} 470462306a36Sopenharmony_cistatic DEVICE_ATTR(lpfc_req_fw_upgrade, S_IRUGO | S_IWUSR, 470562306a36Sopenharmony_ci lpfc_request_firmware_upgrade_show, 470662306a36Sopenharmony_ci lpfc_request_firmware_upgrade_store); 470762306a36Sopenharmony_ci 470862306a36Sopenharmony_ci/** 470962306a36Sopenharmony_ci * lpfc_force_rscn_store 471062306a36Sopenharmony_ci * 471162306a36Sopenharmony_ci * @dev: class device that is converted into a Scsi_host. 471262306a36Sopenharmony_ci * @attr: device attribute, not used. 471362306a36Sopenharmony_ci * @buf: unused string 471462306a36Sopenharmony_ci * @count: unused variable. 471562306a36Sopenharmony_ci * 471662306a36Sopenharmony_ci * Description: 471762306a36Sopenharmony_ci * Force the switch to send a RSCN to all other NPorts in our zone 471862306a36Sopenharmony_ci * If we are direct connect pt2pt, build the RSCN command ourself 471962306a36Sopenharmony_ci * and send to the other NPort. Not supported for private loop. 472062306a36Sopenharmony_ci * 472162306a36Sopenharmony_ci * Returns: 472262306a36Sopenharmony_ci * 0 - on success 472362306a36Sopenharmony_ci * -EIO - if command is not sent 472462306a36Sopenharmony_ci **/ 472562306a36Sopenharmony_cistatic ssize_t 472662306a36Sopenharmony_cilpfc_force_rscn_store(struct device *dev, struct device_attribute *attr, 472762306a36Sopenharmony_ci const char *buf, size_t count) 472862306a36Sopenharmony_ci{ 472962306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 473062306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata; 473162306a36Sopenharmony_ci int i; 473262306a36Sopenharmony_ci 473362306a36Sopenharmony_ci i = lpfc_issue_els_rscn(vport, 0); 473462306a36Sopenharmony_ci if (i) 473562306a36Sopenharmony_ci return -EIO; 473662306a36Sopenharmony_ci return strlen(buf); 473762306a36Sopenharmony_ci} 473862306a36Sopenharmony_ci 473962306a36Sopenharmony_ci/* 474062306a36Sopenharmony_ci * lpfc_force_rscn: Force an RSCN to be sent to all remote NPorts 474162306a36Sopenharmony_ci * connected to the HBA. 474262306a36Sopenharmony_ci * 474362306a36Sopenharmony_ci * Value range is any ascii value 474462306a36Sopenharmony_ci */ 474562306a36Sopenharmony_cistatic int lpfc_force_rscn; 474662306a36Sopenharmony_cimodule_param(lpfc_force_rscn, int, 0644); 474762306a36Sopenharmony_ciMODULE_PARM_DESC(lpfc_force_rscn, 474862306a36Sopenharmony_ci "Force an RSCN to be sent to all remote NPorts"); 474962306a36Sopenharmony_cilpfc_param_show(force_rscn) 475062306a36Sopenharmony_ci 475162306a36Sopenharmony_ci/** 475262306a36Sopenharmony_ci * lpfc_force_rscn_init - Force an RSCN to be sent to all remote NPorts 475362306a36Sopenharmony_ci * @phba: lpfc_hba pointer. 475462306a36Sopenharmony_ci * @val: unused value. 475562306a36Sopenharmony_ci * 475662306a36Sopenharmony_ci * Returns: 475762306a36Sopenharmony_ci * zero if val saved. 475862306a36Sopenharmony_ci **/ 475962306a36Sopenharmony_cistatic int 476062306a36Sopenharmony_cilpfc_force_rscn_init(struct lpfc_hba *phba, int val) 476162306a36Sopenharmony_ci{ 476262306a36Sopenharmony_ci return 0; 476362306a36Sopenharmony_ci} 476462306a36Sopenharmony_cistatic DEVICE_ATTR_RW(lpfc_force_rscn); 476562306a36Sopenharmony_ci 476662306a36Sopenharmony_ci/** 476762306a36Sopenharmony_ci * lpfc_fcp_imax_store 476862306a36Sopenharmony_ci * 476962306a36Sopenharmony_ci * @dev: class device that is converted into a Scsi_host. 477062306a36Sopenharmony_ci * @attr: device attribute, not used. 477162306a36Sopenharmony_ci * @buf: string with the number of fast-path FCP interrupts per second. 477262306a36Sopenharmony_ci * @count: unused variable. 477362306a36Sopenharmony_ci * 477462306a36Sopenharmony_ci * Description: 477562306a36Sopenharmony_ci * If val is in a valid range [636,651042], then set the adapter's 477662306a36Sopenharmony_ci * maximum number of fast-path FCP interrupts per second. 477762306a36Sopenharmony_ci * 477862306a36Sopenharmony_ci * Returns: 477962306a36Sopenharmony_ci * length of the buf on success if val is in range the intended mode 478062306a36Sopenharmony_ci * is supported. 478162306a36Sopenharmony_ci * -EINVAL if val out of range or intended mode is not supported. 478262306a36Sopenharmony_ci **/ 478362306a36Sopenharmony_cistatic ssize_t 478462306a36Sopenharmony_cilpfc_fcp_imax_store(struct device *dev, struct device_attribute *attr, 478562306a36Sopenharmony_ci const char *buf, size_t count) 478662306a36Sopenharmony_ci{ 478762306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 478862306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata; 478962306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 479062306a36Sopenharmony_ci struct lpfc_eq_intr_info *eqi; 479162306a36Sopenharmony_ci uint32_t usdelay; 479262306a36Sopenharmony_ci int val = 0, i; 479362306a36Sopenharmony_ci 479462306a36Sopenharmony_ci /* fcp_imax is only valid for SLI4 */ 479562306a36Sopenharmony_ci if (phba->sli_rev != LPFC_SLI_REV4) 479662306a36Sopenharmony_ci return -EINVAL; 479762306a36Sopenharmony_ci 479862306a36Sopenharmony_ci /* Sanity check on user data */ 479962306a36Sopenharmony_ci if (!isdigit(buf[0])) 480062306a36Sopenharmony_ci return -EINVAL; 480162306a36Sopenharmony_ci if (sscanf(buf, "%i", &val) != 1) 480262306a36Sopenharmony_ci return -EINVAL; 480362306a36Sopenharmony_ci 480462306a36Sopenharmony_ci /* 480562306a36Sopenharmony_ci * Value range for the HBA is [5000,5000000] 480662306a36Sopenharmony_ci * The value for each EQ depends on how many EQs are configured. 480762306a36Sopenharmony_ci * Allow value == 0 480862306a36Sopenharmony_ci */ 480962306a36Sopenharmony_ci if (val && (val < LPFC_MIN_IMAX || val > LPFC_MAX_IMAX)) 481062306a36Sopenharmony_ci return -EINVAL; 481162306a36Sopenharmony_ci 481262306a36Sopenharmony_ci phba->cfg_auto_imax = (val) ? 0 : 1; 481362306a36Sopenharmony_ci if (phba->cfg_fcp_imax && !val) { 481462306a36Sopenharmony_ci queue_delayed_work(phba->wq, &phba->eq_delay_work, 481562306a36Sopenharmony_ci msecs_to_jiffies(LPFC_EQ_DELAY_MSECS)); 481662306a36Sopenharmony_ci 481762306a36Sopenharmony_ci for_each_present_cpu(i) { 481862306a36Sopenharmony_ci eqi = per_cpu_ptr(phba->sli4_hba.eq_info, i); 481962306a36Sopenharmony_ci eqi->icnt = 0; 482062306a36Sopenharmony_ci } 482162306a36Sopenharmony_ci } 482262306a36Sopenharmony_ci 482362306a36Sopenharmony_ci phba->cfg_fcp_imax = (uint32_t)val; 482462306a36Sopenharmony_ci 482562306a36Sopenharmony_ci if (phba->cfg_fcp_imax) 482662306a36Sopenharmony_ci usdelay = LPFC_SEC_TO_USEC / phba->cfg_fcp_imax; 482762306a36Sopenharmony_ci else 482862306a36Sopenharmony_ci usdelay = 0; 482962306a36Sopenharmony_ci 483062306a36Sopenharmony_ci for (i = 0; i < phba->cfg_irq_chann; i += LPFC_MAX_EQ_DELAY_EQID_CNT) 483162306a36Sopenharmony_ci lpfc_modify_hba_eq_delay(phba, i, LPFC_MAX_EQ_DELAY_EQID_CNT, 483262306a36Sopenharmony_ci usdelay); 483362306a36Sopenharmony_ci 483462306a36Sopenharmony_ci return strlen(buf); 483562306a36Sopenharmony_ci} 483662306a36Sopenharmony_ci 483762306a36Sopenharmony_ci/* 483862306a36Sopenharmony_ci# lpfc_fcp_imax: The maximum number of fast-path FCP interrupts per second 483962306a36Sopenharmony_ci# for the HBA. 484062306a36Sopenharmony_ci# 484162306a36Sopenharmony_ci# Value range is [5,000 to 5,000,000]. Default value is 50,000. 484262306a36Sopenharmony_ci*/ 484362306a36Sopenharmony_cistatic int lpfc_fcp_imax = LPFC_DEF_IMAX; 484462306a36Sopenharmony_cimodule_param(lpfc_fcp_imax, int, S_IRUGO|S_IWUSR); 484562306a36Sopenharmony_ciMODULE_PARM_DESC(lpfc_fcp_imax, 484662306a36Sopenharmony_ci "Set the maximum number of FCP interrupts per second per HBA"); 484762306a36Sopenharmony_cilpfc_param_show(fcp_imax) 484862306a36Sopenharmony_ci 484962306a36Sopenharmony_ci/** 485062306a36Sopenharmony_ci * lpfc_fcp_imax_init - Set the initial sr-iov virtual function enable 485162306a36Sopenharmony_ci * @phba: lpfc_hba pointer. 485262306a36Sopenharmony_ci * @val: link speed value. 485362306a36Sopenharmony_ci * 485462306a36Sopenharmony_ci * Description: 485562306a36Sopenharmony_ci * If val is in a valid range [636,651042], then initialize the adapter's 485662306a36Sopenharmony_ci * maximum number of fast-path FCP interrupts per second. 485762306a36Sopenharmony_ci * 485862306a36Sopenharmony_ci * Returns: 485962306a36Sopenharmony_ci * zero if val saved. 486062306a36Sopenharmony_ci * -EINVAL val out of range 486162306a36Sopenharmony_ci **/ 486262306a36Sopenharmony_cistatic int 486362306a36Sopenharmony_cilpfc_fcp_imax_init(struct lpfc_hba *phba, int val) 486462306a36Sopenharmony_ci{ 486562306a36Sopenharmony_ci if (phba->sli_rev != LPFC_SLI_REV4) { 486662306a36Sopenharmony_ci phba->cfg_fcp_imax = 0; 486762306a36Sopenharmony_ci return 0; 486862306a36Sopenharmony_ci } 486962306a36Sopenharmony_ci 487062306a36Sopenharmony_ci if ((val >= LPFC_MIN_IMAX && val <= LPFC_MAX_IMAX) || 487162306a36Sopenharmony_ci (val == 0)) { 487262306a36Sopenharmony_ci phba->cfg_fcp_imax = val; 487362306a36Sopenharmony_ci return 0; 487462306a36Sopenharmony_ci } 487562306a36Sopenharmony_ci 487662306a36Sopenharmony_ci lpfc_printf_log(phba, KERN_ERR, LOG_INIT, 487762306a36Sopenharmony_ci "3016 lpfc_fcp_imax: %d out of range, using default\n", 487862306a36Sopenharmony_ci val); 487962306a36Sopenharmony_ci phba->cfg_fcp_imax = LPFC_DEF_IMAX; 488062306a36Sopenharmony_ci 488162306a36Sopenharmony_ci return 0; 488262306a36Sopenharmony_ci} 488362306a36Sopenharmony_ci 488462306a36Sopenharmony_cistatic DEVICE_ATTR_RW(lpfc_fcp_imax); 488562306a36Sopenharmony_ci 488662306a36Sopenharmony_ci/** 488762306a36Sopenharmony_ci * lpfc_cq_max_proc_limit_store 488862306a36Sopenharmony_ci * 488962306a36Sopenharmony_ci * @dev: class device that is converted into a Scsi_host. 489062306a36Sopenharmony_ci * @attr: device attribute, not used. 489162306a36Sopenharmony_ci * @buf: string with the cq max processing limit of cqes 489262306a36Sopenharmony_ci * @count: unused variable. 489362306a36Sopenharmony_ci * 489462306a36Sopenharmony_ci * Description: 489562306a36Sopenharmony_ci * If val is in a valid range, then set value on each cq 489662306a36Sopenharmony_ci * 489762306a36Sopenharmony_ci * Returns: 489862306a36Sopenharmony_ci * The length of the buf: if successful 489962306a36Sopenharmony_ci * -ERANGE: if val is not in the valid range 490062306a36Sopenharmony_ci * -EINVAL: if bad value format or intended mode is not supported. 490162306a36Sopenharmony_ci **/ 490262306a36Sopenharmony_cistatic ssize_t 490362306a36Sopenharmony_cilpfc_cq_max_proc_limit_store(struct device *dev, struct device_attribute *attr, 490462306a36Sopenharmony_ci const char *buf, size_t count) 490562306a36Sopenharmony_ci{ 490662306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 490762306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata; 490862306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 490962306a36Sopenharmony_ci struct lpfc_queue *eq, *cq; 491062306a36Sopenharmony_ci unsigned long val; 491162306a36Sopenharmony_ci int i; 491262306a36Sopenharmony_ci 491362306a36Sopenharmony_ci /* cq_max_proc_limit is only valid for SLI4 */ 491462306a36Sopenharmony_ci if (phba->sli_rev != LPFC_SLI_REV4) 491562306a36Sopenharmony_ci return -EINVAL; 491662306a36Sopenharmony_ci 491762306a36Sopenharmony_ci /* Sanity check on user data */ 491862306a36Sopenharmony_ci if (!isdigit(buf[0])) 491962306a36Sopenharmony_ci return -EINVAL; 492062306a36Sopenharmony_ci if (kstrtoul(buf, 0, &val)) 492162306a36Sopenharmony_ci return -EINVAL; 492262306a36Sopenharmony_ci 492362306a36Sopenharmony_ci if (val < LPFC_CQ_MIN_PROC_LIMIT || val > LPFC_CQ_MAX_PROC_LIMIT) 492462306a36Sopenharmony_ci return -ERANGE; 492562306a36Sopenharmony_ci 492662306a36Sopenharmony_ci phba->cfg_cq_max_proc_limit = (uint32_t)val; 492762306a36Sopenharmony_ci 492862306a36Sopenharmony_ci /* set the values on the cq's */ 492962306a36Sopenharmony_ci for (i = 0; i < phba->cfg_irq_chann; i++) { 493062306a36Sopenharmony_ci /* Get the EQ corresponding to the IRQ vector */ 493162306a36Sopenharmony_ci eq = phba->sli4_hba.hba_eq_hdl[i].eq; 493262306a36Sopenharmony_ci if (!eq) 493362306a36Sopenharmony_ci continue; 493462306a36Sopenharmony_ci 493562306a36Sopenharmony_ci list_for_each_entry(cq, &eq->child_list, list) 493662306a36Sopenharmony_ci cq->max_proc_limit = min(phba->cfg_cq_max_proc_limit, 493762306a36Sopenharmony_ci cq->entry_count); 493862306a36Sopenharmony_ci } 493962306a36Sopenharmony_ci 494062306a36Sopenharmony_ci return strlen(buf); 494162306a36Sopenharmony_ci} 494262306a36Sopenharmony_ci 494362306a36Sopenharmony_ci/* 494462306a36Sopenharmony_ci * lpfc_cq_max_proc_limit: The maximum number CQE entries processed in an 494562306a36Sopenharmony_ci * itteration of CQ processing. 494662306a36Sopenharmony_ci */ 494762306a36Sopenharmony_cistatic int lpfc_cq_max_proc_limit = LPFC_CQ_DEF_MAX_PROC_LIMIT; 494862306a36Sopenharmony_cimodule_param(lpfc_cq_max_proc_limit, int, 0644); 494962306a36Sopenharmony_ciMODULE_PARM_DESC(lpfc_cq_max_proc_limit, 495062306a36Sopenharmony_ci "Set the maximum number CQEs processed in an iteration of " 495162306a36Sopenharmony_ci "CQ processing"); 495262306a36Sopenharmony_cilpfc_param_show(cq_max_proc_limit) 495362306a36Sopenharmony_ci 495462306a36Sopenharmony_ci/* 495562306a36Sopenharmony_ci * lpfc_cq_poll_threshold: Set the threshold of CQE completions in a 495662306a36Sopenharmony_ci * single handler call which should request a polled completion rather 495762306a36Sopenharmony_ci * than re-enabling interrupts. 495862306a36Sopenharmony_ci */ 495962306a36Sopenharmony_ciLPFC_ATTR_RW(cq_poll_threshold, LPFC_CQ_DEF_THRESHOLD_TO_POLL, 496062306a36Sopenharmony_ci LPFC_CQ_MIN_THRESHOLD_TO_POLL, 496162306a36Sopenharmony_ci LPFC_CQ_MAX_THRESHOLD_TO_POLL, 496262306a36Sopenharmony_ci "CQE Processing Threshold to enable Polling"); 496362306a36Sopenharmony_ci 496462306a36Sopenharmony_ci/** 496562306a36Sopenharmony_ci * lpfc_cq_max_proc_limit_init - Set the initial cq max_proc_limit 496662306a36Sopenharmony_ci * @phba: lpfc_hba pointer. 496762306a36Sopenharmony_ci * @val: entry limit 496862306a36Sopenharmony_ci * 496962306a36Sopenharmony_ci * Description: 497062306a36Sopenharmony_ci * If val is in a valid range, then initialize the adapter's maximum 497162306a36Sopenharmony_ci * value. 497262306a36Sopenharmony_ci * 497362306a36Sopenharmony_ci * Returns: 497462306a36Sopenharmony_ci * Always returns 0 for success, even if value not always set to 497562306a36Sopenharmony_ci * requested value. If value out of range or not supported, will fall 497662306a36Sopenharmony_ci * back to default. 497762306a36Sopenharmony_ci **/ 497862306a36Sopenharmony_cistatic int 497962306a36Sopenharmony_cilpfc_cq_max_proc_limit_init(struct lpfc_hba *phba, int val) 498062306a36Sopenharmony_ci{ 498162306a36Sopenharmony_ci phba->cfg_cq_max_proc_limit = LPFC_CQ_DEF_MAX_PROC_LIMIT; 498262306a36Sopenharmony_ci 498362306a36Sopenharmony_ci if (phba->sli_rev != LPFC_SLI_REV4) 498462306a36Sopenharmony_ci return 0; 498562306a36Sopenharmony_ci 498662306a36Sopenharmony_ci if (val >= LPFC_CQ_MIN_PROC_LIMIT && val <= LPFC_CQ_MAX_PROC_LIMIT) { 498762306a36Sopenharmony_ci phba->cfg_cq_max_proc_limit = val; 498862306a36Sopenharmony_ci return 0; 498962306a36Sopenharmony_ci } 499062306a36Sopenharmony_ci 499162306a36Sopenharmony_ci lpfc_printf_log(phba, KERN_ERR, LOG_INIT, 499262306a36Sopenharmony_ci "0371 lpfc_cq_max_proc_limit: %d out of range, using " 499362306a36Sopenharmony_ci "default\n", 499462306a36Sopenharmony_ci phba->cfg_cq_max_proc_limit); 499562306a36Sopenharmony_ci 499662306a36Sopenharmony_ci return 0; 499762306a36Sopenharmony_ci} 499862306a36Sopenharmony_ci 499962306a36Sopenharmony_cistatic DEVICE_ATTR_RW(lpfc_cq_max_proc_limit); 500062306a36Sopenharmony_ci 500162306a36Sopenharmony_ci/** 500262306a36Sopenharmony_ci * lpfc_fcp_cpu_map_show - Display current driver CPU affinity 500362306a36Sopenharmony_ci * @dev: class converted to a Scsi_host structure. 500462306a36Sopenharmony_ci * @attr: device attribute, not used. 500562306a36Sopenharmony_ci * @buf: on return contains text describing the state of the link. 500662306a36Sopenharmony_ci * 500762306a36Sopenharmony_ci * Returns: size of formatted string. 500862306a36Sopenharmony_ci **/ 500962306a36Sopenharmony_cistatic ssize_t 501062306a36Sopenharmony_cilpfc_fcp_cpu_map_show(struct device *dev, struct device_attribute *attr, 501162306a36Sopenharmony_ci char *buf) 501262306a36Sopenharmony_ci{ 501362306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 501462306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata; 501562306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 501662306a36Sopenharmony_ci struct lpfc_vector_map_info *cpup; 501762306a36Sopenharmony_ci int len = 0; 501862306a36Sopenharmony_ci 501962306a36Sopenharmony_ci if ((phba->sli_rev != LPFC_SLI_REV4) || 502062306a36Sopenharmony_ci (phba->intr_type != MSIX)) 502162306a36Sopenharmony_ci return len; 502262306a36Sopenharmony_ci 502362306a36Sopenharmony_ci switch (phba->cfg_fcp_cpu_map) { 502462306a36Sopenharmony_ci case 0: 502562306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, 502662306a36Sopenharmony_ci "fcp_cpu_map: No mapping (%d)\n", 502762306a36Sopenharmony_ci phba->cfg_fcp_cpu_map); 502862306a36Sopenharmony_ci return len; 502962306a36Sopenharmony_ci case 1: 503062306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE-len, 503162306a36Sopenharmony_ci "fcp_cpu_map: HBA centric mapping (%d): " 503262306a36Sopenharmony_ci "%d of %d CPUs online from %d possible CPUs\n", 503362306a36Sopenharmony_ci phba->cfg_fcp_cpu_map, num_online_cpus(), 503462306a36Sopenharmony_ci num_present_cpus(), 503562306a36Sopenharmony_ci phba->sli4_hba.num_possible_cpu); 503662306a36Sopenharmony_ci break; 503762306a36Sopenharmony_ci } 503862306a36Sopenharmony_ci 503962306a36Sopenharmony_ci while (phba->sli4_hba.curr_disp_cpu < 504062306a36Sopenharmony_ci phba->sli4_hba.num_possible_cpu) { 504162306a36Sopenharmony_ci cpup = &phba->sli4_hba.cpu_map[phba->sli4_hba.curr_disp_cpu]; 504262306a36Sopenharmony_ci 504362306a36Sopenharmony_ci if (!cpu_present(phba->sli4_hba.curr_disp_cpu)) 504462306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, 504562306a36Sopenharmony_ci "CPU %02d not present\n", 504662306a36Sopenharmony_ci phba->sli4_hba.curr_disp_cpu); 504762306a36Sopenharmony_ci else if (cpup->eq == LPFC_VECTOR_MAP_EMPTY) { 504862306a36Sopenharmony_ci if (cpup->hdwq == LPFC_VECTOR_MAP_EMPTY) 504962306a36Sopenharmony_ci len += scnprintf( 505062306a36Sopenharmony_ci buf + len, PAGE_SIZE - len, 505162306a36Sopenharmony_ci "CPU %02d hdwq None " 505262306a36Sopenharmony_ci "physid %d coreid %d ht %d ua %d\n", 505362306a36Sopenharmony_ci phba->sli4_hba.curr_disp_cpu, 505462306a36Sopenharmony_ci cpup->phys_id, cpup->core_id, 505562306a36Sopenharmony_ci (cpup->flag & LPFC_CPU_MAP_HYPER), 505662306a36Sopenharmony_ci (cpup->flag & LPFC_CPU_MAP_UNASSIGN)); 505762306a36Sopenharmony_ci else 505862306a36Sopenharmony_ci len += scnprintf( 505962306a36Sopenharmony_ci buf + len, PAGE_SIZE - len, 506062306a36Sopenharmony_ci "CPU %02d EQ None hdwq %04d " 506162306a36Sopenharmony_ci "physid %d coreid %d ht %d ua %d\n", 506262306a36Sopenharmony_ci phba->sli4_hba.curr_disp_cpu, 506362306a36Sopenharmony_ci cpup->hdwq, cpup->phys_id, 506462306a36Sopenharmony_ci cpup->core_id, 506562306a36Sopenharmony_ci (cpup->flag & LPFC_CPU_MAP_HYPER), 506662306a36Sopenharmony_ci (cpup->flag & LPFC_CPU_MAP_UNASSIGN)); 506762306a36Sopenharmony_ci } else { 506862306a36Sopenharmony_ci if (cpup->hdwq == LPFC_VECTOR_MAP_EMPTY) 506962306a36Sopenharmony_ci len += scnprintf( 507062306a36Sopenharmony_ci buf + len, PAGE_SIZE - len, 507162306a36Sopenharmony_ci "CPU %02d hdwq None " 507262306a36Sopenharmony_ci "physid %d coreid %d ht %d ua %d IRQ %d\n", 507362306a36Sopenharmony_ci phba->sli4_hba.curr_disp_cpu, 507462306a36Sopenharmony_ci cpup->phys_id, 507562306a36Sopenharmony_ci cpup->core_id, 507662306a36Sopenharmony_ci (cpup->flag & LPFC_CPU_MAP_HYPER), 507762306a36Sopenharmony_ci (cpup->flag & LPFC_CPU_MAP_UNASSIGN), 507862306a36Sopenharmony_ci lpfc_get_irq(cpup->eq)); 507962306a36Sopenharmony_ci else 508062306a36Sopenharmony_ci len += scnprintf( 508162306a36Sopenharmony_ci buf + len, PAGE_SIZE - len, 508262306a36Sopenharmony_ci "CPU %02d EQ %04d hdwq %04d " 508362306a36Sopenharmony_ci "physid %d coreid %d ht %d ua %d IRQ %d\n", 508462306a36Sopenharmony_ci phba->sli4_hba.curr_disp_cpu, 508562306a36Sopenharmony_ci cpup->eq, cpup->hdwq, cpup->phys_id, 508662306a36Sopenharmony_ci cpup->core_id, 508762306a36Sopenharmony_ci (cpup->flag & LPFC_CPU_MAP_HYPER), 508862306a36Sopenharmony_ci (cpup->flag & LPFC_CPU_MAP_UNASSIGN), 508962306a36Sopenharmony_ci lpfc_get_irq(cpup->eq)); 509062306a36Sopenharmony_ci } 509162306a36Sopenharmony_ci 509262306a36Sopenharmony_ci phba->sli4_hba.curr_disp_cpu++; 509362306a36Sopenharmony_ci 509462306a36Sopenharmony_ci /* display max number of CPUs keeping some margin */ 509562306a36Sopenharmony_ci if (phba->sli4_hba.curr_disp_cpu < 509662306a36Sopenharmony_ci phba->sli4_hba.num_possible_cpu && 509762306a36Sopenharmony_ci (len >= (PAGE_SIZE - 64))) { 509862306a36Sopenharmony_ci len += scnprintf(buf + len, 509962306a36Sopenharmony_ci PAGE_SIZE - len, "more...\n"); 510062306a36Sopenharmony_ci break; 510162306a36Sopenharmony_ci } 510262306a36Sopenharmony_ci } 510362306a36Sopenharmony_ci 510462306a36Sopenharmony_ci if (phba->sli4_hba.curr_disp_cpu == phba->sli4_hba.num_possible_cpu) 510562306a36Sopenharmony_ci phba->sli4_hba.curr_disp_cpu = 0; 510662306a36Sopenharmony_ci 510762306a36Sopenharmony_ci return len; 510862306a36Sopenharmony_ci} 510962306a36Sopenharmony_ci 511062306a36Sopenharmony_ci/** 511162306a36Sopenharmony_ci * lpfc_fcp_cpu_map_store - Change CPU affinity of driver vectors 511262306a36Sopenharmony_ci * @dev: class device that is converted into a Scsi_host. 511362306a36Sopenharmony_ci * @attr: device attribute, not used. 511462306a36Sopenharmony_ci * @buf: one or more lpfc_polling_flags values. 511562306a36Sopenharmony_ci * @count: not used. 511662306a36Sopenharmony_ci * 511762306a36Sopenharmony_ci * Returns: 511862306a36Sopenharmony_ci * -EINVAL - Not implemented yet. 511962306a36Sopenharmony_ci **/ 512062306a36Sopenharmony_cistatic ssize_t 512162306a36Sopenharmony_cilpfc_fcp_cpu_map_store(struct device *dev, struct device_attribute *attr, 512262306a36Sopenharmony_ci const char *buf, size_t count) 512362306a36Sopenharmony_ci{ 512462306a36Sopenharmony_ci return -EINVAL; 512562306a36Sopenharmony_ci} 512662306a36Sopenharmony_ci 512762306a36Sopenharmony_ci/* 512862306a36Sopenharmony_ci# lpfc_fcp_cpu_map: Defines how to map CPUs to IRQ vectors 512962306a36Sopenharmony_ci# for the HBA. 513062306a36Sopenharmony_ci# 513162306a36Sopenharmony_ci# Value range is [0 to 1]. Default value is LPFC_HBA_CPU_MAP (1). 513262306a36Sopenharmony_ci# 0 - Do not affinitze IRQ vectors 513362306a36Sopenharmony_ci# 1 - Affintize HBA vectors with respect to each HBA 513462306a36Sopenharmony_ci# (start with CPU0 for each HBA) 513562306a36Sopenharmony_ci# This also defines how Hardware Queues are mapped to specific CPUs. 513662306a36Sopenharmony_ci*/ 513762306a36Sopenharmony_cistatic int lpfc_fcp_cpu_map = LPFC_HBA_CPU_MAP; 513862306a36Sopenharmony_cimodule_param(lpfc_fcp_cpu_map, int, S_IRUGO|S_IWUSR); 513962306a36Sopenharmony_ciMODULE_PARM_DESC(lpfc_fcp_cpu_map, 514062306a36Sopenharmony_ci "Defines how to map CPUs to IRQ vectors per HBA"); 514162306a36Sopenharmony_ci 514262306a36Sopenharmony_ci/** 514362306a36Sopenharmony_ci * lpfc_fcp_cpu_map_init - Set the initial sr-iov virtual function enable 514462306a36Sopenharmony_ci * @phba: lpfc_hba pointer. 514562306a36Sopenharmony_ci * @val: link speed value. 514662306a36Sopenharmony_ci * 514762306a36Sopenharmony_ci * Description: 514862306a36Sopenharmony_ci * If val is in a valid range [0-2], then affinitze the adapter's 514962306a36Sopenharmony_ci * MSIX vectors. 515062306a36Sopenharmony_ci * 515162306a36Sopenharmony_ci * Returns: 515262306a36Sopenharmony_ci * zero if val saved. 515362306a36Sopenharmony_ci * -EINVAL val out of range 515462306a36Sopenharmony_ci **/ 515562306a36Sopenharmony_cistatic int 515662306a36Sopenharmony_cilpfc_fcp_cpu_map_init(struct lpfc_hba *phba, int val) 515762306a36Sopenharmony_ci{ 515862306a36Sopenharmony_ci if (phba->sli_rev != LPFC_SLI_REV4) { 515962306a36Sopenharmony_ci phba->cfg_fcp_cpu_map = 0; 516062306a36Sopenharmony_ci return 0; 516162306a36Sopenharmony_ci } 516262306a36Sopenharmony_ci 516362306a36Sopenharmony_ci if (val >= LPFC_MIN_CPU_MAP && val <= LPFC_MAX_CPU_MAP) { 516462306a36Sopenharmony_ci phba->cfg_fcp_cpu_map = val; 516562306a36Sopenharmony_ci return 0; 516662306a36Sopenharmony_ci } 516762306a36Sopenharmony_ci 516862306a36Sopenharmony_ci lpfc_printf_log(phba, KERN_ERR, LOG_INIT, 516962306a36Sopenharmony_ci "3326 lpfc_fcp_cpu_map: %d out of range, using " 517062306a36Sopenharmony_ci "default\n", val); 517162306a36Sopenharmony_ci phba->cfg_fcp_cpu_map = LPFC_HBA_CPU_MAP; 517262306a36Sopenharmony_ci 517362306a36Sopenharmony_ci return 0; 517462306a36Sopenharmony_ci} 517562306a36Sopenharmony_ci 517662306a36Sopenharmony_cistatic DEVICE_ATTR_RW(lpfc_fcp_cpu_map); 517762306a36Sopenharmony_ci 517862306a36Sopenharmony_ci/* 517962306a36Sopenharmony_ci# lpfc_fcp_class: Determines FC class to use for the FCP protocol. 518062306a36Sopenharmony_ci# Value range is [2,3]. Default value is 3. 518162306a36Sopenharmony_ci*/ 518262306a36Sopenharmony_ciLPFC_VPORT_ATTR_R(fcp_class, 3, 2, 3, 518362306a36Sopenharmony_ci "Select Fibre Channel class of service for FCP sequences"); 518462306a36Sopenharmony_ci 518562306a36Sopenharmony_ci/* 518662306a36Sopenharmony_ci# lpfc_use_adisc: Use ADISC for FCP rediscovery instead of PLOGI. Value range 518762306a36Sopenharmony_ci# is [0,1]. Default value is 1. 518862306a36Sopenharmony_ci*/ 518962306a36Sopenharmony_ciLPFC_VPORT_ATTR_RW(use_adisc, 1, 0, 1, 519062306a36Sopenharmony_ci "Use ADISC on rediscovery to authenticate FCP devices"); 519162306a36Sopenharmony_ci 519262306a36Sopenharmony_ci/* 519362306a36Sopenharmony_ci# lpfc_first_burst_size: First burst size to use on the NPorts 519462306a36Sopenharmony_ci# that support first burst. 519562306a36Sopenharmony_ci# Value range is [0,65536]. Default value is 0. 519662306a36Sopenharmony_ci*/ 519762306a36Sopenharmony_ciLPFC_VPORT_ATTR_RW(first_burst_size, 0, 0, 65536, 519862306a36Sopenharmony_ci "First burst size for Targets that support first burst"); 519962306a36Sopenharmony_ci 520062306a36Sopenharmony_ci/* 520162306a36Sopenharmony_ci* lpfc_nvmet_fb_size: NVME Target mode supported first burst size. 520262306a36Sopenharmony_ci* When the driver is configured as an NVME target, this value is 520362306a36Sopenharmony_ci* communicated to the NVME initiator in the PRLI response. It is 520462306a36Sopenharmony_ci* used only when the lpfc_nvme_enable_fb and lpfc_nvmet_support 520562306a36Sopenharmony_ci* parameters are set and the target is sending the PRLI RSP. 520662306a36Sopenharmony_ci* Parameter supported on physical port only - no NPIV support. 520762306a36Sopenharmony_ci* Value range is [0,65536]. Default value is 0. 520862306a36Sopenharmony_ci*/ 520962306a36Sopenharmony_ciLPFC_ATTR_RW(nvmet_fb_size, 0, 0, 65536, 521062306a36Sopenharmony_ci "NVME Target mode first burst size in 512B increments."); 521162306a36Sopenharmony_ci 521262306a36Sopenharmony_ci/* 521362306a36Sopenharmony_ci * lpfc_nvme_enable_fb: Enable NVME first burst on I and T functions. 521462306a36Sopenharmony_ci * For the Initiator (I), enabling this parameter means that an NVMET 521562306a36Sopenharmony_ci * PRLI response with FBA enabled and an FB_SIZE set to a nonzero value will be 521662306a36Sopenharmony_ci * processed by the initiator for subsequent NVME FCP IO. 521762306a36Sopenharmony_ci * Currently, this feature is not supported on the NVME target 521862306a36Sopenharmony_ci * Value range is [0,1]. Default value is 0 (disabled). 521962306a36Sopenharmony_ci */ 522062306a36Sopenharmony_ciLPFC_ATTR_RW(nvme_enable_fb, 0, 0, 1, 522162306a36Sopenharmony_ci "Enable First Burst feature for NVME Initiator."); 522262306a36Sopenharmony_ci 522362306a36Sopenharmony_ci/* 522462306a36Sopenharmony_ci# lpfc_max_scsicmpl_time: Use scsi command completion time to control I/O queue 522562306a36Sopenharmony_ci# depth. Default value is 0. When the value of this parameter is zero the 522662306a36Sopenharmony_ci# SCSI command completion time is not used for controlling I/O queue depth. When 522762306a36Sopenharmony_ci# the parameter is set to a non-zero value, the I/O queue depth is controlled 522862306a36Sopenharmony_ci# to limit the I/O completion time to the parameter value. 522962306a36Sopenharmony_ci# The value is set in milliseconds. 523062306a36Sopenharmony_ci*/ 523162306a36Sopenharmony_ciLPFC_VPORT_ATTR(max_scsicmpl_time, 0, 0, 60000, 523262306a36Sopenharmony_ci "Use command completion time to control queue depth"); 523362306a36Sopenharmony_ci 523462306a36Sopenharmony_cilpfc_vport_param_show(max_scsicmpl_time); 523562306a36Sopenharmony_cistatic int 523662306a36Sopenharmony_cilpfc_max_scsicmpl_time_set(struct lpfc_vport *vport, int val) 523762306a36Sopenharmony_ci{ 523862306a36Sopenharmony_ci struct Scsi_Host *shost = lpfc_shost_from_vport(vport); 523962306a36Sopenharmony_ci struct lpfc_nodelist *ndlp, *next_ndlp; 524062306a36Sopenharmony_ci 524162306a36Sopenharmony_ci if (val == vport->cfg_max_scsicmpl_time) 524262306a36Sopenharmony_ci return 0; 524362306a36Sopenharmony_ci if ((val < 0) || (val > 60000)) 524462306a36Sopenharmony_ci return -EINVAL; 524562306a36Sopenharmony_ci vport->cfg_max_scsicmpl_time = val; 524662306a36Sopenharmony_ci 524762306a36Sopenharmony_ci spin_lock_irq(shost->host_lock); 524862306a36Sopenharmony_ci list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) { 524962306a36Sopenharmony_ci if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) 525062306a36Sopenharmony_ci continue; 525162306a36Sopenharmony_ci ndlp->cmd_qdepth = vport->cfg_tgt_queue_depth; 525262306a36Sopenharmony_ci } 525362306a36Sopenharmony_ci spin_unlock_irq(shost->host_lock); 525462306a36Sopenharmony_ci return 0; 525562306a36Sopenharmony_ci} 525662306a36Sopenharmony_cilpfc_vport_param_store(max_scsicmpl_time); 525762306a36Sopenharmony_cistatic DEVICE_ATTR_RW(lpfc_max_scsicmpl_time); 525862306a36Sopenharmony_ci 525962306a36Sopenharmony_ci/* 526062306a36Sopenharmony_ci# lpfc_ack0: Use ACK0, instead of ACK1 for class 2 acknowledgement. Value 526162306a36Sopenharmony_ci# range is [0,1]. Default value is 0. 526262306a36Sopenharmony_ci*/ 526362306a36Sopenharmony_ciLPFC_ATTR_R(ack0, 0, 0, 1, "Enable ACK0 support"); 526462306a36Sopenharmony_ci 526562306a36Sopenharmony_ci/* 526662306a36Sopenharmony_ci# lpfc_xri_rebalancing: enable or disable XRI rebalancing feature 526762306a36Sopenharmony_ci# range is [0,1]. Default value is 1. 526862306a36Sopenharmony_ci*/ 526962306a36Sopenharmony_ciLPFC_ATTR_R(xri_rebalancing, 1, 0, 1, "Enable/Disable XRI rebalancing"); 527062306a36Sopenharmony_ci 527162306a36Sopenharmony_ci/* 527262306a36Sopenharmony_ci * lpfc_io_sched: Determine scheduling algrithmn for issuing FCP cmds 527362306a36Sopenharmony_ci * range is [0,1]. Default value is 0. 527462306a36Sopenharmony_ci * For [0], FCP commands are issued to Work Queues based on upper layer 527562306a36Sopenharmony_ci * hardware queue index. 527662306a36Sopenharmony_ci * For [1], FCP commands are issued to a Work Queue associated with the 527762306a36Sopenharmony_ci * current CPU. 527862306a36Sopenharmony_ci * 527962306a36Sopenharmony_ci * LPFC_FCP_SCHED_BY_HDWQ == 0 528062306a36Sopenharmony_ci * LPFC_FCP_SCHED_BY_CPU == 1 528162306a36Sopenharmony_ci * 528262306a36Sopenharmony_ci * The driver dynamically sets this to 1 (BY_CPU) if it's able to set up cpu 528362306a36Sopenharmony_ci * affinity for FCP/NVME I/Os through Work Queues associated with the current 528462306a36Sopenharmony_ci * CPU. Otherwise, the default 0 (Round Robin) scheduling of FCP/NVME I/Os 528562306a36Sopenharmony_ci * through WQs will be used. 528662306a36Sopenharmony_ci */ 528762306a36Sopenharmony_ciLPFC_ATTR_RW(fcp_io_sched, LPFC_FCP_SCHED_BY_CPU, 528862306a36Sopenharmony_ci LPFC_FCP_SCHED_BY_HDWQ, 528962306a36Sopenharmony_ci LPFC_FCP_SCHED_BY_CPU, 529062306a36Sopenharmony_ci "Determine scheduling algorithm for " 529162306a36Sopenharmony_ci "issuing commands [0] - Hardware Queue, [1] - Current CPU"); 529262306a36Sopenharmony_ci 529362306a36Sopenharmony_ci/* 529462306a36Sopenharmony_ci * lpfc_ns_query: Determine algrithmn for NameServer queries after RSCN 529562306a36Sopenharmony_ci * range is [0,1]. Default value is 0. 529662306a36Sopenharmony_ci * For [0], GID_FT is used for NameServer queries after RSCN (default) 529762306a36Sopenharmony_ci * For [1], GID_PT is used for NameServer queries after RSCN 529862306a36Sopenharmony_ci * 529962306a36Sopenharmony_ci */ 530062306a36Sopenharmony_ciLPFC_ATTR_RW(ns_query, LPFC_NS_QUERY_GID_FT, 530162306a36Sopenharmony_ci LPFC_NS_QUERY_GID_FT, LPFC_NS_QUERY_GID_PT, 530262306a36Sopenharmony_ci "Determine algorithm NameServer queries after RSCN " 530362306a36Sopenharmony_ci "[0] - GID_FT, [1] - GID_PT"); 530462306a36Sopenharmony_ci 530562306a36Sopenharmony_ci/* 530662306a36Sopenharmony_ci# lpfc_fcp2_no_tgt_reset: Determine bus reset behavior 530762306a36Sopenharmony_ci# range is [0,1]. Default value is 0. 530862306a36Sopenharmony_ci# For [0], bus reset issues target reset to ALL devices 530962306a36Sopenharmony_ci# For [1], bus reset issues target reset to non-FCP2 devices 531062306a36Sopenharmony_ci*/ 531162306a36Sopenharmony_ciLPFC_ATTR_RW(fcp2_no_tgt_reset, 0, 0, 1, "Determine bus reset behavior for " 531262306a36Sopenharmony_ci "FCP2 devices [0] - issue tgt reset, [1] - no tgt reset"); 531362306a36Sopenharmony_ci 531462306a36Sopenharmony_ci 531562306a36Sopenharmony_ci/* 531662306a36Sopenharmony_ci# lpfc_cr_delay & lpfc_cr_count: Default values for I/O colaesing 531762306a36Sopenharmony_ci# cr_delay (msec) or cr_count outstanding commands. cr_delay can take 531862306a36Sopenharmony_ci# value [0,63]. cr_count can take value [1,255]. Default value of cr_delay 531962306a36Sopenharmony_ci# is 0. Default value of cr_count is 1. The cr_count feature is disabled if 532062306a36Sopenharmony_ci# cr_delay is set to 0. 532162306a36Sopenharmony_ci*/ 532262306a36Sopenharmony_ciLPFC_ATTR_RW(cr_delay, 0, 0, 63, "A count of milliseconds after which an " 532362306a36Sopenharmony_ci "interrupt response is generated"); 532462306a36Sopenharmony_ci 532562306a36Sopenharmony_ciLPFC_ATTR_RW(cr_count, 1, 1, 255, "A count of I/O completions after which an " 532662306a36Sopenharmony_ci "interrupt response is generated"); 532762306a36Sopenharmony_ci 532862306a36Sopenharmony_ci/* 532962306a36Sopenharmony_ci# lpfc_multi_ring_support: Determines how many rings to spread available 533062306a36Sopenharmony_ci# cmd/rsp IOCB entries across. 533162306a36Sopenharmony_ci# Value range is [1,2]. Default value is 1. 533262306a36Sopenharmony_ci*/ 533362306a36Sopenharmony_ciLPFC_ATTR_R(multi_ring_support, 1, 1, 2, "Determines number of primary " 533462306a36Sopenharmony_ci "SLI rings to spread IOCB entries across"); 533562306a36Sopenharmony_ci 533662306a36Sopenharmony_ci/* 533762306a36Sopenharmony_ci# lpfc_multi_ring_rctl: If lpfc_multi_ring_support is enabled, this 533862306a36Sopenharmony_ci# identifies what rctl value to configure the additional ring for. 533962306a36Sopenharmony_ci# Value range is [1,0xff]. Default value is 4 (Unsolicated Data). 534062306a36Sopenharmony_ci*/ 534162306a36Sopenharmony_ciLPFC_ATTR_R(multi_ring_rctl, FC_RCTL_DD_UNSOL_DATA, 1, 534262306a36Sopenharmony_ci 255, "Identifies RCTL for additional ring configuration"); 534362306a36Sopenharmony_ci 534462306a36Sopenharmony_ci/* 534562306a36Sopenharmony_ci# lpfc_multi_ring_type: If lpfc_multi_ring_support is enabled, this 534662306a36Sopenharmony_ci# identifies what type value to configure the additional ring for. 534762306a36Sopenharmony_ci# Value range is [1,0xff]. Default value is 5 (LLC/SNAP). 534862306a36Sopenharmony_ci*/ 534962306a36Sopenharmony_ciLPFC_ATTR_R(multi_ring_type, FC_TYPE_IP, 1, 535062306a36Sopenharmony_ci 255, "Identifies TYPE for additional ring configuration"); 535162306a36Sopenharmony_ci 535262306a36Sopenharmony_ci/* 535362306a36Sopenharmony_ci# lpfc_enable_SmartSAN: Sets up FDMI support for SmartSAN 535462306a36Sopenharmony_ci# 0 = SmartSAN functionality disabled (default) 535562306a36Sopenharmony_ci# 1 = SmartSAN functionality enabled 535662306a36Sopenharmony_ci# This parameter will override the value of lpfc_fdmi_on module parameter. 535762306a36Sopenharmony_ci# Value range is [0,1]. Default value is 0. 535862306a36Sopenharmony_ci*/ 535962306a36Sopenharmony_ciLPFC_ATTR_R(enable_SmartSAN, 0, 0, 1, "Enable SmartSAN functionality"); 536062306a36Sopenharmony_ci 536162306a36Sopenharmony_ci/* 536262306a36Sopenharmony_ci# lpfc_fdmi_on: Controls FDMI support. 536362306a36Sopenharmony_ci# 0 No FDMI support 536462306a36Sopenharmony_ci# 1 Traditional FDMI support (default) 536562306a36Sopenharmony_ci# Traditional FDMI support means the driver will assume FDMI-2 support; 536662306a36Sopenharmony_ci# however, if that fails, it will fallback to FDMI-1. 536762306a36Sopenharmony_ci# If lpfc_enable_SmartSAN is set to 1, the driver ignores lpfc_fdmi_on. 536862306a36Sopenharmony_ci# If lpfc_enable_SmartSAN is set 0, the driver uses the current value of 536962306a36Sopenharmony_ci# lpfc_fdmi_on. 537062306a36Sopenharmony_ci# Value range [0,1]. Default value is 1. 537162306a36Sopenharmony_ci*/ 537262306a36Sopenharmony_ciLPFC_ATTR_R(fdmi_on, 1, 0, 1, "Enable FDMI support"); 537362306a36Sopenharmony_ci 537462306a36Sopenharmony_ci/* 537562306a36Sopenharmony_ci# Specifies the maximum number of ELS cmds we can have outstanding (for 537662306a36Sopenharmony_ci# discovery). Value range is [1,64]. Default value = 32. 537762306a36Sopenharmony_ci*/ 537862306a36Sopenharmony_ciLPFC_VPORT_ATTR(discovery_threads, 32, 1, 64, "Maximum number of ELS commands " 537962306a36Sopenharmony_ci "during discovery"); 538062306a36Sopenharmony_ci 538162306a36Sopenharmony_ci/* 538262306a36Sopenharmony_ci# lpfc_max_luns: maximum allowed LUN ID. This is the highest LUN ID that 538362306a36Sopenharmony_ci# will be scanned by the SCSI midlayer when sequential scanning is 538462306a36Sopenharmony_ci# used; and is also the highest LUN ID allowed when the SCSI midlayer 538562306a36Sopenharmony_ci# parses REPORT_LUN responses. The lpfc driver has no LUN count or 538662306a36Sopenharmony_ci# LUN ID limit, but the SCSI midlayer requires this field for the uses 538762306a36Sopenharmony_ci# above. The lpfc driver limits the default value to 255 for two reasons. 538862306a36Sopenharmony_ci# As it bounds the sequential scan loop, scanning for thousands of luns 538962306a36Sopenharmony_ci# on a target can take minutes of wall clock time. Additionally, 539062306a36Sopenharmony_ci# there are FC targets, such as JBODs, that only recognize 8-bits of 539162306a36Sopenharmony_ci# LUN ID. When they receive a value greater than 8 bits, they chop off 539262306a36Sopenharmony_ci# the high order bits. In other words, they see LUN IDs 0, 256, 512, 539362306a36Sopenharmony_ci# and so on all as LUN ID 0. This causes the linux kernel, which sees 539462306a36Sopenharmony_ci# valid responses at each of the LUN IDs, to believe there are multiple 539562306a36Sopenharmony_ci# devices present, when in fact, there is only 1. 539662306a36Sopenharmony_ci# A customer that is aware of their target behaviors, and the results as 539762306a36Sopenharmony_ci# indicated above, is welcome to increase the lpfc_max_luns value. 539862306a36Sopenharmony_ci# As mentioned, this value is not used by the lpfc driver, only the 539962306a36Sopenharmony_ci# SCSI midlayer. 540062306a36Sopenharmony_ci# Value range is [0,65535]. Default value is 255. 540162306a36Sopenharmony_ci# NOTE: The SCSI layer might probe all allowed LUN on some old targets. 540262306a36Sopenharmony_ci*/ 540362306a36Sopenharmony_ciLPFC_VPORT_ULL_ATTR_R(max_luns, 255, 0, 65535, "Maximum allowed LUN ID"); 540462306a36Sopenharmony_ci 540562306a36Sopenharmony_ci/* 540662306a36Sopenharmony_ci# lpfc_poll_tmo: .Milliseconds driver will wait between polling FCP ring. 540762306a36Sopenharmony_ci# Value range is [1,255], default value is 10. 540862306a36Sopenharmony_ci*/ 540962306a36Sopenharmony_ciLPFC_ATTR_RW(poll_tmo, 10, 1, 255, 541062306a36Sopenharmony_ci "Milliseconds driver will wait between polling FCP ring"); 541162306a36Sopenharmony_ci 541262306a36Sopenharmony_ci/* 541362306a36Sopenharmony_ci# lpfc_task_mgmt_tmo: Maximum time to wait for task management commands 541462306a36Sopenharmony_ci# to complete in seconds. Value range is [5,180], default value is 60. 541562306a36Sopenharmony_ci*/ 541662306a36Sopenharmony_ciLPFC_ATTR_RW(task_mgmt_tmo, 60, 5, 180, 541762306a36Sopenharmony_ci "Maximum time to wait for task management commands to complete"); 541862306a36Sopenharmony_ci/* 541962306a36Sopenharmony_ci# lpfc_use_msi: Use MSI (Message Signaled Interrupts) in systems that 542062306a36Sopenharmony_ci# support this feature 542162306a36Sopenharmony_ci# 0 = MSI disabled 542262306a36Sopenharmony_ci# 1 = MSI enabled 542362306a36Sopenharmony_ci# 2 = MSI-X enabled (default) 542462306a36Sopenharmony_ci# Value range is [0,2]. Default value is 2. 542562306a36Sopenharmony_ci*/ 542662306a36Sopenharmony_ciLPFC_ATTR_R(use_msi, 2, 0, 2, "Use Message Signaled Interrupts (1) or " 542762306a36Sopenharmony_ci "MSI-X (2), if possible"); 542862306a36Sopenharmony_ci 542962306a36Sopenharmony_ci/* 543062306a36Sopenharmony_ci * lpfc_nvme_oas: Use the oas bit when sending NVME/NVMET IOs 543162306a36Sopenharmony_ci * 543262306a36Sopenharmony_ci * 0 = NVME OAS disabled 543362306a36Sopenharmony_ci * 1 = NVME OAS enabled 543462306a36Sopenharmony_ci * 543562306a36Sopenharmony_ci * Value range is [0,1]. Default value is 0. 543662306a36Sopenharmony_ci */ 543762306a36Sopenharmony_ciLPFC_ATTR_RW(nvme_oas, 0, 0, 1, 543862306a36Sopenharmony_ci "Use OAS bit on NVME IOs"); 543962306a36Sopenharmony_ci 544062306a36Sopenharmony_ci/* 544162306a36Sopenharmony_ci * lpfc_nvme_embed_cmd: Use the oas bit when sending NVME/NVMET IOs 544262306a36Sopenharmony_ci * 544362306a36Sopenharmony_ci * 0 = Put NVME Command in SGL 544462306a36Sopenharmony_ci * 1 = Embed NVME Command in WQE (unless G7) 544562306a36Sopenharmony_ci * 2 = Embed NVME Command in WQE (force) 544662306a36Sopenharmony_ci * 544762306a36Sopenharmony_ci * Value range is [0,2]. Default value is 1. 544862306a36Sopenharmony_ci */ 544962306a36Sopenharmony_ciLPFC_ATTR_RW(nvme_embed_cmd, 1, 0, 2, 545062306a36Sopenharmony_ci "Embed NVME Command in WQE"); 545162306a36Sopenharmony_ci 545262306a36Sopenharmony_ci/* 545362306a36Sopenharmony_ci * lpfc_fcp_mq_threshold: Set the maximum number of Hardware Queues 545462306a36Sopenharmony_ci * the driver will advertise it supports to the SCSI layer. 545562306a36Sopenharmony_ci * 545662306a36Sopenharmony_ci * 0 = Set nr_hw_queues by the number of CPUs or HW queues. 545762306a36Sopenharmony_ci * 1,256 = Manually specify nr_hw_queue value to be advertised, 545862306a36Sopenharmony_ci * 545962306a36Sopenharmony_ci * Value range is [0,256]. Default value is 8. 546062306a36Sopenharmony_ci */ 546162306a36Sopenharmony_ciLPFC_ATTR_R(fcp_mq_threshold, LPFC_FCP_MQ_THRESHOLD_DEF, 546262306a36Sopenharmony_ci LPFC_FCP_MQ_THRESHOLD_MIN, LPFC_FCP_MQ_THRESHOLD_MAX, 546362306a36Sopenharmony_ci "Set the number of SCSI Queues advertised"); 546462306a36Sopenharmony_ci 546562306a36Sopenharmony_ci/* 546662306a36Sopenharmony_ci * lpfc_hdw_queue: Set the number of Hardware Queues the driver 546762306a36Sopenharmony_ci * will advertise it supports to the NVME and SCSI layers. This also 546862306a36Sopenharmony_ci * will map to the number of CQ/WQ pairs the driver will create. 546962306a36Sopenharmony_ci * 547062306a36Sopenharmony_ci * The NVME Layer will try to create this many, plus 1 administrative 547162306a36Sopenharmony_ci * hardware queue. The administrative queue will always map to WQ 0 547262306a36Sopenharmony_ci * A hardware IO queue maps (qidx) to a specific driver CQ/WQ. 547362306a36Sopenharmony_ci * 547462306a36Sopenharmony_ci * 0 = Configure the number of hdw queues to the number of active CPUs. 547562306a36Sopenharmony_ci * 1,256 = Manually specify how many hdw queues to use. 547662306a36Sopenharmony_ci * 547762306a36Sopenharmony_ci * Value range is [0,256]. Default value is 0. 547862306a36Sopenharmony_ci */ 547962306a36Sopenharmony_ciLPFC_ATTR_R(hdw_queue, 548062306a36Sopenharmony_ci LPFC_HBA_HDWQ_DEF, 548162306a36Sopenharmony_ci LPFC_HBA_HDWQ_MIN, LPFC_HBA_HDWQ_MAX, 548262306a36Sopenharmony_ci "Set the number of I/O Hardware Queues"); 548362306a36Sopenharmony_ci 548462306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_X86) 548562306a36Sopenharmony_ci/** 548662306a36Sopenharmony_ci * lpfc_cpumask_irq_mode_init - initalizes cpumask of phba based on 548762306a36Sopenharmony_ci * irq_chann_mode 548862306a36Sopenharmony_ci * @phba: Pointer to HBA context object. 548962306a36Sopenharmony_ci **/ 549062306a36Sopenharmony_cistatic void 549162306a36Sopenharmony_cilpfc_cpumask_irq_mode_init(struct lpfc_hba *phba) 549262306a36Sopenharmony_ci{ 549362306a36Sopenharmony_ci unsigned int cpu, first_cpu, numa_node = NUMA_NO_NODE; 549462306a36Sopenharmony_ci const struct cpumask *sibling_mask; 549562306a36Sopenharmony_ci struct cpumask *aff_mask = &phba->sli4_hba.irq_aff_mask; 549662306a36Sopenharmony_ci 549762306a36Sopenharmony_ci cpumask_clear(aff_mask); 549862306a36Sopenharmony_ci 549962306a36Sopenharmony_ci if (phba->irq_chann_mode == NUMA_MODE) { 550062306a36Sopenharmony_ci /* Check if we're a NUMA architecture */ 550162306a36Sopenharmony_ci numa_node = dev_to_node(&phba->pcidev->dev); 550262306a36Sopenharmony_ci if (numa_node == NUMA_NO_NODE) { 550362306a36Sopenharmony_ci phba->irq_chann_mode = NORMAL_MODE; 550462306a36Sopenharmony_ci return; 550562306a36Sopenharmony_ci } 550662306a36Sopenharmony_ci } 550762306a36Sopenharmony_ci 550862306a36Sopenharmony_ci for_each_possible_cpu(cpu) { 550962306a36Sopenharmony_ci switch (phba->irq_chann_mode) { 551062306a36Sopenharmony_ci case NUMA_MODE: 551162306a36Sopenharmony_ci if (cpu_to_node(cpu) == numa_node) 551262306a36Sopenharmony_ci cpumask_set_cpu(cpu, aff_mask); 551362306a36Sopenharmony_ci break; 551462306a36Sopenharmony_ci case NHT_MODE: 551562306a36Sopenharmony_ci sibling_mask = topology_sibling_cpumask(cpu); 551662306a36Sopenharmony_ci first_cpu = cpumask_first(sibling_mask); 551762306a36Sopenharmony_ci if (first_cpu < nr_cpu_ids) 551862306a36Sopenharmony_ci cpumask_set_cpu(first_cpu, aff_mask); 551962306a36Sopenharmony_ci break; 552062306a36Sopenharmony_ci default: 552162306a36Sopenharmony_ci break; 552262306a36Sopenharmony_ci } 552362306a36Sopenharmony_ci } 552462306a36Sopenharmony_ci} 552562306a36Sopenharmony_ci#endif 552662306a36Sopenharmony_ci 552762306a36Sopenharmony_cistatic void 552862306a36Sopenharmony_cilpfc_assign_default_irq_chann(struct lpfc_hba *phba) 552962306a36Sopenharmony_ci{ 553062306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_X86) 553162306a36Sopenharmony_ci switch (boot_cpu_data.x86_vendor) { 553262306a36Sopenharmony_ci case X86_VENDOR_AMD: 553362306a36Sopenharmony_ci /* If AMD architecture, then default is NUMA_MODE */ 553462306a36Sopenharmony_ci phba->irq_chann_mode = NUMA_MODE; 553562306a36Sopenharmony_ci break; 553662306a36Sopenharmony_ci case X86_VENDOR_INTEL: 553762306a36Sopenharmony_ci /* If Intel architecture, then default is no hyperthread mode */ 553862306a36Sopenharmony_ci phba->irq_chann_mode = NHT_MODE; 553962306a36Sopenharmony_ci break; 554062306a36Sopenharmony_ci default: 554162306a36Sopenharmony_ci phba->irq_chann_mode = NORMAL_MODE; 554262306a36Sopenharmony_ci break; 554362306a36Sopenharmony_ci } 554462306a36Sopenharmony_ci lpfc_cpumask_irq_mode_init(phba); 554562306a36Sopenharmony_ci#else 554662306a36Sopenharmony_ci phba->irq_chann_mode = NORMAL_MODE; 554762306a36Sopenharmony_ci#endif 554862306a36Sopenharmony_ci} 554962306a36Sopenharmony_ci 555062306a36Sopenharmony_ci/* 555162306a36Sopenharmony_ci * lpfc_irq_chann: Set the number of IRQ vectors that are available 555262306a36Sopenharmony_ci * for Hardware Queues to utilize. This also will map to the number 555362306a36Sopenharmony_ci * of EQ / MSI-X vectors the driver will create. This should never be 555462306a36Sopenharmony_ci * more than the number of Hardware Queues 555562306a36Sopenharmony_ci * 555662306a36Sopenharmony_ci * 0 = Configure number of IRQ Channels to: 555762306a36Sopenharmony_ci * if AMD architecture, number of CPUs on HBA's NUMA node 555862306a36Sopenharmony_ci * if Intel architecture, number of physical CPUs. 555962306a36Sopenharmony_ci * otherwise, number of active CPUs. 556062306a36Sopenharmony_ci * [1,256] = Manually specify how many IRQ Channels to use. 556162306a36Sopenharmony_ci * 556262306a36Sopenharmony_ci * Value range is [0,256]. Default value is [0]. 556362306a36Sopenharmony_ci */ 556462306a36Sopenharmony_cistatic uint lpfc_irq_chann = LPFC_IRQ_CHANN_DEF; 556562306a36Sopenharmony_cimodule_param(lpfc_irq_chann, uint, 0444); 556662306a36Sopenharmony_ciMODULE_PARM_DESC(lpfc_irq_chann, "Set number of interrupt vectors to allocate"); 556762306a36Sopenharmony_ci 556862306a36Sopenharmony_ci/* lpfc_irq_chann_init - Set the hba irq_chann initial value 556962306a36Sopenharmony_ci * @phba: lpfc_hba pointer. 557062306a36Sopenharmony_ci * @val: contains the initial value 557162306a36Sopenharmony_ci * 557262306a36Sopenharmony_ci * Description: 557362306a36Sopenharmony_ci * Validates the initial value is within range and assigns it to the 557462306a36Sopenharmony_ci * adapter. If not in range, an error message is posted and the 557562306a36Sopenharmony_ci * default value is assigned. 557662306a36Sopenharmony_ci * 557762306a36Sopenharmony_ci * Returns: 557862306a36Sopenharmony_ci * zero if value is in range and is set 557962306a36Sopenharmony_ci * -EINVAL if value was out of range 558062306a36Sopenharmony_ci **/ 558162306a36Sopenharmony_cistatic int 558262306a36Sopenharmony_cilpfc_irq_chann_init(struct lpfc_hba *phba, uint32_t val) 558362306a36Sopenharmony_ci{ 558462306a36Sopenharmony_ci const struct cpumask *aff_mask; 558562306a36Sopenharmony_ci 558662306a36Sopenharmony_ci if (phba->cfg_use_msi != 2) { 558762306a36Sopenharmony_ci lpfc_printf_log(phba, KERN_INFO, LOG_INIT, 558862306a36Sopenharmony_ci "8532 use_msi = %u ignoring cfg_irq_numa\n", 558962306a36Sopenharmony_ci phba->cfg_use_msi); 559062306a36Sopenharmony_ci phba->irq_chann_mode = NORMAL_MODE; 559162306a36Sopenharmony_ci phba->cfg_irq_chann = LPFC_IRQ_CHANN_DEF; 559262306a36Sopenharmony_ci return 0; 559362306a36Sopenharmony_ci } 559462306a36Sopenharmony_ci 559562306a36Sopenharmony_ci /* Check if default setting was passed */ 559662306a36Sopenharmony_ci if (val == LPFC_IRQ_CHANN_DEF && 559762306a36Sopenharmony_ci phba->cfg_hdw_queue == LPFC_HBA_HDWQ_DEF && 559862306a36Sopenharmony_ci phba->sli_rev == LPFC_SLI_REV4) 559962306a36Sopenharmony_ci lpfc_assign_default_irq_chann(phba); 560062306a36Sopenharmony_ci 560162306a36Sopenharmony_ci if (phba->irq_chann_mode != NORMAL_MODE) { 560262306a36Sopenharmony_ci aff_mask = &phba->sli4_hba.irq_aff_mask; 560362306a36Sopenharmony_ci 560462306a36Sopenharmony_ci if (cpumask_empty(aff_mask)) { 560562306a36Sopenharmony_ci lpfc_printf_log(phba, KERN_INFO, LOG_INIT, 560662306a36Sopenharmony_ci "8533 Could not identify CPUS for " 560762306a36Sopenharmony_ci "mode %d, ignoring\n", 560862306a36Sopenharmony_ci phba->irq_chann_mode); 560962306a36Sopenharmony_ci phba->irq_chann_mode = NORMAL_MODE; 561062306a36Sopenharmony_ci phba->cfg_irq_chann = LPFC_IRQ_CHANN_DEF; 561162306a36Sopenharmony_ci } else { 561262306a36Sopenharmony_ci phba->cfg_irq_chann = cpumask_weight(aff_mask); 561362306a36Sopenharmony_ci 561462306a36Sopenharmony_ci /* If no hyperthread mode, then set hdwq count to 561562306a36Sopenharmony_ci * aff_mask weight as well 561662306a36Sopenharmony_ci */ 561762306a36Sopenharmony_ci if (phba->irq_chann_mode == NHT_MODE) 561862306a36Sopenharmony_ci phba->cfg_hdw_queue = phba->cfg_irq_chann; 561962306a36Sopenharmony_ci 562062306a36Sopenharmony_ci lpfc_printf_log(phba, KERN_INFO, LOG_INIT, 562162306a36Sopenharmony_ci "8543 lpfc_irq_chann set to %u " 562262306a36Sopenharmony_ci "(mode: %d)\n", phba->cfg_irq_chann, 562362306a36Sopenharmony_ci phba->irq_chann_mode); 562462306a36Sopenharmony_ci } 562562306a36Sopenharmony_ci } else { 562662306a36Sopenharmony_ci if (val > LPFC_IRQ_CHANN_MAX) { 562762306a36Sopenharmony_ci lpfc_printf_log(phba, KERN_INFO, LOG_INIT, 562862306a36Sopenharmony_ci "8545 lpfc_irq_chann attribute cannot " 562962306a36Sopenharmony_ci "be set to %u, allowed range is " 563062306a36Sopenharmony_ci "[%u,%u]\n", 563162306a36Sopenharmony_ci val, 563262306a36Sopenharmony_ci LPFC_IRQ_CHANN_MIN, 563362306a36Sopenharmony_ci LPFC_IRQ_CHANN_MAX); 563462306a36Sopenharmony_ci phba->cfg_irq_chann = LPFC_IRQ_CHANN_DEF; 563562306a36Sopenharmony_ci return -EINVAL; 563662306a36Sopenharmony_ci } 563762306a36Sopenharmony_ci if (phba->sli_rev == LPFC_SLI_REV4) { 563862306a36Sopenharmony_ci phba->cfg_irq_chann = val; 563962306a36Sopenharmony_ci } else { 564062306a36Sopenharmony_ci phba->cfg_irq_chann = 2; 564162306a36Sopenharmony_ci phba->cfg_hdw_queue = 1; 564262306a36Sopenharmony_ci } 564362306a36Sopenharmony_ci } 564462306a36Sopenharmony_ci 564562306a36Sopenharmony_ci return 0; 564662306a36Sopenharmony_ci} 564762306a36Sopenharmony_ci 564862306a36Sopenharmony_ci/** 564962306a36Sopenharmony_ci * lpfc_irq_chann_show - Display value of irq_chann 565062306a36Sopenharmony_ci * @dev: class converted to a Scsi_host structure. 565162306a36Sopenharmony_ci * @attr: device attribute, not used. 565262306a36Sopenharmony_ci * @buf: on return contains a string with the list sizes 565362306a36Sopenharmony_ci * 565462306a36Sopenharmony_ci * Returns: size of formatted string. 565562306a36Sopenharmony_ci **/ 565662306a36Sopenharmony_cistatic ssize_t 565762306a36Sopenharmony_cilpfc_irq_chann_show(struct device *dev, struct device_attribute *attr, 565862306a36Sopenharmony_ci char *buf) 565962306a36Sopenharmony_ci{ 566062306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 566162306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata; 566262306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 566362306a36Sopenharmony_ci 566462306a36Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%u\n", phba->cfg_irq_chann); 566562306a36Sopenharmony_ci} 566662306a36Sopenharmony_ci 566762306a36Sopenharmony_cistatic DEVICE_ATTR_RO(lpfc_irq_chann); 566862306a36Sopenharmony_ci 566962306a36Sopenharmony_ci/* 567062306a36Sopenharmony_ci# lpfc_enable_hba_reset: Allow or prevent HBA resets to the hardware. 567162306a36Sopenharmony_ci# 0 = HBA resets disabled 567262306a36Sopenharmony_ci# 1 = HBA resets enabled (default) 567362306a36Sopenharmony_ci# 2 = HBA reset via PCI bus reset enabled 567462306a36Sopenharmony_ci# Value range is [0,2]. Default value is 1. 567562306a36Sopenharmony_ci*/ 567662306a36Sopenharmony_ciLPFC_ATTR_RW(enable_hba_reset, 1, 0, 2, "Enable HBA resets from the driver."); 567762306a36Sopenharmony_ci 567862306a36Sopenharmony_ci/* 567962306a36Sopenharmony_ci# lpfc_enable_hba_heartbeat: Disable HBA heartbeat timer.. 568062306a36Sopenharmony_ci# 0 = HBA Heartbeat disabled 568162306a36Sopenharmony_ci# 1 = HBA Heartbeat enabled (default) 568262306a36Sopenharmony_ci# Value range is [0,1]. Default value is 1. 568362306a36Sopenharmony_ci*/ 568462306a36Sopenharmony_ciLPFC_ATTR_R(enable_hba_heartbeat, 0, 0, 1, "Enable HBA Heartbeat."); 568562306a36Sopenharmony_ci 568662306a36Sopenharmony_ci/* 568762306a36Sopenharmony_ci# lpfc_EnableXLane: Enable Express Lane Feature 568862306a36Sopenharmony_ci# 0x0 Express Lane Feature disabled 568962306a36Sopenharmony_ci# 0x1 Express Lane Feature enabled 569062306a36Sopenharmony_ci# Value range is [0,1]. Default value is 0. 569162306a36Sopenharmony_ci*/ 569262306a36Sopenharmony_ciLPFC_ATTR_R(EnableXLane, 0, 0, 1, "Enable Express Lane Feature."); 569362306a36Sopenharmony_ci 569462306a36Sopenharmony_ci/* 569562306a36Sopenharmony_ci# lpfc_XLanePriority: Define CS_CTL priority for Express Lane Feature 569662306a36Sopenharmony_ci# 0x0 - 0x7f = CS_CTL field in FC header (high 7 bits) 569762306a36Sopenharmony_ci# Value range is [0x0,0x7f]. Default value is 0 569862306a36Sopenharmony_ci*/ 569962306a36Sopenharmony_ciLPFC_ATTR_RW(XLanePriority, 0, 0x0, 0x7f, "CS_CTL for Express Lane Feature."); 570062306a36Sopenharmony_ci 570162306a36Sopenharmony_ci/* 570262306a36Sopenharmony_ci# lpfc_enable_bg: Enable BlockGuard (Emulex's Implementation of T10-DIF) 570362306a36Sopenharmony_ci# 0 = BlockGuard disabled (default) 570462306a36Sopenharmony_ci# 1 = BlockGuard enabled 570562306a36Sopenharmony_ci# Value range is [0,1]. Default value is 0. 570662306a36Sopenharmony_ci*/ 570762306a36Sopenharmony_ciLPFC_ATTR_R(enable_bg, 0, 0, 1, "Enable BlockGuard Support"); 570862306a36Sopenharmony_ci 570962306a36Sopenharmony_ci/* 571062306a36Sopenharmony_ci# lpfc_prot_mask: 571162306a36Sopenharmony_ci# - Bit mask of host protection capabilities used to register with the 571262306a36Sopenharmony_ci# SCSI mid-layer 571362306a36Sopenharmony_ci# - Only meaningful if BG is turned on (lpfc_enable_bg=1). 571462306a36Sopenharmony_ci# - Allows you to ultimately specify which profiles to use 571562306a36Sopenharmony_ci# - Default will result in registering capabilities for all profiles. 571662306a36Sopenharmony_ci# - SHOST_DIF_TYPE1_PROTECTION 1 571762306a36Sopenharmony_ci# HBA supports T10 DIF Type 1: HBA to Target Type 1 Protection 571862306a36Sopenharmony_ci# - SHOST_DIX_TYPE0_PROTECTION 8 571962306a36Sopenharmony_ci# HBA supports DIX Type 0: Host to HBA protection only 572062306a36Sopenharmony_ci# - SHOST_DIX_TYPE1_PROTECTION 16 572162306a36Sopenharmony_ci# HBA supports DIX Type 1: Host to HBA Type 1 protection 572262306a36Sopenharmony_ci# 572362306a36Sopenharmony_ci*/ 572462306a36Sopenharmony_ciLPFC_ATTR(prot_mask, 572562306a36Sopenharmony_ci (SHOST_DIF_TYPE1_PROTECTION | 572662306a36Sopenharmony_ci SHOST_DIX_TYPE0_PROTECTION | 572762306a36Sopenharmony_ci SHOST_DIX_TYPE1_PROTECTION), 572862306a36Sopenharmony_ci 0, 572962306a36Sopenharmony_ci (SHOST_DIF_TYPE1_PROTECTION | 573062306a36Sopenharmony_ci SHOST_DIX_TYPE0_PROTECTION | 573162306a36Sopenharmony_ci SHOST_DIX_TYPE1_PROTECTION), 573262306a36Sopenharmony_ci "T10-DIF host protection capabilities mask"); 573362306a36Sopenharmony_ci 573462306a36Sopenharmony_ci/* 573562306a36Sopenharmony_ci# lpfc_prot_guard: 573662306a36Sopenharmony_ci# - Bit mask of protection guard types to register with the SCSI mid-layer 573762306a36Sopenharmony_ci# - Guard types are currently either 1) T10-DIF CRC 2) IP checksum 573862306a36Sopenharmony_ci# - Allows you to ultimately specify which profiles to use 573962306a36Sopenharmony_ci# - Default will result in registering capabilities for all guard types 574062306a36Sopenharmony_ci# 574162306a36Sopenharmony_ci*/ 574262306a36Sopenharmony_ciLPFC_ATTR(prot_guard, 574362306a36Sopenharmony_ci SHOST_DIX_GUARD_IP, SHOST_DIX_GUARD_CRC, SHOST_DIX_GUARD_IP, 574462306a36Sopenharmony_ci "T10-DIF host protection guard type"); 574562306a36Sopenharmony_ci 574662306a36Sopenharmony_ci/* 574762306a36Sopenharmony_ci * Delay initial NPort discovery when Clean Address bit is cleared in 574862306a36Sopenharmony_ci * FLOGI/FDISC accept and FCID/Fabric name/Fabric portname is changed. 574962306a36Sopenharmony_ci * This parameter can have value 0 or 1. 575062306a36Sopenharmony_ci * When this parameter is set to 0, no delay is added to the initial 575162306a36Sopenharmony_ci * discovery. 575262306a36Sopenharmony_ci * When this parameter is set to non-zero value, initial Nport discovery is 575362306a36Sopenharmony_ci * delayed by ra_tov seconds when Clean Address bit is cleared in FLOGI/FDISC 575462306a36Sopenharmony_ci * accept and FCID/Fabric name/Fabric portname is changed. 575562306a36Sopenharmony_ci * Driver always delay Nport discovery for subsequent FLOGI/FDISC completion 575662306a36Sopenharmony_ci * when Clean Address bit is cleared in FLOGI/FDISC 575762306a36Sopenharmony_ci * accept and FCID/Fabric name/Fabric portname is changed. 575862306a36Sopenharmony_ci * Default value is 0. 575962306a36Sopenharmony_ci */ 576062306a36Sopenharmony_ciLPFC_ATTR(delay_discovery, 0, 0, 1, 576162306a36Sopenharmony_ci "Delay NPort discovery when Clean Address bit is cleared."); 576262306a36Sopenharmony_ci 576362306a36Sopenharmony_ci/* 576462306a36Sopenharmony_ci * lpfc_sg_seg_cnt - Initial Maximum DMA Segment Count 576562306a36Sopenharmony_ci * This value can be set to values between 64 and 4096. The default value 576662306a36Sopenharmony_ci * is 64, but may be increased to allow for larger Max I/O sizes. The scsi 576762306a36Sopenharmony_ci * and nvme layers will allow I/O sizes up to (MAX_SEG_COUNT * SEG_SIZE). 576862306a36Sopenharmony_ci * Because of the additional overhead involved in setting up T10-DIF, 576962306a36Sopenharmony_ci * this parameter will be limited to 128 if BlockGuard is enabled under SLI4 577062306a36Sopenharmony_ci * and will be limited to 512 if BlockGuard is enabled under SLI3. 577162306a36Sopenharmony_ci */ 577262306a36Sopenharmony_cistatic uint lpfc_sg_seg_cnt = LPFC_DEFAULT_SG_SEG_CNT; 577362306a36Sopenharmony_cimodule_param(lpfc_sg_seg_cnt, uint, 0444); 577462306a36Sopenharmony_ciMODULE_PARM_DESC(lpfc_sg_seg_cnt, "Max Scatter Gather Segment Count"); 577562306a36Sopenharmony_ci 577662306a36Sopenharmony_ci/** 577762306a36Sopenharmony_ci * lpfc_sg_seg_cnt_show - Display the scatter/gather list sizes 577862306a36Sopenharmony_ci * configured for the adapter 577962306a36Sopenharmony_ci * @dev: class converted to a Scsi_host structure. 578062306a36Sopenharmony_ci * @attr: device attribute, not used. 578162306a36Sopenharmony_ci * @buf: on return contains a string with the list sizes 578262306a36Sopenharmony_ci * 578362306a36Sopenharmony_ci * Returns: size of formatted string. 578462306a36Sopenharmony_ci **/ 578562306a36Sopenharmony_cistatic ssize_t 578662306a36Sopenharmony_cilpfc_sg_seg_cnt_show(struct device *dev, struct device_attribute *attr, 578762306a36Sopenharmony_ci char *buf) 578862306a36Sopenharmony_ci{ 578962306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 579062306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata; 579162306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 579262306a36Sopenharmony_ci int len; 579362306a36Sopenharmony_ci 579462306a36Sopenharmony_ci len = scnprintf(buf, PAGE_SIZE, "SGL sz: %d total SGEs: %d\n", 579562306a36Sopenharmony_ci phba->cfg_sg_dma_buf_size, phba->cfg_total_seg_cnt); 579662306a36Sopenharmony_ci 579762306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, 579862306a36Sopenharmony_ci "Cfg: %d SCSI: %d NVME: %d\n", 579962306a36Sopenharmony_ci phba->cfg_sg_seg_cnt, phba->cfg_scsi_seg_cnt, 580062306a36Sopenharmony_ci phba->cfg_nvme_seg_cnt); 580162306a36Sopenharmony_ci return len; 580262306a36Sopenharmony_ci} 580362306a36Sopenharmony_ci 580462306a36Sopenharmony_cistatic DEVICE_ATTR_RO(lpfc_sg_seg_cnt); 580562306a36Sopenharmony_ci 580662306a36Sopenharmony_ci/** 580762306a36Sopenharmony_ci * lpfc_sg_seg_cnt_init - Set the hba sg_seg_cnt initial value 580862306a36Sopenharmony_ci * @phba: lpfc_hba pointer. 580962306a36Sopenharmony_ci * @val: contains the initial value 581062306a36Sopenharmony_ci * 581162306a36Sopenharmony_ci * Description: 581262306a36Sopenharmony_ci * Validates the initial value is within range and assigns it to the 581362306a36Sopenharmony_ci * adapter. If not in range, an error message is posted and the 581462306a36Sopenharmony_ci * default value is assigned. 581562306a36Sopenharmony_ci * 581662306a36Sopenharmony_ci * Returns: 581762306a36Sopenharmony_ci * zero if value is in range and is set 581862306a36Sopenharmony_ci * -EINVAL if value was out of range 581962306a36Sopenharmony_ci **/ 582062306a36Sopenharmony_cistatic int 582162306a36Sopenharmony_cilpfc_sg_seg_cnt_init(struct lpfc_hba *phba, int val) 582262306a36Sopenharmony_ci{ 582362306a36Sopenharmony_ci if (val >= LPFC_MIN_SG_SEG_CNT && val <= LPFC_MAX_SG_SEG_CNT) { 582462306a36Sopenharmony_ci phba->cfg_sg_seg_cnt = val; 582562306a36Sopenharmony_ci return 0; 582662306a36Sopenharmony_ci } 582762306a36Sopenharmony_ci lpfc_printf_log(phba, KERN_ERR, LOG_INIT, 582862306a36Sopenharmony_ci "0409 lpfc_sg_seg_cnt attribute cannot be set to %d, " 582962306a36Sopenharmony_ci "allowed range is [%d, %d]\n", 583062306a36Sopenharmony_ci val, LPFC_MIN_SG_SEG_CNT, LPFC_MAX_SG_SEG_CNT); 583162306a36Sopenharmony_ci phba->cfg_sg_seg_cnt = LPFC_DEFAULT_SG_SEG_CNT; 583262306a36Sopenharmony_ci return -EINVAL; 583362306a36Sopenharmony_ci} 583462306a36Sopenharmony_ci 583562306a36Sopenharmony_ci/* 583662306a36Sopenharmony_ci * lpfc_enable_mds_diags: Enable MDS Diagnostics 583762306a36Sopenharmony_ci * 0 = MDS Diagnostics disabled (default) 583862306a36Sopenharmony_ci * 1 = MDS Diagnostics enabled 583962306a36Sopenharmony_ci * Value range is [0,1]. Default value is 0. 584062306a36Sopenharmony_ci */ 584162306a36Sopenharmony_ciLPFC_ATTR_RW(enable_mds_diags, 0, 0, 1, "Enable MDS Diagnostics"); 584262306a36Sopenharmony_ci 584362306a36Sopenharmony_ci/* 584462306a36Sopenharmony_ci * lpfc_ras_fwlog_buffsize: Firmware logging host buffer size 584562306a36Sopenharmony_ci * 0 = Disable firmware logging (default) 584662306a36Sopenharmony_ci * [1-4] = Multiple of 1/4th Mb of host memory for FW logging 584762306a36Sopenharmony_ci * Value range [0..4]. Default value is 0 584862306a36Sopenharmony_ci */ 584962306a36Sopenharmony_ciLPFC_ATTR(ras_fwlog_buffsize, 0, 0, 4, "Host memory for FW logging"); 585062306a36Sopenharmony_cilpfc_param_show(ras_fwlog_buffsize); 585162306a36Sopenharmony_ci 585262306a36Sopenharmony_cistatic ssize_t 585362306a36Sopenharmony_cilpfc_ras_fwlog_buffsize_set(struct lpfc_hba *phba, uint val) 585462306a36Sopenharmony_ci{ 585562306a36Sopenharmony_ci int ret = 0; 585662306a36Sopenharmony_ci enum ras_state state; 585762306a36Sopenharmony_ci 585862306a36Sopenharmony_ci if (!lpfc_rangecheck(val, 0, 4)) 585962306a36Sopenharmony_ci return -EINVAL; 586062306a36Sopenharmony_ci 586162306a36Sopenharmony_ci if (phba->cfg_ras_fwlog_buffsize == val) 586262306a36Sopenharmony_ci return 0; 586362306a36Sopenharmony_ci 586462306a36Sopenharmony_ci if (phba->cfg_ras_fwlog_func != PCI_FUNC(phba->pcidev->devfn)) 586562306a36Sopenharmony_ci return -EINVAL; 586662306a36Sopenharmony_ci 586762306a36Sopenharmony_ci spin_lock_irq(&phba->hbalock); 586862306a36Sopenharmony_ci state = phba->ras_fwlog.state; 586962306a36Sopenharmony_ci spin_unlock_irq(&phba->hbalock); 587062306a36Sopenharmony_ci 587162306a36Sopenharmony_ci if (state == REG_INPROGRESS) { 587262306a36Sopenharmony_ci lpfc_printf_log(phba, KERN_ERR, LOG_SLI, "6147 RAS Logging " 587362306a36Sopenharmony_ci "registration is in progress\n"); 587462306a36Sopenharmony_ci return -EBUSY; 587562306a36Sopenharmony_ci } 587662306a36Sopenharmony_ci 587762306a36Sopenharmony_ci /* For disable logging: stop the logs and free the DMA. 587862306a36Sopenharmony_ci * For ras_fwlog_buffsize size change we still need to free and 587962306a36Sopenharmony_ci * reallocate the DMA in lpfc_sli4_ras_fwlog_init. 588062306a36Sopenharmony_ci */ 588162306a36Sopenharmony_ci phba->cfg_ras_fwlog_buffsize = val; 588262306a36Sopenharmony_ci if (state == ACTIVE) { 588362306a36Sopenharmony_ci lpfc_ras_stop_fwlog(phba); 588462306a36Sopenharmony_ci lpfc_sli4_ras_dma_free(phba); 588562306a36Sopenharmony_ci } 588662306a36Sopenharmony_ci 588762306a36Sopenharmony_ci lpfc_sli4_ras_init(phba); 588862306a36Sopenharmony_ci if (phba->ras_fwlog.ras_enabled) 588962306a36Sopenharmony_ci ret = lpfc_sli4_ras_fwlog_init(phba, phba->cfg_ras_fwlog_level, 589062306a36Sopenharmony_ci LPFC_RAS_ENABLE_LOGGING); 589162306a36Sopenharmony_ci return ret; 589262306a36Sopenharmony_ci} 589362306a36Sopenharmony_ci 589462306a36Sopenharmony_cilpfc_param_store(ras_fwlog_buffsize); 589562306a36Sopenharmony_cistatic DEVICE_ATTR_RW(lpfc_ras_fwlog_buffsize); 589662306a36Sopenharmony_ci 589762306a36Sopenharmony_ci/* 589862306a36Sopenharmony_ci * lpfc_ras_fwlog_level: Firmware logging verbosity level 589962306a36Sopenharmony_ci * Valid only if firmware logging is enabled 590062306a36Sopenharmony_ci * 0(Least Verbosity) 4 (most verbosity) 590162306a36Sopenharmony_ci * Value range is [0..4]. Default value is 0 590262306a36Sopenharmony_ci */ 590362306a36Sopenharmony_ciLPFC_ATTR_RW(ras_fwlog_level, 0, 0, 4, "Firmware Logging Level"); 590462306a36Sopenharmony_ci 590562306a36Sopenharmony_ci/* 590662306a36Sopenharmony_ci * lpfc_ras_fwlog_func: Firmware logging enabled on function number 590762306a36Sopenharmony_ci * Default function which has RAS support : 0 590862306a36Sopenharmony_ci * Value Range is [0..7]. 590962306a36Sopenharmony_ci * FW logging is a global action and enablement is via a specific 591062306a36Sopenharmony_ci * port. 591162306a36Sopenharmony_ci */ 591262306a36Sopenharmony_ciLPFC_ATTR_RW(ras_fwlog_func, 0, 0, 7, "Firmware Logging Enabled on Function"); 591362306a36Sopenharmony_ci 591462306a36Sopenharmony_ci/* 591562306a36Sopenharmony_ci * lpfc_enable_bbcr: Enable BB Credit Recovery 591662306a36Sopenharmony_ci * 0 = BB Credit Recovery disabled 591762306a36Sopenharmony_ci * 1 = BB Credit Recovery enabled (default) 591862306a36Sopenharmony_ci * Value range is [0,1]. Default value is 1. 591962306a36Sopenharmony_ci */ 592062306a36Sopenharmony_ciLPFC_BBCR_ATTR_RW(enable_bbcr, 1, 0, 1, "Enable BBC Recovery"); 592162306a36Sopenharmony_ci 592262306a36Sopenharmony_ci/* Signaling module parameters */ 592362306a36Sopenharmony_ciint lpfc_fabric_cgn_frequency = 100; /* 100 ms default */ 592462306a36Sopenharmony_cimodule_param(lpfc_fabric_cgn_frequency, int, 0444); 592562306a36Sopenharmony_ciMODULE_PARM_DESC(lpfc_fabric_cgn_frequency, "Congestion signaling fabric freq"); 592662306a36Sopenharmony_ci 592762306a36Sopenharmony_ciunsigned char lpfc_acqe_cgn_frequency = 10; /* 10 sec default */ 592862306a36Sopenharmony_cimodule_param(lpfc_acqe_cgn_frequency, byte, 0444); 592962306a36Sopenharmony_ciMODULE_PARM_DESC(lpfc_acqe_cgn_frequency, "Congestion signaling ACQE freq"); 593062306a36Sopenharmony_ci 593162306a36Sopenharmony_ciint lpfc_use_cgn_signal = 1; /* 0 - only use FPINs, 1 - Use signals if avail */ 593262306a36Sopenharmony_cimodule_param(lpfc_use_cgn_signal, int, 0444); 593362306a36Sopenharmony_ciMODULE_PARM_DESC(lpfc_use_cgn_signal, "Use Congestion signaling if available"); 593462306a36Sopenharmony_ci 593562306a36Sopenharmony_ci/* 593662306a36Sopenharmony_ci * lpfc_enable_dpp: Enable DPP on G7 593762306a36Sopenharmony_ci * 0 = DPP on G7 disabled 593862306a36Sopenharmony_ci * 1 = DPP on G7 enabled (default) 593962306a36Sopenharmony_ci * Value range is [0,1]. Default value is 1. 594062306a36Sopenharmony_ci */ 594162306a36Sopenharmony_ciLPFC_ATTR_RW(enable_dpp, 1, 0, 1, "Enable Direct Packet Push"); 594262306a36Sopenharmony_ci 594362306a36Sopenharmony_ci/* 594462306a36Sopenharmony_ci * lpfc_enable_mi: Enable FDMI MIB 594562306a36Sopenharmony_ci * 0 = disabled 594662306a36Sopenharmony_ci * 1 = enabled (default) 594762306a36Sopenharmony_ci * Value range is [0,1]. 594862306a36Sopenharmony_ci */ 594962306a36Sopenharmony_ciLPFC_ATTR_R(enable_mi, 1, 0, 1, "Enable MI"); 595062306a36Sopenharmony_ci 595162306a36Sopenharmony_ci/* 595262306a36Sopenharmony_ci * lpfc_max_vmid: Maximum number of VMs to be tagged. This is valid only if 595362306a36Sopenharmony_ci * either vmid_app_header or vmid_priority_tagging is enabled. 595462306a36Sopenharmony_ci * 4 - 255 = vmid support enabled for 4-255 VMs 595562306a36Sopenharmony_ci * Value range is [4,255]. 595662306a36Sopenharmony_ci */ 595762306a36Sopenharmony_ciLPFC_ATTR_RW(max_vmid, LPFC_MIN_VMID, LPFC_MIN_VMID, LPFC_MAX_VMID, 595862306a36Sopenharmony_ci "Maximum number of VMs supported"); 595962306a36Sopenharmony_ci 596062306a36Sopenharmony_ci/* 596162306a36Sopenharmony_ci * lpfc_vmid_inactivity_timeout: Inactivity timeout duration in hours 596262306a36Sopenharmony_ci * 0 = Timeout is disabled 596362306a36Sopenharmony_ci * Value range is [0,24]. 596462306a36Sopenharmony_ci */ 596562306a36Sopenharmony_ciLPFC_ATTR_RW(vmid_inactivity_timeout, 4, 0, 24, 596662306a36Sopenharmony_ci "Inactivity timeout in hours"); 596762306a36Sopenharmony_ci 596862306a36Sopenharmony_ci/* 596962306a36Sopenharmony_ci * lpfc_vmid_app_header: Enable App Header VMID support 597062306a36Sopenharmony_ci * 0 = Support is disabled (default) 597162306a36Sopenharmony_ci * 1 = Support is enabled 597262306a36Sopenharmony_ci * Value range is [0,1]. 597362306a36Sopenharmony_ci */ 597462306a36Sopenharmony_ciLPFC_ATTR_RW(vmid_app_header, LPFC_VMID_APP_HEADER_DISABLE, 597562306a36Sopenharmony_ci LPFC_VMID_APP_HEADER_DISABLE, LPFC_VMID_APP_HEADER_ENABLE, 597662306a36Sopenharmony_ci "Enable App Header VMID support"); 597762306a36Sopenharmony_ci 597862306a36Sopenharmony_ci/* 597962306a36Sopenharmony_ci * lpfc_vmid_priority_tagging: Enable Priority Tagging VMID support 598062306a36Sopenharmony_ci * 0 = Support is disabled (default) 598162306a36Sopenharmony_ci * 1 = Allow supported targets only 598262306a36Sopenharmony_ci * 2 = Allow all targets 598362306a36Sopenharmony_ci * Value range is [0,2]. 598462306a36Sopenharmony_ci */ 598562306a36Sopenharmony_ciLPFC_ATTR_RW(vmid_priority_tagging, LPFC_VMID_PRIO_TAG_DISABLE, 598662306a36Sopenharmony_ci LPFC_VMID_PRIO_TAG_DISABLE, 598762306a36Sopenharmony_ci LPFC_VMID_PRIO_TAG_ALL_TARGETS, 598862306a36Sopenharmony_ci "Enable Priority Tagging VMID support"); 598962306a36Sopenharmony_ci 599062306a36Sopenharmony_cistatic struct attribute *lpfc_hba_attrs[] = { 599162306a36Sopenharmony_ci &dev_attr_nvme_info.attr, 599262306a36Sopenharmony_ci &dev_attr_scsi_stat.attr, 599362306a36Sopenharmony_ci &dev_attr_bg_info.attr, 599462306a36Sopenharmony_ci &dev_attr_bg_guard_err.attr, 599562306a36Sopenharmony_ci &dev_attr_bg_apptag_err.attr, 599662306a36Sopenharmony_ci &dev_attr_bg_reftag_err.attr, 599762306a36Sopenharmony_ci &dev_attr_info.attr, 599862306a36Sopenharmony_ci &dev_attr_serialnum.attr, 599962306a36Sopenharmony_ci &dev_attr_modeldesc.attr, 600062306a36Sopenharmony_ci &dev_attr_modelname.attr, 600162306a36Sopenharmony_ci &dev_attr_programtype.attr, 600262306a36Sopenharmony_ci &dev_attr_portnum.attr, 600362306a36Sopenharmony_ci &dev_attr_fwrev.attr, 600462306a36Sopenharmony_ci &dev_attr_hdw.attr, 600562306a36Sopenharmony_ci &dev_attr_option_rom_version.attr, 600662306a36Sopenharmony_ci &dev_attr_link_state.attr, 600762306a36Sopenharmony_ci &dev_attr_num_discovered_ports.attr, 600862306a36Sopenharmony_ci &dev_attr_lpfc_drvr_version.attr, 600962306a36Sopenharmony_ci &dev_attr_lpfc_enable_fip.attr, 601062306a36Sopenharmony_ci &dev_attr_lpfc_temp_sensor.attr, 601162306a36Sopenharmony_ci &dev_attr_lpfc_log_verbose.attr, 601262306a36Sopenharmony_ci &dev_attr_lpfc_lun_queue_depth.attr, 601362306a36Sopenharmony_ci &dev_attr_lpfc_tgt_queue_depth.attr, 601462306a36Sopenharmony_ci &dev_attr_lpfc_hba_queue_depth.attr, 601562306a36Sopenharmony_ci &dev_attr_lpfc_peer_port_login.attr, 601662306a36Sopenharmony_ci &dev_attr_lpfc_nodev_tmo.attr, 601762306a36Sopenharmony_ci &dev_attr_lpfc_devloss_tmo.attr, 601862306a36Sopenharmony_ci &dev_attr_lpfc_enable_fc4_type.attr, 601962306a36Sopenharmony_ci &dev_attr_lpfc_fcp_class.attr, 602062306a36Sopenharmony_ci &dev_attr_lpfc_use_adisc.attr, 602162306a36Sopenharmony_ci &dev_attr_lpfc_first_burst_size.attr, 602262306a36Sopenharmony_ci &dev_attr_lpfc_ack0.attr, 602362306a36Sopenharmony_ci &dev_attr_lpfc_xri_rebalancing.attr, 602462306a36Sopenharmony_ci &dev_attr_lpfc_topology.attr, 602562306a36Sopenharmony_ci &dev_attr_lpfc_scan_down.attr, 602662306a36Sopenharmony_ci &dev_attr_lpfc_link_speed.attr, 602762306a36Sopenharmony_ci &dev_attr_lpfc_fcp_io_sched.attr, 602862306a36Sopenharmony_ci &dev_attr_lpfc_ns_query.attr, 602962306a36Sopenharmony_ci &dev_attr_lpfc_fcp2_no_tgt_reset.attr, 603062306a36Sopenharmony_ci &dev_attr_lpfc_cr_delay.attr, 603162306a36Sopenharmony_ci &dev_attr_lpfc_cr_count.attr, 603262306a36Sopenharmony_ci &dev_attr_lpfc_multi_ring_support.attr, 603362306a36Sopenharmony_ci &dev_attr_lpfc_multi_ring_rctl.attr, 603462306a36Sopenharmony_ci &dev_attr_lpfc_multi_ring_type.attr, 603562306a36Sopenharmony_ci &dev_attr_lpfc_fdmi_on.attr, 603662306a36Sopenharmony_ci &dev_attr_lpfc_enable_SmartSAN.attr, 603762306a36Sopenharmony_ci &dev_attr_lpfc_max_luns.attr, 603862306a36Sopenharmony_ci &dev_attr_lpfc_enable_npiv.attr, 603962306a36Sopenharmony_ci &dev_attr_lpfc_fcf_failover_policy.attr, 604062306a36Sopenharmony_ci &dev_attr_lpfc_enable_rrq.attr, 604162306a36Sopenharmony_ci &dev_attr_lpfc_fcp_wait_abts_rsp.attr, 604262306a36Sopenharmony_ci &dev_attr_nport_evt_cnt.attr, 604362306a36Sopenharmony_ci &dev_attr_board_mode.attr, 604462306a36Sopenharmony_ci &dev_attr_lpfc_xcvr_data.attr, 604562306a36Sopenharmony_ci &dev_attr_max_vpi.attr, 604662306a36Sopenharmony_ci &dev_attr_used_vpi.attr, 604762306a36Sopenharmony_ci &dev_attr_max_rpi.attr, 604862306a36Sopenharmony_ci &dev_attr_used_rpi.attr, 604962306a36Sopenharmony_ci &dev_attr_max_xri.attr, 605062306a36Sopenharmony_ci &dev_attr_used_xri.attr, 605162306a36Sopenharmony_ci &dev_attr_npiv_info.attr, 605262306a36Sopenharmony_ci &dev_attr_issue_reset.attr, 605362306a36Sopenharmony_ci &dev_attr_lpfc_poll.attr, 605462306a36Sopenharmony_ci &dev_attr_lpfc_poll_tmo.attr, 605562306a36Sopenharmony_ci &dev_attr_lpfc_task_mgmt_tmo.attr, 605662306a36Sopenharmony_ci &dev_attr_lpfc_use_msi.attr, 605762306a36Sopenharmony_ci &dev_attr_lpfc_nvme_oas.attr, 605862306a36Sopenharmony_ci &dev_attr_lpfc_nvme_embed_cmd.attr, 605962306a36Sopenharmony_ci &dev_attr_lpfc_fcp_imax.attr, 606062306a36Sopenharmony_ci &dev_attr_lpfc_force_rscn.attr, 606162306a36Sopenharmony_ci &dev_attr_lpfc_cq_poll_threshold.attr, 606262306a36Sopenharmony_ci &dev_attr_lpfc_cq_max_proc_limit.attr, 606362306a36Sopenharmony_ci &dev_attr_lpfc_fcp_cpu_map.attr, 606462306a36Sopenharmony_ci &dev_attr_lpfc_fcp_mq_threshold.attr, 606562306a36Sopenharmony_ci &dev_attr_lpfc_hdw_queue.attr, 606662306a36Sopenharmony_ci &dev_attr_lpfc_irq_chann.attr, 606762306a36Sopenharmony_ci &dev_attr_lpfc_suppress_rsp.attr, 606862306a36Sopenharmony_ci &dev_attr_lpfc_nvmet_mrq.attr, 606962306a36Sopenharmony_ci &dev_attr_lpfc_nvmet_mrq_post.attr, 607062306a36Sopenharmony_ci &dev_attr_lpfc_nvme_enable_fb.attr, 607162306a36Sopenharmony_ci &dev_attr_lpfc_nvmet_fb_size.attr, 607262306a36Sopenharmony_ci &dev_attr_lpfc_enable_bg.attr, 607362306a36Sopenharmony_ci &dev_attr_lpfc_enable_hba_reset.attr, 607462306a36Sopenharmony_ci &dev_attr_lpfc_enable_hba_heartbeat.attr, 607562306a36Sopenharmony_ci &dev_attr_lpfc_EnableXLane.attr, 607662306a36Sopenharmony_ci &dev_attr_lpfc_XLanePriority.attr, 607762306a36Sopenharmony_ci &dev_attr_lpfc_xlane_lun.attr, 607862306a36Sopenharmony_ci &dev_attr_lpfc_xlane_tgt.attr, 607962306a36Sopenharmony_ci &dev_attr_lpfc_xlane_vpt.attr, 608062306a36Sopenharmony_ci &dev_attr_lpfc_xlane_lun_state.attr, 608162306a36Sopenharmony_ci &dev_attr_lpfc_xlane_lun_status.attr, 608262306a36Sopenharmony_ci &dev_attr_lpfc_xlane_priority.attr, 608362306a36Sopenharmony_ci &dev_attr_lpfc_sg_seg_cnt.attr, 608462306a36Sopenharmony_ci &dev_attr_lpfc_max_scsicmpl_time.attr, 608562306a36Sopenharmony_ci &dev_attr_lpfc_aer_support.attr, 608662306a36Sopenharmony_ci &dev_attr_lpfc_aer_state_cleanup.attr, 608762306a36Sopenharmony_ci &dev_attr_lpfc_sriov_nr_virtfn.attr, 608862306a36Sopenharmony_ci &dev_attr_lpfc_req_fw_upgrade.attr, 608962306a36Sopenharmony_ci &dev_attr_lpfc_suppress_link_up.attr, 609062306a36Sopenharmony_ci &dev_attr_iocb_hw.attr, 609162306a36Sopenharmony_ci &dev_attr_pls.attr, 609262306a36Sopenharmony_ci &dev_attr_pt.attr, 609362306a36Sopenharmony_ci &dev_attr_txq_hw.attr, 609462306a36Sopenharmony_ci &dev_attr_txcmplq_hw.attr, 609562306a36Sopenharmony_ci &dev_attr_lpfc_sriov_hw_max_virtfn.attr, 609662306a36Sopenharmony_ci &dev_attr_protocol.attr, 609762306a36Sopenharmony_ci &dev_attr_lpfc_xlane_supported.attr, 609862306a36Sopenharmony_ci &dev_attr_lpfc_enable_mds_diags.attr, 609962306a36Sopenharmony_ci &dev_attr_lpfc_ras_fwlog_buffsize.attr, 610062306a36Sopenharmony_ci &dev_attr_lpfc_ras_fwlog_level.attr, 610162306a36Sopenharmony_ci &dev_attr_lpfc_ras_fwlog_func.attr, 610262306a36Sopenharmony_ci &dev_attr_lpfc_enable_bbcr.attr, 610362306a36Sopenharmony_ci &dev_attr_lpfc_enable_dpp.attr, 610462306a36Sopenharmony_ci &dev_attr_lpfc_enable_mi.attr, 610562306a36Sopenharmony_ci &dev_attr_cmf_info.attr, 610662306a36Sopenharmony_ci &dev_attr_lpfc_max_vmid.attr, 610762306a36Sopenharmony_ci &dev_attr_lpfc_vmid_inactivity_timeout.attr, 610862306a36Sopenharmony_ci &dev_attr_lpfc_vmid_app_header.attr, 610962306a36Sopenharmony_ci &dev_attr_lpfc_vmid_priority_tagging.attr, 611062306a36Sopenharmony_ci NULL, 611162306a36Sopenharmony_ci}; 611262306a36Sopenharmony_ci 611362306a36Sopenharmony_cistatic const struct attribute_group lpfc_hba_attr_group = { 611462306a36Sopenharmony_ci .attrs = lpfc_hba_attrs 611562306a36Sopenharmony_ci}; 611662306a36Sopenharmony_ci 611762306a36Sopenharmony_ciconst struct attribute_group *lpfc_hba_groups[] = { 611862306a36Sopenharmony_ci &lpfc_hba_attr_group, 611962306a36Sopenharmony_ci NULL 612062306a36Sopenharmony_ci}; 612162306a36Sopenharmony_ci 612262306a36Sopenharmony_cistatic struct attribute *lpfc_vport_attrs[] = { 612362306a36Sopenharmony_ci &dev_attr_info.attr, 612462306a36Sopenharmony_ci &dev_attr_link_state.attr, 612562306a36Sopenharmony_ci &dev_attr_num_discovered_ports.attr, 612662306a36Sopenharmony_ci &dev_attr_lpfc_drvr_version.attr, 612762306a36Sopenharmony_ci &dev_attr_lpfc_log_verbose.attr, 612862306a36Sopenharmony_ci &dev_attr_lpfc_lun_queue_depth.attr, 612962306a36Sopenharmony_ci &dev_attr_lpfc_tgt_queue_depth.attr, 613062306a36Sopenharmony_ci &dev_attr_lpfc_nodev_tmo.attr, 613162306a36Sopenharmony_ci &dev_attr_lpfc_devloss_tmo.attr, 613262306a36Sopenharmony_ci &dev_attr_lpfc_hba_queue_depth.attr, 613362306a36Sopenharmony_ci &dev_attr_lpfc_peer_port_login.attr, 613462306a36Sopenharmony_ci &dev_attr_lpfc_restrict_login.attr, 613562306a36Sopenharmony_ci &dev_attr_lpfc_fcp_class.attr, 613662306a36Sopenharmony_ci &dev_attr_lpfc_use_adisc.attr, 613762306a36Sopenharmony_ci &dev_attr_lpfc_first_burst_size.attr, 613862306a36Sopenharmony_ci &dev_attr_lpfc_max_luns.attr, 613962306a36Sopenharmony_ci &dev_attr_nport_evt_cnt.attr, 614062306a36Sopenharmony_ci &dev_attr_npiv_info.attr, 614162306a36Sopenharmony_ci &dev_attr_lpfc_enable_da_id.attr, 614262306a36Sopenharmony_ci &dev_attr_lpfc_max_scsicmpl_time.attr, 614362306a36Sopenharmony_ci &dev_attr_lpfc_static_vport.attr, 614462306a36Sopenharmony_ci &dev_attr_cmf_info.attr, 614562306a36Sopenharmony_ci NULL, 614662306a36Sopenharmony_ci}; 614762306a36Sopenharmony_ci 614862306a36Sopenharmony_cistatic const struct attribute_group lpfc_vport_attr_group = { 614962306a36Sopenharmony_ci .attrs = lpfc_vport_attrs 615062306a36Sopenharmony_ci}; 615162306a36Sopenharmony_ci 615262306a36Sopenharmony_ciconst struct attribute_group *lpfc_vport_groups[] = { 615362306a36Sopenharmony_ci &lpfc_vport_attr_group, 615462306a36Sopenharmony_ci NULL 615562306a36Sopenharmony_ci}; 615662306a36Sopenharmony_ci 615762306a36Sopenharmony_ci/** 615862306a36Sopenharmony_ci * sysfs_ctlreg_write - Write method for writing to ctlreg 615962306a36Sopenharmony_ci * @filp: open sysfs file 616062306a36Sopenharmony_ci * @kobj: kernel kobject that contains the kernel class device. 616162306a36Sopenharmony_ci * @bin_attr: kernel attributes passed to us. 616262306a36Sopenharmony_ci * @buf: contains the data to be written to the adapter IOREG space. 616362306a36Sopenharmony_ci * @off: offset into buffer to beginning of data. 616462306a36Sopenharmony_ci * @count: bytes to transfer. 616562306a36Sopenharmony_ci * 616662306a36Sopenharmony_ci * Description: 616762306a36Sopenharmony_ci * Accessed via /sys/class/scsi_host/hostxxx/ctlreg. 616862306a36Sopenharmony_ci * Uses the adapter io control registers to send buf contents to the adapter. 616962306a36Sopenharmony_ci * 617062306a36Sopenharmony_ci * Returns: 617162306a36Sopenharmony_ci * -ERANGE off and count combo out of range 617262306a36Sopenharmony_ci * -EINVAL off, count or buff address invalid 617362306a36Sopenharmony_ci * -EPERM adapter is offline 617462306a36Sopenharmony_ci * value of count, buf contents written 617562306a36Sopenharmony_ci **/ 617662306a36Sopenharmony_cistatic ssize_t 617762306a36Sopenharmony_cisysfs_ctlreg_write(struct file *filp, struct kobject *kobj, 617862306a36Sopenharmony_ci struct bin_attribute *bin_attr, 617962306a36Sopenharmony_ci char *buf, loff_t off, size_t count) 618062306a36Sopenharmony_ci{ 618162306a36Sopenharmony_ci size_t buf_off; 618262306a36Sopenharmony_ci struct device *dev = container_of(kobj, struct device, kobj); 618362306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 618462306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 618562306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 618662306a36Sopenharmony_ci 618762306a36Sopenharmony_ci if (phba->sli_rev >= LPFC_SLI_REV4) 618862306a36Sopenharmony_ci return -EPERM; 618962306a36Sopenharmony_ci 619062306a36Sopenharmony_ci if ((off + count) > FF_REG_AREA_SIZE) 619162306a36Sopenharmony_ci return -ERANGE; 619262306a36Sopenharmony_ci 619362306a36Sopenharmony_ci if (count <= LPFC_REG_WRITE_KEY_SIZE) 619462306a36Sopenharmony_ci return 0; 619562306a36Sopenharmony_ci 619662306a36Sopenharmony_ci if (off % 4 || count % 4 || (unsigned long)buf % 4) 619762306a36Sopenharmony_ci return -EINVAL; 619862306a36Sopenharmony_ci 619962306a36Sopenharmony_ci /* This is to protect HBA registers from accidental writes. */ 620062306a36Sopenharmony_ci if (memcmp(buf, LPFC_REG_WRITE_KEY, LPFC_REG_WRITE_KEY_SIZE)) 620162306a36Sopenharmony_ci return -EINVAL; 620262306a36Sopenharmony_ci 620362306a36Sopenharmony_ci if (!(vport->fc_flag & FC_OFFLINE_MODE)) 620462306a36Sopenharmony_ci return -EPERM; 620562306a36Sopenharmony_ci 620662306a36Sopenharmony_ci spin_lock_irq(&phba->hbalock); 620762306a36Sopenharmony_ci for (buf_off = 0; buf_off < count - LPFC_REG_WRITE_KEY_SIZE; 620862306a36Sopenharmony_ci buf_off += sizeof(uint32_t)) 620962306a36Sopenharmony_ci writel(*((uint32_t *)(buf + buf_off + LPFC_REG_WRITE_KEY_SIZE)), 621062306a36Sopenharmony_ci phba->ctrl_regs_memmap_p + off + buf_off); 621162306a36Sopenharmony_ci 621262306a36Sopenharmony_ci spin_unlock_irq(&phba->hbalock); 621362306a36Sopenharmony_ci 621462306a36Sopenharmony_ci return count; 621562306a36Sopenharmony_ci} 621662306a36Sopenharmony_ci 621762306a36Sopenharmony_ci/** 621862306a36Sopenharmony_ci * sysfs_ctlreg_read - Read method for reading from ctlreg 621962306a36Sopenharmony_ci * @filp: open sysfs file 622062306a36Sopenharmony_ci * @kobj: kernel kobject that contains the kernel class device. 622162306a36Sopenharmony_ci * @bin_attr: kernel attributes passed to us. 622262306a36Sopenharmony_ci * @buf: if successful contains the data from the adapter IOREG space. 622362306a36Sopenharmony_ci * @off: offset into buffer to beginning of data. 622462306a36Sopenharmony_ci * @count: bytes to transfer. 622562306a36Sopenharmony_ci * 622662306a36Sopenharmony_ci * Description: 622762306a36Sopenharmony_ci * Accessed via /sys/class/scsi_host/hostxxx/ctlreg. 622862306a36Sopenharmony_ci * Uses the adapter io control registers to read data into buf. 622962306a36Sopenharmony_ci * 623062306a36Sopenharmony_ci * Returns: 623162306a36Sopenharmony_ci * -ERANGE off and count combo out of range 623262306a36Sopenharmony_ci * -EINVAL off, count or buff address invalid 623362306a36Sopenharmony_ci * value of count, buf contents read 623462306a36Sopenharmony_ci **/ 623562306a36Sopenharmony_cistatic ssize_t 623662306a36Sopenharmony_cisysfs_ctlreg_read(struct file *filp, struct kobject *kobj, 623762306a36Sopenharmony_ci struct bin_attribute *bin_attr, 623862306a36Sopenharmony_ci char *buf, loff_t off, size_t count) 623962306a36Sopenharmony_ci{ 624062306a36Sopenharmony_ci size_t buf_off; 624162306a36Sopenharmony_ci uint32_t * tmp_ptr; 624262306a36Sopenharmony_ci struct device *dev = container_of(kobj, struct device, kobj); 624362306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 624462306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 624562306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 624662306a36Sopenharmony_ci 624762306a36Sopenharmony_ci if (phba->sli_rev >= LPFC_SLI_REV4) 624862306a36Sopenharmony_ci return -EPERM; 624962306a36Sopenharmony_ci 625062306a36Sopenharmony_ci if (off > FF_REG_AREA_SIZE) 625162306a36Sopenharmony_ci return -ERANGE; 625262306a36Sopenharmony_ci 625362306a36Sopenharmony_ci if ((off + count) > FF_REG_AREA_SIZE) 625462306a36Sopenharmony_ci count = FF_REG_AREA_SIZE - off; 625562306a36Sopenharmony_ci 625662306a36Sopenharmony_ci if (count == 0) return 0; 625762306a36Sopenharmony_ci 625862306a36Sopenharmony_ci if (off % 4 || count % 4 || (unsigned long)buf % 4) 625962306a36Sopenharmony_ci return -EINVAL; 626062306a36Sopenharmony_ci 626162306a36Sopenharmony_ci spin_lock_irq(&phba->hbalock); 626262306a36Sopenharmony_ci 626362306a36Sopenharmony_ci for (buf_off = 0; buf_off < count; buf_off += sizeof(uint32_t)) { 626462306a36Sopenharmony_ci tmp_ptr = (uint32_t *)(buf + buf_off); 626562306a36Sopenharmony_ci *tmp_ptr = readl(phba->ctrl_regs_memmap_p + off + buf_off); 626662306a36Sopenharmony_ci } 626762306a36Sopenharmony_ci 626862306a36Sopenharmony_ci spin_unlock_irq(&phba->hbalock); 626962306a36Sopenharmony_ci 627062306a36Sopenharmony_ci return count; 627162306a36Sopenharmony_ci} 627262306a36Sopenharmony_ci 627362306a36Sopenharmony_cistatic struct bin_attribute sysfs_ctlreg_attr = { 627462306a36Sopenharmony_ci .attr = { 627562306a36Sopenharmony_ci .name = "ctlreg", 627662306a36Sopenharmony_ci .mode = S_IRUSR | S_IWUSR, 627762306a36Sopenharmony_ci }, 627862306a36Sopenharmony_ci .size = 256, 627962306a36Sopenharmony_ci .read = sysfs_ctlreg_read, 628062306a36Sopenharmony_ci .write = sysfs_ctlreg_write, 628162306a36Sopenharmony_ci}; 628262306a36Sopenharmony_ci 628362306a36Sopenharmony_ci/** 628462306a36Sopenharmony_ci * sysfs_mbox_write - Write method for writing information via mbox 628562306a36Sopenharmony_ci * @filp: open sysfs file 628662306a36Sopenharmony_ci * @kobj: kernel kobject that contains the kernel class device. 628762306a36Sopenharmony_ci * @bin_attr: kernel attributes passed to us. 628862306a36Sopenharmony_ci * @buf: contains the data to be written to sysfs mbox. 628962306a36Sopenharmony_ci * @off: offset into buffer to beginning of data. 629062306a36Sopenharmony_ci * @count: bytes to transfer. 629162306a36Sopenharmony_ci * 629262306a36Sopenharmony_ci * Description: 629362306a36Sopenharmony_ci * Deprecated function. All mailbox access from user space is performed via the 629462306a36Sopenharmony_ci * bsg interface. 629562306a36Sopenharmony_ci * 629662306a36Sopenharmony_ci * Returns: 629762306a36Sopenharmony_ci * -EPERM operation not permitted 629862306a36Sopenharmony_ci **/ 629962306a36Sopenharmony_cistatic ssize_t 630062306a36Sopenharmony_cisysfs_mbox_write(struct file *filp, struct kobject *kobj, 630162306a36Sopenharmony_ci struct bin_attribute *bin_attr, 630262306a36Sopenharmony_ci char *buf, loff_t off, size_t count) 630362306a36Sopenharmony_ci{ 630462306a36Sopenharmony_ci return -EPERM; 630562306a36Sopenharmony_ci} 630662306a36Sopenharmony_ci 630762306a36Sopenharmony_ci/** 630862306a36Sopenharmony_ci * sysfs_mbox_read - Read method for reading information via mbox 630962306a36Sopenharmony_ci * @filp: open sysfs file 631062306a36Sopenharmony_ci * @kobj: kernel kobject that contains the kernel class device. 631162306a36Sopenharmony_ci * @bin_attr: kernel attributes passed to us. 631262306a36Sopenharmony_ci * @buf: contains the data to be read from sysfs mbox. 631362306a36Sopenharmony_ci * @off: offset into buffer to beginning of data. 631462306a36Sopenharmony_ci * @count: bytes to transfer. 631562306a36Sopenharmony_ci * 631662306a36Sopenharmony_ci * Description: 631762306a36Sopenharmony_ci * Deprecated function. All mailbox access from user space is performed via the 631862306a36Sopenharmony_ci * bsg interface. 631962306a36Sopenharmony_ci * 632062306a36Sopenharmony_ci * Returns: 632162306a36Sopenharmony_ci * -EPERM operation not permitted 632262306a36Sopenharmony_ci **/ 632362306a36Sopenharmony_cistatic ssize_t 632462306a36Sopenharmony_cisysfs_mbox_read(struct file *filp, struct kobject *kobj, 632562306a36Sopenharmony_ci struct bin_attribute *bin_attr, 632662306a36Sopenharmony_ci char *buf, loff_t off, size_t count) 632762306a36Sopenharmony_ci{ 632862306a36Sopenharmony_ci return -EPERM; 632962306a36Sopenharmony_ci} 633062306a36Sopenharmony_ci 633162306a36Sopenharmony_cistatic struct bin_attribute sysfs_mbox_attr = { 633262306a36Sopenharmony_ci .attr = { 633362306a36Sopenharmony_ci .name = "mbox", 633462306a36Sopenharmony_ci .mode = S_IRUSR | S_IWUSR, 633562306a36Sopenharmony_ci }, 633662306a36Sopenharmony_ci .size = MAILBOX_SYSFS_MAX, 633762306a36Sopenharmony_ci .read = sysfs_mbox_read, 633862306a36Sopenharmony_ci .write = sysfs_mbox_write, 633962306a36Sopenharmony_ci}; 634062306a36Sopenharmony_ci 634162306a36Sopenharmony_ci/** 634262306a36Sopenharmony_ci * lpfc_alloc_sysfs_attr - Creates the ctlreg and mbox entries 634362306a36Sopenharmony_ci * @vport: address of lpfc vport structure. 634462306a36Sopenharmony_ci * 634562306a36Sopenharmony_ci * Return codes: 634662306a36Sopenharmony_ci * zero on success 634762306a36Sopenharmony_ci * error return code from sysfs_create_bin_file() 634862306a36Sopenharmony_ci **/ 634962306a36Sopenharmony_ciint 635062306a36Sopenharmony_cilpfc_alloc_sysfs_attr(struct lpfc_vport *vport) 635162306a36Sopenharmony_ci{ 635262306a36Sopenharmony_ci struct Scsi_Host *shost = lpfc_shost_from_vport(vport); 635362306a36Sopenharmony_ci int error; 635462306a36Sopenharmony_ci 635562306a36Sopenharmony_ci /* Virtual ports do not need ctrl_reg and mbox */ 635662306a36Sopenharmony_ci if (vport->port_type == LPFC_NPIV_PORT) 635762306a36Sopenharmony_ci return 0; 635862306a36Sopenharmony_ci 635962306a36Sopenharmony_ci error = sysfs_create_bin_file(&shost->shost_dev.kobj, 636062306a36Sopenharmony_ci &sysfs_ctlreg_attr); 636162306a36Sopenharmony_ci if (error) 636262306a36Sopenharmony_ci goto out; 636362306a36Sopenharmony_ci 636462306a36Sopenharmony_ci error = sysfs_create_bin_file(&shost->shost_dev.kobj, 636562306a36Sopenharmony_ci &sysfs_mbox_attr); 636662306a36Sopenharmony_ci if (error) 636762306a36Sopenharmony_ci goto out_remove_ctlreg_attr; 636862306a36Sopenharmony_ci 636962306a36Sopenharmony_ci return 0; 637062306a36Sopenharmony_ciout_remove_ctlreg_attr: 637162306a36Sopenharmony_ci sysfs_remove_bin_file(&shost->shost_dev.kobj, &sysfs_ctlreg_attr); 637262306a36Sopenharmony_ciout: 637362306a36Sopenharmony_ci return error; 637462306a36Sopenharmony_ci} 637562306a36Sopenharmony_ci 637662306a36Sopenharmony_ci/** 637762306a36Sopenharmony_ci * lpfc_free_sysfs_attr - Removes the ctlreg and mbox entries 637862306a36Sopenharmony_ci * @vport: address of lpfc vport structure. 637962306a36Sopenharmony_ci **/ 638062306a36Sopenharmony_civoid 638162306a36Sopenharmony_cilpfc_free_sysfs_attr(struct lpfc_vport *vport) 638262306a36Sopenharmony_ci{ 638362306a36Sopenharmony_ci struct Scsi_Host *shost = lpfc_shost_from_vport(vport); 638462306a36Sopenharmony_ci 638562306a36Sopenharmony_ci /* Virtual ports do not need ctrl_reg and mbox */ 638662306a36Sopenharmony_ci if (vport->port_type == LPFC_NPIV_PORT) 638762306a36Sopenharmony_ci return; 638862306a36Sopenharmony_ci sysfs_remove_bin_file(&shost->shost_dev.kobj, &sysfs_mbox_attr); 638962306a36Sopenharmony_ci sysfs_remove_bin_file(&shost->shost_dev.kobj, &sysfs_ctlreg_attr); 639062306a36Sopenharmony_ci} 639162306a36Sopenharmony_ci 639262306a36Sopenharmony_ci/* 639362306a36Sopenharmony_ci * Dynamic FC Host Attributes Support 639462306a36Sopenharmony_ci */ 639562306a36Sopenharmony_ci 639662306a36Sopenharmony_ci/** 639762306a36Sopenharmony_ci * lpfc_get_host_symbolic_name - Copy symbolic name into the scsi host 639862306a36Sopenharmony_ci * @shost: kernel scsi host pointer. 639962306a36Sopenharmony_ci **/ 640062306a36Sopenharmony_cistatic void 640162306a36Sopenharmony_cilpfc_get_host_symbolic_name(struct Scsi_Host *shost) 640262306a36Sopenharmony_ci{ 640362306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata; 640462306a36Sopenharmony_ci 640562306a36Sopenharmony_ci lpfc_vport_symbolic_node_name(vport, fc_host_symbolic_name(shost), 640662306a36Sopenharmony_ci sizeof fc_host_symbolic_name(shost)); 640762306a36Sopenharmony_ci} 640862306a36Sopenharmony_ci 640962306a36Sopenharmony_ci/** 641062306a36Sopenharmony_ci * lpfc_get_host_port_id - Copy the vport DID into the scsi host port id 641162306a36Sopenharmony_ci * @shost: kernel scsi host pointer. 641262306a36Sopenharmony_ci **/ 641362306a36Sopenharmony_cistatic void 641462306a36Sopenharmony_cilpfc_get_host_port_id(struct Scsi_Host *shost) 641562306a36Sopenharmony_ci{ 641662306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 641762306a36Sopenharmony_ci 641862306a36Sopenharmony_ci /* note: fc_myDID already in cpu endianness */ 641962306a36Sopenharmony_ci fc_host_port_id(shost) = vport->fc_myDID; 642062306a36Sopenharmony_ci} 642162306a36Sopenharmony_ci 642262306a36Sopenharmony_ci/** 642362306a36Sopenharmony_ci * lpfc_get_host_port_type - Set the value of the scsi host port type 642462306a36Sopenharmony_ci * @shost: kernel scsi host pointer. 642562306a36Sopenharmony_ci **/ 642662306a36Sopenharmony_cistatic void 642762306a36Sopenharmony_cilpfc_get_host_port_type(struct Scsi_Host *shost) 642862306a36Sopenharmony_ci{ 642962306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 643062306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 643162306a36Sopenharmony_ci 643262306a36Sopenharmony_ci spin_lock_irq(shost->host_lock); 643362306a36Sopenharmony_ci 643462306a36Sopenharmony_ci if (vport->port_type == LPFC_NPIV_PORT) { 643562306a36Sopenharmony_ci fc_host_port_type(shost) = FC_PORTTYPE_NPIV; 643662306a36Sopenharmony_ci } else if (lpfc_is_link_up(phba)) { 643762306a36Sopenharmony_ci if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) { 643862306a36Sopenharmony_ci if (vport->fc_flag & FC_PUBLIC_LOOP) 643962306a36Sopenharmony_ci fc_host_port_type(shost) = FC_PORTTYPE_NLPORT; 644062306a36Sopenharmony_ci else 644162306a36Sopenharmony_ci fc_host_port_type(shost) = FC_PORTTYPE_LPORT; 644262306a36Sopenharmony_ci } else { 644362306a36Sopenharmony_ci if (vport->fc_flag & FC_FABRIC) 644462306a36Sopenharmony_ci fc_host_port_type(shost) = FC_PORTTYPE_NPORT; 644562306a36Sopenharmony_ci else 644662306a36Sopenharmony_ci fc_host_port_type(shost) = FC_PORTTYPE_PTP; 644762306a36Sopenharmony_ci } 644862306a36Sopenharmony_ci } else 644962306a36Sopenharmony_ci fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN; 645062306a36Sopenharmony_ci 645162306a36Sopenharmony_ci spin_unlock_irq(shost->host_lock); 645262306a36Sopenharmony_ci} 645362306a36Sopenharmony_ci 645462306a36Sopenharmony_ci/** 645562306a36Sopenharmony_ci * lpfc_get_host_port_state - Set the value of the scsi host port state 645662306a36Sopenharmony_ci * @shost: kernel scsi host pointer. 645762306a36Sopenharmony_ci **/ 645862306a36Sopenharmony_cistatic void 645962306a36Sopenharmony_cilpfc_get_host_port_state(struct Scsi_Host *shost) 646062306a36Sopenharmony_ci{ 646162306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 646262306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 646362306a36Sopenharmony_ci 646462306a36Sopenharmony_ci spin_lock_irq(shost->host_lock); 646562306a36Sopenharmony_ci 646662306a36Sopenharmony_ci if (vport->fc_flag & FC_OFFLINE_MODE) 646762306a36Sopenharmony_ci fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE; 646862306a36Sopenharmony_ci else { 646962306a36Sopenharmony_ci switch (phba->link_state) { 647062306a36Sopenharmony_ci case LPFC_LINK_UNKNOWN: 647162306a36Sopenharmony_ci case LPFC_LINK_DOWN: 647262306a36Sopenharmony_ci fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN; 647362306a36Sopenharmony_ci break; 647462306a36Sopenharmony_ci case LPFC_LINK_UP: 647562306a36Sopenharmony_ci case LPFC_CLEAR_LA: 647662306a36Sopenharmony_ci case LPFC_HBA_READY: 647762306a36Sopenharmony_ci /* Links up, reports port state accordingly */ 647862306a36Sopenharmony_ci if (vport->port_state < LPFC_VPORT_READY) 647962306a36Sopenharmony_ci fc_host_port_state(shost) = 648062306a36Sopenharmony_ci FC_PORTSTATE_BYPASSED; 648162306a36Sopenharmony_ci else 648262306a36Sopenharmony_ci fc_host_port_state(shost) = 648362306a36Sopenharmony_ci FC_PORTSTATE_ONLINE; 648462306a36Sopenharmony_ci break; 648562306a36Sopenharmony_ci case LPFC_HBA_ERROR: 648662306a36Sopenharmony_ci fc_host_port_state(shost) = FC_PORTSTATE_ERROR; 648762306a36Sopenharmony_ci break; 648862306a36Sopenharmony_ci default: 648962306a36Sopenharmony_ci fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN; 649062306a36Sopenharmony_ci break; 649162306a36Sopenharmony_ci } 649262306a36Sopenharmony_ci } 649362306a36Sopenharmony_ci 649462306a36Sopenharmony_ci spin_unlock_irq(shost->host_lock); 649562306a36Sopenharmony_ci} 649662306a36Sopenharmony_ci 649762306a36Sopenharmony_ci/** 649862306a36Sopenharmony_ci * lpfc_get_host_speed - Set the value of the scsi host speed 649962306a36Sopenharmony_ci * @shost: kernel scsi host pointer. 650062306a36Sopenharmony_ci **/ 650162306a36Sopenharmony_cistatic void 650262306a36Sopenharmony_cilpfc_get_host_speed(struct Scsi_Host *shost) 650362306a36Sopenharmony_ci{ 650462306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 650562306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 650662306a36Sopenharmony_ci 650762306a36Sopenharmony_ci spin_lock_irq(shost->host_lock); 650862306a36Sopenharmony_ci 650962306a36Sopenharmony_ci if ((lpfc_is_link_up(phba)) && (!(phba->hba_flag & HBA_FCOE_MODE))) { 651062306a36Sopenharmony_ci switch(phba->fc_linkspeed) { 651162306a36Sopenharmony_ci case LPFC_LINK_SPEED_1GHZ: 651262306a36Sopenharmony_ci fc_host_speed(shost) = FC_PORTSPEED_1GBIT; 651362306a36Sopenharmony_ci break; 651462306a36Sopenharmony_ci case LPFC_LINK_SPEED_2GHZ: 651562306a36Sopenharmony_ci fc_host_speed(shost) = FC_PORTSPEED_2GBIT; 651662306a36Sopenharmony_ci break; 651762306a36Sopenharmony_ci case LPFC_LINK_SPEED_4GHZ: 651862306a36Sopenharmony_ci fc_host_speed(shost) = FC_PORTSPEED_4GBIT; 651962306a36Sopenharmony_ci break; 652062306a36Sopenharmony_ci case LPFC_LINK_SPEED_8GHZ: 652162306a36Sopenharmony_ci fc_host_speed(shost) = FC_PORTSPEED_8GBIT; 652262306a36Sopenharmony_ci break; 652362306a36Sopenharmony_ci case LPFC_LINK_SPEED_10GHZ: 652462306a36Sopenharmony_ci fc_host_speed(shost) = FC_PORTSPEED_10GBIT; 652562306a36Sopenharmony_ci break; 652662306a36Sopenharmony_ci case LPFC_LINK_SPEED_16GHZ: 652762306a36Sopenharmony_ci fc_host_speed(shost) = FC_PORTSPEED_16GBIT; 652862306a36Sopenharmony_ci break; 652962306a36Sopenharmony_ci case LPFC_LINK_SPEED_32GHZ: 653062306a36Sopenharmony_ci fc_host_speed(shost) = FC_PORTSPEED_32GBIT; 653162306a36Sopenharmony_ci break; 653262306a36Sopenharmony_ci case LPFC_LINK_SPEED_64GHZ: 653362306a36Sopenharmony_ci fc_host_speed(shost) = FC_PORTSPEED_64GBIT; 653462306a36Sopenharmony_ci break; 653562306a36Sopenharmony_ci case LPFC_LINK_SPEED_128GHZ: 653662306a36Sopenharmony_ci fc_host_speed(shost) = FC_PORTSPEED_128GBIT; 653762306a36Sopenharmony_ci break; 653862306a36Sopenharmony_ci case LPFC_LINK_SPEED_256GHZ: 653962306a36Sopenharmony_ci fc_host_speed(shost) = FC_PORTSPEED_256GBIT; 654062306a36Sopenharmony_ci break; 654162306a36Sopenharmony_ci default: 654262306a36Sopenharmony_ci fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN; 654362306a36Sopenharmony_ci break; 654462306a36Sopenharmony_ci } 654562306a36Sopenharmony_ci } else if (lpfc_is_link_up(phba) && (phba->hba_flag & HBA_FCOE_MODE)) { 654662306a36Sopenharmony_ci switch (phba->fc_linkspeed) { 654762306a36Sopenharmony_ci case LPFC_ASYNC_LINK_SPEED_1GBPS: 654862306a36Sopenharmony_ci fc_host_speed(shost) = FC_PORTSPEED_1GBIT; 654962306a36Sopenharmony_ci break; 655062306a36Sopenharmony_ci case LPFC_ASYNC_LINK_SPEED_10GBPS: 655162306a36Sopenharmony_ci fc_host_speed(shost) = FC_PORTSPEED_10GBIT; 655262306a36Sopenharmony_ci break; 655362306a36Sopenharmony_ci case LPFC_ASYNC_LINK_SPEED_20GBPS: 655462306a36Sopenharmony_ci fc_host_speed(shost) = FC_PORTSPEED_20GBIT; 655562306a36Sopenharmony_ci break; 655662306a36Sopenharmony_ci case LPFC_ASYNC_LINK_SPEED_25GBPS: 655762306a36Sopenharmony_ci fc_host_speed(shost) = FC_PORTSPEED_25GBIT; 655862306a36Sopenharmony_ci break; 655962306a36Sopenharmony_ci case LPFC_ASYNC_LINK_SPEED_40GBPS: 656062306a36Sopenharmony_ci fc_host_speed(shost) = FC_PORTSPEED_40GBIT; 656162306a36Sopenharmony_ci break; 656262306a36Sopenharmony_ci case LPFC_ASYNC_LINK_SPEED_100GBPS: 656362306a36Sopenharmony_ci fc_host_speed(shost) = FC_PORTSPEED_100GBIT; 656462306a36Sopenharmony_ci break; 656562306a36Sopenharmony_ci default: 656662306a36Sopenharmony_ci fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN; 656762306a36Sopenharmony_ci break; 656862306a36Sopenharmony_ci } 656962306a36Sopenharmony_ci } else 657062306a36Sopenharmony_ci fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN; 657162306a36Sopenharmony_ci 657262306a36Sopenharmony_ci spin_unlock_irq(shost->host_lock); 657362306a36Sopenharmony_ci} 657462306a36Sopenharmony_ci 657562306a36Sopenharmony_ci/** 657662306a36Sopenharmony_ci * lpfc_get_host_fabric_name - Set the value of the scsi host fabric name 657762306a36Sopenharmony_ci * @shost: kernel scsi host pointer. 657862306a36Sopenharmony_ci **/ 657962306a36Sopenharmony_cistatic void 658062306a36Sopenharmony_cilpfc_get_host_fabric_name (struct Scsi_Host *shost) 658162306a36Sopenharmony_ci{ 658262306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 658362306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 658462306a36Sopenharmony_ci u64 node_name; 658562306a36Sopenharmony_ci 658662306a36Sopenharmony_ci spin_lock_irq(shost->host_lock); 658762306a36Sopenharmony_ci 658862306a36Sopenharmony_ci if ((vport->port_state > LPFC_FLOGI) && 658962306a36Sopenharmony_ci ((vport->fc_flag & FC_FABRIC) || 659062306a36Sopenharmony_ci ((phba->fc_topology == LPFC_TOPOLOGY_LOOP) && 659162306a36Sopenharmony_ci (vport->fc_flag & FC_PUBLIC_LOOP)))) 659262306a36Sopenharmony_ci node_name = wwn_to_u64(phba->fc_fabparam.nodeName.u.wwn); 659362306a36Sopenharmony_ci else 659462306a36Sopenharmony_ci /* fabric is local port if there is no F/FL_Port */ 659562306a36Sopenharmony_ci node_name = 0; 659662306a36Sopenharmony_ci 659762306a36Sopenharmony_ci spin_unlock_irq(shost->host_lock); 659862306a36Sopenharmony_ci 659962306a36Sopenharmony_ci fc_host_fabric_name(shost) = node_name; 660062306a36Sopenharmony_ci} 660162306a36Sopenharmony_ci 660262306a36Sopenharmony_ci/** 660362306a36Sopenharmony_ci * lpfc_get_stats - Return statistical information about the adapter 660462306a36Sopenharmony_ci * @shost: kernel scsi host pointer. 660562306a36Sopenharmony_ci * 660662306a36Sopenharmony_ci * Notes: 660762306a36Sopenharmony_ci * NULL on error for link down, no mbox pool, sli2 active, 660862306a36Sopenharmony_ci * management not allowed, memory allocation error, or mbox error. 660962306a36Sopenharmony_ci * 661062306a36Sopenharmony_ci * Returns: 661162306a36Sopenharmony_ci * NULL for error 661262306a36Sopenharmony_ci * address of the adapter host statistics 661362306a36Sopenharmony_ci **/ 661462306a36Sopenharmony_cistatic struct fc_host_statistics * 661562306a36Sopenharmony_cilpfc_get_stats(struct Scsi_Host *shost) 661662306a36Sopenharmony_ci{ 661762306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 661862306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 661962306a36Sopenharmony_ci struct lpfc_sli *psli = &phba->sli; 662062306a36Sopenharmony_ci struct fc_host_statistics *hs = &phba->link_stats; 662162306a36Sopenharmony_ci struct lpfc_lnk_stat * lso = &psli->lnk_stat_offsets; 662262306a36Sopenharmony_ci LPFC_MBOXQ_t *pmboxq; 662362306a36Sopenharmony_ci MAILBOX_t *pmb; 662462306a36Sopenharmony_ci int rc = 0; 662562306a36Sopenharmony_ci 662662306a36Sopenharmony_ci /* 662762306a36Sopenharmony_ci * prevent udev from issuing mailbox commands until the port is 662862306a36Sopenharmony_ci * configured. 662962306a36Sopenharmony_ci */ 663062306a36Sopenharmony_ci if (phba->link_state < LPFC_LINK_DOWN || 663162306a36Sopenharmony_ci !phba->mbox_mem_pool || 663262306a36Sopenharmony_ci (phba->sli.sli_flag & LPFC_SLI_ACTIVE) == 0) 663362306a36Sopenharmony_ci return NULL; 663462306a36Sopenharmony_ci 663562306a36Sopenharmony_ci if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO) 663662306a36Sopenharmony_ci return NULL; 663762306a36Sopenharmony_ci 663862306a36Sopenharmony_ci pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); 663962306a36Sopenharmony_ci if (!pmboxq) 664062306a36Sopenharmony_ci return NULL; 664162306a36Sopenharmony_ci memset(pmboxq, 0, sizeof (LPFC_MBOXQ_t)); 664262306a36Sopenharmony_ci 664362306a36Sopenharmony_ci pmb = &pmboxq->u.mb; 664462306a36Sopenharmony_ci pmb->mbxCommand = MBX_READ_STATUS; 664562306a36Sopenharmony_ci pmb->mbxOwner = OWN_HOST; 664662306a36Sopenharmony_ci pmboxq->ctx_buf = NULL; 664762306a36Sopenharmony_ci pmboxq->vport = vport; 664862306a36Sopenharmony_ci 664962306a36Sopenharmony_ci if (vport->fc_flag & FC_OFFLINE_MODE) { 665062306a36Sopenharmony_ci rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL); 665162306a36Sopenharmony_ci if (rc != MBX_SUCCESS) { 665262306a36Sopenharmony_ci mempool_free(pmboxq, phba->mbox_mem_pool); 665362306a36Sopenharmony_ci return NULL; 665462306a36Sopenharmony_ci } 665562306a36Sopenharmony_ci } else { 665662306a36Sopenharmony_ci rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2); 665762306a36Sopenharmony_ci if (rc != MBX_SUCCESS) { 665862306a36Sopenharmony_ci if (rc != MBX_TIMEOUT) 665962306a36Sopenharmony_ci mempool_free(pmboxq, phba->mbox_mem_pool); 666062306a36Sopenharmony_ci return NULL; 666162306a36Sopenharmony_ci } 666262306a36Sopenharmony_ci } 666362306a36Sopenharmony_ci 666462306a36Sopenharmony_ci memset(hs, 0, sizeof (struct fc_host_statistics)); 666562306a36Sopenharmony_ci 666662306a36Sopenharmony_ci hs->tx_frames = pmb->un.varRdStatus.xmitFrameCnt; 666762306a36Sopenharmony_ci hs->rx_frames = pmb->un.varRdStatus.rcvFrameCnt; 666862306a36Sopenharmony_ci 666962306a36Sopenharmony_ci /* 667062306a36Sopenharmony_ci * The MBX_READ_STATUS returns tx_k_bytes which has to be 667162306a36Sopenharmony_ci * converted to words. 667262306a36Sopenharmony_ci * 667362306a36Sopenharmony_ci * Check if extended byte flag is set, to know when to collect upper 667462306a36Sopenharmony_ci * bits of 64 bit wide statistics counter. 667562306a36Sopenharmony_ci */ 667662306a36Sopenharmony_ci if (pmb->un.varRdStatus.xkb & RD_ST_XKB) { 667762306a36Sopenharmony_ci hs->tx_words = (u64) 667862306a36Sopenharmony_ci ((((u64)(pmb->un.varRdStatus.xmit_xkb & 667962306a36Sopenharmony_ci RD_ST_XMIT_XKB_MASK) << 32) | 668062306a36Sopenharmony_ci (u64)pmb->un.varRdStatus.xmitByteCnt) * 668162306a36Sopenharmony_ci (u64)256); 668262306a36Sopenharmony_ci hs->rx_words = (u64) 668362306a36Sopenharmony_ci ((((u64)(pmb->un.varRdStatus.rcv_xkb & 668462306a36Sopenharmony_ci RD_ST_RCV_XKB_MASK) << 32) | 668562306a36Sopenharmony_ci (u64)pmb->un.varRdStatus.rcvByteCnt) * 668662306a36Sopenharmony_ci (u64)256); 668762306a36Sopenharmony_ci } else { 668862306a36Sopenharmony_ci hs->tx_words = (uint64_t) 668962306a36Sopenharmony_ci ((uint64_t)pmb->un.varRdStatus.xmitByteCnt 669062306a36Sopenharmony_ci * (uint64_t)256); 669162306a36Sopenharmony_ci hs->rx_words = (uint64_t) 669262306a36Sopenharmony_ci ((uint64_t)pmb->un.varRdStatus.rcvByteCnt 669362306a36Sopenharmony_ci * (uint64_t)256); 669462306a36Sopenharmony_ci } 669562306a36Sopenharmony_ci 669662306a36Sopenharmony_ci memset(pmboxq, 0, sizeof (LPFC_MBOXQ_t)); 669762306a36Sopenharmony_ci pmb->mbxCommand = MBX_READ_LNK_STAT; 669862306a36Sopenharmony_ci pmb->mbxOwner = OWN_HOST; 669962306a36Sopenharmony_ci pmboxq->ctx_buf = NULL; 670062306a36Sopenharmony_ci pmboxq->vport = vport; 670162306a36Sopenharmony_ci 670262306a36Sopenharmony_ci if (vport->fc_flag & FC_OFFLINE_MODE) { 670362306a36Sopenharmony_ci rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL); 670462306a36Sopenharmony_ci if (rc != MBX_SUCCESS) { 670562306a36Sopenharmony_ci mempool_free(pmboxq, phba->mbox_mem_pool); 670662306a36Sopenharmony_ci return NULL; 670762306a36Sopenharmony_ci } 670862306a36Sopenharmony_ci } else { 670962306a36Sopenharmony_ci rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2); 671062306a36Sopenharmony_ci if (rc != MBX_SUCCESS) { 671162306a36Sopenharmony_ci if (rc != MBX_TIMEOUT) 671262306a36Sopenharmony_ci mempool_free(pmboxq, phba->mbox_mem_pool); 671362306a36Sopenharmony_ci return NULL; 671462306a36Sopenharmony_ci } 671562306a36Sopenharmony_ci } 671662306a36Sopenharmony_ci 671762306a36Sopenharmony_ci hs->link_failure_count = pmb->un.varRdLnk.linkFailureCnt; 671862306a36Sopenharmony_ci hs->loss_of_sync_count = pmb->un.varRdLnk.lossSyncCnt; 671962306a36Sopenharmony_ci hs->loss_of_signal_count = pmb->un.varRdLnk.lossSignalCnt; 672062306a36Sopenharmony_ci hs->prim_seq_protocol_err_count = pmb->un.varRdLnk.primSeqErrCnt; 672162306a36Sopenharmony_ci hs->invalid_tx_word_count = pmb->un.varRdLnk.invalidXmitWord; 672262306a36Sopenharmony_ci hs->invalid_crc_count = pmb->un.varRdLnk.crcCnt; 672362306a36Sopenharmony_ci hs->error_frames = pmb->un.varRdLnk.crcCnt; 672462306a36Sopenharmony_ci 672562306a36Sopenharmony_ci hs->cn_sig_warn = atomic64_read(&phba->cgn_acqe_stat.warn); 672662306a36Sopenharmony_ci hs->cn_sig_alarm = atomic64_read(&phba->cgn_acqe_stat.alarm); 672762306a36Sopenharmony_ci 672862306a36Sopenharmony_ci hs->link_failure_count -= lso->link_failure_count; 672962306a36Sopenharmony_ci hs->loss_of_sync_count -= lso->loss_of_sync_count; 673062306a36Sopenharmony_ci hs->loss_of_signal_count -= lso->loss_of_signal_count; 673162306a36Sopenharmony_ci hs->prim_seq_protocol_err_count -= lso->prim_seq_protocol_err_count; 673262306a36Sopenharmony_ci hs->invalid_tx_word_count -= lso->invalid_tx_word_count; 673362306a36Sopenharmony_ci hs->invalid_crc_count -= lso->invalid_crc_count; 673462306a36Sopenharmony_ci hs->error_frames -= lso->error_frames; 673562306a36Sopenharmony_ci 673662306a36Sopenharmony_ci if (phba->hba_flag & HBA_FCOE_MODE) { 673762306a36Sopenharmony_ci hs->lip_count = -1; 673862306a36Sopenharmony_ci hs->nos_count = (phba->link_events >> 1); 673962306a36Sopenharmony_ci hs->nos_count -= lso->link_events; 674062306a36Sopenharmony_ci } else if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) { 674162306a36Sopenharmony_ci hs->lip_count = (phba->fc_eventTag >> 1); 674262306a36Sopenharmony_ci hs->lip_count -= lso->link_events; 674362306a36Sopenharmony_ci hs->nos_count = -1; 674462306a36Sopenharmony_ci } else { 674562306a36Sopenharmony_ci hs->lip_count = -1; 674662306a36Sopenharmony_ci hs->nos_count = (phba->fc_eventTag >> 1); 674762306a36Sopenharmony_ci hs->nos_count -= lso->link_events; 674862306a36Sopenharmony_ci } 674962306a36Sopenharmony_ci 675062306a36Sopenharmony_ci hs->dumped_frames = -1; 675162306a36Sopenharmony_ci 675262306a36Sopenharmony_ci hs->seconds_since_last_reset = ktime_get_seconds() - psli->stats_start; 675362306a36Sopenharmony_ci 675462306a36Sopenharmony_ci mempool_free(pmboxq, phba->mbox_mem_pool); 675562306a36Sopenharmony_ci 675662306a36Sopenharmony_ci return hs; 675762306a36Sopenharmony_ci} 675862306a36Sopenharmony_ci 675962306a36Sopenharmony_ci/** 676062306a36Sopenharmony_ci * lpfc_reset_stats - Copy the adapter link stats information 676162306a36Sopenharmony_ci * @shost: kernel scsi host pointer. 676262306a36Sopenharmony_ci **/ 676362306a36Sopenharmony_cistatic void 676462306a36Sopenharmony_cilpfc_reset_stats(struct Scsi_Host *shost) 676562306a36Sopenharmony_ci{ 676662306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 676762306a36Sopenharmony_ci struct lpfc_hba *phba = vport->phba; 676862306a36Sopenharmony_ci struct lpfc_sli *psli = &phba->sli; 676962306a36Sopenharmony_ci struct lpfc_lnk_stat *lso = &psli->lnk_stat_offsets; 677062306a36Sopenharmony_ci LPFC_MBOXQ_t *pmboxq; 677162306a36Sopenharmony_ci MAILBOX_t *pmb; 677262306a36Sopenharmony_ci int rc = 0; 677362306a36Sopenharmony_ci 677462306a36Sopenharmony_ci if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO) 677562306a36Sopenharmony_ci return; 677662306a36Sopenharmony_ci 677762306a36Sopenharmony_ci pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); 677862306a36Sopenharmony_ci if (!pmboxq) 677962306a36Sopenharmony_ci return; 678062306a36Sopenharmony_ci memset(pmboxq, 0, sizeof(LPFC_MBOXQ_t)); 678162306a36Sopenharmony_ci 678262306a36Sopenharmony_ci pmb = &pmboxq->u.mb; 678362306a36Sopenharmony_ci pmb->mbxCommand = MBX_READ_STATUS; 678462306a36Sopenharmony_ci pmb->mbxOwner = OWN_HOST; 678562306a36Sopenharmony_ci pmb->un.varWords[0] = 0x1; /* reset request */ 678662306a36Sopenharmony_ci pmboxq->ctx_buf = NULL; 678762306a36Sopenharmony_ci pmboxq->vport = vport; 678862306a36Sopenharmony_ci 678962306a36Sopenharmony_ci if ((vport->fc_flag & FC_OFFLINE_MODE) || 679062306a36Sopenharmony_ci (!(psli->sli_flag & LPFC_SLI_ACTIVE))) { 679162306a36Sopenharmony_ci rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL); 679262306a36Sopenharmony_ci if (rc != MBX_SUCCESS) { 679362306a36Sopenharmony_ci mempool_free(pmboxq, phba->mbox_mem_pool); 679462306a36Sopenharmony_ci return; 679562306a36Sopenharmony_ci } 679662306a36Sopenharmony_ci } else { 679762306a36Sopenharmony_ci rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2); 679862306a36Sopenharmony_ci if (rc != MBX_SUCCESS) { 679962306a36Sopenharmony_ci if (rc != MBX_TIMEOUT) 680062306a36Sopenharmony_ci mempool_free(pmboxq, phba->mbox_mem_pool); 680162306a36Sopenharmony_ci return; 680262306a36Sopenharmony_ci } 680362306a36Sopenharmony_ci } 680462306a36Sopenharmony_ci 680562306a36Sopenharmony_ci memset(pmboxq, 0, sizeof(LPFC_MBOXQ_t)); 680662306a36Sopenharmony_ci pmb->mbxCommand = MBX_READ_LNK_STAT; 680762306a36Sopenharmony_ci pmb->mbxOwner = OWN_HOST; 680862306a36Sopenharmony_ci pmboxq->ctx_buf = NULL; 680962306a36Sopenharmony_ci pmboxq->vport = vport; 681062306a36Sopenharmony_ci 681162306a36Sopenharmony_ci if ((vport->fc_flag & FC_OFFLINE_MODE) || 681262306a36Sopenharmony_ci (!(psli->sli_flag & LPFC_SLI_ACTIVE))) { 681362306a36Sopenharmony_ci rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL); 681462306a36Sopenharmony_ci if (rc != MBX_SUCCESS) { 681562306a36Sopenharmony_ci mempool_free(pmboxq, phba->mbox_mem_pool); 681662306a36Sopenharmony_ci return; 681762306a36Sopenharmony_ci } 681862306a36Sopenharmony_ci } else { 681962306a36Sopenharmony_ci rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2); 682062306a36Sopenharmony_ci if (rc != MBX_SUCCESS) { 682162306a36Sopenharmony_ci if (rc != MBX_TIMEOUT) 682262306a36Sopenharmony_ci mempool_free(pmboxq, phba->mbox_mem_pool); 682362306a36Sopenharmony_ci return; 682462306a36Sopenharmony_ci } 682562306a36Sopenharmony_ci } 682662306a36Sopenharmony_ci 682762306a36Sopenharmony_ci lso->link_failure_count = pmb->un.varRdLnk.linkFailureCnt; 682862306a36Sopenharmony_ci lso->loss_of_sync_count = pmb->un.varRdLnk.lossSyncCnt; 682962306a36Sopenharmony_ci lso->loss_of_signal_count = pmb->un.varRdLnk.lossSignalCnt; 683062306a36Sopenharmony_ci lso->prim_seq_protocol_err_count = pmb->un.varRdLnk.primSeqErrCnt; 683162306a36Sopenharmony_ci lso->invalid_tx_word_count = pmb->un.varRdLnk.invalidXmitWord; 683262306a36Sopenharmony_ci lso->invalid_crc_count = pmb->un.varRdLnk.crcCnt; 683362306a36Sopenharmony_ci lso->error_frames = pmb->un.varRdLnk.crcCnt; 683462306a36Sopenharmony_ci if (phba->hba_flag & HBA_FCOE_MODE) 683562306a36Sopenharmony_ci lso->link_events = (phba->link_events >> 1); 683662306a36Sopenharmony_ci else 683762306a36Sopenharmony_ci lso->link_events = (phba->fc_eventTag >> 1); 683862306a36Sopenharmony_ci 683962306a36Sopenharmony_ci atomic64_set(&phba->cgn_acqe_stat.warn, 0); 684062306a36Sopenharmony_ci atomic64_set(&phba->cgn_acqe_stat.alarm, 0); 684162306a36Sopenharmony_ci 684262306a36Sopenharmony_ci memset(&shost_to_fc_host(shost)->fpin_stats, 0, 684362306a36Sopenharmony_ci sizeof(shost_to_fc_host(shost)->fpin_stats)); 684462306a36Sopenharmony_ci 684562306a36Sopenharmony_ci psli->stats_start = ktime_get_seconds(); 684662306a36Sopenharmony_ci 684762306a36Sopenharmony_ci mempool_free(pmboxq, phba->mbox_mem_pool); 684862306a36Sopenharmony_ci 684962306a36Sopenharmony_ci return; 685062306a36Sopenharmony_ci} 685162306a36Sopenharmony_ci 685262306a36Sopenharmony_ci/* 685362306a36Sopenharmony_ci * The LPFC driver treats linkdown handling as target loss events so there 685462306a36Sopenharmony_ci * are no sysfs handlers for link_down_tmo. 685562306a36Sopenharmony_ci */ 685662306a36Sopenharmony_ci 685762306a36Sopenharmony_ci/** 685862306a36Sopenharmony_ci * lpfc_get_node_by_target - Return the nodelist for a target 685962306a36Sopenharmony_ci * @starget: kernel scsi target pointer. 686062306a36Sopenharmony_ci * 686162306a36Sopenharmony_ci * Returns: 686262306a36Sopenharmony_ci * address of the node list if found 686362306a36Sopenharmony_ci * NULL target not found 686462306a36Sopenharmony_ci **/ 686562306a36Sopenharmony_cistatic struct lpfc_nodelist * 686662306a36Sopenharmony_cilpfc_get_node_by_target(struct scsi_target *starget) 686762306a36Sopenharmony_ci{ 686862306a36Sopenharmony_ci struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); 686962306a36Sopenharmony_ci struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 687062306a36Sopenharmony_ci struct lpfc_nodelist *ndlp; 687162306a36Sopenharmony_ci 687262306a36Sopenharmony_ci spin_lock_irq(shost->host_lock); 687362306a36Sopenharmony_ci /* Search for this, mapped, target ID */ 687462306a36Sopenharmony_ci list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) { 687562306a36Sopenharmony_ci if (ndlp->nlp_state == NLP_STE_MAPPED_NODE && 687662306a36Sopenharmony_ci starget->id == ndlp->nlp_sid) { 687762306a36Sopenharmony_ci spin_unlock_irq(shost->host_lock); 687862306a36Sopenharmony_ci return ndlp; 687962306a36Sopenharmony_ci } 688062306a36Sopenharmony_ci } 688162306a36Sopenharmony_ci spin_unlock_irq(shost->host_lock); 688262306a36Sopenharmony_ci return NULL; 688362306a36Sopenharmony_ci} 688462306a36Sopenharmony_ci 688562306a36Sopenharmony_ci/** 688662306a36Sopenharmony_ci * lpfc_get_starget_port_id - Set the target port id to the ndlp DID or -1 688762306a36Sopenharmony_ci * @starget: kernel scsi target pointer. 688862306a36Sopenharmony_ci **/ 688962306a36Sopenharmony_cistatic void 689062306a36Sopenharmony_cilpfc_get_starget_port_id(struct scsi_target *starget) 689162306a36Sopenharmony_ci{ 689262306a36Sopenharmony_ci struct lpfc_nodelist *ndlp = lpfc_get_node_by_target(starget); 689362306a36Sopenharmony_ci 689462306a36Sopenharmony_ci fc_starget_port_id(starget) = ndlp ? ndlp->nlp_DID : -1; 689562306a36Sopenharmony_ci} 689662306a36Sopenharmony_ci 689762306a36Sopenharmony_ci/** 689862306a36Sopenharmony_ci * lpfc_get_starget_node_name - Set the target node name 689962306a36Sopenharmony_ci * @starget: kernel scsi target pointer. 690062306a36Sopenharmony_ci * 690162306a36Sopenharmony_ci * Description: Set the target node name to the ndlp node name wwn or zero. 690262306a36Sopenharmony_ci **/ 690362306a36Sopenharmony_cistatic void 690462306a36Sopenharmony_cilpfc_get_starget_node_name(struct scsi_target *starget) 690562306a36Sopenharmony_ci{ 690662306a36Sopenharmony_ci struct lpfc_nodelist *ndlp = lpfc_get_node_by_target(starget); 690762306a36Sopenharmony_ci 690862306a36Sopenharmony_ci fc_starget_node_name(starget) = 690962306a36Sopenharmony_ci ndlp ? wwn_to_u64(ndlp->nlp_nodename.u.wwn) : 0; 691062306a36Sopenharmony_ci} 691162306a36Sopenharmony_ci 691262306a36Sopenharmony_ci/** 691362306a36Sopenharmony_ci * lpfc_get_starget_port_name - Set the target port name 691462306a36Sopenharmony_ci * @starget: kernel scsi target pointer. 691562306a36Sopenharmony_ci * 691662306a36Sopenharmony_ci * Description: set the target port name to the ndlp port name wwn or zero. 691762306a36Sopenharmony_ci **/ 691862306a36Sopenharmony_cistatic void 691962306a36Sopenharmony_cilpfc_get_starget_port_name(struct scsi_target *starget) 692062306a36Sopenharmony_ci{ 692162306a36Sopenharmony_ci struct lpfc_nodelist *ndlp = lpfc_get_node_by_target(starget); 692262306a36Sopenharmony_ci 692362306a36Sopenharmony_ci fc_starget_port_name(starget) = 692462306a36Sopenharmony_ci ndlp ? wwn_to_u64(ndlp->nlp_portname.u.wwn) : 0; 692562306a36Sopenharmony_ci} 692662306a36Sopenharmony_ci 692762306a36Sopenharmony_ci/** 692862306a36Sopenharmony_ci * lpfc_set_rport_loss_tmo - Set the rport dev loss tmo 692962306a36Sopenharmony_ci * @rport: fc rport address. 693062306a36Sopenharmony_ci * @timeout: new value for dev loss tmo. 693162306a36Sopenharmony_ci * 693262306a36Sopenharmony_ci * Description: 693362306a36Sopenharmony_ci * If timeout is non zero set the dev_loss_tmo to timeout, else set 693462306a36Sopenharmony_ci * dev_loss_tmo to one. 693562306a36Sopenharmony_ci **/ 693662306a36Sopenharmony_cistatic void 693762306a36Sopenharmony_cilpfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout) 693862306a36Sopenharmony_ci{ 693962306a36Sopenharmony_ci struct lpfc_rport_data *rdata = rport->dd_data; 694062306a36Sopenharmony_ci struct lpfc_nodelist *ndlp = rdata->pnode; 694162306a36Sopenharmony_ci#if (IS_ENABLED(CONFIG_NVME_FC)) 694262306a36Sopenharmony_ci struct lpfc_nvme_rport *nrport = NULL; 694362306a36Sopenharmony_ci#endif 694462306a36Sopenharmony_ci 694562306a36Sopenharmony_ci if (timeout) 694662306a36Sopenharmony_ci rport->dev_loss_tmo = timeout; 694762306a36Sopenharmony_ci else 694862306a36Sopenharmony_ci rport->dev_loss_tmo = 1; 694962306a36Sopenharmony_ci 695062306a36Sopenharmony_ci if (!ndlp) { 695162306a36Sopenharmony_ci dev_info(&rport->dev, "Cannot find remote node to " 695262306a36Sopenharmony_ci "set rport dev loss tmo, port_id x%x\n", 695362306a36Sopenharmony_ci rport->port_id); 695462306a36Sopenharmony_ci return; 695562306a36Sopenharmony_ci } 695662306a36Sopenharmony_ci 695762306a36Sopenharmony_ci#if (IS_ENABLED(CONFIG_NVME_FC)) 695862306a36Sopenharmony_ci nrport = lpfc_ndlp_get_nrport(ndlp); 695962306a36Sopenharmony_ci 696062306a36Sopenharmony_ci if (nrport && nrport->remoteport) 696162306a36Sopenharmony_ci nvme_fc_set_remoteport_devloss(nrport->remoteport, 696262306a36Sopenharmony_ci rport->dev_loss_tmo); 696362306a36Sopenharmony_ci#endif 696462306a36Sopenharmony_ci} 696562306a36Sopenharmony_ci 696662306a36Sopenharmony_ci/* 696762306a36Sopenharmony_ci * lpfc_rport_show_function - Return rport target information 696862306a36Sopenharmony_ci * 696962306a36Sopenharmony_ci * Description: 697062306a36Sopenharmony_ci * Macro that uses field to generate a function with the name lpfc_show_rport_ 697162306a36Sopenharmony_ci * 697262306a36Sopenharmony_ci * lpfc_show_rport_##field: returns the bytes formatted in buf 697362306a36Sopenharmony_ci * @cdev: class converted to an fc_rport. 697462306a36Sopenharmony_ci * @buf: on return contains the target_field or zero. 697562306a36Sopenharmony_ci * 697662306a36Sopenharmony_ci * Returns: size of formatted string. 697762306a36Sopenharmony_ci **/ 697862306a36Sopenharmony_ci#define lpfc_rport_show_function(field, format_string, sz, cast) \ 697962306a36Sopenharmony_cistatic ssize_t \ 698062306a36Sopenharmony_cilpfc_show_rport_##field (struct device *dev, \ 698162306a36Sopenharmony_ci struct device_attribute *attr, \ 698262306a36Sopenharmony_ci char *buf) \ 698362306a36Sopenharmony_ci{ \ 698462306a36Sopenharmony_ci struct fc_rport *rport = transport_class_to_rport(dev); \ 698562306a36Sopenharmony_ci struct lpfc_rport_data *rdata = rport->hostdata; \ 698662306a36Sopenharmony_ci return scnprintf(buf, sz, format_string, \ 698762306a36Sopenharmony_ci (rdata->target) ? cast rdata->target->field : 0); \ 698862306a36Sopenharmony_ci} 698962306a36Sopenharmony_ci 699062306a36Sopenharmony_ci#define lpfc_rport_rd_attr(field, format_string, sz) \ 699162306a36Sopenharmony_ci lpfc_rport_show_function(field, format_string, sz, ) \ 699262306a36Sopenharmony_cistatic FC_RPORT_ATTR(field, S_IRUGO, lpfc_show_rport_##field, NULL) 699362306a36Sopenharmony_ci 699462306a36Sopenharmony_ci/** 699562306a36Sopenharmony_ci * lpfc_set_vport_symbolic_name - Set the vport's symbolic name 699662306a36Sopenharmony_ci * @fc_vport: The fc_vport who's symbolic name has been changed. 699762306a36Sopenharmony_ci * 699862306a36Sopenharmony_ci * Description: 699962306a36Sopenharmony_ci * This function is called by the transport after the @fc_vport's symbolic name 700062306a36Sopenharmony_ci * has been changed. This function re-registers the symbolic name with the 700162306a36Sopenharmony_ci * switch to propagate the change into the fabric if the vport is active. 700262306a36Sopenharmony_ci **/ 700362306a36Sopenharmony_cistatic void 700462306a36Sopenharmony_cilpfc_set_vport_symbolic_name(struct fc_vport *fc_vport) 700562306a36Sopenharmony_ci{ 700662306a36Sopenharmony_ci struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data; 700762306a36Sopenharmony_ci 700862306a36Sopenharmony_ci if (vport->port_state == LPFC_VPORT_READY) 700962306a36Sopenharmony_ci lpfc_ns_cmd(vport, SLI_CTNS_RSPN_ID, 0, 0); 701062306a36Sopenharmony_ci} 701162306a36Sopenharmony_ci 701262306a36Sopenharmony_ci/** 701362306a36Sopenharmony_ci * lpfc_hba_log_verbose_init - Set hba's log verbose level 701462306a36Sopenharmony_ci * @phba: Pointer to lpfc_hba struct. 701562306a36Sopenharmony_ci * @verbose: Verbose level to set. 701662306a36Sopenharmony_ci * 701762306a36Sopenharmony_ci * This function is called by the lpfc_get_cfgparam() routine to set the 701862306a36Sopenharmony_ci * module lpfc_log_verbose into the @phba cfg_log_verbose for use with 701962306a36Sopenharmony_ci * log message according to the module's lpfc_log_verbose parameter setting 702062306a36Sopenharmony_ci * before hba port or vport created. 702162306a36Sopenharmony_ci **/ 702262306a36Sopenharmony_cistatic void 702362306a36Sopenharmony_cilpfc_hba_log_verbose_init(struct lpfc_hba *phba, uint32_t verbose) 702462306a36Sopenharmony_ci{ 702562306a36Sopenharmony_ci phba->cfg_log_verbose = verbose; 702662306a36Sopenharmony_ci} 702762306a36Sopenharmony_ci 702862306a36Sopenharmony_cistruct fc_function_template lpfc_transport_functions = { 702962306a36Sopenharmony_ci /* fixed attributes the driver supports */ 703062306a36Sopenharmony_ci .show_host_node_name = 1, 703162306a36Sopenharmony_ci .show_host_port_name = 1, 703262306a36Sopenharmony_ci .show_host_supported_classes = 1, 703362306a36Sopenharmony_ci .show_host_supported_fc4s = 1, 703462306a36Sopenharmony_ci .show_host_supported_speeds = 1, 703562306a36Sopenharmony_ci .show_host_maxframe_size = 1, 703662306a36Sopenharmony_ci 703762306a36Sopenharmony_ci .get_host_symbolic_name = lpfc_get_host_symbolic_name, 703862306a36Sopenharmony_ci .show_host_symbolic_name = 1, 703962306a36Sopenharmony_ci 704062306a36Sopenharmony_ci /* dynamic attributes the driver supports */ 704162306a36Sopenharmony_ci .get_host_port_id = lpfc_get_host_port_id, 704262306a36Sopenharmony_ci .show_host_port_id = 1, 704362306a36Sopenharmony_ci 704462306a36Sopenharmony_ci .get_host_port_type = lpfc_get_host_port_type, 704562306a36Sopenharmony_ci .show_host_port_type = 1, 704662306a36Sopenharmony_ci 704762306a36Sopenharmony_ci .get_host_port_state = lpfc_get_host_port_state, 704862306a36Sopenharmony_ci .show_host_port_state = 1, 704962306a36Sopenharmony_ci 705062306a36Sopenharmony_ci /* active_fc4s is shown but doesn't change (thus no get function) */ 705162306a36Sopenharmony_ci .show_host_active_fc4s = 1, 705262306a36Sopenharmony_ci 705362306a36Sopenharmony_ci .get_host_speed = lpfc_get_host_speed, 705462306a36Sopenharmony_ci .show_host_speed = 1, 705562306a36Sopenharmony_ci 705662306a36Sopenharmony_ci .get_host_fabric_name = lpfc_get_host_fabric_name, 705762306a36Sopenharmony_ci .show_host_fabric_name = 1, 705862306a36Sopenharmony_ci 705962306a36Sopenharmony_ci /* 706062306a36Sopenharmony_ci * The LPFC driver treats linkdown handling as target loss events 706162306a36Sopenharmony_ci * so there are no sysfs handlers for link_down_tmo. 706262306a36Sopenharmony_ci */ 706362306a36Sopenharmony_ci 706462306a36Sopenharmony_ci .get_fc_host_stats = lpfc_get_stats, 706562306a36Sopenharmony_ci .reset_fc_host_stats = lpfc_reset_stats, 706662306a36Sopenharmony_ci 706762306a36Sopenharmony_ci .dd_fcrport_size = sizeof(struct lpfc_rport_data), 706862306a36Sopenharmony_ci .show_rport_maxframe_size = 1, 706962306a36Sopenharmony_ci .show_rport_supported_classes = 1, 707062306a36Sopenharmony_ci 707162306a36Sopenharmony_ci .set_rport_dev_loss_tmo = lpfc_set_rport_loss_tmo, 707262306a36Sopenharmony_ci .show_rport_dev_loss_tmo = 1, 707362306a36Sopenharmony_ci 707462306a36Sopenharmony_ci .get_starget_port_id = lpfc_get_starget_port_id, 707562306a36Sopenharmony_ci .show_starget_port_id = 1, 707662306a36Sopenharmony_ci 707762306a36Sopenharmony_ci .get_starget_node_name = lpfc_get_starget_node_name, 707862306a36Sopenharmony_ci .show_starget_node_name = 1, 707962306a36Sopenharmony_ci 708062306a36Sopenharmony_ci .get_starget_port_name = lpfc_get_starget_port_name, 708162306a36Sopenharmony_ci .show_starget_port_name = 1, 708262306a36Sopenharmony_ci 708362306a36Sopenharmony_ci .issue_fc_host_lip = lpfc_issue_lip, 708462306a36Sopenharmony_ci .dev_loss_tmo_callbk = lpfc_dev_loss_tmo_callbk, 708562306a36Sopenharmony_ci .terminate_rport_io = lpfc_terminate_rport_io, 708662306a36Sopenharmony_ci 708762306a36Sopenharmony_ci .dd_fcvport_size = sizeof(struct lpfc_vport *), 708862306a36Sopenharmony_ci 708962306a36Sopenharmony_ci .vport_disable = lpfc_vport_disable, 709062306a36Sopenharmony_ci 709162306a36Sopenharmony_ci .set_vport_symbolic_name = lpfc_set_vport_symbolic_name, 709262306a36Sopenharmony_ci 709362306a36Sopenharmony_ci .bsg_request = lpfc_bsg_request, 709462306a36Sopenharmony_ci .bsg_timeout = lpfc_bsg_timeout, 709562306a36Sopenharmony_ci}; 709662306a36Sopenharmony_ci 709762306a36Sopenharmony_cistruct fc_function_template lpfc_vport_transport_functions = { 709862306a36Sopenharmony_ci /* fixed attributes the driver supports */ 709962306a36Sopenharmony_ci .show_host_node_name = 1, 710062306a36Sopenharmony_ci .show_host_port_name = 1, 710162306a36Sopenharmony_ci .show_host_supported_classes = 1, 710262306a36Sopenharmony_ci .show_host_supported_fc4s = 1, 710362306a36Sopenharmony_ci .show_host_supported_speeds = 1, 710462306a36Sopenharmony_ci .show_host_maxframe_size = 1, 710562306a36Sopenharmony_ci 710662306a36Sopenharmony_ci .get_host_symbolic_name = lpfc_get_host_symbolic_name, 710762306a36Sopenharmony_ci .show_host_symbolic_name = 1, 710862306a36Sopenharmony_ci 710962306a36Sopenharmony_ci /* dynamic attributes the driver supports */ 711062306a36Sopenharmony_ci .get_host_port_id = lpfc_get_host_port_id, 711162306a36Sopenharmony_ci .show_host_port_id = 1, 711262306a36Sopenharmony_ci 711362306a36Sopenharmony_ci .get_host_port_type = lpfc_get_host_port_type, 711462306a36Sopenharmony_ci .show_host_port_type = 1, 711562306a36Sopenharmony_ci 711662306a36Sopenharmony_ci .get_host_port_state = lpfc_get_host_port_state, 711762306a36Sopenharmony_ci .show_host_port_state = 1, 711862306a36Sopenharmony_ci 711962306a36Sopenharmony_ci /* active_fc4s is shown but doesn't change (thus no get function) */ 712062306a36Sopenharmony_ci .show_host_active_fc4s = 1, 712162306a36Sopenharmony_ci 712262306a36Sopenharmony_ci .get_host_speed = lpfc_get_host_speed, 712362306a36Sopenharmony_ci .show_host_speed = 1, 712462306a36Sopenharmony_ci 712562306a36Sopenharmony_ci .get_host_fabric_name = lpfc_get_host_fabric_name, 712662306a36Sopenharmony_ci .show_host_fabric_name = 1, 712762306a36Sopenharmony_ci 712862306a36Sopenharmony_ci /* 712962306a36Sopenharmony_ci * The LPFC driver treats linkdown handling as target loss events 713062306a36Sopenharmony_ci * so there are no sysfs handlers for link_down_tmo. 713162306a36Sopenharmony_ci */ 713262306a36Sopenharmony_ci 713362306a36Sopenharmony_ci .get_fc_host_stats = lpfc_get_stats, 713462306a36Sopenharmony_ci .reset_fc_host_stats = lpfc_reset_stats, 713562306a36Sopenharmony_ci 713662306a36Sopenharmony_ci .dd_fcrport_size = sizeof(struct lpfc_rport_data), 713762306a36Sopenharmony_ci .show_rport_maxframe_size = 1, 713862306a36Sopenharmony_ci .show_rport_supported_classes = 1, 713962306a36Sopenharmony_ci 714062306a36Sopenharmony_ci .set_rport_dev_loss_tmo = lpfc_set_rport_loss_tmo, 714162306a36Sopenharmony_ci .show_rport_dev_loss_tmo = 1, 714262306a36Sopenharmony_ci 714362306a36Sopenharmony_ci .get_starget_port_id = lpfc_get_starget_port_id, 714462306a36Sopenharmony_ci .show_starget_port_id = 1, 714562306a36Sopenharmony_ci 714662306a36Sopenharmony_ci .get_starget_node_name = lpfc_get_starget_node_name, 714762306a36Sopenharmony_ci .show_starget_node_name = 1, 714862306a36Sopenharmony_ci 714962306a36Sopenharmony_ci .get_starget_port_name = lpfc_get_starget_port_name, 715062306a36Sopenharmony_ci .show_starget_port_name = 1, 715162306a36Sopenharmony_ci 715262306a36Sopenharmony_ci .dev_loss_tmo_callbk = lpfc_dev_loss_tmo_callbk, 715362306a36Sopenharmony_ci .terminate_rport_io = lpfc_terminate_rport_io, 715462306a36Sopenharmony_ci 715562306a36Sopenharmony_ci .vport_disable = lpfc_vport_disable, 715662306a36Sopenharmony_ci 715762306a36Sopenharmony_ci .set_vport_symbolic_name = lpfc_set_vport_symbolic_name, 715862306a36Sopenharmony_ci}; 715962306a36Sopenharmony_ci 716062306a36Sopenharmony_ci/** 716162306a36Sopenharmony_ci * lpfc_get_hba_function_mode - Used to determine the HBA function in FCoE 716262306a36Sopenharmony_ci * Mode 716362306a36Sopenharmony_ci * @phba: lpfc_hba pointer. 716462306a36Sopenharmony_ci **/ 716562306a36Sopenharmony_cistatic void 716662306a36Sopenharmony_cilpfc_get_hba_function_mode(struct lpfc_hba *phba) 716762306a36Sopenharmony_ci{ 716862306a36Sopenharmony_ci /* If the adapter supports FCoE mode */ 716962306a36Sopenharmony_ci switch (phba->pcidev->device) { 717062306a36Sopenharmony_ci case PCI_DEVICE_ID_SKYHAWK: 717162306a36Sopenharmony_ci case PCI_DEVICE_ID_SKYHAWK_VF: 717262306a36Sopenharmony_ci case PCI_DEVICE_ID_LANCER_FCOE: 717362306a36Sopenharmony_ci case PCI_DEVICE_ID_LANCER_FCOE_VF: 717462306a36Sopenharmony_ci case PCI_DEVICE_ID_ZEPHYR_DCSP: 717562306a36Sopenharmony_ci case PCI_DEVICE_ID_TIGERSHARK: 717662306a36Sopenharmony_ci case PCI_DEVICE_ID_TOMCAT: 717762306a36Sopenharmony_ci phba->hba_flag |= HBA_FCOE_MODE; 717862306a36Sopenharmony_ci break; 717962306a36Sopenharmony_ci default: 718062306a36Sopenharmony_ci /* for others, clear the flag */ 718162306a36Sopenharmony_ci phba->hba_flag &= ~HBA_FCOE_MODE; 718262306a36Sopenharmony_ci } 718362306a36Sopenharmony_ci} 718462306a36Sopenharmony_ci 718562306a36Sopenharmony_ci/** 718662306a36Sopenharmony_ci * lpfc_get_cfgparam - Used during probe_one to init the adapter structure 718762306a36Sopenharmony_ci * @phba: lpfc_hba pointer. 718862306a36Sopenharmony_ci **/ 718962306a36Sopenharmony_civoid 719062306a36Sopenharmony_cilpfc_get_cfgparam(struct lpfc_hba *phba) 719162306a36Sopenharmony_ci{ 719262306a36Sopenharmony_ci lpfc_hba_log_verbose_init(phba, lpfc_log_verbose); 719362306a36Sopenharmony_ci lpfc_fcp_io_sched_init(phba, lpfc_fcp_io_sched); 719462306a36Sopenharmony_ci lpfc_ns_query_init(phba, lpfc_ns_query); 719562306a36Sopenharmony_ci lpfc_fcp2_no_tgt_reset_init(phba, lpfc_fcp2_no_tgt_reset); 719662306a36Sopenharmony_ci lpfc_cr_delay_init(phba, lpfc_cr_delay); 719762306a36Sopenharmony_ci lpfc_cr_count_init(phba, lpfc_cr_count); 719862306a36Sopenharmony_ci lpfc_multi_ring_support_init(phba, lpfc_multi_ring_support); 719962306a36Sopenharmony_ci lpfc_multi_ring_rctl_init(phba, lpfc_multi_ring_rctl); 720062306a36Sopenharmony_ci lpfc_multi_ring_type_init(phba, lpfc_multi_ring_type); 720162306a36Sopenharmony_ci lpfc_ack0_init(phba, lpfc_ack0); 720262306a36Sopenharmony_ci lpfc_xri_rebalancing_init(phba, lpfc_xri_rebalancing); 720362306a36Sopenharmony_ci lpfc_topology_init(phba, lpfc_topology); 720462306a36Sopenharmony_ci lpfc_link_speed_init(phba, lpfc_link_speed); 720562306a36Sopenharmony_ci lpfc_poll_tmo_init(phba, lpfc_poll_tmo); 720662306a36Sopenharmony_ci lpfc_task_mgmt_tmo_init(phba, lpfc_task_mgmt_tmo); 720762306a36Sopenharmony_ci lpfc_enable_npiv_init(phba, lpfc_enable_npiv); 720862306a36Sopenharmony_ci lpfc_fcf_failover_policy_init(phba, lpfc_fcf_failover_policy); 720962306a36Sopenharmony_ci lpfc_enable_rrq_init(phba, lpfc_enable_rrq); 721062306a36Sopenharmony_ci lpfc_fcp_wait_abts_rsp_init(phba, lpfc_fcp_wait_abts_rsp); 721162306a36Sopenharmony_ci lpfc_fdmi_on_init(phba, lpfc_fdmi_on); 721262306a36Sopenharmony_ci lpfc_enable_SmartSAN_init(phba, lpfc_enable_SmartSAN); 721362306a36Sopenharmony_ci lpfc_use_msi_init(phba, lpfc_use_msi); 721462306a36Sopenharmony_ci lpfc_nvme_oas_init(phba, lpfc_nvme_oas); 721562306a36Sopenharmony_ci lpfc_nvme_embed_cmd_init(phba, lpfc_nvme_embed_cmd); 721662306a36Sopenharmony_ci lpfc_fcp_imax_init(phba, lpfc_fcp_imax); 721762306a36Sopenharmony_ci lpfc_force_rscn_init(phba, lpfc_force_rscn); 721862306a36Sopenharmony_ci lpfc_cq_poll_threshold_init(phba, lpfc_cq_poll_threshold); 721962306a36Sopenharmony_ci lpfc_cq_max_proc_limit_init(phba, lpfc_cq_max_proc_limit); 722062306a36Sopenharmony_ci lpfc_fcp_cpu_map_init(phba, lpfc_fcp_cpu_map); 722162306a36Sopenharmony_ci lpfc_enable_hba_reset_init(phba, lpfc_enable_hba_reset); 722262306a36Sopenharmony_ci lpfc_enable_hba_heartbeat_init(phba, lpfc_enable_hba_heartbeat); 722362306a36Sopenharmony_ci 722462306a36Sopenharmony_ci lpfc_EnableXLane_init(phba, lpfc_EnableXLane); 722562306a36Sopenharmony_ci /* VMID Inits */ 722662306a36Sopenharmony_ci lpfc_max_vmid_init(phba, lpfc_max_vmid); 722762306a36Sopenharmony_ci lpfc_vmid_inactivity_timeout_init(phba, lpfc_vmid_inactivity_timeout); 722862306a36Sopenharmony_ci lpfc_vmid_app_header_init(phba, lpfc_vmid_app_header); 722962306a36Sopenharmony_ci lpfc_vmid_priority_tagging_init(phba, lpfc_vmid_priority_tagging); 723062306a36Sopenharmony_ci if (phba->sli_rev != LPFC_SLI_REV4) 723162306a36Sopenharmony_ci phba->cfg_EnableXLane = 0; 723262306a36Sopenharmony_ci lpfc_XLanePriority_init(phba, lpfc_XLanePriority); 723362306a36Sopenharmony_ci 723462306a36Sopenharmony_ci memset(phba->cfg_oas_tgt_wwpn, 0, (8 * sizeof(uint8_t))); 723562306a36Sopenharmony_ci memset(phba->cfg_oas_vpt_wwpn, 0, (8 * sizeof(uint8_t))); 723662306a36Sopenharmony_ci phba->cfg_oas_lun_state = 0; 723762306a36Sopenharmony_ci phba->cfg_oas_lun_status = 0; 723862306a36Sopenharmony_ci phba->cfg_oas_flags = 0; 723962306a36Sopenharmony_ci phba->cfg_oas_priority = 0; 724062306a36Sopenharmony_ci lpfc_enable_bg_init(phba, lpfc_enable_bg); 724162306a36Sopenharmony_ci lpfc_prot_mask_init(phba, lpfc_prot_mask); 724262306a36Sopenharmony_ci lpfc_prot_guard_init(phba, lpfc_prot_guard); 724362306a36Sopenharmony_ci if (phba->sli_rev == LPFC_SLI_REV4) 724462306a36Sopenharmony_ci phba->cfg_poll = 0; 724562306a36Sopenharmony_ci else 724662306a36Sopenharmony_ci phba->cfg_poll = lpfc_poll; 724762306a36Sopenharmony_ci 724862306a36Sopenharmony_ci /* Get the function mode */ 724962306a36Sopenharmony_ci lpfc_get_hba_function_mode(phba); 725062306a36Sopenharmony_ci 725162306a36Sopenharmony_ci /* BlockGuard allowed for FC only. */ 725262306a36Sopenharmony_ci if (phba->cfg_enable_bg && phba->hba_flag & HBA_FCOE_MODE) { 725362306a36Sopenharmony_ci lpfc_printf_log(phba, KERN_INFO, LOG_INIT, 725462306a36Sopenharmony_ci "0581 BlockGuard feature not supported\n"); 725562306a36Sopenharmony_ci /* If set, clear the BlockGuard support param */ 725662306a36Sopenharmony_ci phba->cfg_enable_bg = 0; 725762306a36Sopenharmony_ci } else if (phba->cfg_enable_bg) { 725862306a36Sopenharmony_ci phba->sli3_options |= LPFC_SLI3_BG_ENABLED; 725962306a36Sopenharmony_ci } 726062306a36Sopenharmony_ci 726162306a36Sopenharmony_ci lpfc_suppress_rsp_init(phba, lpfc_suppress_rsp); 726262306a36Sopenharmony_ci 726362306a36Sopenharmony_ci lpfc_enable_fc4_type_init(phba, lpfc_enable_fc4_type); 726462306a36Sopenharmony_ci lpfc_nvmet_mrq_init(phba, lpfc_nvmet_mrq); 726562306a36Sopenharmony_ci lpfc_nvmet_mrq_post_init(phba, lpfc_nvmet_mrq_post); 726662306a36Sopenharmony_ci 726762306a36Sopenharmony_ci /* Initialize first burst. Target vs Initiator are different. */ 726862306a36Sopenharmony_ci lpfc_nvme_enable_fb_init(phba, lpfc_nvme_enable_fb); 726962306a36Sopenharmony_ci lpfc_nvmet_fb_size_init(phba, lpfc_nvmet_fb_size); 727062306a36Sopenharmony_ci lpfc_fcp_mq_threshold_init(phba, lpfc_fcp_mq_threshold); 727162306a36Sopenharmony_ci lpfc_hdw_queue_init(phba, lpfc_hdw_queue); 727262306a36Sopenharmony_ci lpfc_irq_chann_init(phba, lpfc_irq_chann); 727362306a36Sopenharmony_ci lpfc_enable_bbcr_init(phba, lpfc_enable_bbcr); 727462306a36Sopenharmony_ci lpfc_enable_dpp_init(phba, lpfc_enable_dpp); 727562306a36Sopenharmony_ci lpfc_enable_mi_init(phba, lpfc_enable_mi); 727662306a36Sopenharmony_ci 727762306a36Sopenharmony_ci phba->cgn_p.cgn_param_mode = LPFC_CFG_OFF; 727862306a36Sopenharmony_ci phba->cmf_active_mode = LPFC_CFG_OFF; 727962306a36Sopenharmony_ci if (lpfc_fabric_cgn_frequency > EDC_CG_SIGFREQ_CNT_MAX || 728062306a36Sopenharmony_ci lpfc_fabric_cgn_frequency < EDC_CG_SIGFREQ_CNT_MIN) 728162306a36Sopenharmony_ci lpfc_fabric_cgn_frequency = 100; /* 100 ms default */ 728262306a36Sopenharmony_ci 728362306a36Sopenharmony_ci if (phba->sli_rev != LPFC_SLI_REV4) { 728462306a36Sopenharmony_ci /* NVME only supported on SLI4 */ 728562306a36Sopenharmony_ci phba->nvmet_support = 0; 728662306a36Sopenharmony_ci phba->cfg_nvmet_mrq = 0; 728762306a36Sopenharmony_ci phba->cfg_enable_fc4_type = LPFC_ENABLE_FCP; 728862306a36Sopenharmony_ci phba->cfg_enable_bbcr = 0; 728962306a36Sopenharmony_ci phba->cfg_xri_rebalancing = 0; 729062306a36Sopenharmony_ci } else { 729162306a36Sopenharmony_ci /* We MUST have FCP support */ 729262306a36Sopenharmony_ci if (!(phba->cfg_enable_fc4_type & LPFC_ENABLE_FCP)) 729362306a36Sopenharmony_ci phba->cfg_enable_fc4_type |= LPFC_ENABLE_FCP; 729462306a36Sopenharmony_ci } 729562306a36Sopenharmony_ci 729662306a36Sopenharmony_ci phba->cfg_auto_imax = (phba->cfg_fcp_imax) ? 0 : 1; 729762306a36Sopenharmony_ci 729862306a36Sopenharmony_ci phba->cfg_enable_pbde = 0; 729962306a36Sopenharmony_ci 730062306a36Sopenharmony_ci /* A value of 0 means use the number of CPUs found in the system */ 730162306a36Sopenharmony_ci if (phba->cfg_hdw_queue == 0) 730262306a36Sopenharmony_ci phba->cfg_hdw_queue = phba->sli4_hba.num_present_cpu; 730362306a36Sopenharmony_ci if (phba->cfg_irq_chann == 0) 730462306a36Sopenharmony_ci phba->cfg_irq_chann = phba->sli4_hba.num_present_cpu; 730562306a36Sopenharmony_ci if (phba->cfg_irq_chann > phba->cfg_hdw_queue && 730662306a36Sopenharmony_ci phba->sli_rev == LPFC_SLI_REV4) 730762306a36Sopenharmony_ci phba->cfg_irq_chann = phba->cfg_hdw_queue; 730862306a36Sopenharmony_ci 730962306a36Sopenharmony_ci lpfc_sg_seg_cnt_init(phba, lpfc_sg_seg_cnt); 731062306a36Sopenharmony_ci lpfc_hba_queue_depth_init(phba, lpfc_hba_queue_depth); 731162306a36Sopenharmony_ci lpfc_sriov_nr_virtfn_init(phba, lpfc_sriov_nr_virtfn); 731262306a36Sopenharmony_ci lpfc_request_firmware_upgrade_init(phba, lpfc_req_fw_upgrade); 731362306a36Sopenharmony_ci lpfc_suppress_link_up_init(phba, lpfc_suppress_link_up); 731462306a36Sopenharmony_ci lpfc_delay_discovery_init(phba, lpfc_delay_discovery); 731562306a36Sopenharmony_ci lpfc_sli_mode_init(phba, lpfc_sli_mode); 731662306a36Sopenharmony_ci lpfc_enable_mds_diags_init(phba, lpfc_enable_mds_diags); 731762306a36Sopenharmony_ci lpfc_ras_fwlog_buffsize_init(phba, lpfc_ras_fwlog_buffsize); 731862306a36Sopenharmony_ci lpfc_ras_fwlog_level_init(phba, lpfc_ras_fwlog_level); 731962306a36Sopenharmony_ci lpfc_ras_fwlog_func_init(phba, lpfc_ras_fwlog_func); 732062306a36Sopenharmony_ci 732162306a36Sopenharmony_ci return; 732262306a36Sopenharmony_ci} 732362306a36Sopenharmony_ci 732462306a36Sopenharmony_ci/** 732562306a36Sopenharmony_ci * lpfc_nvme_mod_param_dep - Adjust module parameter value based on 732662306a36Sopenharmony_ci * dependencies between protocols and roles. 732762306a36Sopenharmony_ci * @phba: lpfc_hba pointer. 732862306a36Sopenharmony_ci **/ 732962306a36Sopenharmony_civoid 733062306a36Sopenharmony_cilpfc_nvme_mod_param_dep(struct lpfc_hba *phba) 733162306a36Sopenharmony_ci{ 733262306a36Sopenharmony_ci int logit = 0; 733362306a36Sopenharmony_ci 733462306a36Sopenharmony_ci if (phba->cfg_hdw_queue > phba->sli4_hba.num_present_cpu) { 733562306a36Sopenharmony_ci phba->cfg_hdw_queue = phba->sli4_hba.num_present_cpu; 733662306a36Sopenharmony_ci logit = 1; 733762306a36Sopenharmony_ci } 733862306a36Sopenharmony_ci if (phba->cfg_irq_chann > phba->sli4_hba.num_present_cpu) { 733962306a36Sopenharmony_ci phba->cfg_irq_chann = phba->sli4_hba.num_present_cpu; 734062306a36Sopenharmony_ci logit = 1; 734162306a36Sopenharmony_ci } 734262306a36Sopenharmony_ci if (phba->cfg_irq_chann > phba->cfg_hdw_queue) { 734362306a36Sopenharmony_ci phba->cfg_irq_chann = phba->cfg_hdw_queue; 734462306a36Sopenharmony_ci logit = 1; 734562306a36Sopenharmony_ci } 734662306a36Sopenharmony_ci if (logit) 734762306a36Sopenharmony_ci lpfc_printf_log(phba, KERN_ERR, LOG_SLI, 734862306a36Sopenharmony_ci "2006 Reducing Queues - CPU limitation: " 734962306a36Sopenharmony_ci "IRQ %d HDWQ %d\n", 735062306a36Sopenharmony_ci phba->cfg_irq_chann, 735162306a36Sopenharmony_ci phba->cfg_hdw_queue); 735262306a36Sopenharmony_ci 735362306a36Sopenharmony_ci if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME && 735462306a36Sopenharmony_ci phba->nvmet_support) { 735562306a36Sopenharmony_ci phba->cfg_enable_fc4_type &= ~LPFC_ENABLE_FCP; 735662306a36Sopenharmony_ci 735762306a36Sopenharmony_ci lpfc_printf_log(phba, KERN_INFO, LOG_NVME_DISC, 735862306a36Sopenharmony_ci "6013 %s x%x fb_size x%x, fb_max x%x\n", 735962306a36Sopenharmony_ci "NVME Target PRLI ACC enable_fb ", 736062306a36Sopenharmony_ci phba->cfg_nvme_enable_fb, 736162306a36Sopenharmony_ci phba->cfg_nvmet_fb_size, 736262306a36Sopenharmony_ci LPFC_NVMET_FB_SZ_MAX); 736362306a36Sopenharmony_ci 736462306a36Sopenharmony_ci if (phba->cfg_nvme_enable_fb == 0) 736562306a36Sopenharmony_ci phba->cfg_nvmet_fb_size = 0; 736662306a36Sopenharmony_ci else { 736762306a36Sopenharmony_ci if (phba->cfg_nvmet_fb_size > LPFC_NVMET_FB_SZ_MAX) 736862306a36Sopenharmony_ci phba->cfg_nvmet_fb_size = LPFC_NVMET_FB_SZ_MAX; 736962306a36Sopenharmony_ci } 737062306a36Sopenharmony_ci 737162306a36Sopenharmony_ci if (!phba->cfg_nvmet_mrq) 737262306a36Sopenharmony_ci phba->cfg_nvmet_mrq = phba->cfg_hdw_queue; 737362306a36Sopenharmony_ci 737462306a36Sopenharmony_ci /* Adjust lpfc_nvmet_mrq to avoid running out of WQE slots */ 737562306a36Sopenharmony_ci if (phba->cfg_nvmet_mrq > phba->cfg_hdw_queue) { 737662306a36Sopenharmony_ci phba->cfg_nvmet_mrq = phba->cfg_hdw_queue; 737762306a36Sopenharmony_ci lpfc_printf_log(phba, KERN_ERR, LOG_NVME_DISC, 737862306a36Sopenharmony_ci "6018 Adjust lpfc_nvmet_mrq to %d\n", 737962306a36Sopenharmony_ci phba->cfg_nvmet_mrq); 738062306a36Sopenharmony_ci } 738162306a36Sopenharmony_ci if (phba->cfg_nvmet_mrq > LPFC_NVMET_MRQ_MAX) 738262306a36Sopenharmony_ci phba->cfg_nvmet_mrq = LPFC_NVMET_MRQ_MAX; 738362306a36Sopenharmony_ci 738462306a36Sopenharmony_ci } else { 738562306a36Sopenharmony_ci /* Not NVME Target mode. Turn off Target parameters. */ 738662306a36Sopenharmony_ci phba->nvmet_support = 0; 738762306a36Sopenharmony_ci phba->cfg_nvmet_mrq = 0; 738862306a36Sopenharmony_ci phba->cfg_nvmet_fb_size = 0; 738962306a36Sopenharmony_ci } 739062306a36Sopenharmony_ci} 739162306a36Sopenharmony_ci 739262306a36Sopenharmony_ci/** 739362306a36Sopenharmony_ci * lpfc_get_vport_cfgparam - Used during port create, init the vport structure 739462306a36Sopenharmony_ci * @vport: lpfc_vport pointer. 739562306a36Sopenharmony_ci **/ 739662306a36Sopenharmony_civoid 739762306a36Sopenharmony_cilpfc_get_vport_cfgparam(struct lpfc_vport *vport) 739862306a36Sopenharmony_ci{ 739962306a36Sopenharmony_ci lpfc_log_verbose_init(vport, lpfc_log_verbose); 740062306a36Sopenharmony_ci lpfc_lun_queue_depth_init(vport, lpfc_lun_queue_depth); 740162306a36Sopenharmony_ci lpfc_tgt_queue_depth_init(vport, lpfc_tgt_queue_depth); 740262306a36Sopenharmony_ci lpfc_devloss_tmo_init(vport, lpfc_devloss_tmo); 740362306a36Sopenharmony_ci lpfc_nodev_tmo_init(vport, lpfc_nodev_tmo); 740462306a36Sopenharmony_ci lpfc_peer_port_login_init(vport, lpfc_peer_port_login); 740562306a36Sopenharmony_ci lpfc_restrict_login_init(vport, lpfc_restrict_login); 740662306a36Sopenharmony_ci lpfc_fcp_class_init(vport, lpfc_fcp_class); 740762306a36Sopenharmony_ci lpfc_use_adisc_init(vport, lpfc_use_adisc); 740862306a36Sopenharmony_ci lpfc_first_burst_size_init(vport, lpfc_first_burst_size); 740962306a36Sopenharmony_ci lpfc_max_scsicmpl_time_init(vport, lpfc_max_scsicmpl_time); 741062306a36Sopenharmony_ci lpfc_discovery_threads_init(vport, lpfc_discovery_threads); 741162306a36Sopenharmony_ci lpfc_max_luns_init(vport, lpfc_max_luns); 741262306a36Sopenharmony_ci lpfc_scan_down_init(vport, lpfc_scan_down); 741362306a36Sopenharmony_ci lpfc_enable_da_id_init(vport, lpfc_enable_da_id); 741462306a36Sopenharmony_ci return; 741562306a36Sopenharmony_ci} 7416