xref: /OK3568_Linux_fs/kernel/drivers/scsi/lpfc/lpfc_attr.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*******************************************************************
2*4882a593Smuzhiyun  * This file is part of the Emulex Linux Device Driver for         *
3*4882a593Smuzhiyun  * Fibre Channel Host Bus Adapters.                                *
4*4882a593Smuzhiyun  * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term *
5*4882a593Smuzhiyun  * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.  *
6*4882a593Smuzhiyun  * Copyright (C) 2004-2016 Emulex.  All rights reserved.           *
7*4882a593Smuzhiyun  * EMULEX and SLI are trademarks of Emulex.                        *
8*4882a593Smuzhiyun  * www.broadcom.com                                                *
9*4882a593Smuzhiyun  * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
10*4882a593Smuzhiyun  *                                                                 *
11*4882a593Smuzhiyun  * This program is free software; you can redistribute it and/or   *
12*4882a593Smuzhiyun  * modify it under the terms of version 2 of the GNU General       *
13*4882a593Smuzhiyun  * Public License as published by the Free Software Foundation.    *
14*4882a593Smuzhiyun  * This program is distributed in the hope that it will be useful. *
15*4882a593Smuzhiyun  * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND          *
16*4882a593Smuzhiyun  * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,  *
17*4882a593Smuzhiyun  * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE      *
18*4882a593Smuzhiyun  * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
19*4882a593Smuzhiyun  * TO BE LEGALLY INVALID.  See the GNU General Public License for  *
20*4882a593Smuzhiyun  * more details, a copy of which can be found in the file COPYING  *
21*4882a593Smuzhiyun  * included with this package.                                     *
22*4882a593Smuzhiyun  *******************************************************************/
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun #include <linux/ctype.h>
25*4882a593Smuzhiyun #include <linux/delay.h>
26*4882a593Smuzhiyun #include <linux/pci.h>
27*4882a593Smuzhiyun #include <linux/interrupt.h>
28*4882a593Smuzhiyun #include <linux/module.h>
29*4882a593Smuzhiyun #include <linux/aer.h>
30*4882a593Smuzhiyun #include <linux/gfp.h>
31*4882a593Smuzhiyun #include <linux/kernel.h>
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun #include <scsi/scsi.h>
34*4882a593Smuzhiyun #include <scsi/scsi_device.h>
35*4882a593Smuzhiyun #include <scsi/scsi_host.h>
36*4882a593Smuzhiyun #include <scsi/scsi_tcq.h>
37*4882a593Smuzhiyun #include <scsi/scsi_transport_fc.h>
38*4882a593Smuzhiyun #include <scsi/fc/fc_fs.h>
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun #include "lpfc_hw4.h"
41*4882a593Smuzhiyun #include "lpfc_hw.h"
42*4882a593Smuzhiyun #include "lpfc_sli.h"
43*4882a593Smuzhiyun #include "lpfc_sli4.h"
44*4882a593Smuzhiyun #include "lpfc_nl.h"
45*4882a593Smuzhiyun #include "lpfc_disc.h"
46*4882a593Smuzhiyun #include "lpfc.h"
47*4882a593Smuzhiyun #include "lpfc_scsi.h"
48*4882a593Smuzhiyun #include "lpfc_nvme.h"
49*4882a593Smuzhiyun #include "lpfc_logmsg.h"
50*4882a593Smuzhiyun #include "lpfc_version.h"
51*4882a593Smuzhiyun #include "lpfc_compat.h"
52*4882a593Smuzhiyun #include "lpfc_crtn.h"
53*4882a593Smuzhiyun #include "lpfc_vport.h"
54*4882a593Smuzhiyun #include "lpfc_attr.h"
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun #define LPFC_DEF_DEVLOSS_TMO	30
57*4882a593Smuzhiyun #define LPFC_MIN_DEVLOSS_TMO	1
58*4882a593Smuzhiyun #define LPFC_MAX_DEVLOSS_TMO	255
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun #define LPFC_DEF_MRQ_POST	512
61*4882a593Smuzhiyun #define LPFC_MIN_MRQ_POST	512
62*4882a593Smuzhiyun #define LPFC_MAX_MRQ_POST	2048
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun /*
65*4882a593Smuzhiyun  * Write key size should be multiple of 4. If write key is changed
66*4882a593Smuzhiyun  * make sure that library write key is also changed.
67*4882a593Smuzhiyun  */
68*4882a593Smuzhiyun #define LPFC_REG_WRITE_KEY_SIZE	4
69*4882a593Smuzhiyun #define LPFC_REG_WRITE_KEY	"EMLX"
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun const char *const trunk_errmsg[] = {	/* map errcode */
72*4882a593Smuzhiyun 	"",	/* There is no such error code at index 0*/
73*4882a593Smuzhiyun 	"link negotiated speed does not match existing"
74*4882a593Smuzhiyun 		" trunk - link was \"low\" speed",
75*4882a593Smuzhiyun 	"link negotiated speed does not match"
76*4882a593Smuzhiyun 		" existing trunk - link was \"middle\" speed",
77*4882a593Smuzhiyun 	"link negotiated speed does not match existing"
78*4882a593Smuzhiyun 		" trunk - link was \"high\" speed",
79*4882a593Smuzhiyun 	"Attached to non-trunking port - F_Port",
80*4882a593Smuzhiyun 	"Attached to non-trunking port - N_Port",
81*4882a593Smuzhiyun 	"FLOGI response timeout",
82*4882a593Smuzhiyun 	"non-FLOGI frame received",
83*4882a593Smuzhiyun 	"Invalid FLOGI response",
84*4882a593Smuzhiyun 	"Trunking initialization protocol",
85*4882a593Smuzhiyun 	"Trunk peer device mismatch",
86*4882a593Smuzhiyun };
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun /**
89*4882a593Smuzhiyun  * lpfc_jedec_to_ascii - Hex to ascii convertor according to JEDEC rules
90*4882a593Smuzhiyun  * @incr: integer to convert.
91*4882a593Smuzhiyun  * @hdw: ascii string holding converted integer plus a string terminator.
92*4882a593Smuzhiyun  *
93*4882a593Smuzhiyun  * Description:
94*4882a593Smuzhiyun  * JEDEC Joint Electron Device Engineering Council.
95*4882a593Smuzhiyun  * Convert a 32 bit integer composed of 8 nibbles into an 8 byte ascii
96*4882a593Smuzhiyun  * character string. The string is then terminated with a NULL in byte 9.
97*4882a593Smuzhiyun  * Hex 0-9 becomes ascii '0' to '9'.
98*4882a593Smuzhiyun  * Hex a-f becomes ascii '=' to 'B' capital B.
99*4882a593Smuzhiyun  *
100*4882a593Smuzhiyun  * Notes:
101*4882a593Smuzhiyun  * Coded for 32 bit integers only.
102*4882a593Smuzhiyun  **/
103*4882a593Smuzhiyun static void
lpfc_jedec_to_ascii(int incr,char hdw[])104*4882a593Smuzhiyun lpfc_jedec_to_ascii(int incr, char hdw[])
105*4882a593Smuzhiyun {
106*4882a593Smuzhiyun 	int i, j;
107*4882a593Smuzhiyun 	for (i = 0; i < 8; i++) {
108*4882a593Smuzhiyun 		j = (incr & 0xf);
109*4882a593Smuzhiyun 		if (j <= 9)
110*4882a593Smuzhiyun 			hdw[7 - i] = 0x30 +  j;
111*4882a593Smuzhiyun 		 else
112*4882a593Smuzhiyun 			hdw[7 - i] = 0x61 + j - 10;
113*4882a593Smuzhiyun 		incr = (incr >> 4);
114*4882a593Smuzhiyun 	}
115*4882a593Smuzhiyun 	hdw[8] = 0;
116*4882a593Smuzhiyun 	return;
117*4882a593Smuzhiyun }
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun /**
120*4882a593Smuzhiyun  * lpfc_drvr_version_show - Return the Emulex driver string with version number
121*4882a593Smuzhiyun  * @dev: class unused variable.
122*4882a593Smuzhiyun  * @attr: device attribute, not used.
123*4882a593Smuzhiyun  * @buf: on return contains the module description text.
124*4882a593Smuzhiyun  *
125*4882a593Smuzhiyun  * Returns: size of formatted string.
126*4882a593Smuzhiyun  **/
127*4882a593Smuzhiyun static ssize_t
lpfc_drvr_version_show(struct device * dev,struct device_attribute * attr,char * buf)128*4882a593Smuzhiyun lpfc_drvr_version_show(struct device *dev, struct device_attribute *attr,
129*4882a593Smuzhiyun 		       char *buf)
130*4882a593Smuzhiyun {
131*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, LPFC_MODULE_DESC "\n");
132*4882a593Smuzhiyun }
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun /**
135*4882a593Smuzhiyun  * lpfc_enable_fip_show - Return the fip mode of the HBA
136*4882a593Smuzhiyun  * @dev: class unused variable.
137*4882a593Smuzhiyun  * @attr: device attribute, not used.
138*4882a593Smuzhiyun  * @buf: on return contains the module description text.
139*4882a593Smuzhiyun  *
140*4882a593Smuzhiyun  * Returns: size of formatted string.
141*4882a593Smuzhiyun  **/
142*4882a593Smuzhiyun static ssize_t
lpfc_enable_fip_show(struct device * dev,struct device_attribute * attr,char * buf)143*4882a593Smuzhiyun lpfc_enable_fip_show(struct device *dev, struct device_attribute *attr,
144*4882a593Smuzhiyun 		       char *buf)
145*4882a593Smuzhiyun {
146*4882a593Smuzhiyun 	struct Scsi_Host *shost = class_to_shost(dev);
147*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
148*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 	if (phba->hba_flag & HBA_FIP_SUPPORT)
151*4882a593Smuzhiyun 		return scnprintf(buf, PAGE_SIZE, "1\n");
152*4882a593Smuzhiyun 	else
153*4882a593Smuzhiyun 		return scnprintf(buf, PAGE_SIZE, "0\n");
154*4882a593Smuzhiyun }
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun static ssize_t
lpfc_nvme_info_show(struct device * dev,struct device_attribute * attr,char * buf)157*4882a593Smuzhiyun lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr,
158*4882a593Smuzhiyun 		    char *buf)
159*4882a593Smuzhiyun {
160*4882a593Smuzhiyun 	struct Scsi_Host *shost = class_to_shost(dev);
161*4882a593Smuzhiyun 	struct lpfc_vport *vport = shost_priv(shost);
162*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
163*4882a593Smuzhiyun 	struct lpfc_nvmet_tgtport *tgtp;
164*4882a593Smuzhiyun 	struct nvme_fc_local_port *localport;
165*4882a593Smuzhiyun 	struct lpfc_nvme_lport *lport;
166*4882a593Smuzhiyun 	struct lpfc_nvme_rport *rport;
167*4882a593Smuzhiyun 	struct lpfc_nodelist *ndlp;
168*4882a593Smuzhiyun 	struct nvme_fc_remote_port *nrport;
169*4882a593Smuzhiyun 	struct lpfc_fc4_ctrl_stat *cstat;
170*4882a593Smuzhiyun 	uint64_t data1, data2, data3;
171*4882a593Smuzhiyun 	uint64_t totin, totout, tot;
172*4882a593Smuzhiyun 	char *statep;
173*4882a593Smuzhiyun 	int i;
174*4882a593Smuzhiyun 	int len = 0;
175*4882a593Smuzhiyun 	char tmp[LPFC_MAX_NVME_INFO_TMP_LEN] = {0};
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun 	if (!(vport->cfg_enable_fc4_type & LPFC_ENABLE_NVME)) {
178*4882a593Smuzhiyun 		len = scnprintf(buf, PAGE_SIZE, "NVME Disabled\n");
179*4882a593Smuzhiyun 		return len;
180*4882a593Smuzhiyun 	}
181*4882a593Smuzhiyun 	if (phba->nvmet_support) {
182*4882a593Smuzhiyun 		if (!phba->targetport) {
183*4882a593Smuzhiyun 			len = scnprintf(buf, PAGE_SIZE,
184*4882a593Smuzhiyun 					"NVME Target: x%llx is not allocated\n",
185*4882a593Smuzhiyun 					wwn_to_u64(vport->fc_portname.u.wwn));
186*4882a593Smuzhiyun 			return len;
187*4882a593Smuzhiyun 		}
188*4882a593Smuzhiyun 		/* Port state is only one of two values for now. */
189*4882a593Smuzhiyun 		if (phba->targetport->port_id)
190*4882a593Smuzhiyun 			statep = "REGISTERED";
191*4882a593Smuzhiyun 		else
192*4882a593Smuzhiyun 			statep = "INIT";
193*4882a593Smuzhiyun 		scnprintf(tmp, sizeof(tmp),
194*4882a593Smuzhiyun 			  "NVME Target Enabled  State %s\n",
195*4882a593Smuzhiyun 			  statep);
196*4882a593Smuzhiyun 		if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
197*4882a593Smuzhiyun 			goto buffer_done;
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun 		scnprintf(tmp, sizeof(tmp),
200*4882a593Smuzhiyun 			  "%s%d WWPN x%llx WWNN x%llx DID x%06x\n",
201*4882a593Smuzhiyun 			  "NVME Target: lpfc",
202*4882a593Smuzhiyun 			  phba->brd_no,
203*4882a593Smuzhiyun 			  wwn_to_u64(vport->fc_portname.u.wwn),
204*4882a593Smuzhiyun 			  wwn_to_u64(vport->fc_nodename.u.wwn),
205*4882a593Smuzhiyun 			  phba->targetport->port_id);
206*4882a593Smuzhiyun 		if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
207*4882a593Smuzhiyun 			goto buffer_done;
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun 		if (strlcat(buf, "\nNVME Target: Statistics\n", PAGE_SIZE)
210*4882a593Smuzhiyun 		    >= PAGE_SIZE)
211*4882a593Smuzhiyun 			goto buffer_done;
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun 		tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
214*4882a593Smuzhiyun 		scnprintf(tmp, sizeof(tmp),
215*4882a593Smuzhiyun 			  "LS: Rcv %08x Drop %08x Abort %08x\n",
216*4882a593Smuzhiyun 			  atomic_read(&tgtp->rcv_ls_req_in),
217*4882a593Smuzhiyun 			  atomic_read(&tgtp->rcv_ls_req_drop),
218*4882a593Smuzhiyun 			  atomic_read(&tgtp->xmt_ls_abort));
219*4882a593Smuzhiyun 		if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
220*4882a593Smuzhiyun 			goto buffer_done;
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun 		if (atomic_read(&tgtp->rcv_ls_req_in) !=
223*4882a593Smuzhiyun 		    atomic_read(&tgtp->rcv_ls_req_out)) {
224*4882a593Smuzhiyun 			scnprintf(tmp, sizeof(tmp),
225*4882a593Smuzhiyun 				  "Rcv LS: in %08x != out %08x\n",
226*4882a593Smuzhiyun 				  atomic_read(&tgtp->rcv_ls_req_in),
227*4882a593Smuzhiyun 				  atomic_read(&tgtp->rcv_ls_req_out));
228*4882a593Smuzhiyun 			if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
229*4882a593Smuzhiyun 				goto buffer_done;
230*4882a593Smuzhiyun 		}
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun 		scnprintf(tmp, sizeof(tmp),
233*4882a593Smuzhiyun 			  "LS: Xmt %08x Drop %08x Cmpl %08x\n",
234*4882a593Smuzhiyun 			  atomic_read(&tgtp->xmt_ls_rsp),
235*4882a593Smuzhiyun 			  atomic_read(&tgtp->xmt_ls_drop),
236*4882a593Smuzhiyun 			  atomic_read(&tgtp->xmt_ls_rsp_cmpl));
237*4882a593Smuzhiyun 		if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
238*4882a593Smuzhiyun 			goto buffer_done;
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun 		scnprintf(tmp, sizeof(tmp),
241*4882a593Smuzhiyun 			  "LS: RSP Abort %08x xb %08x Err %08x\n",
242*4882a593Smuzhiyun 			  atomic_read(&tgtp->xmt_ls_rsp_aborted),
243*4882a593Smuzhiyun 			  atomic_read(&tgtp->xmt_ls_rsp_xb_set),
244*4882a593Smuzhiyun 			  atomic_read(&tgtp->xmt_ls_rsp_error));
245*4882a593Smuzhiyun 		if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
246*4882a593Smuzhiyun 			goto buffer_done;
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 		scnprintf(tmp, sizeof(tmp),
249*4882a593Smuzhiyun 			  "FCP: Rcv %08x Defer %08x Release %08x "
250*4882a593Smuzhiyun 			  "Drop %08x\n",
251*4882a593Smuzhiyun 			  atomic_read(&tgtp->rcv_fcp_cmd_in),
252*4882a593Smuzhiyun 			  atomic_read(&tgtp->rcv_fcp_cmd_defer),
253*4882a593Smuzhiyun 			  atomic_read(&tgtp->xmt_fcp_release),
254*4882a593Smuzhiyun 			  atomic_read(&tgtp->rcv_fcp_cmd_drop));
255*4882a593Smuzhiyun 		if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
256*4882a593Smuzhiyun 			goto buffer_done;
257*4882a593Smuzhiyun 
258*4882a593Smuzhiyun 		if (atomic_read(&tgtp->rcv_fcp_cmd_in) !=
259*4882a593Smuzhiyun 		    atomic_read(&tgtp->rcv_fcp_cmd_out)) {
260*4882a593Smuzhiyun 			scnprintf(tmp, sizeof(tmp),
261*4882a593Smuzhiyun 				  "Rcv FCP: in %08x != out %08x\n",
262*4882a593Smuzhiyun 				  atomic_read(&tgtp->rcv_fcp_cmd_in),
263*4882a593Smuzhiyun 				  atomic_read(&tgtp->rcv_fcp_cmd_out));
264*4882a593Smuzhiyun 			if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
265*4882a593Smuzhiyun 				goto buffer_done;
266*4882a593Smuzhiyun 		}
267*4882a593Smuzhiyun 
268*4882a593Smuzhiyun 		scnprintf(tmp, sizeof(tmp),
269*4882a593Smuzhiyun 			  "FCP Rsp: RD %08x rsp %08x WR %08x rsp %08x "
270*4882a593Smuzhiyun 			  "drop %08x\n",
271*4882a593Smuzhiyun 			  atomic_read(&tgtp->xmt_fcp_read),
272*4882a593Smuzhiyun 			  atomic_read(&tgtp->xmt_fcp_read_rsp),
273*4882a593Smuzhiyun 			  atomic_read(&tgtp->xmt_fcp_write),
274*4882a593Smuzhiyun 			  atomic_read(&tgtp->xmt_fcp_rsp),
275*4882a593Smuzhiyun 			  atomic_read(&tgtp->xmt_fcp_drop));
276*4882a593Smuzhiyun 		if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
277*4882a593Smuzhiyun 			goto buffer_done;
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun 		scnprintf(tmp, sizeof(tmp),
280*4882a593Smuzhiyun 			  "FCP Rsp Cmpl: %08x err %08x drop %08x\n",
281*4882a593Smuzhiyun 			  atomic_read(&tgtp->xmt_fcp_rsp_cmpl),
282*4882a593Smuzhiyun 			  atomic_read(&tgtp->xmt_fcp_rsp_error),
283*4882a593Smuzhiyun 			  atomic_read(&tgtp->xmt_fcp_rsp_drop));
284*4882a593Smuzhiyun 		if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
285*4882a593Smuzhiyun 			goto buffer_done;
286*4882a593Smuzhiyun 
287*4882a593Smuzhiyun 		scnprintf(tmp, sizeof(tmp),
288*4882a593Smuzhiyun 			  "FCP Rsp Abort: %08x xb %08x xricqe  %08x\n",
289*4882a593Smuzhiyun 			  atomic_read(&tgtp->xmt_fcp_rsp_aborted),
290*4882a593Smuzhiyun 			  atomic_read(&tgtp->xmt_fcp_rsp_xb_set),
291*4882a593Smuzhiyun 			  atomic_read(&tgtp->xmt_fcp_xri_abort_cqe));
292*4882a593Smuzhiyun 		if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
293*4882a593Smuzhiyun 			goto buffer_done;
294*4882a593Smuzhiyun 
295*4882a593Smuzhiyun 		scnprintf(tmp, sizeof(tmp),
296*4882a593Smuzhiyun 			  "ABORT: Xmt %08x Cmpl %08x\n",
297*4882a593Smuzhiyun 			  atomic_read(&tgtp->xmt_fcp_abort),
298*4882a593Smuzhiyun 			  atomic_read(&tgtp->xmt_fcp_abort_cmpl));
299*4882a593Smuzhiyun 		if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
300*4882a593Smuzhiyun 			goto buffer_done;
301*4882a593Smuzhiyun 
302*4882a593Smuzhiyun 		scnprintf(tmp, sizeof(tmp),
303*4882a593Smuzhiyun 			  "ABORT: Sol %08x  Usol %08x Err %08x Cmpl %08x\n",
304*4882a593Smuzhiyun 			  atomic_read(&tgtp->xmt_abort_sol),
305*4882a593Smuzhiyun 			  atomic_read(&tgtp->xmt_abort_unsol),
306*4882a593Smuzhiyun 			  atomic_read(&tgtp->xmt_abort_rsp),
307*4882a593Smuzhiyun 			  atomic_read(&tgtp->xmt_abort_rsp_error));
308*4882a593Smuzhiyun 		if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
309*4882a593Smuzhiyun 			goto buffer_done;
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun 		scnprintf(tmp, sizeof(tmp),
312*4882a593Smuzhiyun 			  "DELAY: ctx %08x  fod %08x wqfull %08x\n",
313*4882a593Smuzhiyun 			  atomic_read(&tgtp->defer_ctx),
314*4882a593Smuzhiyun 			  atomic_read(&tgtp->defer_fod),
315*4882a593Smuzhiyun 			  atomic_read(&tgtp->defer_wqfull));
316*4882a593Smuzhiyun 		if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
317*4882a593Smuzhiyun 			goto buffer_done;
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun 		/* Calculate outstanding IOs */
320*4882a593Smuzhiyun 		tot = atomic_read(&tgtp->rcv_fcp_cmd_drop);
321*4882a593Smuzhiyun 		tot += atomic_read(&tgtp->xmt_fcp_release);
322*4882a593Smuzhiyun 		tot = atomic_read(&tgtp->rcv_fcp_cmd_in) - tot;
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun 		scnprintf(tmp, sizeof(tmp),
325*4882a593Smuzhiyun 			  "IO_CTX: %08x  WAIT: cur %08x tot %08x\n"
326*4882a593Smuzhiyun 			  "CTX Outstanding %08llx\n\n",
327*4882a593Smuzhiyun 			  phba->sli4_hba.nvmet_xri_cnt,
328*4882a593Smuzhiyun 			  phba->sli4_hba.nvmet_io_wait_cnt,
329*4882a593Smuzhiyun 			  phba->sli4_hba.nvmet_io_wait_total,
330*4882a593Smuzhiyun 			  tot);
331*4882a593Smuzhiyun 		strlcat(buf, tmp, PAGE_SIZE);
332*4882a593Smuzhiyun 		goto buffer_done;
333*4882a593Smuzhiyun 	}
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun 	localport = vport->localport;
336*4882a593Smuzhiyun 	if (!localport) {
337*4882a593Smuzhiyun 		len = scnprintf(buf, PAGE_SIZE,
338*4882a593Smuzhiyun 				"NVME Initiator x%llx is not allocated\n",
339*4882a593Smuzhiyun 				wwn_to_u64(vport->fc_portname.u.wwn));
340*4882a593Smuzhiyun 		return len;
341*4882a593Smuzhiyun 	}
342*4882a593Smuzhiyun 	lport = (struct lpfc_nvme_lport *)localport->private;
343*4882a593Smuzhiyun 	if (strlcat(buf, "\nNVME Initiator Enabled\n", PAGE_SIZE) >= PAGE_SIZE)
344*4882a593Smuzhiyun 		goto buffer_done;
345*4882a593Smuzhiyun 
346*4882a593Smuzhiyun 	scnprintf(tmp, sizeof(tmp),
347*4882a593Smuzhiyun 		  "XRI Dist lpfc%d Total %d IO %d ELS %d\n",
348*4882a593Smuzhiyun 		  phba->brd_no,
349*4882a593Smuzhiyun 		  phba->sli4_hba.max_cfg_param.max_xri,
350*4882a593Smuzhiyun 		  phba->sli4_hba.io_xri_max,
351*4882a593Smuzhiyun 		  lpfc_sli4_get_els_iocb_cnt(phba));
352*4882a593Smuzhiyun 	if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
353*4882a593Smuzhiyun 		goto buffer_done;
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun 	/* Port state is only one of two values for now. */
356*4882a593Smuzhiyun 	if (localport->port_id)
357*4882a593Smuzhiyun 		statep = "ONLINE";
358*4882a593Smuzhiyun 	else
359*4882a593Smuzhiyun 		statep = "UNKNOWN ";
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun 	scnprintf(tmp, sizeof(tmp),
362*4882a593Smuzhiyun 		  "%s%d WWPN x%llx WWNN x%llx DID x%06x %s\n",
363*4882a593Smuzhiyun 		  "NVME LPORT lpfc",
364*4882a593Smuzhiyun 		  phba->brd_no,
365*4882a593Smuzhiyun 		  wwn_to_u64(vport->fc_portname.u.wwn),
366*4882a593Smuzhiyun 		  wwn_to_u64(vport->fc_nodename.u.wwn),
367*4882a593Smuzhiyun 		  localport->port_id, statep);
368*4882a593Smuzhiyun 	if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
369*4882a593Smuzhiyun 		goto buffer_done;
370*4882a593Smuzhiyun 
371*4882a593Smuzhiyun 	spin_lock_irq(shost->host_lock);
372*4882a593Smuzhiyun 
373*4882a593Smuzhiyun 	list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
374*4882a593Smuzhiyun 		nrport = NULL;
375*4882a593Smuzhiyun 		spin_lock(&vport->phba->hbalock);
376*4882a593Smuzhiyun 		rport = lpfc_ndlp_get_nrport(ndlp);
377*4882a593Smuzhiyun 		if (rport)
378*4882a593Smuzhiyun 			nrport = rport->remoteport;
379*4882a593Smuzhiyun 		spin_unlock(&vport->phba->hbalock);
380*4882a593Smuzhiyun 		if (!nrport)
381*4882a593Smuzhiyun 			continue;
382*4882a593Smuzhiyun 
383*4882a593Smuzhiyun 		/* Port state is only one of two values for now. */
384*4882a593Smuzhiyun 		switch (nrport->port_state) {
385*4882a593Smuzhiyun 		case FC_OBJSTATE_ONLINE:
386*4882a593Smuzhiyun 			statep = "ONLINE";
387*4882a593Smuzhiyun 			break;
388*4882a593Smuzhiyun 		case FC_OBJSTATE_UNKNOWN:
389*4882a593Smuzhiyun 			statep = "UNKNOWN ";
390*4882a593Smuzhiyun 			break;
391*4882a593Smuzhiyun 		default:
392*4882a593Smuzhiyun 			statep = "UNSUPPORTED";
393*4882a593Smuzhiyun 			break;
394*4882a593Smuzhiyun 		}
395*4882a593Smuzhiyun 
396*4882a593Smuzhiyun 		/* Tab in to show lport ownership. */
397*4882a593Smuzhiyun 		if (strlcat(buf, "NVME RPORT       ", PAGE_SIZE) >= PAGE_SIZE)
398*4882a593Smuzhiyun 			goto unlock_buf_done;
399*4882a593Smuzhiyun 		if (phba->brd_no >= 10) {
400*4882a593Smuzhiyun 			if (strlcat(buf, " ", PAGE_SIZE) >= PAGE_SIZE)
401*4882a593Smuzhiyun 				goto unlock_buf_done;
402*4882a593Smuzhiyun 		}
403*4882a593Smuzhiyun 
404*4882a593Smuzhiyun 		scnprintf(tmp, sizeof(tmp), "WWPN x%llx ",
405*4882a593Smuzhiyun 			  nrport->port_name);
406*4882a593Smuzhiyun 		if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
407*4882a593Smuzhiyun 			goto unlock_buf_done;
408*4882a593Smuzhiyun 
409*4882a593Smuzhiyun 		scnprintf(tmp, sizeof(tmp), "WWNN x%llx ",
410*4882a593Smuzhiyun 			  nrport->node_name);
411*4882a593Smuzhiyun 		if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
412*4882a593Smuzhiyun 			goto unlock_buf_done;
413*4882a593Smuzhiyun 
414*4882a593Smuzhiyun 		scnprintf(tmp, sizeof(tmp), "DID x%06x ",
415*4882a593Smuzhiyun 			  nrport->port_id);
416*4882a593Smuzhiyun 		if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
417*4882a593Smuzhiyun 			goto unlock_buf_done;
418*4882a593Smuzhiyun 
419*4882a593Smuzhiyun 		/* An NVME rport can have multiple roles. */
420*4882a593Smuzhiyun 		if (nrport->port_role & FC_PORT_ROLE_NVME_INITIATOR) {
421*4882a593Smuzhiyun 			if (strlcat(buf, "INITIATOR ", PAGE_SIZE) >= PAGE_SIZE)
422*4882a593Smuzhiyun 				goto unlock_buf_done;
423*4882a593Smuzhiyun 		}
424*4882a593Smuzhiyun 		if (nrport->port_role & FC_PORT_ROLE_NVME_TARGET) {
425*4882a593Smuzhiyun 			if (strlcat(buf, "TARGET ", PAGE_SIZE) >= PAGE_SIZE)
426*4882a593Smuzhiyun 				goto unlock_buf_done;
427*4882a593Smuzhiyun 		}
428*4882a593Smuzhiyun 		if (nrport->port_role & FC_PORT_ROLE_NVME_DISCOVERY) {
429*4882a593Smuzhiyun 			if (strlcat(buf, "DISCSRVC ", PAGE_SIZE) >= PAGE_SIZE)
430*4882a593Smuzhiyun 				goto unlock_buf_done;
431*4882a593Smuzhiyun 		}
432*4882a593Smuzhiyun 		if (nrport->port_role & ~(FC_PORT_ROLE_NVME_INITIATOR |
433*4882a593Smuzhiyun 					  FC_PORT_ROLE_NVME_TARGET |
434*4882a593Smuzhiyun 					  FC_PORT_ROLE_NVME_DISCOVERY)) {
435*4882a593Smuzhiyun 			scnprintf(tmp, sizeof(tmp), "UNKNOWN ROLE x%x",
436*4882a593Smuzhiyun 				  nrport->port_role);
437*4882a593Smuzhiyun 			if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
438*4882a593Smuzhiyun 				goto unlock_buf_done;
439*4882a593Smuzhiyun 		}
440*4882a593Smuzhiyun 
441*4882a593Smuzhiyun 		scnprintf(tmp, sizeof(tmp), "%s\n", statep);
442*4882a593Smuzhiyun 		if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
443*4882a593Smuzhiyun 			goto unlock_buf_done;
444*4882a593Smuzhiyun 	}
445*4882a593Smuzhiyun 	spin_unlock_irq(shost->host_lock);
446*4882a593Smuzhiyun 
447*4882a593Smuzhiyun 	if (!lport)
448*4882a593Smuzhiyun 		goto buffer_done;
449*4882a593Smuzhiyun 
450*4882a593Smuzhiyun 	if (strlcat(buf, "\nNVME Statistics\n", PAGE_SIZE) >= PAGE_SIZE)
451*4882a593Smuzhiyun 		goto buffer_done;
452*4882a593Smuzhiyun 
453*4882a593Smuzhiyun 	scnprintf(tmp, sizeof(tmp),
454*4882a593Smuzhiyun 		  "LS: Xmt %010x Cmpl %010x Abort %08x\n",
455*4882a593Smuzhiyun 		  atomic_read(&lport->fc4NvmeLsRequests),
456*4882a593Smuzhiyun 		  atomic_read(&lport->fc4NvmeLsCmpls),
457*4882a593Smuzhiyun 		  atomic_read(&lport->xmt_ls_abort));
458*4882a593Smuzhiyun 	if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
459*4882a593Smuzhiyun 		goto buffer_done;
460*4882a593Smuzhiyun 
461*4882a593Smuzhiyun 	scnprintf(tmp, sizeof(tmp),
462*4882a593Smuzhiyun 		  "LS XMIT: Err %08x  CMPL: xb %08x Err %08x\n",
463*4882a593Smuzhiyun 		  atomic_read(&lport->xmt_ls_err),
464*4882a593Smuzhiyun 		  atomic_read(&lport->cmpl_ls_xb),
465*4882a593Smuzhiyun 		  atomic_read(&lport->cmpl_ls_err));
466*4882a593Smuzhiyun 	if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
467*4882a593Smuzhiyun 		goto buffer_done;
468*4882a593Smuzhiyun 
469*4882a593Smuzhiyun 	totin = 0;
470*4882a593Smuzhiyun 	totout = 0;
471*4882a593Smuzhiyun 	for (i = 0; i < phba->cfg_hdw_queue; i++) {
472*4882a593Smuzhiyun 		cstat = &phba->sli4_hba.hdwq[i].nvme_cstat;
473*4882a593Smuzhiyun 		tot = cstat->io_cmpls;
474*4882a593Smuzhiyun 		totin += tot;
475*4882a593Smuzhiyun 		data1 = cstat->input_requests;
476*4882a593Smuzhiyun 		data2 = cstat->output_requests;
477*4882a593Smuzhiyun 		data3 = cstat->control_requests;
478*4882a593Smuzhiyun 		totout += (data1 + data2 + data3);
479*4882a593Smuzhiyun 	}
480*4882a593Smuzhiyun 	scnprintf(tmp, sizeof(tmp),
481*4882a593Smuzhiyun 		  "Total FCP Cmpl %016llx Issue %016llx "
482*4882a593Smuzhiyun 		  "OutIO %016llx\n",
483*4882a593Smuzhiyun 		  totin, totout, totout - totin);
484*4882a593Smuzhiyun 	if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
485*4882a593Smuzhiyun 		goto buffer_done;
486*4882a593Smuzhiyun 
487*4882a593Smuzhiyun 	scnprintf(tmp, sizeof(tmp),
488*4882a593Smuzhiyun 		  "\tabort %08x noxri %08x nondlp %08x qdepth %08x "
489*4882a593Smuzhiyun 		  "wqerr %08x err %08x\n",
490*4882a593Smuzhiyun 		  atomic_read(&lport->xmt_fcp_abort),
491*4882a593Smuzhiyun 		  atomic_read(&lport->xmt_fcp_noxri),
492*4882a593Smuzhiyun 		  atomic_read(&lport->xmt_fcp_bad_ndlp),
493*4882a593Smuzhiyun 		  atomic_read(&lport->xmt_fcp_qdepth),
494*4882a593Smuzhiyun 		  atomic_read(&lport->xmt_fcp_err),
495*4882a593Smuzhiyun 		  atomic_read(&lport->xmt_fcp_wqerr));
496*4882a593Smuzhiyun 	if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
497*4882a593Smuzhiyun 		goto buffer_done;
498*4882a593Smuzhiyun 
499*4882a593Smuzhiyun 	scnprintf(tmp, sizeof(tmp),
500*4882a593Smuzhiyun 		  "FCP CMPL: xb %08x Err %08x\n",
501*4882a593Smuzhiyun 		  atomic_read(&lport->cmpl_fcp_xb),
502*4882a593Smuzhiyun 		  atomic_read(&lport->cmpl_fcp_err));
503*4882a593Smuzhiyun 	strlcat(buf, tmp, PAGE_SIZE);
504*4882a593Smuzhiyun 
505*4882a593Smuzhiyun 	/* host_lock is already unlocked. */
506*4882a593Smuzhiyun 	goto buffer_done;
507*4882a593Smuzhiyun 
508*4882a593Smuzhiyun  unlock_buf_done:
509*4882a593Smuzhiyun 	spin_unlock_irq(shost->host_lock);
510*4882a593Smuzhiyun 
511*4882a593Smuzhiyun  buffer_done:
512*4882a593Smuzhiyun 	len = strnlen(buf, PAGE_SIZE);
513*4882a593Smuzhiyun 
514*4882a593Smuzhiyun 	if (unlikely(len >= (PAGE_SIZE - 1))) {
515*4882a593Smuzhiyun 		lpfc_printf_log(phba, KERN_INFO, LOG_NVME,
516*4882a593Smuzhiyun 				"6314 Catching potential buffer "
517*4882a593Smuzhiyun 				"overflow > PAGE_SIZE = %lu bytes\n",
518*4882a593Smuzhiyun 				PAGE_SIZE);
519*4882a593Smuzhiyun 		strlcpy(buf + PAGE_SIZE - 1 -
520*4882a593Smuzhiyun 			strnlen(LPFC_NVME_INFO_MORE_STR, PAGE_SIZE - 1),
521*4882a593Smuzhiyun 			LPFC_NVME_INFO_MORE_STR,
522*4882a593Smuzhiyun 			strnlen(LPFC_NVME_INFO_MORE_STR, PAGE_SIZE - 1)
523*4882a593Smuzhiyun 			+ 1);
524*4882a593Smuzhiyun 	}
525*4882a593Smuzhiyun 
526*4882a593Smuzhiyun 	return len;
527*4882a593Smuzhiyun }
528*4882a593Smuzhiyun 
529*4882a593Smuzhiyun static ssize_t
lpfc_scsi_stat_show(struct device * dev,struct device_attribute * attr,char * buf)530*4882a593Smuzhiyun lpfc_scsi_stat_show(struct device *dev, struct device_attribute *attr,
531*4882a593Smuzhiyun 		    char *buf)
532*4882a593Smuzhiyun {
533*4882a593Smuzhiyun 	struct Scsi_Host *shost = class_to_shost(dev);
534*4882a593Smuzhiyun 	struct lpfc_vport *vport = shost_priv(shost);
535*4882a593Smuzhiyun 	struct lpfc_hba *phba = vport->phba;
536*4882a593Smuzhiyun 	int len;
537*4882a593Smuzhiyun 	struct lpfc_fc4_ctrl_stat *cstat;
538*4882a593Smuzhiyun 	u64 data1, data2, data3;
539*4882a593Smuzhiyun 	u64 tot, totin, totout;
540*4882a593Smuzhiyun 	int i;
541*4882a593Smuzhiyun 	char tmp[LPFC_MAX_SCSI_INFO_TMP_LEN] = {0};
542*4882a593Smuzhiyun 
543*4882a593Smuzhiyun 	if (!(vport->cfg_enable_fc4_type & LPFC_ENABLE_FCP) ||
544*4882a593Smuzhiyun 	    (phba->sli_rev != LPFC_SLI_REV4))
545*4882a593Smuzhiyun 		return 0;
546*4882a593Smuzhiyun 
547*4882a593Smuzhiyun 	scnprintf(buf, PAGE_SIZE, "SCSI HDWQ Statistics\n");
548*4882a593Smuzhiyun 
549*4882a593Smuzhiyun 	totin = 0;
550*4882a593Smuzhiyun 	totout = 0;
551*4882a593Smuzhiyun 	for (i = 0; i < phba->cfg_hdw_queue; i++) {
552*4882a593Smuzhiyun 		cstat = &phba->sli4_hba.hdwq[i].scsi_cstat;
553*4882a593Smuzhiyun 		tot = cstat->io_cmpls;
554*4882a593Smuzhiyun 		totin += tot;
555*4882a593Smuzhiyun 		data1 = cstat->input_requests;
556*4882a593Smuzhiyun 		data2 = cstat->output_requests;
557*4882a593Smuzhiyun 		data3 = cstat->control_requests;
558*4882a593Smuzhiyun 		totout += (data1 + data2 + data3);
559*4882a593Smuzhiyun 
560*4882a593Smuzhiyun 		scnprintf(tmp, sizeof(tmp), "HDWQ (%d): Rd %016llx Wr %016llx "
561*4882a593Smuzhiyun 			  "IO %016llx ", i, data1, data2, data3);
562*4882a593Smuzhiyun 		if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
563*4882a593Smuzhiyun 			goto buffer_done;
564*4882a593Smuzhiyun 
565*4882a593Smuzhiyun 		scnprintf(tmp, sizeof(tmp), "Cmpl %016llx OutIO %016llx\n",
566*4882a593Smuzhiyun 			  tot, ((data1 + data2 + data3) - tot));
567*4882a593Smuzhiyun 		if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
568*4882a593Smuzhiyun 			goto buffer_done;
569*4882a593Smuzhiyun 	}
570*4882a593Smuzhiyun 	scnprintf(tmp, sizeof(tmp), "Total FCP Cmpl %016llx Issue %016llx "
571*4882a593Smuzhiyun 		  "OutIO %016llx\n", totin, totout, totout - totin);
572*4882a593Smuzhiyun 	strlcat(buf, tmp, PAGE_SIZE);
573*4882a593Smuzhiyun 
574*4882a593Smuzhiyun buffer_done:
575*4882a593Smuzhiyun 	len = strnlen(buf, PAGE_SIZE);
576*4882a593Smuzhiyun 
577*4882a593Smuzhiyun 	return len;
578*4882a593Smuzhiyun }
579*4882a593Smuzhiyun 
580*4882a593Smuzhiyun static ssize_t
lpfc_bg_info_show(struct device * dev,struct device_attribute * attr,char * buf)581*4882a593Smuzhiyun lpfc_bg_info_show(struct device *dev, struct device_attribute *attr,
582*4882a593Smuzhiyun 		  char *buf)
583*4882a593Smuzhiyun {
584*4882a593Smuzhiyun 	struct Scsi_Host *shost = class_to_shost(dev);
585*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
586*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
587*4882a593Smuzhiyun 
588*4882a593Smuzhiyun 	if (phba->cfg_enable_bg) {
589*4882a593Smuzhiyun 		if (phba->sli3_options & LPFC_SLI3_BG_ENABLED)
590*4882a593Smuzhiyun 			return scnprintf(buf, PAGE_SIZE,
591*4882a593Smuzhiyun 					"BlockGuard Enabled\n");
592*4882a593Smuzhiyun 		else
593*4882a593Smuzhiyun 			return scnprintf(buf, PAGE_SIZE,
594*4882a593Smuzhiyun 					"BlockGuard Not Supported\n");
595*4882a593Smuzhiyun 	} else
596*4882a593Smuzhiyun 		return scnprintf(buf, PAGE_SIZE,
597*4882a593Smuzhiyun 					"BlockGuard Disabled\n");
598*4882a593Smuzhiyun }
599*4882a593Smuzhiyun 
600*4882a593Smuzhiyun static ssize_t
lpfc_bg_guard_err_show(struct device * dev,struct device_attribute * attr,char * buf)601*4882a593Smuzhiyun lpfc_bg_guard_err_show(struct device *dev, struct device_attribute *attr,
602*4882a593Smuzhiyun 		       char *buf)
603*4882a593Smuzhiyun {
604*4882a593Smuzhiyun 	struct Scsi_Host *shost = class_to_shost(dev);
605*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
606*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
607*4882a593Smuzhiyun 
608*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "%llu\n",
609*4882a593Smuzhiyun 			(unsigned long long)phba->bg_guard_err_cnt);
610*4882a593Smuzhiyun }
611*4882a593Smuzhiyun 
612*4882a593Smuzhiyun static ssize_t
lpfc_bg_apptag_err_show(struct device * dev,struct device_attribute * attr,char * buf)613*4882a593Smuzhiyun lpfc_bg_apptag_err_show(struct device *dev, struct device_attribute *attr,
614*4882a593Smuzhiyun 			char *buf)
615*4882a593Smuzhiyun {
616*4882a593Smuzhiyun 	struct Scsi_Host *shost = class_to_shost(dev);
617*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
618*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
619*4882a593Smuzhiyun 
620*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "%llu\n",
621*4882a593Smuzhiyun 			(unsigned long long)phba->bg_apptag_err_cnt);
622*4882a593Smuzhiyun }
623*4882a593Smuzhiyun 
624*4882a593Smuzhiyun static ssize_t
lpfc_bg_reftag_err_show(struct device * dev,struct device_attribute * attr,char * buf)625*4882a593Smuzhiyun lpfc_bg_reftag_err_show(struct device *dev, struct device_attribute *attr,
626*4882a593Smuzhiyun 			char *buf)
627*4882a593Smuzhiyun {
628*4882a593Smuzhiyun 	struct Scsi_Host *shost = class_to_shost(dev);
629*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
630*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
631*4882a593Smuzhiyun 
632*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "%llu\n",
633*4882a593Smuzhiyun 			(unsigned long long)phba->bg_reftag_err_cnt);
634*4882a593Smuzhiyun }
635*4882a593Smuzhiyun 
636*4882a593Smuzhiyun /**
637*4882a593Smuzhiyun  * lpfc_info_show - Return some pci info about the host in ascii
638*4882a593Smuzhiyun  * @dev: class converted to a Scsi_host structure.
639*4882a593Smuzhiyun  * @attr: device attribute, not used.
640*4882a593Smuzhiyun  * @buf: on return contains the formatted text from lpfc_info().
641*4882a593Smuzhiyun  *
642*4882a593Smuzhiyun  * Returns: size of formatted string.
643*4882a593Smuzhiyun  **/
644*4882a593Smuzhiyun static ssize_t
lpfc_info_show(struct device * dev,struct device_attribute * attr,char * buf)645*4882a593Smuzhiyun lpfc_info_show(struct device *dev, struct device_attribute *attr,
646*4882a593Smuzhiyun 	       char *buf)
647*4882a593Smuzhiyun {
648*4882a593Smuzhiyun 	struct Scsi_Host *host = class_to_shost(dev);
649*4882a593Smuzhiyun 
650*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "%s\n", lpfc_info(host));
651*4882a593Smuzhiyun }
652*4882a593Smuzhiyun 
653*4882a593Smuzhiyun /**
654*4882a593Smuzhiyun  * lpfc_serialnum_show - Return the hba serial number in ascii
655*4882a593Smuzhiyun  * @dev: class converted to a Scsi_host structure.
656*4882a593Smuzhiyun  * @attr: device attribute, not used.
657*4882a593Smuzhiyun  * @buf: on return contains the formatted text serial number.
658*4882a593Smuzhiyun  *
659*4882a593Smuzhiyun  * Returns: size of formatted string.
660*4882a593Smuzhiyun  **/
661*4882a593Smuzhiyun static ssize_t
lpfc_serialnum_show(struct device * dev,struct device_attribute * attr,char * buf)662*4882a593Smuzhiyun lpfc_serialnum_show(struct device *dev, struct device_attribute *attr,
663*4882a593Smuzhiyun 		    char *buf)
664*4882a593Smuzhiyun {
665*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
666*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
667*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
668*4882a593Smuzhiyun 
669*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "%s\n", phba->SerialNumber);
670*4882a593Smuzhiyun }
671*4882a593Smuzhiyun 
672*4882a593Smuzhiyun /**
673*4882a593Smuzhiyun  * lpfc_temp_sensor_show - Return the temperature sensor level
674*4882a593Smuzhiyun  * @dev: class converted to a Scsi_host structure.
675*4882a593Smuzhiyun  * @attr: device attribute, not used.
676*4882a593Smuzhiyun  * @buf: on return contains the formatted support level.
677*4882a593Smuzhiyun  *
678*4882a593Smuzhiyun  * Description:
679*4882a593Smuzhiyun  * Returns a number indicating the temperature sensor level currently
680*4882a593Smuzhiyun  * supported, zero or one in ascii.
681*4882a593Smuzhiyun  *
682*4882a593Smuzhiyun  * Returns: size of formatted string.
683*4882a593Smuzhiyun  **/
684*4882a593Smuzhiyun static ssize_t
lpfc_temp_sensor_show(struct device * dev,struct device_attribute * attr,char * buf)685*4882a593Smuzhiyun lpfc_temp_sensor_show(struct device *dev, struct device_attribute *attr,
686*4882a593Smuzhiyun 		      char *buf)
687*4882a593Smuzhiyun {
688*4882a593Smuzhiyun 	struct Scsi_Host *shost = class_to_shost(dev);
689*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
690*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
691*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "%d\n", phba->temp_sensor_support);
692*4882a593Smuzhiyun }
693*4882a593Smuzhiyun 
694*4882a593Smuzhiyun /**
695*4882a593Smuzhiyun  * lpfc_modeldesc_show - Return the model description of the hba
696*4882a593Smuzhiyun  * @dev: class converted to a Scsi_host structure.
697*4882a593Smuzhiyun  * @attr: device attribute, not used.
698*4882a593Smuzhiyun  * @buf: on return contains the scsi vpd model description.
699*4882a593Smuzhiyun  *
700*4882a593Smuzhiyun  * Returns: size of formatted string.
701*4882a593Smuzhiyun  **/
702*4882a593Smuzhiyun static ssize_t
lpfc_modeldesc_show(struct device * dev,struct device_attribute * attr,char * buf)703*4882a593Smuzhiyun lpfc_modeldesc_show(struct device *dev, struct device_attribute *attr,
704*4882a593Smuzhiyun 		    char *buf)
705*4882a593Smuzhiyun {
706*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
707*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
708*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
709*4882a593Smuzhiyun 
710*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "%s\n", phba->ModelDesc);
711*4882a593Smuzhiyun }
712*4882a593Smuzhiyun 
713*4882a593Smuzhiyun /**
714*4882a593Smuzhiyun  * lpfc_modelname_show - Return the model name of the hba
715*4882a593Smuzhiyun  * @dev: class converted to a Scsi_host structure.
716*4882a593Smuzhiyun  * @attr: device attribute, not used.
717*4882a593Smuzhiyun  * @buf: on return contains the scsi vpd model name.
718*4882a593Smuzhiyun  *
719*4882a593Smuzhiyun  * Returns: size of formatted string.
720*4882a593Smuzhiyun  **/
721*4882a593Smuzhiyun static ssize_t
lpfc_modelname_show(struct device * dev,struct device_attribute * attr,char * buf)722*4882a593Smuzhiyun lpfc_modelname_show(struct device *dev, struct device_attribute *attr,
723*4882a593Smuzhiyun 		    char *buf)
724*4882a593Smuzhiyun {
725*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
726*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
727*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
728*4882a593Smuzhiyun 
729*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "%s\n", phba->ModelName);
730*4882a593Smuzhiyun }
731*4882a593Smuzhiyun 
732*4882a593Smuzhiyun /**
733*4882a593Smuzhiyun  * lpfc_programtype_show - Return the program type of the hba
734*4882a593Smuzhiyun  * @dev: class converted to a Scsi_host structure.
735*4882a593Smuzhiyun  * @attr: device attribute, not used.
736*4882a593Smuzhiyun  * @buf: on return contains the scsi vpd program type.
737*4882a593Smuzhiyun  *
738*4882a593Smuzhiyun  * Returns: size of formatted string.
739*4882a593Smuzhiyun  **/
740*4882a593Smuzhiyun static ssize_t
lpfc_programtype_show(struct device * dev,struct device_attribute * attr,char * buf)741*4882a593Smuzhiyun lpfc_programtype_show(struct device *dev, struct device_attribute *attr,
742*4882a593Smuzhiyun 		      char *buf)
743*4882a593Smuzhiyun {
744*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
745*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
746*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
747*4882a593Smuzhiyun 
748*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "%s\n", phba->ProgramType);
749*4882a593Smuzhiyun }
750*4882a593Smuzhiyun 
751*4882a593Smuzhiyun /**
752*4882a593Smuzhiyun  * lpfc_mlomgmt_show - Return the Menlo Maintenance sli flag
753*4882a593Smuzhiyun  * @dev: class converted to a Scsi_host structure.
754*4882a593Smuzhiyun  * @attr: device attribute, not used.
755*4882a593Smuzhiyun  * @buf: on return contains the Menlo Maintenance sli flag.
756*4882a593Smuzhiyun  *
757*4882a593Smuzhiyun  * Returns: size of formatted string.
758*4882a593Smuzhiyun  **/
759*4882a593Smuzhiyun static ssize_t
lpfc_mlomgmt_show(struct device * dev,struct device_attribute * attr,char * buf)760*4882a593Smuzhiyun lpfc_mlomgmt_show(struct device *dev, struct device_attribute *attr, char *buf)
761*4882a593Smuzhiyun {
762*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
763*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata;
764*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
765*4882a593Smuzhiyun 
766*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "%d\n",
767*4882a593Smuzhiyun 		(phba->sli.sli_flag & LPFC_MENLO_MAINT));
768*4882a593Smuzhiyun }
769*4882a593Smuzhiyun 
770*4882a593Smuzhiyun /**
771*4882a593Smuzhiyun  * lpfc_vportnum_show - Return the port number in ascii of the hba
772*4882a593Smuzhiyun  * @dev: class converted to a Scsi_host structure.
773*4882a593Smuzhiyun  * @attr: device attribute, not used.
774*4882a593Smuzhiyun  * @buf: on return contains scsi vpd program type.
775*4882a593Smuzhiyun  *
776*4882a593Smuzhiyun  * Returns: size of formatted string.
777*4882a593Smuzhiyun  **/
778*4882a593Smuzhiyun static ssize_t
lpfc_vportnum_show(struct device * dev,struct device_attribute * attr,char * buf)779*4882a593Smuzhiyun lpfc_vportnum_show(struct device *dev, struct device_attribute *attr,
780*4882a593Smuzhiyun 		   char *buf)
781*4882a593Smuzhiyun {
782*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
783*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
784*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
785*4882a593Smuzhiyun 
786*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "%s\n", phba->Port);
787*4882a593Smuzhiyun }
788*4882a593Smuzhiyun 
789*4882a593Smuzhiyun /**
790*4882a593Smuzhiyun  * lpfc_fwrev_show - Return the firmware rev running in the hba
791*4882a593Smuzhiyun  * @dev: class converted to a Scsi_host structure.
792*4882a593Smuzhiyun  * @attr: device attribute, not used.
793*4882a593Smuzhiyun  * @buf: on return contains the scsi vpd program type.
794*4882a593Smuzhiyun  *
795*4882a593Smuzhiyun  * Returns: size of formatted string.
796*4882a593Smuzhiyun  **/
797*4882a593Smuzhiyun static ssize_t
lpfc_fwrev_show(struct device * dev,struct device_attribute * attr,char * buf)798*4882a593Smuzhiyun lpfc_fwrev_show(struct device *dev, struct device_attribute *attr,
799*4882a593Smuzhiyun 		char *buf)
800*4882a593Smuzhiyun {
801*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
802*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
803*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
804*4882a593Smuzhiyun 	uint32_t if_type;
805*4882a593Smuzhiyun 	uint8_t sli_family;
806*4882a593Smuzhiyun 	char fwrev[FW_REV_STR_SIZE];
807*4882a593Smuzhiyun 	int len;
808*4882a593Smuzhiyun 
809*4882a593Smuzhiyun 	lpfc_decode_firmware_rev(phba, fwrev, 1);
810*4882a593Smuzhiyun 	if_type = phba->sli4_hba.pc_sli4_params.if_type;
811*4882a593Smuzhiyun 	sli_family = phba->sli4_hba.pc_sli4_params.sli_family;
812*4882a593Smuzhiyun 
813*4882a593Smuzhiyun 	if (phba->sli_rev < LPFC_SLI_REV4)
814*4882a593Smuzhiyun 		len = scnprintf(buf, PAGE_SIZE, "%s, sli-%d\n",
815*4882a593Smuzhiyun 			       fwrev, phba->sli_rev);
816*4882a593Smuzhiyun 	else
817*4882a593Smuzhiyun 		len = scnprintf(buf, PAGE_SIZE, "%s, sli-%d:%d:%x\n",
818*4882a593Smuzhiyun 			       fwrev, phba->sli_rev, if_type, sli_family);
819*4882a593Smuzhiyun 
820*4882a593Smuzhiyun 	return len;
821*4882a593Smuzhiyun }
822*4882a593Smuzhiyun 
823*4882a593Smuzhiyun /**
824*4882a593Smuzhiyun  * lpfc_hdw_show - Return the jedec information about the hba
825*4882a593Smuzhiyun  * @dev: class converted to a Scsi_host structure.
826*4882a593Smuzhiyun  * @attr: device attribute, not used.
827*4882a593Smuzhiyun  * @buf: on return contains the scsi vpd program type.
828*4882a593Smuzhiyun  *
829*4882a593Smuzhiyun  * Returns: size of formatted string.
830*4882a593Smuzhiyun  **/
831*4882a593Smuzhiyun static ssize_t
lpfc_hdw_show(struct device * dev,struct device_attribute * attr,char * buf)832*4882a593Smuzhiyun lpfc_hdw_show(struct device *dev, struct device_attribute *attr, char *buf)
833*4882a593Smuzhiyun {
834*4882a593Smuzhiyun 	char hdw[9];
835*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
836*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
837*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
838*4882a593Smuzhiyun 	lpfc_vpd_t *vp = &phba->vpd;
839*4882a593Smuzhiyun 
840*4882a593Smuzhiyun 	lpfc_jedec_to_ascii(vp->rev.biuRev, hdw);
841*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "%s %08x %08x\n", hdw,
842*4882a593Smuzhiyun 			 vp->rev.smRev, vp->rev.smFwRev);
843*4882a593Smuzhiyun }
844*4882a593Smuzhiyun 
845*4882a593Smuzhiyun /**
846*4882a593Smuzhiyun  * lpfc_option_rom_version_show - Return the adapter ROM FCode version
847*4882a593Smuzhiyun  * @dev: class converted to a Scsi_host structure.
848*4882a593Smuzhiyun  * @attr: device attribute, not used.
849*4882a593Smuzhiyun  * @buf: on return contains the ROM and FCode ascii strings.
850*4882a593Smuzhiyun  *
851*4882a593Smuzhiyun  * Returns: size of formatted string.
852*4882a593Smuzhiyun  **/
853*4882a593Smuzhiyun static ssize_t
lpfc_option_rom_version_show(struct device * dev,struct device_attribute * attr,char * buf)854*4882a593Smuzhiyun lpfc_option_rom_version_show(struct device *dev, struct device_attribute *attr,
855*4882a593Smuzhiyun 			     char *buf)
856*4882a593Smuzhiyun {
857*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
858*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
859*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
860*4882a593Smuzhiyun 	char fwrev[FW_REV_STR_SIZE];
861*4882a593Smuzhiyun 
862*4882a593Smuzhiyun 	if (phba->sli_rev < LPFC_SLI_REV4)
863*4882a593Smuzhiyun 		return scnprintf(buf, PAGE_SIZE, "%s\n",
864*4882a593Smuzhiyun 				phba->OptionROMVersion);
865*4882a593Smuzhiyun 
866*4882a593Smuzhiyun 	lpfc_decode_firmware_rev(phba, fwrev, 1);
867*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "%s\n", fwrev);
868*4882a593Smuzhiyun }
869*4882a593Smuzhiyun 
870*4882a593Smuzhiyun /**
871*4882a593Smuzhiyun  * lpfc_state_show - Return the link state of the port
872*4882a593Smuzhiyun  * @dev: class converted to a Scsi_host structure.
873*4882a593Smuzhiyun  * @attr: device attribute, not used.
874*4882a593Smuzhiyun  * @buf: on return contains text describing the state of the link.
875*4882a593Smuzhiyun  *
876*4882a593Smuzhiyun  * Notes:
877*4882a593Smuzhiyun  * The switch statement has no default so zero will be returned.
878*4882a593Smuzhiyun  *
879*4882a593Smuzhiyun  * Returns: size of formatted string.
880*4882a593Smuzhiyun  **/
881*4882a593Smuzhiyun static ssize_t
lpfc_link_state_show(struct device * dev,struct device_attribute * attr,char * buf)882*4882a593Smuzhiyun lpfc_link_state_show(struct device *dev, struct device_attribute *attr,
883*4882a593Smuzhiyun 		     char *buf)
884*4882a593Smuzhiyun {
885*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
886*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
887*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
888*4882a593Smuzhiyun 	int  len = 0;
889*4882a593Smuzhiyun 
890*4882a593Smuzhiyun 	switch (phba->link_state) {
891*4882a593Smuzhiyun 	case LPFC_LINK_UNKNOWN:
892*4882a593Smuzhiyun 	case LPFC_WARM_START:
893*4882a593Smuzhiyun 	case LPFC_INIT_START:
894*4882a593Smuzhiyun 	case LPFC_INIT_MBX_CMDS:
895*4882a593Smuzhiyun 	case LPFC_LINK_DOWN:
896*4882a593Smuzhiyun 	case LPFC_HBA_ERROR:
897*4882a593Smuzhiyun 		if (phba->hba_flag & LINK_DISABLED)
898*4882a593Smuzhiyun 			len += scnprintf(buf + len, PAGE_SIZE-len,
899*4882a593Smuzhiyun 				"Link Down - User disabled\n");
900*4882a593Smuzhiyun 		else
901*4882a593Smuzhiyun 			len += scnprintf(buf + len, PAGE_SIZE-len,
902*4882a593Smuzhiyun 				"Link Down\n");
903*4882a593Smuzhiyun 		break;
904*4882a593Smuzhiyun 	case LPFC_LINK_UP:
905*4882a593Smuzhiyun 	case LPFC_CLEAR_LA:
906*4882a593Smuzhiyun 	case LPFC_HBA_READY:
907*4882a593Smuzhiyun 		len += scnprintf(buf + len, PAGE_SIZE-len, "Link Up - ");
908*4882a593Smuzhiyun 
909*4882a593Smuzhiyun 		switch (vport->port_state) {
910*4882a593Smuzhiyun 		case LPFC_LOCAL_CFG_LINK:
911*4882a593Smuzhiyun 			len += scnprintf(buf + len, PAGE_SIZE-len,
912*4882a593Smuzhiyun 					"Configuring Link\n");
913*4882a593Smuzhiyun 			break;
914*4882a593Smuzhiyun 		case LPFC_FDISC:
915*4882a593Smuzhiyun 		case LPFC_FLOGI:
916*4882a593Smuzhiyun 		case LPFC_FABRIC_CFG_LINK:
917*4882a593Smuzhiyun 		case LPFC_NS_REG:
918*4882a593Smuzhiyun 		case LPFC_NS_QRY:
919*4882a593Smuzhiyun 		case LPFC_BUILD_DISC_LIST:
920*4882a593Smuzhiyun 		case LPFC_DISC_AUTH:
921*4882a593Smuzhiyun 			len += scnprintf(buf + len, PAGE_SIZE - len,
922*4882a593Smuzhiyun 					"Discovery\n");
923*4882a593Smuzhiyun 			break;
924*4882a593Smuzhiyun 		case LPFC_VPORT_READY:
925*4882a593Smuzhiyun 			len += scnprintf(buf + len, PAGE_SIZE - len,
926*4882a593Smuzhiyun 					"Ready\n");
927*4882a593Smuzhiyun 			break;
928*4882a593Smuzhiyun 
929*4882a593Smuzhiyun 		case LPFC_VPORT_FAILED:
930*4882a593Smuzhiyun 			len += scnprintf(buf + len, PAGE_SIZE - len,
931*4882a593Smuzhiyun 					"Failed\n");
932*4882a593Smuzhiyun 			break;
933*4882a593Smuzhiyun 
934*4882a593Smuzhiyun 		case LPFC_VPORT_UNKNOWN:
935*4882a593Smuzhiyun 			len += scnprintf(buf + len, PAGE_SIZE - len,
936*4882a593Smuzhiyun 					"Unknown\n");
937*4882a593Smuzhiyun 			break;
938*4882a593Smuzhiyun 		}
939*4882a593Smuzhiyun 		if (phba->sli.sli_flag & LPFC_MENLO_MAINT)
940*4882a593Smuzhiyun 			len += scnprintf(buf + len, PAGE_SIZE-len,
941*4882a593Smuzhiyun 					"   Menlo Maint Mode\n");
942*4882a593Smuzhiyun 		else if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
943*4882a593Smuzhiyun 			if (vport->fc_flag & FC_PUBLIC_LOOP)
944*4882a593Smuzhiyun 				len += scnprintf(buf + len, PAGE_SIZE-len,
945*4882a593Smuzhiyun 						"   Public Loop\n");
946*4882a593Smuzhiyun 			else
947*4882a593Smuzhiyun 				len += scnprintf(buf + len, PAGE_SIZE-len,
948*4882a593Smuzhiyun 						"   Private Loop\n");
949*4882a593Smuzhiyun 		} else {
950*4882a593Smuzhiyun 			if (vport->fc_flag & FC_FABRIC)
951*4882a593Smuzhiyun 				len += scnprintf(buf + len, PAGE_SIZE-len,
952*4882a593Smuzhiyun 						"   Fabric\n");
953*4882a593Smuzhiyun 			else
954*4882a593Smuzhiyun 				len += scnprintf(buf + len, PAGE_SIZE-len,
955*4882a593Smuzhiyun 						"   Point-2-Point\n");
956*4882a593Smuzhiyun 		}
957*4882a593Smuzhiyun 	}
958*4882a593Smuzhiyun 
959*4882a593Smuzhiyun 	if ((phba->sli_rev == LPFC_SLI_REV4) &&
960*4882a593Smuzhiyun 	    ((bf_get(lpfc_sli_intf_if_type,
961*4882a593Smuzhiyun 	     &phba->sli4_hba.sli_intf) ==
962*4882a593Smuzhiyun 	     LPFC_SLI_INTF_IF_TYPE_6))) {
963*4882a593Smuzhiyun 		struct lpfc_trunk_link link = phba->trunk_link;
964*4882a593Smuzhiyun 
965*4882a593Smuzhiyun 		if (bf_get(lpfc_conf_trunk_port0, &phba->sli4_hba))
966*4882a593Smuzhiyun 			len += scnprintf(buf + len, PAGE_SIZE - len,
967*4882a593Smuzhiyun 				"Trunk port 0: Link %s %s\n",
968*4882a593Smuzhiyun 				(link.link0.state == LPFC_LINK_UP) ?
969*4882a593Smuzhiyun 				 "Up" : "Down. ",
970*4882a593Smuzhiyun 				trunk_errmsg[link.link0.fault]);
971*4882a593Smuzhiyun 
972*4882a593Smuzhiyun 		if (bf_get(lpfc_conf_trunk_port1, &phba->sli4_hba))
973*4882a593Smuzhiyun 			len += scnprintf(buf + len, PAGE_SIZE - len,
974*4882a593Smuzhiyun 				"Trunk port 1: Link %s %s\n",
975*4882a593Smuzhiyun 				(link.link1.state == LPFC_LINK_UP) ?
976*4882a593Smuzhiyun 				 "Up" : "Down. ",
977*4882a593Smuzhiyun 				trunk_errmsg[link.link1.fault]);
978*4882a593Smuzhiyun 
979*4882a593Smuzhiyun 		if (bf_get(lpfc_conf_trunk_port2, &phba->sli4_hba))
980*4882a593Smuzhiyun 			len += scnprintf(buf + len, PAGE_SIZE - len,
981*4882a593Smuzhiyun 				"Trunk port 2: Link %s %s\n",
982*4882a593Smuzhiyun 				(link.link2.state == LPFC_LINK_UP) ?
983*4882a593Smuzhiyun 				 "Up" : "Down. ",
984*4882a593Smuzhiyun 				trunk_errmsg[link.link2.fault]);
985*4882a593Smuzhiyun 
986*4882a593Smuzhiyun 		if (bf_get(lpfc_conf_trunk_port3, &phba->sli4_hba))
987*4882a593Smuzhiyun 			len += scnprintf(buf + len, PAGE_SIZE - len,
988*4882a593Smuzhiyun 				"Trunk port 3: Link %s %s\n",
989*4882a593Smuzhiyun 				(link.link3.state == LPFC_LINK_UP) ?
990*4882a593Smuzhiyun 				 "Up" : "Down. ",
991*4882a593Smuzhiyun 				trunk_errmsg[link.link3.fault]);
992*4882a593Smuzhiyun 
993*4882a593Smuzhiyun 	}
994*4882a593Smuzhiyun 
995*4882a593Smuzhiyun 	return len;
996*4882a593Smuzhiyun }
997*4882a593Smuzhiyun 
998*4882a593Smuzhiyun /**
999*4882a593Smuzhiyun  * lpfc_sli4_protocol_show - Return the fip mode of the HBA
1000*4882a593Smuzhiyun  * @dev: class unused variable.
1001*4882a593Smuzhiyun  * @attr: device attribute, not used.
1002*4882a593Smuzhiyun  * @buf: on return contains the module description text.
1003*4882a593Smuzhiyun  *
1004*4882a593Smuzhiyun  * Returns: size of formatted string.
1005*4882a593Smuzhiyun  **/
1006*4882a593Smuzhiyun static ssize_t
lpfc_sli4_protocol_show(struct device * dev,struct device_attribute * attr,char * buf)1007*4882a593Smuzhiyun lpfc_sli4_protocol_show(struct device *dev, struct device_attribute *attr,
1008*4882a593Smuzhiyun 			char *buf)
1009*4882a593Smuzhiyun {
1010*4882a593Smuzhiyun 	struct Scsi_Host *shost = class_to_shost(dev);
1011*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
1012*4882a593Smuzhiyun 	struct lpfc_hba *phba = vport->phba;
1013*4882a593Smuzhiyun 
1014*4882a593Smuzhiyun 	if (phba->sli_rev < LPFC_SLI_REV4)
1015*4882a593Smuzhiyun 		return scnprintf(buf, PAGE_SIZE, "fc\n");
1016*4882a593Smuzhiyun 
1017*4882a593Smuzhiyun 	if (phba->sli4_hba.lnk_info.lnk_dv == LPFC_LNK_DAT_VAL) {
1018*4882a593Smuzhiyun 		if (phba->sli4_hba.lnk_info.lnk_tp == LPFC_LNK_TYPE_GE)
1019*4882a593Smuzhiyun 			return scnprintf(buf, PAGE_SIZE, "fcoe\n");
1020*4882a593Smuzhiyun 		if (phba->sli4_hba.lnk_info.lnk_tp == LPFC_LNK_TYPE_FC)
1021*4882a593Smuzhiyun 			return scnprintf(buf, PAGE_SIZE, "fc\n");
1022*4882a593Smuzhiyun 	}
1023*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "unknown\n");
1024*4882a593Smuzhiyun }
1025*4882a593Smuzhiyun 
1026*4882a593Smuzhiyun /**
1027*4882a593Smuzhiyun  * lpfc_oas_supported_show - Return whether or not Optimized Access Storage
1028*4882a593Smuzhiyun  *			    (OAS) is supported.
1029*4882a593Smuzhiyun  * @dev: class unused variable.
1030*4882a593Smuzhiyun  * @attr: device attribute, not used.
1031*4882a593Smuzhiyun  * @buf: on return contains the module description text.
1032*4882a593Smuzhiyun  *
1033*4882a593Smuzhiyun  * Returns: size of formatted string.
1034*4882a593Smuzhiyun  **/
1035*4882a593Smuzhiyun static ssize_t
lpfc_oas_supported_show(struct device * dev,struct device_attribute * attr,char * buf)1036*4882a593Smuzhiyun lpfc_oas_supported_show(struct device *dev, struct device_attribute *attr,
1037*4882a593Smuzhiyun 			char *buf)
1038*4882a593Smuzhiyun {
1039*4882a593Smuzhiyun 	struct Scsi_Host *shost = class_to_shost(dev);
1040*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata;
1041*4882a593Smuzhiyun 	struct lpfc_hba *phba = vport->phba;
1042*4882a593Smuzhiyun 
1043*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "%d\n",
1044*4882a593Smuzhiyun 			phba->sli4_hba.pc_sli4_params.oas_supported);
1045*4882a593Smuzhiyun }
1046*4882a593Smuzhiyun 
1047*4882a593Smuzhiyun /**
1048*4882a593Smuzhiyun  * lpfc_link_state_store - Transition the link_state on an HBA port
1049*4882a593Smuzhiyun  * @dev: class device that is converted into a Scsi_host.
1050*4882a593Smuzhiyun  * @attr: device attribute, not used.
1051*4882a593Smuzhiyun  * @buf: one or more lpfc_polling_flags values.
1052*4882a593Smuzhiyun  * @count: not used.
1053*4882a593Smuzhiyun  *
1054*4882a593Smuzhiyun  * Returns:
1055*4882a593Smuzhiyun  * -EINVAL if the buffer is not "up" or "down"
1056*4882a593Smuzhiyun  * return from link state change function if non-zero
1057*4882a593Smuzhiyun  * length of the buf on success
1058*4882a593Smuzhiyun  **/
1059*4882a593Smuzhiyun static ssize_t
lpfc_link_state_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)1060*4882a593Smuzhiyun lpfc_link_state_store(struct device *dev, struct device_attribute *attr,
1061*4882a593Smuzhiyun 		const char *buf, size_t count)
1062*4882a593Smuzhiyun {
1063*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
1064*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
1065*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
1066*4882a593Smuzhiyun 
1067*4882a593Smuzhiyun 	int status = -EINVAL;
1068*4882a593Smuzhiyun 
1069*4882a593Smuzhiyun 	if ((strncmp(buf, "up", sizeof("up") - 1) == 0) &&
1070*4882a593Smuzhiyun 			(phba->link_state == LPFC_LINK_DOWN))
1071*4882a593Smuzhiyun 		status = phba->lpfc_hba_init_link(phba, MBX_NOWAIT);
1072*4882a593Smuzhiyun 	else if ((strncmp(buf, "down", sizeof("down") - 1) == 0) &&
1073*4882a593Smuzhiyun 			(phba->link_state >= LPFC_LINK_UP))
1074*4882a593Smuzhiyun 		status = phba->lpfc_hba_down_link(phba, MBX_NOWAIT);
1075*4882a593Smuzhiyun 
1076*4882a593Smuzhiyun 	if (status == 0)
1077*4882a593Smuzhiyun 		return strlen(buf);
1078*4882a593Smuzhiyun 	else
1079*4882a593Smuzhiyun 		return status;
1080*4882a593Smuzhiyun }
1081*4882a593Smuzhiyun 
1082*4882a593Smuzhiyun /**
1083*4882a593Smuzhiyun  * lpfc_num_discovered_ports_show - Return sum of mapped and unmapped vports
1084*4882a593Smuzhiyun  * @dev: class device that is converted into a Scsi_host.
1085*4882a593Smuzhiyun  * @attr: device attribute, not used.
1086*4882a593Smuzhiyun  * @buf: on return contains the sum of fc mapped and unmapped.
1087*4882a593Smuzhiyun  *
1088*4882a593Smuzhiyun  * Description:
1089*4882a593Smuzhiyun  * Returns the ascii text number of the sum of the fc mapped and unmapped
1090*4882a593Smuzhiyun  * vport counts.
1091*4882a593Smuzhiyun  *
1092*4882a593Smuzhiyun  * Returns: size of formatted string.
1093*4882a593Smuzhiyun  **/
1094*4882a593Smuzhiyun static ssize_t
lpfc_num_discovered_ports_show(struct device * dev,struct device_attribute * attr,char * buf)1095*4882a593Smuzhiyun lpfc_num_discovered_ports_show(struct device *dev,
1096*4882a593Smuzhiyun 			       struct device_attribute *attr, char *buf)
1097*4882a593Smuzhiyun {
1098*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
1099*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
1100*4882a593Smuzhiyun 
1101*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "%d\n",
1102*4882a593Smuzhiyun 			vport->fc_map_cnt + vport->fc_unmap_cnt);
1103*4882a593Smuzhiyun }
1104*4882a593Smuzhiyun 
1105*4882a593Smuzhiyun /**
1106*4882a593Smuzhiyun  * lpfc_issue_lip - Misnomer, name carried over from long ago
1107*4882a593Smuzhiyun  * @shost: Scsi_Host pointer.
1108*4882a593Smuzhiyun  *
1109*4882a593Smuzhiyun  * Description:
1110*4882a593Smuzhiyun  * Bring the link down gracefully then re-init the link. The firmware will
1111*4882a593Smuzhiyun  * re-init the fiber channel interface as required. Does not issue a LIP.
1112*4882a593Smuzhiyun  *
1113*4882a593Smuzhiyun  * Returns:
1114*4882a593Smuzhiyun  * -EPERM port offline or management commands are being blocked
1115*4882a593Smuzhiyun  * -ENOMEM cannot allocate memory for the mailbox command
1116*4882a593Smuzhiyun  * -EIO error sending the mailbox command
1117*4882a593Smuzhiyun  * zero for success
1118*4882a593Smuzhiyun  **/
1119*4882a593Smuzhiyun static int
lpfc_issue_lip(struct Scsi_Host * shost)1120*4882a593Smuzhiyun lpfc_issue_lip(struct Scsi_Host *shost)
1121*4882a593Smuzhiyun {
1122*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
1123*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
1124*4882a593Smuzhiyun 	LPFC_MBOXQ_t *pmboxq;
1125*4882a593Smuzhiyun 	int mbxstatus = MBXERR_ERROR;
1126*4882a593Smuzhiyun 
1127*4882a593Smuzhiyun 	/*
1128*4882a593Smuzhiyun 	 * If the link is offline, disabled or BLOCK_MGMT_IO
1129*4882a593Smuzhiyun 	 * it doesn't make any sense to allow issue_lip
1130*4882a593Smuzhiyun 	 */
1131*4882a593Smuzhiyun 	if ((vport->fc_flag & FC_OFFLINE_MODE) ||
1132*4882a593Smuzhiyun 	    (phba->hba_flag & LINK_DISABLED) ||
1133*4882a593Smuzhiyun 	    (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO))
1134*4882a593Smuzhiyun 		return -EPERM;
1135*4882a593Smuzhiyun 
1136*4882a593Smuzhiyun 	pmboxq = mempool_alloc(phba->mbox_mem_pool,GFP_KERNEL);
1137*4882a593Smuzhiyun 
1138*4882a593Smuzhiyun 	if (!pmboxq)
1139*4882a593Smuzhiyun 		return -ENOMEM;
1140*4882a593Smuzhiyun 
1141*4882a593Smuzhiyun 	memset((void *)pmboxq, 0, sizeof (LPFC_MBOXQ_t));
1142*4882a593Smuzhiyun 	pmboxq->u.mb.mbxCommand = MBX_DOWN_LINK;
1143*4882a593Smuzhiyun 	pmboxq->u.mb.mbxOwner = OWN_HOST;
1144*4882a593Smuzhiyun 
1145*4882a593Smuzhiyun 	if ((vport->fc_flag & FC_PT2PT) && (vport->fc_flag & FC_PT2PT_NO_NVME))
1146*4882a593Smuzhiyun 		vport->fc_flag &= ~FC_PT2PT_NO_NVME;
1147*4882a593Smuzhiyun 
1148*4882a593Smuzhiyun 	mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq, LPFC_MBOX_TMO * 2);
1149*4882a593Smuzhiyun 
1150*4882a593Smuzhiyun 	if ((mbxstatus == MBX_SUCCESS) &&
1151*4882a593Smuzhiyun 	    (pmboxq->u.mb.mbxStatus == 0 ||
1152*4882a593Smuzhiyun 	     pmboxq->u.mb.mbxStatus == MBXERR_LINK_DOWN)) {
1153*4882a593Smuzhiyun 		memset((void *)pmboxq, 0, sizeof (LPFC_MBOXQ_t));
1154*4882a593Smuzhiyun 		lpfc_init_link(phba, pmboxq, phba->cfg_topology,
1155*4882a593Smuzhiyun 			       phba->cfg_link_speed);
1156*4882a593Smuzhiyun 		mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq,
1157*4882a593Smuzhiyun 						     phba->fc_ratov * 2);
1158*4882a593Smuzhiyun 		if ((mbxstatus == MBX_SUCCESS) &&
1159*4882a593Smuzhiyun 		    (pmboxq->u.mb.mbxStatus == MBXERR_SEC_NO_PERMISSION))
1160*4882a593Smuzhiyun 			lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
1161*4882a593Smuzhiyun 					"2859 SLI authentication is required "
1162*4882a593Smuzhiyun 					"for INIT_LINK but has not done yet\n");
1163*4882a593Smuzhiyun 	}
1164*4882a593Smuzhiyun 
1165*4882a593Smuzhiyun 	lpfc_set_loopback_flag(phba);
1166*4882a593Smuzhiyun 	if (mbxstatus != MBX_TIMEOUT)
1167*4882a593Smuzhiyun 		mempool_free(pmboxq, phba->mbox_mem_pool);
1168*4882a593Smuzhiyun 
1169*4882a593Smuzhiyun 	if (mbxstatus == MBXERR_ERROR)
1170*4882a593Smuzhiyun 		return -EIO;
1171*4882a593Smuzhiyun 
1172*4882a593Smuzhiyun 	return 0;
1173*4882a593Smuzhiyun }
1174*4882a593Smuzhiyun 
1175*4882a593Smuzhiyun int
lpfc_emptyq_wait(struct lpfc_hba * phba,struct list_head * q,spinlock_t * lock)1176*4882a593Smuzhiyun lpfc_emptyq_wait(struct lpfc_hba *phba, struct list_head *q, spinlock_t *lock)
1177*4882a593Smuzhiyun {
1178*4882a593Smuzhiyun 	int cnt = 0;
1179*4882a593Smuzhiyun 
1180*4882a593Smuzhiyun 	spin_lock_irq(lock);
1181*4882a593Smuzhiyun 	while (!list_empty(q)) {
1182*4882a593Smuzhiyun 		spin_unlock_irq(lock);
1183*4882a593Smuzhiyun 		msleep(20);
1184*4882a593Smuzhiyun 		if (cnt++ > 250) {  /* 5 secs */
1185*4882a593Smuzhiyun 			lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
1186*4882a593Smuzhiyun 					"0466 %s %s\n",
1187*4882a593Smuzhiyun 					"Outstanding IO when ",
1188*4882a593Smuzhiyun 					"bringing Adapter offline\n");
1189*4882a593Smuzhiyun 				return 0;
1190*4882a593Smuzhiyun 		}
1191*4882a593Smuzhiyun 		spin_lock_irq(lock);
1192*4882a593Smuzhiyun 	}
1193*4882a593Smuzhiyun 	spin_unlock_irq(lock);
1194*4882a593Smuzhiyun 	return 1;
1195*4882a593Smuzhiyun }
1196*4882a593Smuzhiyun 
1197*4882a593Smuzhiyun /**
1198*4882a593Smuzhiyun  * lpfc_do_offline - Issues a mailbox command to bring the link down
1199*4882a593Smuzhiyun  * @phba: lpfc_hba pointer.
1200*4882a593Smuzhiyun  * @type: LPFC_EVT_OFFLINE, LPFC_EVT_WARM_START, LPFC_EVT_KILL.
1201*4882a593Smuzhiyun  *
1202*4882a593Smuzhiyun  * Notes:
1203*4882a593Smuzhiyun  * Assumes any error from lpfc_do_offline() will be negative.
1204*4882a593Smuzhiyun  * Can wait up to 5 seconds for the port ring buffers count
1205*4882a593Smuzhiyun  * to reach zero, prints a warning if it is not zero and continues.
1206*4882a593Smuzhiyun  * lpfc_workq_post_event() returns a non-zero return code if call fails.
1207*4882a593Smuzhiyun  *
1208*4882a593Smuzhiyun  * Returns:
1209*4882a593Smuzhiyun  * -EIO error posting the event
1210*4882a593Smuzhiyun  * zero for success
1211*4882a593Smuzhiyun  **/
1212*4882a593Smuzhiyun static int
lpfc_do_offline(struct lpfc_hba * phba,uint32_t type)1213*4882a593Smuzhiyun lpfc_do_offline(struct lpfc_hba *phba, uint32_t type)
1214*4882a593Smuzhiyun {
1215*4882a593Smuzhiyun 	struct completion online_compl;
1216*4882a593Smuzhiyun 	struct lpfc_queue *qp = NULL;
1217*4882a593Smuzhiyun 	struct lpfc_sli_ring *pring;
1218*4882a593Smuzhiyun 	struct lpfc_sli *psli;
1219*4882a593Smuzhiyun 	int status = 0;
1220*4882a593Smuzhiyun 	int i;
1221*4882a593Smuzhiyun 	int rc;
1222*4882a593Smuzhiyun 
1223*4882a593Smuzhiyun 	init_completion(&online_compl);
1224*4882a593Smuzhiyun 	rc = lpfc_workq_post_event(phba, &status, &online_compl,
1225*4882a593Smuzhiyun 			      LPFC_EVT_OFFLINE_PREP);
1226*4882a593Smuzhiyun 	if (rc == 0)
1227*4882a593Smuzhiyun 		return -ENOMEM;
1228*4882a593Smuzhiyun 
1229*4882a593Smuzhiyun 	wait_for_completion(&online_compl);
1230*4882a593Smuzhiyun 
1231*4882a593Smuzhiyun 	if (status != 0)
1232*4882a593Smuzhiyun 		return -EIO;
1233*4882a593Smuzhiyun 
1234*4882a593Smuzhiyun 	psli = &phba->sli;
1235*4882a593Smuzhiyun 
1236*4882a593Smuzhiyun 	/*
1237*4882a593Smuzhiyun 	 * If freeing the queues have already started, don't access them.
1238*4882a593Smuzhiyun 	 * Otherwise set FREE_WAIT to indicate that queues are being used
1239*4882a593Smuzhiyun 	 * to hold the freeing process until we finish.
1240*4882a593Smuzhiyun 	 */
1241*4882a593Smuzhiyun 	spin_lock_irq(&phba->hbalock);
1242*4882a593Smuzhiyun 	if (!(psli->sli_flag & LPFC_QUEUE_FREE_INIT)) {
1243*4882a593Smuzhiyun 		psli->sli_flag |= LPFC_QUEUE_FREE_WAIT;
1244*4882a593Smuzhiyun 	} else {
1245*4882a593Smuzhiyun 		spin_unlock_irq(&phba->hbalock);
1246*4882a593Smuzhiyun 		goto skip_wait;
1247*4882a593Smuzhiyun 	}
1248*4882a593Smuzhiyun 	spin_unlock_irq(&phba->hbalock);
1249*4882a593Smuzhiyun 
1250*4882a593Smuzhiyun 	/* Wait a little for things to settle down, but not
1251*4882a593Smuzhiyun 	 * long enough for dev loss timeout to expire.
1252*4882a593Smuzhiyun 	 */
1253*4882a593Smuzhiyun 	if (phba->sli_rev != LPFC_SLI_REV4) {
1254*4882a593Smuzhiyun 		for (i = 0; i < psli->num_rings; i++) {
1255*4882a593Smuzhiyun 			pring = &psli->sli3_ring[i];
1256*4882a593Smuzhiyun 			if (!lpfc_emptyq_wait(phba, &pring->txcmplq,
1257*4882a593Smuzhiyun 					      &phba->hbalock))
1258*4882a593Smuzhiyun 				goto out;
1259*4882a593Smuzhiyun 		}
1260*4882a593Smuzhiyun 	} else {
1261*4882a593Smuzhiyun 		list_for_each_entry(qp, &phba->sli4_hba.lpfc_wq_list, wq_list) {
1262*4882a593Smuzhiyun 			pring = qp->pring;
1263*4882a593Smuzhiyun 			if (!pring)
1264*4882a593Smuzhiyun 				continue;
1265*4882a593Smuzhiyun 			if (!lpfc_emptyq_wait(phba, &pring->txcmplq,
1266*4882a593Smuzhiyun 					      &pring->ring_lock))
1267*4882a593Smuzhiyun 				goto out;
1268*4882a593Smuzhiyun 		}
1269*4882a593Smuzhiyun 	}
1270*4882a593Smuzhiyun out:
1271*4882a593Smuzhiyun 	spin_lock_irq(&phba->hbalock);
1272*4882a593Smuzhiyun 	psli->sli_flag &= ~LPFC_QUEUE_FREE_WAIT;
1273*4882a593Smuzhiyun 	spin_unlock_irq(&phba->hbalock);
1274*4882a593Smuzhiyun 
1275*4882a593Smuzhiyun skip_wait:
1276*4882a593Smuzhiyun 	init_completion(&online_compl);
1277*4882a593Smuzhiyun 	rc = lpfc_workq_post_event(phba, &status, &online_compl, type);
1278*4882a593Smuzhiyun 	if (rc == 0)
1279*4882a593Smuzhiyun 		return -ENOMEM;
1280*4882a593Smuzhiyun 
1281*4882a593Smuzhiyun 	wait_for_completion(&online_compl);
1282*4882a593Smuzhiyun 
1283*4882a593Smuzhiyun 	if (status != 0)
1284*4882a593Smuzhiyun 		return -EIO;
1285*4882a593Smuzhiyun 
1286*4882a593Smuzhiyun 	return 0;
1287*4882a593Smuzhiyun }
1288*4882a593Smuzhiyun 
1289*4882a593Smuzhiyun /**
1290*4882a593Smuzhiyun  * lpfc_reset_pci_bus - resets PCI bridge controller's secondary bus of an HBA
1291*4882a593Smuzhiyun  * @phba: lpfc_hba pointer.
1292*4882a593Smuzhiyun  *
1293*4882a593Smuzhiyun  * Description:
1294*4882a593Smuzhiyun  * Issues a PCI secondary bus reset for the phba->pcidev.
1295*4882a593Smuzhiyun  *
1296*4882a593Smuzhiyun  * Notes:
1297*4882a593Smuzhiyun  * First walks the bus_list to ensure only PCI devices with Emulex
1298*4882a593Smuzhiyun  * vendor id, device ids that support hot reset, only one occurrence
1299*4882a593Smuzhiyun  * of function 0, and all ports on the bus are in offline mode to ensure the
1300*4882a593Smuzhiyun  * hot reset only affects one valid HBA.
1301*4882a593Smuzhiyun  *
1302*4882a593Smuzhiyun  * Returns:
1303*4882a593Smuzhiyun  * -ENOTSUPP, cfg_enable_hba_reset must be of value 2
1304*4882a593Smuzhiyun  * -ENODEV,   NULL ptr to pcidev
1305*4882a593Smuzhiyun  * -EBADSLT,  detected invalid device
1306*4882a593Smuzhiyun  * -EBUSY,    port is not in offline state
1307*4882a593Smuzhiyun  *      0,    successful
1308*4882a593Smuzhiyun  */
1309*4882a593Smuzhiyun static int
lpfc_reset_pci_bus(struct lpfc_hba * phba)1310*4882a593Smuzhiyun lpfc_reset_pci_bus(struct lpfc_hba *phba)
1311*4882a593Smuzhiyun {
1312*4882a593Smuzhiyun 	struct pci_dev *pdev = phba->pcidev;
1313*4882a593Smuzhiyun 	struct Scsi_Host *shost = NULL;
1314*4882a593Smuzhiyun 	struct lpfc_hba *phba_other = NULL;
1315*4882a593Smuzhiyun 	struct pci_dev *ptr = NULL;
1316*4882a593Smuzhiyun 	int res;
1317*4882a593Smuzhiyun 
1318*4882a593Smuzhiyun 	if (phba->cfg_enable_hba_reset != 2)
1319*4882a593Smuzhiyun 		return -ENOTSUPP;
1320*4882a593Smuzhiyun 
1321*4882a593Smuzhiyun 	if (!pdev) {
1322*4882a593Smuzhiyun 		lpfc_printf_log(phba, KERN_INFO, LOG_INIT, "8345 pdev NULL!\n");
1323*4882a593Smuzhiyun 		return -ENODEV;
1324*4882a593Smuzhiyun 	}
1325*4882a593Smuzhiyun 
1326*4882a593Smuzhiyun 	res = lpfc_check_pci_resettable(phba);
1327*4882a593Smuzhiyun 	if (res)
1328*4882a593Smuzhiyun 		return res;
1329*4882a593Smuzhiyun 
1330*4882a593Smuzhiyun 	/* Walk the list of devices on the pci_dev's bus */
1331*4882a593Smuzhiyun 	list_for_each_entry(ptr, &pdev->bus->devices, bus_list) {
1332*4882a593Smuzhiyun 		/* Check port is offline */
1333*4882a593Smuzhiyun 		shost = pci_get_drvdata(ptr);
1334*4882a593Smuzhiyun 		if (shost) {
1335*4882a593Smuzhiyun 			phba_other =
1336*4882a593Smuzhiyun 				((struct lpfc_vport *)shost->hostdata)->phba;
1337*4882a593Smuzhiyun 			if (!(phba_other->pport->fc_flag & FC_OFFLINE_MODE)) {
1338*4882a593Smuzhiyun 				lpfc_printf_log(phba_other, KERN_INFO, LOG_INIT,
1339*4882a593Smuzhiyun 						"8349 WWPN = 0x%02x%02x%02x%02x"
1340*4882a593Smuzhiyun 						"%02x%02x%02x%02x is not "
1341*4882a593Smuzhiyun 						"offline!\n",
1342*4882a593Smuzhiyun 						phba_other->wwpn[0],
1343*4882a593Smuzhiyun 						phba_other->wwpn[1],
1344*4882a593Smuzhiyun 						phba_other->wwpn[2],
1345*4882a593Smuzhiyun 						phba_other->wwpn[3],
1346*4882a593Smuzhiyun 						phba_other->wwpn[4],
1347*4882a593Smuzhiyun 						phba_other->wwpn[5],
1348*4882a593Smuzhiyun 						phba_other->wwpn[6],
1349*4882a593Smuzhiyun 						phba_other->wwpn[7]);
1350*4882a593Smuzhiyun 				return -EBUSY;
1351*4882a593Smuzhiyun 			}
1352*4882a593Smuzhiyun 		}
1353*4882a593Smuzhiyun 	}
1354*4882a593Smuzhiyun 
1355*4882a593Smuzhiyun 	/* Issue PCI bus reset */
1356*4882a593Smuzhiyun 	res = pci_reset_bus(pdev);
1357*4882a593Smuzhiyun 	if (res) {
1358*4882a593Smuzhiyun 		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
1359*4882a593Smuzhiyun 				"8350 PCI reset bus failed: %d\n", res);
1360*4882a593Smuzhiyun 	}
1361*4882a593Smuzhiyun 
1362*4882a593Smuzhiyun 	return res;
1363*4882a593Smuzhiyun }
1364*4882a593Smuzhiyun 
1365*4882a593Smuzhiyun /**
1366*4882a593Smuzhiyun  * lpfc_selective_reset - Offline then onlines the port
1367*4882a593Smuzhiyun  * @phba: lpfc_hba pointer.
1368*4882a593Smuzhiyun  *
1369*4882a593Smuzhiyun  * Description:
1370*4882a593Smuzhiyun  * If the port is configured to allow a reset then the hba is brought
1371*4882a593Smuzhiyun  * offline then online.
1372*4882a593Smuzhiyun  *
1373*4882a593Smuzhiyun  * Notes:
1374*4882a593Smuzhiyun  * Assumes any error from lpfc_do_offline() will be negative.
1375*4882a593Smuzhiyun  * Do not make this function static.
1376*4882a593Smuzhiyun  *
1377*4882a593Smuzhiyun  * Returns:
1378*4882a593Smuzhiyun  * lpfc_do_offline() return code if not zero
1379*4882a593Smuzhiyun  * -EIO reset not configured or error posting the event
1380*4882a593Smuzhiyun  * zero for success
1381*4882a593Smuzhiyun  **/
1382*4882a593Smuzhiyun int
lpfc_selective_reset(struct lpfc_hba * phba)1383*4882a593Smuzhiyun lpfc_selective_reset(struct lpfc_hba *phba)
1384*4882a593Smuzhiyun {
1385*4882a593Smuzhiyun 	struct completion online_compl;
1386*4882a593Smuzhiyun 	int status = 0;
1387*4882a593Smuzhiyun 	int rc;
1388*4882a593Smuzhiyun 
1389*4882a593Smuzhiyun 	if (!phba->cfg_enable_hba_reset)
1390*4882a593Smuzhiyun 		return -EACCES;
1391*4882a593Smuzhiyun 
1392*4882a593Smuzhiyun 	if (!(phba->pport->fc_flag & FC_OFFLINE_MODE)) {
1393*4882a593Smuzhiyun 		status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE);
1394*4882a593Smuzhiyun 
1395*4882a593Smuzhiyun 		if (status != 0)
1396*4882a593Smuzhiyun 			return status;
1397*4882a593Smuzhiyun 	}
1398*4882a593Smuzhiyun 
1399*4882a593Smuzhiyun 	init_completion(&online_compl);
1400*4882a593Smuzhiyun 	rc = lpfc_workq_post_event(phba, &status, &online_compl,
1401*4882a593Smuzhiyun 			      LPFC_EVT_ONLINE);
1402*4882a593Smuzhiyun 	if (rc == 0)
1403*4882a593Smuzhiyun 		return -ENOMEM;
1404*4882a593Smuzhiyun 
1405*4882a593Smuzhiyun 	wait_for_completion(&online_compl);
1406*4882a593Smuzhiyun 
1407*4882a593Smuzhiyun 	if (status != 0)
1408*4882a593Smuzhiyun 		return -EIO;
1409*4882a593Smuzhiyun 
1410*4882a593Smuzhiyun 	return 0;
1411*4882a593Smuzhiyun }
1412*4882a593Smuzhiyun 
1413*4882a593Smuzhiyun /**
1414*4882a593Smuzhiyun  * lpfc_issue_reset - Selectively resets an adapter
1415*4882a593Smuzhiyun  * @dev: class device that is converted into a Scsi_host.
1416*4882a593Smuzhiyun  * @attr: device attribute, not used.
1417*4882a593Smuzhiyun  * @buf: containing the string "selective".
1418*4882a593Smuzhiyun  * @count: unused variable.
1419*4882a593Smuzhiyun  *
1420*4882a593Smuzhiyun  * Description:
1421*4882a593Smuzhiyun  * If the buf contains the string "selective" then lpfc_selective_reset()
1422*4882a593Smuzhiyun  * is called to perform the reset.
1423*4882a593Smuzhiyun  *
1424*4882a593Smuzhiyun  * Notes:
1425*4882a593Smuzhiyun  * Assumes any error from lpfc_selective_reset() will be negative.
1426*4882a593Smuzhiyun  * If lpfc_selective_reset() returns zero then the length of the buffer
1427*4882a593Smuzhiyun  * is returned which indicates success
1428*4882a593Smuzhiyun  *
1429*4882a593Smuzhiyun  * Returns:
1430*4882a593Smuzhiyun  * -EINVAL if the buffer does not contain the string "selective"
1431*4882a593Smuzhiyun  * length of buf if lpfc-selective_reset() if the call succeeds
1432*4882a593Smuzhiyun  * return value of lpfc_selective_reset() if the call fails
1433*4882a593Smuzhiyun **/
1434*4882a593Smuzhiyun static ssize_t
lpfc_issue_reset(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)1435*4882a593Smuzhiyun lpfc_issue_reset(struct device *dev, struct device_attribute *attr,
1436*4882a593Smuzhiyun 		 const char *buf, size_t count)
1437*4882a593Smuzhiyun {
1438*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
1439*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
1440*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
1441*4882a593Smuzhiyun 	int status = -EINVAL;
1442*4882a593Smuzhiyun 
1443*4882a593Smuzhiyun 	if (!phba->cfg_enable_hba_reset)
1444*4882a593Smuzhiyun 		return -EACCES;
1445*4882a593Smuzhiyun 
1446*4882a593Smuzhiyun 	if (strncmp(buf, "selective", sizeof("selective") - 1) == 0)
1447*4882a593Smuzhiyun 		status = phba->lpfc_selective_reset(phba);
1448*4882a593Smuzhiyun 
1449*4882a593Smuzhiyun 	if (status == 0)
1450*4882a593Smuzhiyun 		return strlen(buf);
1451*4882a593Smuzhiyun 	else
1452*4882a593Smuzhiyun 		return status;
1453*4882a593Smuzhiyun }
1454*4882a593Smuzhiyun 
1455*4882a593Smuzhiyun /**
1456*4882a593Smuzhiyun  * lpfc_sli4_pdev_status_reg_wait - Wait for pdev status register for readyness
1457*4882a593Smuzhiyun  * @phba: lpfc_hba pointer.
1458*4882a593Smuzhiyun  *
1459*4882a593Smuzhiyun  * Description:
1460*4882a593Smuzhiyun  * SLI4 interface type-2 device to wait on the sliport status register for
1461*4882a593Smuzhiyun  * the readyness after performing a firmware reset.
1462*4882a593Smuzhiyun  *
1463*4882a593Smuzhiyun  * Returns:
1464*4882a593Smuzhiyun  * zero for success, -EPERM when port does not have privilege to perform the
1465*4882a593Smuzhiyun  * reset, -EIO when port timeout from recovering from the reset.
1466*4882a593Smuzhiyun  *
1467*4882a593Smuzhiyun  * Note:
1468*4882a593Smuzhiyun  * As the caller will interpret the return code by value, be careful in making
1469*4882a593Smuzhiyun  * change or addition to return codes.
1470*4882a593Smuzhiyun  **/
1471*4882a593Smuzhiyun int
lpfc_sli4_pdev_status_reg_wait(struct lpfc_hba * phba)1472*4882a593Smuzhiyun lpfc_sli4_pdev_status_reg_wait(struct lpfc_hba *phba)
1473*4882a593Smuzhiyun {
1474*4882a593Smuzhiyun 	struct lpfc_register portstat_reg = {0};
1475*4882a593Smuzhiyun 	int i;
1476*4882a593Smuzhiyun 
1477*4882a593Smuzhiyun 	msleep(100);
1478*4882a593Smuzhiyun 	if (lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr,
1479*4882a593Smuzhiyun 		       &portstat_reg.word0))
1480*4882a593Smuzhiyun 		return -EIO;
1481*4882a593Smuzhiyun 
1482*4882a593Smuzhiyun 	/* verify if privileged for the request operation */
1483*4882a593Smuzhiyun 	if (!bf_get(lpfc_sliport_status_rn, &portstat_reg) &&
1484*4882a593Smuzhiyun 	    !bf_get(lpfc_sliport_status_err, &portstat_reg))
1485*4882a593Smuzhiyun 		return -EPERM;
1486*4882a593Smuzhiyun 
1487*4882a593Smuzhiyun 	/* wait for the SLI port firmware ready after firmware reset */
1488*4882a593Smuzhiyun 	for (i = 0; i < LPFC_FW_RESET_MAXIMUM_WAIT_10MS_CNT; i++) {
1489*4882a593Smuzhiyun 		msleep(10);
1490*4882a593Smuzhiyun 		if (lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr,
1491*4882a593Smuzhiyun 			       &portstat_reg.word0))
1492*4882a593Smuzhiyun 			continue;
1493*4882a593Smuzhiyun 		if (!bf_get(lpfc_sliport_status_err, &portstat_reg))
1494*4882a593Smuzhiyun 			continue;
1495*4882a593Smuzhiyun 		if (!bf_get(lpfc_sliport_status_rn, &portstat_reg))
1496*4882a593Smuzhiyun 			continue;
1497*4882a593Smuzhiyun 		if (!bf_get(lpfc_sliport_status_rdy, &portstat_reg))
1498*4882a593Smuzhiyun 			continue;
1499*4882a593Smuzhiyun 		break;
1500*4882a593Smuzhiyun 	}
1501*4882a593Smuzhiyun 
1502*4882a593Smuzhiyun 	if (i < LPFC_FW_RESET_MAXIMUM_WAIT_10MS_CNT)
1503*4882a593Smuzhiyun 		return 0;
1504*4882a593Smuzhiyun 	else
1505*4882a593Smuzhiyun 		return -EIO;
1506*4882a593Smuzhiyun }
1507*4882a593Smuzhiyun 
1508*4882a593Smuzhiyun /**
1509*4882a593Smuzhiyun  * lpfc_sli4_pdev_reg_request - Request physical dev to perform a register acc
1510*4882a593Smuzhiyun  * @phba: lpfc_hba pointer.
1511*4882a593Smuzhiyun  *
1512*4882a593Smuzhiyun  * Description:
1513*4882a593Smuzhiyun  * Request SLI4 interface type-2 device to perform a physical register set
1514*4882a593Smuzhiyun  * access.
1515*4882a593Smuzhiyun  *
1516*4882a593Smuzhiyun  * Returns:
1517*4882a593Smuzhiyun  * zero for success
1518*4882a593Smuzhiyun  **/
1519*4882a593Smuzhiyun static ssize_t
lpfc_sli4_pdev_reg_request(struct lpfc_hba * phba,uint32_t opcode)1520*4882a593Smuzhiyun lpfc_sli4_pdev_reg_request(struct lpfc_hba *phba, uint32_t opcode)
1521*4882a593Smuzhiyun {
1522*4882a593Smuzhiyun 	struct completion online_compl;
1523*4882a593Smuzhiyun 	struct pci_dev *pdev = phba->pcidev;
1524*4882a593Smuzhiyun 	uint32_t before_fc_flag;
1525*4882a593Smuzhiyun 	uint32_t sriov_nr_virtfn;
1526*4882a593Smuzhiyun 	uint32_t reg_val;
1527*4882a593Smuzhiyun 	int status = 0, rc = 0;
1528*4882a593Smuzhiyun 	int job_posted = 1, sriov_err;
1529*4882a593Smuzhiyun 
1530*4882a593Smuzhiyun 	if (!phba->cfg_enable_hba_reset)
1531*4882a593Smuzhiyun 		return -EACCES;
1532*4882a593Smuzhiyun 
1533*4882a593Smuzhiyun 	if ((phba->sli_rev < LPFC_SLI_REV4) ||
1534*4882a593Smuzhiyun 	    (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) <
1535*4882a593Smuzhiyun 	     LPFC_SLI_INTF_IF_TYPE_2))
1536*4882a593Smuzhiyun 		return -EPERM;
1537*4882a593Smuzhiyun 
1538*4882a593Smuzhiyun 	/* Keep state if we need to restore back */
1539*4882a593Smuzhiyun 	before_fc_flag = phba->pport->fc_flag;
1540*4882a593Smuzhiyun 	sriov_nr_virtfn = phba->cfg_sriov_nr_virtfn;
1541*4882a593Smuzhiyun 
1542*4882a593Smuzhiyun 	if (opcode == LPFC_FW_DUMP) {
1543*4882a593Smuzhiyun 		init_completion(&online_compl);
1544*4882a593Smuzhiyun 		phba->fw_dump_cmpl = &online_compl;
1545*4882a593Smuzhiyun 	} else {
1546*4882a593Smuzhiyun 		/* Disable SR-IOV virtual functions if enabled */
1547*4882a593Smuzhiyun 		if (phba->cfg_sriov_nr_virtfn) {
1548*4882a593Smuzhiyun 			pci_disable_sriov(pdev);
1549*4882a593Smuzhiyun 			phba->cfg_sriov_nr_virtfn = 0;
1550*4882a593Smuzhiyun 		}
1551*4882a593Smuzhiyun 
1552*4882a593Smuzhiyun 		status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE);
1553*4882a593Smuzhiyun 
1554*4882a593Smuzhiyun 		if (status != 0)
1555*4882a593Smuzhiyun 			return status;
1556*4882a593Smuzhiyun 
1557*4882a593Smuzhiyun 		/* wait for the device to be quiesced before firmware reset */
1558*4882a593Smuzhiyun 		msleep(100);
1559*4882a593Smuzhiyun 	}
1560*4882a593Smuzhiyun 
1561*4882a593Smuzhiyun 	reg_val = readl(phba->sli4_hba.conf_regs_memmap_p +
1562*4882a593Smuzhiyun 			LPFC_CTL_PDEV_CTL_OFFSET);
1563*4882a593Smuzhiyun 
1564*4882a593Smuzhiyun 	if (opcode == LPFC_FW_DUMP)
1565*4882a593Smuzhiyun 		reg_val |= LPFC_FW_DUMP_REQUEST;
1566*4882a593Smuzhiyun 	else if (opcode == LPFC_FW_RESET)
1567*4882a593Smuzhiyun 		reg_val |= LPFC_CTL_PDEV_CTL_FRST;
1568*4882a593Smuzhiyun 	else if (opcode == LPFC_DV_RESET)
1569*4882a593Smuzhiyun 		reg_val |= LPFC_CTL_PDEV_CTL_DRST;
1570*4882a593Smuzhiyun 
1571*4882a593Smuzhiyun 	writel(reg_val, phba->sli4_hba.conf_regs_memmap_p +
1572*4882a593Smuzhiyun 	       LPFC_CTL_PDEV_CTL_OFFSET);
1573*4882a593Smuzhiyun 	/* flush */
1574*4882a593Smuzhiyun 	readl(phba->sli4_hba.conf_regs_memmap_p + LPFC_CTL_PDEV_CTL_OFFSET);
1575*4882a593Smuzhiyun 
1576*4882a593Smuzhiyun 	/* delay driver action following IF_TYPE_2 reset */
1577*4882a593Smuzhiyun 	rc = lpfc_sli4_pdev_status_reg_wait(phba);
1578*4882a593Smuzhiyun 
1579*4882a593Smuzhiyun 	if (rc == -EPERM) {
1580*4882a593Smuzhiyun 		/* no privilege for reset */
1581*4882a593Smuzhiyun 		lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
1582*4882a593Smuzhiyun 				"3150 No privilege to perform the requested "
1583*4882a593Smuzhiyun 				"access: x%x\n", reg_val);
1584*4882a593Smuzhiyun 	} else if (rc == -EIO) {
1585*4882a593Smuzhiyun 		/* reset failed, there is nothing more we can do */
1586*4882a593Smuzhiyun 		lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
1587*4882a593Smuzhiyun 				"3153 Fail to perform the requested "
1588*4882a593Smuzhiyun 				"access: x%x\n", reg_val);
1589*4882a593Smuzhiyun 		if (phba->fw_dump_cmpl)
1590*4882a593Smuzhiyun 			phba->fw_dump_cmpl = NULL;
1591*4882a593Smuzhiyun 		return rc;
1592*4882a593Smuzhiyun 	}
1593*4882a593Smuzhiyun 
1594*4882a593Smuzhiyun 	/* keep the original port state */
1595*4882a593Smuzhiyun 	if (before_fc_flag & FC_OFFLINE_MODE) {
1596*4882a593Smuzhiyun 		if (phba->fw_dump_cmpl)
1597*4882a593Smuzhiyun 			phba->fw_dump_cmpl = NULL;
1598*4882a593Smuzhiyun 		goto out;
1599*4882a593Smuzhiyun 	}
1600*4882a593Smuzhiyun 
1601*4882a593Smuzhiyun 	/* Firmware dump will trigger an HA_ERATT event, and
1602*4882a593Smuzhiyun 	 * lpfc_handle_eratt_s4 routine already handles bringing the port back
1603*4882a593Smuzhiyun 	 * online.
1604*4882a593Smuzhiyun 	 */
1605*4882a593Smuzhiyun 	if (opcode == LPFC_FW_DUMP) {
1606*4882a593Smuzhiyun 		wait_for_completion(phba->fw_dump_cmpl);
1607*4882a593Smuzhiyun 	} else  {
1608*4882a593Smuzhiyun 		init_completion(&online_compl);
1609*4882a593Smuzhiyun 		job_posted = lpfc_workq_post_event(phba, &status, &online_compl,
1610*4882a593Smuzhiyun 						   LPFC_EVT_ONLINE);
1611*4882a593Smuzhiyun 		if (!job_posted)
1612*4882a593Smuzhiyun 			goto out;
1613*4882a593Smuzhiyun 
1614*4882a593Smuzhiyun 		wait_for_completion(&online_compl);
1615*4882a593Smuzhiyun 	}
1616*4882a593Smuzhiyun out:
1617*4882a593Smuzhiyun 	/* in any case, restore the virtual functions enabled as before */
1618*4882a593Smuzhiyun 	if (sriov_nr_virtfn) {
1619*4882a593Smuzhiyun 		/* If fw_dump was performed, first disable to clean up */
1620*4882a593Smuzhiyun 		if (opcode == LPFC_FW_DUMP) {
1621*4882a593Smuzhiyun 			pci_disable_sriov(pdev);
1622*4882a593Smuzhiyun 			phba->cfg_sriov_nr_virtfn = 0;
1623*4882a593Smuzhiyun 		}
1624*4882a593Smuzhiyun 
1625*4882a593Smuzhiyun 		sriov_err =
1626*4882a593Smuzhiyun 			lpfc_sli_probe_sriov_nr_virtfn(phba, sriov_nr_virtfn);
1627*4882a593Smuzhiyun 		if (!sriov_err)
1628*4882a593Smuzhiyun 			phba->cfg_sriov_nr_virtfn = sriov_nr_virtfn;
1629*4882a593Smuzhiyun 	}
1630*4882a593Smuzhiyun 
1631*4882a593Smuzhiyun 	/* return proper error code */
1632*4882a593Smuzhiyun 	if (!rc) {
1633*4882a593Smuzhiyun 		if (!job_posted)
1634*4882a593Smuzhiyun 			rc = -ENOMEM;
1635*4882a593Smuzhiyun 		else if (status)
1636*4882a593Smuzhiyun 			rc = -EIO;
1637*4882a593Smuzhiyun 	}
1638*4882a593Smuzhiyun 	return rc;
1639*4882a593Smuzhiyun }
1640*4882a593Smuzhiyun 
1641*4882a593Smuzhiyun /**
1642*4882a593Smuzhiyun  * lpfc_nport_evt_cnt_show - Return the number of nport events
1643*4882a593Smuzhiyun  * @dev: class device that is converted into a Scsi_host.
1644*4882a593Smuzhiyun  * @attr: device attribute, not used.
1645*4882a593Smuzhiyun  * @buf: on return contains the ascii number of nport events.
1646*4882a593Smuzhiyun  *
1647*4882a593Smuzhiyun  * Returns: size of formatted string.
1648*4882a593Smuzhiyun  **/
1649*4882a593Smuzhiyun static ssize_t
lpfc_nport_evt_cnt_show(struct device * dev,struct device_attribute * attr,char * buf)1650*4882a593Smuzhiyun lpfc_nport_evt_cnt_show(struct device *dev, struct device_attribute *attr,
1651*4882a593Smuzhiyun 			char *buf)
1652*4882a593Smuzhiyun {
1653*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
1654*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
1655*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
1656*4882a593Smuzhiyun 
1657*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "%d\n", phba->nport_event_cnt);
1658*4882a593Smuzhiyun }
1659*4882a593Smuzhiyun 
1660*4882a593Smuzhiyun static int
lpfc_set_trunking(struct lpfc_hba * phba,char * buff_out)1661*4882a593Smuzhiyun lpfc_set_trunking(struct lpfc_hba *phba, char *buff_out)
1662*4882a593Smuzhiyun {
1663*4882a593Smuzhiyun 	LPFC_MBOXQ_t *mbox = NULL;
1664*4882a593Smuzhiyun 	unsigned long val = 0;
1665*4882a593Smuzhiyun 	char *pval = NULL;
1666*4882a593Smuzhiyun 	int rc = 0;
1667*4882a593Smuzhiyun 
1668*4882a593Smuzhiyun 	if (!strncmp("enable", buff_out,
1669*4882a593Smuzhiyun 				 strlen("enable"))) {
1670*4882a593Smuzhiyun 		pval = buff_out + strlen("enable") + 1;
1671*4882a593Smuzhiyun 		rc = kstrtoul(pval, 0, &val);
1672*4882a593Smuzhiyun 		if (rc)
1673*4882a593Smuzhiyun 			return rc; /* Invalid  number */
1674*4882a593Smuzhiyun 	} else if (!strncmp("disable", buff_out,
1675*4882a593Smuzhiyun 				 strlen("disable"))) {
1676*4882a593Smuzhiyun 		val = 0;
1677*4882a593Smuzhiyun 	} else {
1678*4882a593Smuzhiyun 		return -EINVAL;  /* Invalid command */
1679*4882a593Smuzhiyun 	}
1680*4882a593Smuzhiyun 
1681*4882a593Smuzhiyun 	switch (val) {
1682*4882a593Smuzhiyun 	case 0:
1683*4882a593Smuzhiyun 		val = 0x0; /* Disable */
1684*4882a593Smuzhiyun 		break;
1685*4882a593Smuzhiyun 	case 2:
1686*4882a593Smuzhiyun 		val = 0x1; /* Enable two port trunk */
1687*4882a593Smuzhiyun 		break;
1688*4882a593Smuzhiyun 	case 4:
1689*4882a593Smuzhiyun 		val = 0x2; /* Enable four port trunk */
1690*4882a593Smuzhiyun 		break;
1691*4882a593Smuzhiyun 	default:
1692*4882a593Smuzhiyun 		return -EINVAL;
1693*4882a593Smuzhiyun 	}
1694*4882a593Smuzhiyun 
1695*4882a593Smuzhiyun 	lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
1696*4882a593Smuzhiyun 			"0070 Set trunk mode with val %ld ", val);
1697*4882a593Smuzhiyun 
1698*4882a593Smuzhiyun 	mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
1699*4882a593Smuzhiyun 	if (!mbox)
1700*4882a593Smuzhiyun 		return -ENOMEM;
1701*4882a593Smuzhiyun 
1702*4882a593Smuzhiyun 	lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_FCOE,
1703*4882a593Smuzhiyun 			 LPFC_MBOX_OPCODE_FCOE_FC_SET_TRUNK_MODE,
1704*4882a593Smuzhiyun 			 12, LPFC_SLI4_MBX_EMBED);
1705*4882a593Smuzhiyun 
1706*4882a593Smuzhiyun 	bf_set(lpfc_mbx_set_trunk_mode,
1707*4882a593Smuzhiyun 	       &mbox->u.mqe.un.set_trunk_mode,
1708*4882a593Smuzhiyun 	       val);
1709*4882a593Smuzhiyun 	rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
1710*4882a593Smuzhiyun 	if (rc)
1711*4882a593Smuzhiyun 		lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
1712*4882a593Smuzhiyun 				"0071 Set trunk mode failed with status: %d",
1713*4882a593Smuzhiyun 				rc);
1714*4882a593Smuzhiyun 	mempool_free(mbox, phba->mbox_mem_pool);
1715*4882a593Smuzhiyun 
1716*4882a593Smuzhiyun 	return 0;
1717*4882a593Smuzhiyun }
1718*4882a593Smuzhiyun 
1719*4882a593Smuzhiyun /**
1720*4882a593Smuzhiyun  * lpfc_board_mode_show - Return the state of the board
1721*4882a593Smuzhiyun  * @dev: class device that is converted into a Scsi_host.
1722*4882a593Smuzhiyun  * @attr: device attribute, not used.
1723*4882a593Smuzhiyun  * @buf: on return contains the state of the adapter.
1724*4882a593Smuzhiyun  *
1725*4882a593Smuzhiyun  * Returns: size of formatted string.
1726*4882a593Smuzhiyun  **/
1727*4882a593Smuzhiyun static ssize_t
lpfc_board_mode_show(struct device * dev,struct device_attribute * attr,char * buf)1728*4882a593Smuzhiyun lpfc_board_mode_show(struct device *dev, struct device_attribute *attr,
1729*4882a593Smuzhiyun 		     char *buf)
1730*4882a593Smuzhiyun {
1731*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
1732*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
1733*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
1734*4882a593Smuzhiyun 	char  * state;
1735*4882a593Smuzhiyun 
1736*4882a593Smuzhiyun 	if (phba->link_state == LPFC_HBA_ERROR)
1737*4882a593Smuzhiyun 		state = "error";
1738*4882a593Smuzhiyun 	else if (phba->link_state == LPFC_WARM_START)
1739*4882a593Smuzhiyun 		state = "warm start";
1740*4882a593Smuzhiyun 	else if (phba->link_state == LPFC_INIT_START)
1741*4882a593Smuzhiyun 		state = "offline";
1742*4882a593Smuzhiyun 	else
1743*4882a593Smuzhiyun 		state = "online";
1744*4882a593Smuzhiyun 
1745*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "%s\n", state);
1746*4882a593Smuzhiyun }
1747*4882a593Smuzhiyun 
1748*4882a593Smuzhiyun /**
1749*4882a593Smuzhiyun  * lpfc_board_mode_store - Puts the hba in online, offline, warm or error state
1750*4882a593Smuzhiyun  * @dev: class device that is converted into a Scsi_host.
1751*4882a593Smuzhiyun  * @attr: device attribute, not used.
1752*4882a593Smuzhiyun  * @buf: containing one of the strings "online", "offline", "warm" or "error".
1753*4882a593Smuzhiyun  * @count: unused variable.
1754*4882a593Smuzhiyun  *
1755*4882a593Smuzhiyun  * Returns:
1756*4882a593Smuzhiyun  * -EACCES if enable hba reset not enabled
1757*4882a593Smuzhiyun  * -EINVAL if the buffer does not contain a valid string (see above)
1758*4882a593Smuzhiyun  * -EIO if lpfc_workq_post_event() or lpfc_do_offline() fails
1759*4882a593Smuzhiyun  * buf length greater than zero indicates success
1760*4882a593Smuzhiyun  **/
1761*4882a593Smuzhiyun static ssize_t
lpfc_board_mode_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)1762*4882a593Smuzhiyun lpfc_board_mode_store(struct device *dev, struct device_attribute *attr,
1763*4882a593Smuzhiyun 		      const char *buf, size_t count)
1764*4882a593Smuzhiyun {
1765*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
1766*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
1767*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
1768*4882a593Smuzhiyun 	struct completion online_compl;
1769*4882a593Smuzhiyun 	char *board_mode_str = NULL;
1770*4882a593Smuzhiyun 	int status = 0;
1771*4882a593Smuzhiyun 	int rc;
1772*4882a593Smuzhiyun 
1773*4882a593Smuzhiyun 	if (!phba->cfg_enable_hba_reset) {
1774*4882a593Smuzhiyun 		status = -EACCES;
1775*4882a593Smuzhiyun 		goto board_mode_out;
1776*4882a593Smuzhiyun 	}
1777*4882a593Smuzhiyun 
1778*4882a593Smuzhiyun 	lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
1779*4882a593Smuzhiyun 			 "3050 lpfc_board_mode set to %s\n", buf);
1780*4882a593Smuzhiyun 
1781*4882a593Smuzhiyun 	init_completion(&online_compl);
1782*4882a593Smuzhiyun 
1783*4882a593Smuzhiyun 	if(strncmp(buf, "online", sizeof("online") - 1) == 0) {
1784*4882a593Smuzhiyun 		rc = lpfc_workq_post_event(phba, &status, &online_compl,
1785*4882a593Smuzhiyun 				      LPFC_EVT_ONLINE);
1786*4882a593Smuzhiyun 		if (rc == 0) {
1787*4882a593Smuzhiyun 			status = -ENOMEM;
1788*4882a593Smuzhiyun 			goto board_mode_out;
1789*4882a593Smuzhiyun 		}
1790*4882a593Smuzhiyun 		wait_for_completion(&online_compl);
1791*4882a593Smuzhiyun 		if (status)
1792*4882a593Smuzhiyun 			status = -EIO;
1793*4882a593Smuzhiyun 	} else if (strncmp(buf, "offline", sizeof("offline") - 1) == 0)
1794*4882a593Smuzhiyun 		status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE);
1795*4882a593Smuzhiyun 	else if (strncmp(buf, "warm", sizeof("warm") - 1) == 0)
1796*4882a593Smuzhiyun 		if (phba->sli_rev == LPFC_SLI_REV4)
1797*4882a593Smuzhiyun 			status = -EINVAL;
1798*4882a593Smuzhiyun 		else
1799*4882a593Smuzhiyun 			status = lpfc_do_offline(phba, LPFC_EVT_WARM_START);
1800*4882a593Smuzhiyun 	else if (strncmp(buf, "error", sizeof("error") - 1) == 0)
1801*4882a593Smuzhiyun 		if (phba->sli_rev == LPFC_SLI_REV4)
1802*4882a593Smuzhiyun 			status = -EINVAL;
1803*4882a593Smuzhiyun 		else
1804*4882a593Smuzhiyun 			status = lpfc_do_offline(phba, LPFC_EVT_KILL);
1805*4882a593Smuzhiyun 	else if (strncmp(buf, "dump", sizeof("dump") - 1) == 0)
1806*4882a593Smuzhiyun 		status = lpfc_sli4_pdev_reg_request(phba, LPFC_FW_DUMP);
1807*4882a593Smuzhiyun 	else if (strncmp(buf, "fw_reset", sizeof("fw_reset") - 1) == 0)
1808*4882a593Smuzhiyun 		status = lpfc_sli4_pdev_reg_request(phba, LPFC_FW_RESET);
1809*4882a593Smuzhiyun 	else if (strncmp(buf, "dv_reset", sizeof("dv_reset") - 1) == 0)
1810*4882a593Smuzhiyun 		status = lpfc_sli4_pdev_reg_request(phba, LPFC_DV_RESET);
1811*4882a593Smuzhiyun 	else if (strncmp(buf, "pci_bus_reset", sizeof("pci_bus_reset") - 1)
1812*4882a593Smuzhiyun 		 == 0)
1813*4882a593Smuzhiyun 		status = lpfc_reset_pci_bus(phba);
1814*4882a593Smuzhiyun 	else if (strncmp(buf, "trunk", sizeof("trunk") - 1) == 0)
1815*4882a593Smuzhiyun 		status = lpfc_set_trunking(phba, (char *)buf + sizeof("trunk"));
1816*4882a593Smuzhiyun 	else
1817*4882a593Smuzhiyun 		status = -EINVAL;
1818*4882a593Smuzhiyun 
1819*4882a593Smuzhiyun board_mode_out:
1820*4882a593Smuzhiyun 	if (!status)
1821*4882a593Smuzhiyun 		return strlen(buf);
1822*4882a593Smuzhiyun 	else {
1823*4882a593Smuzhiyun 		board_mode_str = strchr(buf, '\n');
1824*4882a593Smuzhiyun 		if (board_mode_str)
1825*4882a593Smuzhiyun 			*board_mode_str = '\0';
1826*4882a593Smuzhiyun 		lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
1827*4882a593Smuzhiyun 				 "3097 Failed \"%s\", status(%d), "
1828*4882a593Smuzhiyun 				 "fc_flag(x%x)\n",
1829*4882a593Smuzhiyun 				 buf, status, phba->pport->fc_flag);
1830*4882a593Smuzhiyun 		return status;
1831*4882a593Smuzhiyun 	}
1832*4882a593Smuzhiyun }
1833*4882a593Smuzhiyun 
1834*4882a593Smuzhiyun /**
1835*4882a593Smuzhiyun  * lpfc_get_hba_info - Return various bits of informaton about the adapter
1836*4882a593Smuzhiyun  * @phba: pointer to the adapter structure.
1837*4882a593Smuzhiyun  * @mxri: max xri count.
1838*4882a593Smuzhiyun  * @axri: available xri count.
1839*4882a593Smuzhiyun  * @mrpi: max rpi count.
1840*4882a593Smuzhiyun  * @arpi: available rpi count.
1841*4882a593Smuzhiyun  * @mvpi: max vpi count.
1842*4882a593Smuzhiyun  * @avpi: available vpi count.
1843*4882a593Smuzhiyun  *
1844*4882a593Smuzhiyun  * Description:
1845*4882a593Smuzhiyun  * If an integer pointer for an count is not null then the value for the
1846*4882a593Smuzhiyun  * count is returned.
1847*4882a593Smuzhiyun  *
1848*4882a593Smuzhiyun  * Returns:
1849*4882a593Smuzhiyun  * zero on error
1850*4882a593Smuzhiyun  * one for success
1851*4882a593Smuzhiyun  **/
1852*4882a593Smuzhiyun static int
lpfc_get_hba_info(struct lpfc_hba * phba,uint32_t * mxri,uint32_t * axri,uint32_t * mrpi,uint32_t * arpi,uint32_t * mvpi,uint32_t * avpi)1853*4882a593Smuzhiyun lpfc_get_hba_info(struct lpfc_hba *phba,
1854*4882a593Smuzhiyun 		  uint32_t *mxri, uint32_t *axri,
1855*4882a593Smuzhiyun 		  uint32_t *mrpi, uint32_t *arpi,
1856*4882a593Smuzhiyun 		  uint32_t *mvpi, uint32_t *avpi)
1857*4882a593Smuzhiyun {
1858*4882a593Smuzhiyun 	struct lpfc_mbx_read_config *rd_config;
1859*4882a593Smuzhiyun 	LPFC_MBOXQ_t *pmboxq;
1860*4882a593Smuzhiyun 	MAILBOX_t *pmb;
1861*4882a593Smuzhiyun 	int rc = 0;
1862*4882a593Smuzhiyun 	uint32_t max_vpi;
1863*4882a593Smuzhiyun 
1864*4882a593Smuzhiyun 	/*
1865*4882a593Smuzhiyun 	 * prevent udev from issuing mailbox commands until the port is
1866*4882a593Smuzhiyun 	 * configured.
1867*4882a593Smuzhiyun 	 */
1868*4882a593Smuzhiyun 	if (phba->link_state < LPFC_LINK_DOWN ||
1869*4882a593Smuzhiyun 	    !phba->mbox_mem_pool ||
1870*4882a593Smuzhiyun 	    (phba->sli.sli_flag & LPFC_SLI_ACTIVE) == 0)
1871*4882a593Smuzhiyun 		return 0;
1872*4882a593Smuzhiyun 
1873*4882a593Smuzhiyun 	if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO)
1874*4882a593Smuzhiyun 		return 0;
1875*4882a593Smuzhiyun 
1876*4882a593Smuzhiyun 	pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
1877*4882a593Smuzhiyun 	if (!pmboxq)
1878*4882a593Smuzhiyun 		return 0;
1879*4882a593Smuzhiyun 	memset(pmboxq, 0, sizeof (LPFC_MBOXQ_t));
1880*4882a593Smuzhiyun 
1881*4882a593Smuzhiyun 	pmb = &pmboxq->u.mb;
1882*4882a593Smuzhiyun 	pmb->mbxCommand = MBX_READ_CONFIG;
1883*4882a593Smuzhiyun 	pmb->mbxOwner = OWN_HOST;
1884*4882a593Smuzhiyun 	pmboxq->ctx_buf = NULL;
1885*4882a593Smuzhiyun 
1886*4882a593Smuzhiyun 	if (phba->pport->fc_flag & FC_OFFLINE_MODE)
1887*4882a593Smuzhiyun 		rc = MBX_NOT_FINISHED;
1888*4882a593Smuzhiyun 	else
1889*4882a593Smuzhiyun 		rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
1890*4882a593Smuzhiyun 
1891*4882a593Smuzhiyun 	if (rc != MBX_SUCCESS) {
1892*4882a593Smuzhiyun 		if (rc != MBX_TIMEOUT)
1893*4882a593Smuzhiyun 			mempool_free(pmboxq, phba->mbox_mem_pool);
1894*4882a593Smuzhiyun 		return 0;
1895*4882a593Smuzhiyun 	}
1896*4882a593Smuzhiyun 
1897*4882a593Smuzhiyun 	if (phba->sli_rev == LPFC_SLI_REV4) {
1898*4882a593Smuzhiyun 		rd_config = &pmboxq->u.mqe.un.rd_config;
1899*4882a593Smuzhiyun 		if (mrpi)
1900*4882a593Smuzhiyun 			*mrpi = bf_get(lpfc_mbx_rd_conf_rpi_count, rd_config);
1901*4882a593Smuzhiyun 		if (arpi)
1902*4882a593Smuzhiyun 			*arpi = bf_get(lpfc_mbx_rd_conf_rpi_count, rd_config) -
1903*4882a593Smuzhiyun 					phba->sli4_hba.max_cfg_param.rpi_used;
1904*4882a593Smuzhiyun 		if (mxri)
1905*4882a593Smuzhiyun 			*mxri = bf_get(lpfc_mbx_rd_conf_xri_count, rd_config);
1906*4882a593Smuzhiyun 		if (axri)
1907*4882a593Smuzhiyun 			*axri = bf_get(lpfc_mbx_rd_conf_xri_count, rd_config) -
1908*4882a593Smuzhiyun 					phba->sli4_hba.max_cfg_param.xri_used;
1909*4882a593Smuzhiyun 
1910*4882a593Smuzhiyun 		/* Account for differences with SLI-3.  Get vpi count from
1911*4882a593Smuzhiyun 		 * mailbox data and subtract one for max vpi value.
1912*4882a593Smuzhiyun 		 */
1913*4882a593Smuzhiyun 		max_vpi = (bf_get(lpfc_mbx_rd_conf_vpi_count, rd_config) > 0) ?
1914*4882a593Smuzhiyun 			(bf_get(lpfc_mbx_rd_conf_vpi_count, rd_config) - 1) : 0;
1915*4882a593Smuzhiyun 
1916*4882a593Smuzhiyun 		/* Limit the max we support */
1917*4882a593Smuzhiyun 		if (max_vpi > LPFC_MAX_VPI)
1918*4882a593Smuzhiyun 			max_vpi = LPFC_MAX_VPI;
1919*4882a593Smuzhiyun 		if (mvpi)
1920*4882a593Smuzhiyun 			*mvpi = max_vpi;
1921*4882a593Smuzhiyun 		if (avpi)
1922*4882a593Smuzhiyun 			*avpi = max_vpi - phba->sli4_hba.max_cfg_param.vpi_used;
1923*4882a593Smuzhiyun 	} else {
1924*4882a593Smuzhiyun 		if (mrpi)
1925*4882a593Smuzhiyun 			*mrpi = pmb->un.varRdConfig.max_rpi;
1926*4882a593Smuzhiyun 		if (arpi)
1927*4882a593Smuzhiyun 			*arpi = pmb->un.varRdConfig.avail_rpi;
1928*4882a593Smuzhiyun 		if (mxri)
1929*4882a593Smuzhiyun 			*mxri = pmb->un.varRdConfig.max_xri;
1930*4882a593Smuzhiyun 		if (axri)
1931*4882a593Smuzhiyun 			*axri = pmb->un.varRdConfig.avail_xri;
1932*4882a593Smuzhiyun 		if (mvpi)
1933*4882a593Smuzhiyun 			*mvpi = pmb->un.varRdConfig.max_vpi;
1934*4882a593Smuzhiyun 		if (avpi) {
1935*4882a593Smuzhiyun 			/* avail_vpi is only valid if link is up and ready */
1936*4882a593Smuzhiyun 			if (phba->link_state == LPFC_HBA_READY)
1937*4882a593Smuzhiyun 				*avpi = pmb->un.varRdConfig.avail_vpi;
1938*4882a593Smuzhiyun 			else
1939*4882a593Smuzhiyun 				*avpi = pmb->un.varRdConfig.max_vpi;
1940*4882a593Smuzhiyun 		}
1941*4882a593Smuzhiyun 	}
1942*4882a593Smuzhiyun 
1943*4882a593Smuzhiyun 	mempool_free(pmboxq, phba->mbox_mem_pool);
1944*4882a593Smuzhiyun 	return 1;
1945*4882a593Smuzhiyun }
1946*4882a593Smuzhiyun 
1947*4882a593Smuzhiyun /**
1948*4882a593Smuzhiyun  * lpfc_max_rpi_show - Return maximum rpi
1949*4882a593Smuzhiyun  * @dev: class device that is converted into a Scsi_host.
1950*4882a593Smuzhiyun  * @attr: device attribute, not used.
1951*4882a593Smuzhiyun  * @buf: on return contains the maximum rpi count in decimal or "Unknown".
1952*4882a593Smuzhiyun  *
1953*4882a593Smuzhiyun  * Description:
1954*4882a593Smuzhiyun  * Calls lpfc_get_hba_info() asking for just the mrpi count.
1955*4882a593Smuzhiyun  * If lpfc_get_hba_info() returns zero (failure) the buffer text is set
1956*4882a593Smuzhiyun  * to "Unknown" and the buffer length is returned, therefore the caller
1957*4882a593Smuzhiyun  * must check for "Unknown" in the buffer to detect a failure.
1958*4882a593Smuzhiyun  *
1959*4882a593Smuzhiyun  * Returns: size of formatted string.
1960*4882a593Smuzhiyun  **/
1961*4882a593Smuzhiyun static ssize_t
lpfc_max_rpi_show(struct device * dev,struct device_attribute * attr,char * buf)1962*4882a593Smuzhiyun lpfc_max_rpi_show(struct device *dev, struct device_attribute *attr,
1963*4882a593Smuzhiyun 		  char *buf)
1964*4882a593Smuzhiyun {
1965*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
1966*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
1967*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
1968*4882a593Smuzhiyun 	uint32_t cnt;
1969*4882a593Smuzhiyun 
1970*4882a593Smuzhiyun 	if (lpfc_get_hba_info(phba, NULL, NULL, &cnt, NULL, NULL, NULL))
1971*4882a593Smuzhiyun 		return scnprintf(buf, PAGE_SIZE, "%d\n", cnt);
1972*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "Unknown\n");
1973*4882a593Smuzhiyun }
1974*4882a593Smuzhiyun 
1975*4882a593Smuzhiyun /**
1976*4882a593Smuzhiyun  * lpfc_used_rpi_show - Return maximum rpi minus available rpi
1977*4882a593Smuzhiyun  * @dev: class device that is converted into a Scsi_host.
1978*4882a593Smuzhiyun  * @attr: device attribute, not used.
1979*4882a593Smuzhiyun  * @buf: containing the used rpi count in decimal or "Unknown".
1980*4882a593Smuzhiyun  *
1981*4882a593Smuzhiyun  * Description:
1982*4882a593Smuzhiyun  * Calls lpfc_get_hba_info() asking for just the mrpi and arpi counts.
1983*4882a593Smuzhiyun  * If lpfc_get_hba_info() returns zero (failure) the buffer text is set
1984*4882a593Smuzhiyun  * to "Unknown" and the buffer length is returned, therefore the caller
1985*4882a593Smuzhiyun  * must check for "Unknown" in the buffer to detect a failure.
1986*4882a593Smuzhiyun  *
1987*4882a593Smuzhiyun  * Returns: size of formatted string.
1988*4882a593Smuzhiyun  **/
1989*4882a593Smuzhiyun static ssize_t
lpfc_used_rpi_show(struct device * dev,struct device_attribute * attr,char * buf)1990*4882a593Smuzhiyun lpfc_used_rpi_show(struct device *dev, struct device_attribute *attr,
1991*4882a593Smuzhiyun 		   char *buf)
1992*4882a593Smuzhiyun {
1993*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
1994*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
1995*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
1996*4882a593Smuzhiyun 	uint32_t cnt, acnt;
1997*4882a593Smuzhiyun 
1998*4882a593Smuzhiyun 	if (lpfc_get_hba_info(phba, NULL, NULL, &cnt, &acnt, NULL, NULL))
1999*4882a593Smuzhiyun 		return scnprintf(buf, PAGE_SIZE, "%d\n", (cnt - acnt));
2000*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "Unknown\n");
2001*4882a593Smuzhiyun }
2002*4882a593Smuzhiyun 
2003*4882a593Smuzhiyun /**
2004*4882a593Smuzhiyun  * lpfc_max_xri_show - Return maximum xri
2005*4882a593Smuzhiyun  * @dev: class device that is converted into a Scsi_host.
2006*4882a593Smuzhiyun  * @attr: device attribute, not used.
2007*4882a593Smuzhiyun  * @buf: on return contains the maximum xri count in decimal or "Unknown".
2008*4882a593Smuzhiyun  *
2009*4882a593Smuzhiyun  * Description:
2010*4882a593Smuzhiyun  * Calls lpfc_get_hba_info() asking for just the mrpi count.
2011*4882a593Smuzhiyun  * If lpfc_get_hba_info() returns zero (failure) the buffer text is set
2012*4882a593Smuzhiyun  * to "Unknown" and the buffer length is returned, therefore the caller
2013*4882a593Smuzhiyun  * must check for "Unknown" in the buffer to detect a failure.
2014*4882a593Smuzhiyun  *
2015*4882a593Smuzhiyun  * Returns: size of formatted string.
2016*4882a593Smuzhiyun  **/
2017*4882a593Smuzhiyun static ssize_t
lpfc_max_xri_show(struct device * dev,struct device_attribute * attr,char * buf)2018*4882a593Smuzhiyun lpfc_max_xri_show(struct device *dev, struct device_attribute *attr,
2019*4882a593Smuzhiyun 		  char *buf)
2020*4882a593Smuzhiyun {
2021*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
2022*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
2023*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
2024*4882a593Smuzhiyun 	uint32_t cnt;
2025*4882a593Smuzhiyun 
2026*4882a593Smuzhiyun 	if (lpfc_get_hba_info(phba, &cnt, NULL, NULL, NULL, NULL, NULL))
2027*4882a593Smuzhiyun 		return scnprintf(buf, PAGE_SIZE, "%d\n", cnt);
2028*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "Unknown\n");
2029*4882a593Smuzhiyun }
2030*4882a593Smuzhiyun 
2031*4882a593Smuzhiyun /**
2032*4882a593Smuzhiyun  * lpfc_used_xri_show - Return maximum xpi minus the available xpi
2033*4882a593Smuzhiyun  * @dev: class device that is converted into a Scsi_host.
2034*4882a593Smuzhiyun  * @attr: device attribute, not used.
2035*4882a593Smuzhiyun  * @buf: on return contains the used xri count in decimal or "Unknown".
2036*4882a593Smuzhiyun  *
2037*4882a593Smuzhiyun  * Description:
2038*4882a593Smuzhiyun  * Calls lpfc_get_hba_info() asking for just the mxri and axri counts.
2039*4882a593Smuzhiyun  * If lpfc_get_hba_info() returns zero (failure) the buffer text is set
2040*4882a593Smuzhiyun  * to "Unknown" and the buffer length is returned, therefore the caller
2041*4882a593Smuzhiyun  * must check for "Unknown" in the buffer to detect a failure.
2042*4882a593Smuzhiyun  *
2043*4882a593Smuzhiyun  * Returns: size of formatted string.
2044*4882a593Smuzhiyun  **/
2045*4882a593Smuzhiyun static ssize_t
lpfc_used_xri_show(struct device * dev,struct device_attribute * attr,char * buf)2046*4882a593Smuzhiyun lpfc_used_xri_show(struct device *dev, struct device_attribute *attr,
2047*4882a593Smuzhiyun 		   char *buf)
2048*4882a593Smuzhiyun {
2049*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
2050*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
2051*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
2052*4882a593Smuzhiyun 	uint32_t cnt, acnt;
2053*4882a593Smuzhiyun 
2054*4882a593Smuzhiyun 	if (lpfc_get_hba_info(phba, &cnt, &acnt, NULL, NULL, NULL, NULL))
2055*4882a593Smuzhiyun 		return scnprintf(buf, PAGE_SIZE, "%d\n", (cnt - acnt));
2056*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "Unknown\n");
2057*4882a593Smuzhiyun }
2058*4882a593Smuzhiyun 
2059*4882a593Smuzhiyun /**
2060*4882a593Smuzhiyun  * lpfc_max_vpi_show - Return maximum vpi
2061*4882a593Smuzhiyun  * @dev: class device that is converted into a Scsi_host.
2062*4882a593Smuzhiyun  * @attr: device attribute, not used.
2063*4882a593Smuzhiyun  * @buf: on return contains the maximum vpi count in decimal or "Unknown".
2064*4882a593Smuzhiyun  *
2065*4882a593Smuzhiyun  * Description:
2066*4882a593Smuzhiyun  * Calls lpfc_get_hba_info() asking for just the mvpi count.
2067*4882a593Smuzhiyun  * If lpfc_get_hba_info() returns zero (failure) the buffer text is set
2068*4882a593Smuzhiyun  * to "Unknown" and the buffer length is returned, therefore the caller
2069*4882a593Smuzhiyun  * must check for "Unknown" in the buffer to detect a failure.
2070*4882a593Smuzhiyun  *
2071*4882a593Smuzhiyun  * Returns: size of formatted string.
2072*4882a593Smuzhiyun  **/
2073*4882a593Smuzhiyun static ssize_t
lpfc_max_vpi_show(struct device * dev,struct device_attribute * attr,char * buf)2074*4882a593Smuzhiyun lpfc_max_vpi_show(struct device *dev, struct device_attribute *attr,
2075*4882a593Smuzhiyun 		  char *buf)
2076*4882a593Smuzhiyun {
2077*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
2078*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
2079*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
2080*4882a593Smuzhiyun 	uint32_t cnt;
2081*4882a593Smuzhiyun 
2082*4882a593Smuzhiyun 	if (lpfc_get_hba_info(phba, NULL, NULL, NULL, NULL, &cnt, NULL))
2083*4882a593Smuzhiyun 		return scnprintf(buf, PAGE_SIZE, "%d\n", cnt);
2084*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "Unknown\n");
2085*4882a593Smuzhiyun }
2086*4882a593Smuzhiyun 
2087*4882a593Smuzhiyun /**
2088*4882a593Smuzhiyun  * lpfc_used_vpi_show - Return maximum vpi minus the available vpi
2089*4882a593Smuzhiyun  * @dev: class device that is converted into a Scsi_host.
2090*4882a593Smuzhiyun  * @attr: device attribute, not used.
2091*4882a593Smuzhiyun  * @buf: on return contains the used vpi count in decimal or "Unknown".
2092*4882a593Smuzhiyun  *
2093*4882a593Smuzhiyun  * Description:
2094*4882a593Smuzhiyun  * Calls lpfc_get_hba_info() asking for just the mvpi and avpi counts.
2095*4882a593Smuzhiyun  * If lpfc_get_hba_info() returns zero (failure) the buffer text is set
2096*4882a593Smuzhiyun  * to "Unknown" and the buffer length is returned, therefore the caller
2097*4882a593Smuzhiyun  * must check for "Unknown" in the buffer to detect a failure.
2098*4882a593Smuzhiyun  *
2099*4882a593Smuzhiyun  * Returns: size of formatted string.
2100*4882a593Smuzhiyun  **/
2101*4882a593Smuzhiyun static ssize_t
lpfc_used_vpi_show(struct device * dev,struct device_attribute * attr,char * buf)2102*4882a593Smuzhiyun lpfc_used_vpi_show(struct device *dev, struct device_attribute *attr,
2103*4882a593Smuzhiyun 		   char *buf)
2104*4882a593Smuzhiyun {
2105*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
2106*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
2107*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
2108*4882a593Smuzhiyun 	uint32_t cnt, acnt;
2109*4882a593Smuzhiyun 
2110*4882a593Smuzhiyun 	if (lpfc_get_hba_info(phba, NULL, NULL, NULL, NULL, &cnt, &acnt))
2111*4882a593Smuzhiyun 		return scnprintf(buf, PAGE_SIZE, "%d\n", (cnt - acnt));
2112*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "Unknown\n");
2113*4882a593Smuzhiyun }
2114*4882a593Smuzhiyun 
2115*4882a593Smuzhiyun /**
2116*4882a593Smuzhiyun  * lpfc_npiv_info_show - Return text about NPIV support for the adapter
2117*4882a593Smuzhiyun  * @dev: class device that is converted into a Scsi_host.
2118*4882a593Smuzhiyun  * @attr: device attribute, not used.
2119*4882a593Smuzhiyun  * @buf: text that must be interpreted to determine if npiv is supported.
2120*4882a593Smuzhiyun  *
2121*4882a593Smuzhiyun  * Description:
2122*4882a593Smuzhiyun  * Buffer will contain text indicating npiv is not suppoerted on the port,
2123*4882a593Smuzhiyun  * the port is an NPIV physical port, or it is an npiv virtual port with
2124*4882a593Smuzhiyun  * the id of the vport.
2125*4882a593Smuzhiyun  *
2126*4882a593Smuzhiyun  * Returns: size of formatted string.
2127*4882a593Smuzhiyun  **/
2128*4882a593Smuzhiyun static ssize_t
lpfc_npiv_info_show(struct device * dev,struct device_attribute * attr,char * buf)2129*4882a593Smuzhiyun lpfc_npiv_info_show(struct device *dev, struct device_attribute *attr,
2130*4882a593Smuzhiyun 		    char *buf)
2131*4882a593Smuzhiyun {
2132*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
2133*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
2134*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
2135*4882a593Smuzhiyun 
2136*4882a593Smuzhiyun 	if (!(phba->max_vpi))
2137*4882a593Smuzhiyun 		return scnprintf(buf, PAGE_SIZE, "NPIV Not Supported\n");
2138*4882a593Smuzhiyun 	if (vport->port_type == LPFC_PHYSICAL_PORT)
2139*4882a593Smuzhiyun 		return scnprintf(buf, PAGE_SIZE, "NPIV Physical\n");
2140*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "NPIV Virtual (VPI %d)\n", vport->vpi);
2141*4882a593Smuzhiyun }
2142*4882a593Smuzhiyun 
2143*4882a593Smuzhiyun /**
2144*4882a593Smuzhiyun  * lpfc_poll_show - Return text about poll support for the adapter
2145*4882a593Smuzhiyun  * @dev: class device that is converted into a Scsi_host.
2146*4882a593Smuzhiyun  * @attr: device attribute, not used.
2147*4882a593Smuzhiyun  * @buf: on return contains the cfg_poll in hex.
2148*4882a593Smuzhiyun  *
2149*4882a593Smuzhiyun  * Notes:
2150*4882a593Smuzhiyun  * cfg_poll should be a lpfc_polling_flags type.
2151*4882a593Smuzhiyun  *
2152*4882a593Smuzhiyun  * Returns: size of formatted string.
2153*4882a593Smuzhiyun  **/
2154*4882a593Smuzhiyun static ssize_t
lpfc_poll_show(struct device * dev,struct device_attribute * attr,char * buf)2155*4882a593Smuzhiyun lpfc_poll_show(struct device *dev, struct device_attribute *attr,
2156*4882a593Smuzhiyun 	       char *buf)
2157*4882a593Smuzhiyun {
2158*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
2159*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
2160*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
2161*4882a593Smuzhiyun 
2162*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "%#x\n", phba->cfg_poll);
2163*4882a593Smuzhiyun }
2164*4882a593Smuzhiyun 
2165*4882a593Smuzhiyun /**
2166*4882a593Smuzhiyun  * lpfc_poll_store - Set the value of cfg_poll for the adapter
2167*4882a593Smuzhiyun  * @dev: class device that is converted into a Scsi_host.
2168*4882a593Smuzhiyun  * @attr: device attribute, not used.
2169*4882a593Smuzhiyun  * @buf: one or more lpfc_polling_flags values.
2170*4882a593Smuzhiyun  * @count: not used.
2171*4882a593Smuzhiyun  *
2172*4882a593Smuzhiyun  * Notes:
2173*4882a593Smuzhiyun  * buf contents converted to integer and checked for a valid value.
2174*4882a593Smuzhiyun  *
2175*4882a593Smuzhiyun  * Returns:
2176*4882a593Smuzhiyun  * -EINVAL if the buffer connot be converted or is out of range
2177*4882a593Smuzhiyun  * length of the buf on success
2178*4882a593Smuzhiyun  **/
2179*4882a593Smuzhiyun static ssize_t
lpfc_poll_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)2180*4882a593Smuzhiyun lpfc_poll_store(struct device *dev, struct device_attribute *attr,
2181*4882a593Smuzhiyun 		const char *buf, size_t count)
2182*4882a593Smuzhiyun {
2183*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
2184*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
2185*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
2186*4882a593Smuzhiyun 	uint32_t creg_val;
2187*4882a593Smuzhiyun 	uint32_t old_val;
2188*4882a593Smuzhiyun 	int val=0;
2189*4882a593Smuzhiyun 
2190*4882a593Smuzhiyun 	if (!isdigit(buf[0]))
2191*4882a593Smuzhiyun 		return -EINVAL;
2192*4882a593Smuzhiyun 
2193*4882a593Smuzhiyun 	if (sscanf(buf, "%i", &val) != 1)
2194*4882a593Smuzhiyun 		return -EINVAL;
2195*4882a593Smuzhiyun 
2196*4882a593Smuzhiyun 	if ((val & 0x3) != val)
2197*4882a593Smuzhiyun 		return -EINVAL;
2198*4882a593Smuzhiyun 
2199*4882a593Smuzhiyun 	if (phba->sli_rev == LPFC_SLI_REV4)
2200*4882a593Smuzhiyun 		val = 0;
2201*4882a593Smuzhiyun 
2202*4882a593Smuzhiyun 	lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
2203*4882a593Smuzhiyun 		"3051 lpfc_poll changed from %d to %d\n",
2204*4882a593Smuzhiyun 		phba->cfg_poll, val);
2205*4882a593Smuzhiyun 
2206*4882a593Smuzhiyun 	spin_lock_irq(&phba->hbalock);
2207*4882a593Smuzhiyun 
2208*4882a593Smuzhiyun 	old_val = phba->cfg_poll;
2209*4882a593Smuzhiyun 
2210*4882a593Smuzhiyun 	if (val & ENABLE_FCP_RING_POLLING) {
2211*4882a593Smuzhiyun 		if ((val & DISABLE_FCP_RING_INT) &&
2212*4882a593Smuzhiyun 		    !(old_val & DISABLE_FCP_RING_INT)) {
2213*4882a593Smuzhiyun 			if (lpfc_readl(phba->HCregaddr, &creg_val)) {
2214*4882a593Smuzhiyun 				spin_unlock_irq(&phba->hbalock);
2215*4882a593Smuzhiyun 				return -EINVAL;
2216*4882a593Smuzhiyun 			}
2217*4882a593Smuzhiyun 			creg_val &= ~(HC_R0INT_ENA << LPFC_FCP_RING);
2218*4882a593Smuzhiyun 			writel(creg_val, phba->HCregaddr);
2219*4882a593Smuzhiyun 			readl(phba->HCregaddr); /* flush */
2220*4882a593Smuzhiyun 
2221*4882a593Smuzhiyun 			lpfc_poll_start_timer(phba);
2222*4882a593Smuzhiyun 		}
2223*4882a593Smuzhiyun 	} else if (val != 0x0) {
2224*4882a593Smuzhiyun 		spin_unlock_irq(&phba->hbalock);
2225*4882a593Smuzhiyun 		return -EINVAL;
2226*4882a593Smuzhiyun 	}
2227*4882a593Smuzhiyun 
2228*4882a593Smuzhiyun 	if (!(val & DISABLE_FCP_RING_INT) &&
2229*4882a593Smuzhiyun 	    (old_val & DISABLE_FCP_RING_INT))
2230*4882a593Smuzhiyun 	{
2231*4882a593Smuzhiyun 		spin_unlock_irq(&phba->hbalock);
2232*4882a593Smuzhiyun 		del_timer(&phba->fcp_poll_timer);
2233*4882a593Smuzhiyun 		spin_lock_irq(&phba->hbalock);
2234*4882a593Smuzhiyun 		if (lpfc_readl(phba->HCregaddr, &creg_val)) {
2235*4882a593Smuzhiyun 			spin_unlock_irq(&phba->hbalock);
2236*4882a593Smuzhiyun 			return -EINVAL;
2237*4882a593Smuzhiyun 		}
2238*4882a593Smuzhiyun 		creg_val |= (HC_R0INT_ENA << LPFC_FCP_RING);
2239*4882a593Smuzhiyun 		writel(creg_val, phba->HCregaddr);
2240*4882a593Smuzhiyun 		readl(phba->HCregaddr); /* flush */
2241*4882a593Smuzhiyun 	}
2242*4882a593Smuzhiyun 
2243*4882a593Smuzhiyun 	phba->cfg_poll = val;
2244*4882a593Smuzhiyun 
2245*4882a593Smuzhiyun 	spin_unlock_irq(&phba->hbalock);
2246*4882a593Smuzhiyun 
2247*4882a593Smuzhiyun 	return strlen(buf);
2248*4882a593Smuzhiyun }
2249*4882a593Smuzhiyun 
2250*4882a593Smuzhiyun /**
2251*4882a593Smuzhiyun  * lpfc_sriov_hw_max_virtfn_show - Return maximum number of virtual functions
2252*4882a593Smuzhiyun  * @dev: class converted to a Scsi_host structure.
2253*4882a593Smuzhiyun  * @attr: device attribute, not used.
2254*4882a593Smuzhiyun  * @buf: on return contains the formatted support level.
2255*4882a593Smuzhiyun  *
2256*4882a593Smuzhiyun  * Description:
2257*4882a593Smuzhiyun  * Returns the maximum number of virtual functions a physical function can
2258*4882a593Smuzhiyun  * support, 0 will be returned if called on virtual function.
2259*4882a593Smuzhiyun  *
2260*4882a593Smuzhiyun  * Returns: size of formatted string.
2261*4882a593Smuzhiyun  **/
2262*4882a593Smuzhiyun static ssize_t
lpfc_sriov_hw_max_virtfn_show(struct device * dev,struct device_attribute * attr,char * buf)2263*4882a593Smuzhiyun lpfc_sriov_hw_max_virtfn_show(struct device *dev,
2264*4882a593Smuzhiyun 			      struct device_attribute *attr,
2265*4882a593Smuzhiyun 			      char *buf)
2266*4882a593Smuzhiyun {
2267*4882a593Smuzhiyun 	struct Scsi_Host *shost = class_to_shost(dev);
2268*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
2269*4882a593Smuzhiyun 	struct lpfc_hba *phba = vport->phba;
2270*4882a593Smuzhiyun 	uint16_t max_nr_virtfn;
2271*4882a593Smuzhiyun 
2272*4882a593Smuzhiyun 	max_nr_virtfn = lpfc_sli_sriov_nr_virtfn_get(phba);
2273*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "%d\n", max_nr_virtfn);
2274*4882a593Smuzhiyun }
2275*4882a593Smuzhiyun 
lpfc_rangecheck(uint val,uint min,uint max)2276*4882a593Smuzhiyun static inline bool lpfc_rangecheck(uint val, uint min, uint max)
2277*4882a593Smuzhiyun {
2278*4882a593Smuzhiyun 	return val >= min && val <= max;
2279*4882a593Smuzhiyun }
2280*4882a593Smuzhiyun 
2281*4882a593Smuzhiyun /**
2282*4882a593Smuzhiyun  * lpfc_enable_bbcr_set: Sets an attribute value.
2283*4882a593Smuzhiyun  * @phba: pointer the the adapter structure.
2284*4882a593Smuzhiyun  * @val: integer attribute value.
2285*4882a593Smuzhiyun  *
2286*4882a593Smuzhiyun  * Description:
2287*4882a593Smuzhiyun  * Validates the min and max values then sets the
2288*4882a593Smuzhiyun  * adapter config field if in the valid range. prints error message
2289*4882a593Smuzhiyun  * and does not set the parameter if invalid.
2290*4882a593Smuzhiyun  *
2291*4882a593Smuzhiyun  * Returns:
2292*4882a593Smuzhiyun  * zero on success
2293*4882a593Smuzhiyun  * -EINVAL if val is invalid
2294*4882a593Smuzhiyun  */
2295*4882a593Smuzhiyun static ssize_t
lpfc_enable_bbcr_set(struct lpfc_hba * phba,uint val)2296*4882a593Smuzhiyun lpfc_enable_bbcr_set(struct lpfc_hba *phba, uint val)
2297*4882a593Smuzhiyun {
2298*4882a593Smuzhiyun 	if (lpfc_rangecheck(val, 0, 1) && phba->sli_rev == LPFC_SLI_REV4) {
2299*4882a593Smuzhiyun 		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
2300*4882a593Smuzhiyun 				"3068 %s_enable_bbcr changed from %d to %d\n",
2301*4882a593Smuzhiyun 				LPFC_DRIVER_NAME, phba->cfg_enable_bbcr, val);
2302*4882a593Smuzhiyun 		phba->cfg_enable_bbcr = val;
2303*4882a593Smuzhiyun 		return 0;
2304*4882a593Smuzhiyun 	}
2305*4882a593Smuzhiyun 	lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
2306*4882a593Smuzhiyun 			"0451 %s_enable_bbcr cannot set to %d, range is 0, 1\n",
2307*4882a593Smuzhiyun 			LPFC_DRIVER_NAME, val);
2308*4882a593Smuzhiyun 	return -EINVAL;
2309*4882a593Smuzhiyun }
2310*4882a593Smuzhiyun 
2311*4882a593Smuzhiyun /**
2312*4882a593Smuzhiyun  * lpfc_param_show - Return a cfg attribute value in decimal
2313*4882a593Smuzhiyun  *
2314*4882a593Smuzhiyun  * Description:
2315*4882a593Smuzhiyun  * Macro that given an attr e.g. hba_queue_depth expands
2316*4882a593Smuzhiyun  * into a function with the name lpfc_hba_queue_depth_show.
2317*4882a593Smuzhiyun  *
2318*4882a593Smuzhiyun  * lpfc_##attr##_show: Return the decimal value of an adapters cfg_xxx field.
2319*4882a593Smuzhiyun  * @dev: class device that is converted into a Scsi_host.
2320*4882a593Smuzhiyun  * @attr: device attribute, not used.
2321*4882a593Smuzhiyun  * @buf: on return contains the attribute value in decimal.
2322*4882a593Smuzhiyun  *
2323*4882a593Smuzhiyun  * Returns: size of formatted string.
2324*4882a593Smuzhiyun  **/
2325*4882a593Smuzhiyun #define lpfc_param_show(attr)	\
2326*4882a593Smuzhiyun static ssize_t \
2327*4882a593Smuzhiyun lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
2328*4882a593Smuzhiyun 		   char *buf) \
2329*4882a593Smuzhiyun { \
2330*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);\
2331*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\
2332*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;\
2333*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "%d\n",\
2334*4882a593Smuzhiyun 			phba->cfg_##attr);\
2335*4882a593Smuzhiyun }
2336*4882a593Smuzhiyun 
2337*4882a593Smuzhiyun /**
2338*4882a593Smuzhiyun  * lpfc_param_hex_show - Return a cfg attribute value in hex
2339*4882a593Smuzhiyun  *
2340*4882a593Smuzhiyun  * Description:
2341*4882a593Smuzhiyun  * Macro that given an attr e.g. hba_queue_depth expands
2342*4882a593Smuzhiyun  * into a function with the name lpfc_hba_queue_depth_show
2343*4882a593Smuzhiyun  *
2344*4882a593Smuzhiyun  * lpfc_##attr##_show: Return the hex value of an adapters cfg_xxx field.
2345*4882a593Smuzhiyun  * @dev: class device that is converted into a Scsi_host.
2346*4882a593Smuzhiyun  * @attr: device attribute, not used.
2347*4882a593Smuzhiyun  * @buf: on return contains the attribute value in hexadecimal.
2348*4882a593Smuzhiyun  *
2349*4882a593Smuzhiyun  * Returns: size of formatted string.
2350*4882a593Smuzhiyun  **/
2351*4882a593Smuzhiyun #define lpfc_param_hex_show(attr)	\
2352*4882a593Smuzhiyun static ssize_t \
2353*4882a593Smuzhiyun lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
2354*4882a593Smuzhiyun 		   char *buf) \
2355*4882a593Smuzhiyun { \
2356*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);\
2357*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\
2358*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;\
2359*4882a593Smuzhiyun 	uint val = 0;\
2360*4882a593Smuzhiyun 	val = phba->cfg_##attr;\
2361*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "%#x\n",\
2362*4882a593Smuzhiyun 			phba->cfg_##attr);\
2363*4882a593Smuzhiyun }
2364*4882a593Smuzhiyun 
2365*4882a593Smuzhiyun /**
2366*4882a593Smuzhiyun  * lpfc_param_init - Initializes a cfg attribute
2367*4882a593Smuzhiyun  *
2368*4882a593Smuzhiyun  * Description:
2369*4882a593Smuzhiyun  * Macro that given an attr e.g. hba_queue_depth expands
2370*4882a593Smuzhiyun  * into a function with the name lpfc_hba_queue_depth_init. The macro also
2371*4882a593Smuzhiyun  * takes a default argument, a minimum and maximum argument.
2372*4882a593Smuzhiyun  *
2373*4882a593Smuzhiyun  * lpfc_##attr##_init: Initializes an attribute.
2374*4882a593Smuzhiyun  * @phba: pointer the the adapter structure.
2375*4882a593Smuzhiyun  * @val: integer attribute value.
2376*4882a593Smuzhiyun  *
2377*4882a593Smuzhiyun  * Validates the min and max values then sets the adapter config field
2378*4882a593Smuzhiyun  * accordingly, or uses the default if out of range and prints an error message.
2379*4882a593Smuzhiyun  *
2380*4882a593Smuzhiyun  * Returns:
2381*4882a593Smuzhiyun  * zero on success
2382*4882a593Smuzhiyun  * -EINVAL if default used
2383*4882a593Smuzhiyun  **/
2384*4882a593Smuzhiyun #define lpfc_param_init(attr, default, minval, maxval)	\
2385*4882a593Smuzhiyun static int \
2386*4882a593Smuzhiyun lpfc_##attr##_init(struct lpfc_hba *phba, uint val) \
2387*4882a593Smuzhiyun { \
2388*4882a593Smuzhiyun 	if (lpfc_rangecheck(val, minval, maxval)) {\
2389*4882a593Smuzhiyun 		phba->cfg_##attr = val;\
2390*4882a593Smuzhiyun 		return 0;\
2391*4882a593Smuzhiyun 	}\
2392*4882a593Smuzhiyun 	lpfc_printf_log(phba, KERN_ERR, LOG_INIT, \
2393*4882a593Smuzhiyun 			"0449 lpfc_"#attr" attribute cannot be set to %d, "\
2394*4882a593Smuzhiyun 			"allowed range is ["#minval", "#maxval"]\n", val); \
2395*4882a593Smuzhiyun 	phba->cfg_##attr = default;\
2396*4882a593Smuzhiyun 	return -EINVAL;\
2397*4882a593Smuzhiyun }
2398*4882a593Smuzhiyun 
2399*4882a593Smuzhiyun /**
2400*4882a593Smuzhiyun  * lpfc_param_set - Set a cfg attribute value
2401*4882a593Smuzhiyun  *
2402*4882a593Smuzhiyun  * Description:
2403*4882a593Smuzhiyun  * Macro that given an attr e.g. hba_queue_depth expands
2404*4882a593Smuzhiyun  * into a function with the name lpfc_hba_queue_depth_set
2405*4882a593Smuzhiyun  *
2406*4882a593Smuzhiyun  * lpfc_##attr##_set: Sets an attribute value.
2407*4882a593Smuzhiyun  * @phba: pointer the the adapter structure.
2408*4882a593Smuzhiyun  * @val: integer attribute value.
2409*4882a593Smuzhiyun  *
2410*4882a593Smuzhiyun  * Description:
2411*4882a593Smuzhiyun  * Validates the min and max values then sets the
2412*4882a593Smuzhiyun  * adapter config field if in the valid range. prints error message
2413*4882a593Smuzhiyun  * and does not set the parameter if invalid.
2414*4882a593Smuzhiyun  *
2415*4882a593Smuzhiyun  * Returns:
2416*4882a593Smuzhiyun  * zero on success
2417*4882a593Smuzhiyun  * -EINVAL if val is invalid
2418*4882a593Smuzhiyun  **/
2419*4882a593Smuzhiyun #define lpfc_param_set(attr, default, minval, maxval)	\
2420*4882a593Smuzhiyun static int \
2421*4882a593Smuzhiyun lpfc_##attr##_set(struct lpfc_hba *phba, uint val) \
2422*4882a593Smuzhiyun { \
2423*4882a593Smuzhiyun 	if (lpfc_rangecheck(val, minval, maxval)) {\
2424*4882a593Smuzhiyun 		lpfc_printf_log(phba, KERN_ERR, LOG_INIT, \
2425*4882a593Smuzhiyun 			"3052 lpfc_" #attr " changed from %d to %d\n", \
2426*4882a593Smuzhiyun 			phba->cfg_##attr, val); \
2427*4882a593Smuzhiyun 		phba->cfg_##attr = val;\
2428*4882a593Smuzhiyun 		return 0;\
2429*4882a593Smuzhiyun 	}\
2430*4882a593Smuzhiyun 	lpfc_printf_log(phba, KERN_ERR, LOG_INIT, \
2431*4882a593Smuzhiyun 			"0450 lpfc_"#attr" attribute cannot be set to %d, "\
2432*4882a593Smuzhiyun 			"allowed range is ["#minval", "#maxval"]\n", val); \
2433*4882a593Smuzhiyun 	return -EINVAL;\
2434*4882a593Smuzhiyun }
2435*4882a593Smuzhiyun 
2436*4882a593Smuzhiyun /**
2437*4882a593Smuzhiyun  * lpfc_param_store - Set a vport attribute value
2438*4882a593Smuzhiyun  *
2439*4882a593Smuzhiyun  * Description:
2440*4882a593Smuzhiyun  * Macro that given an attr e.g. hba_queue_depth expands
2441*4882a593Smuzhiyun  * into a function with the name lpfc_hba_queue_depth_store.
2442*4882a593Smuzhiyun  *
2443*4882a593Smuzhiyun  * lpfc_##attr##_store: Set an sttribute value.
2444*4882a593Smuzhiyun  * @dev: class device that is converted into a Scsi_host.
2445*4882a593Smuzhiyun  * @attr: device attribute, not used.
2446*4882a593Smuzhiyun  * @buf: contains the attribute value in ascii.
2447*4882a593Smuzhiyun  * @count: not used.
2448*4882a593Smuzhiyun  *
2449*4882a593Smuzhiyun  * Description:
2450*4882a593Smuzhiyun  * Convert the ascii text number to an integer, then
2451*4882a593Smuzhiyun  * use the lpfc_##attr##_set function to set the value.
2452*4882a593Smuzhiyun  *
2453*4882a593Smuzhiyun  * Returns:
2454*4882a593Smuzhiyun  * -EINVAL if val is invalid or lpfc_##attr##_set() fails
2455*4882a593Smuzhiyun  * length of buffer upon success.
2456*4882a593Smuzhiyun  **/
2457*4882a593Smuzhiyun #define lpfc_param_store(attr)	\
2458*4882a593Smuzhiyun static ssize_t \
2459*4882a593Smuzhiyun lpfc_##attr##_store(struct device *dev, struct device_attribute *attr, \
2460*4882a593Smuzhiyun 		    const char *buf, size_t count) \
2461*4882a593Smuzhiyun { \
2462*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);\
2463*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\
2464*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;\
2465*4882a593Smuzhiyun 	uint val = 0;\
2466*4882a593Smuzhiyun 	if (!isdigit(buf[0]))\
2467*4882a593Smuzhiyun 		return -EINVAL;\
2468*4882a593Smuzhiyun 	if (sscanf(buf, "%i", &val) != 1)\
2469*4882a593Smuzhiyun 		return -EINVAL;\
2470*4882a593Smuzhiyun 	if (lpfc_##attr##_set(phba, val) == 0) \
2471*4882a593Smuzhiyun 		return strlen(buf);\
2472*4882a593Smuzhiyun 	else \
2473*4882a593Smuzhiyun 		return -EINVAL;\
2474*4882a593Smuzhiyun }
2475*4882a593Smuzhiyun 
2476*4882a593Smuzhiyun /**
2477*4882a593Smuzhiyun  * lpfc_vport_param_show - Return decimal formatted cfg attribute value
2478*4882a593Smuzhiyun  *
2479*4882a593Smuzhiyun  * Description:
2480*4882a593Smuzhiyun  * Macro that given an attr e.g. hba_queue_depth expands
2481*4882a593Smuzhiyun  * into a function with the name lpfc_hba_queue_depth_show
2482*4882a593Smuzhiyun  *
2483*4882a593Smuzhiyun  * lpfc_##attr##_show: prints the attribute value in decimal.
2484*4882a593Smuzhiyun  * @dev: class device that is converted into a Scsi_host.
2485*4882a593Smuzhiyun  * @attr: device attribute, not used.
2486*4882a593Smuzhiyun  * @buf: on return contains the attribute value in decimal.
2487*4882a593Smuzhiyun  *
2488*4882a593Smuzhiyun  * Returns: length of formatted string.
2489*4882a593Smuzhiyun  **/
2490*4882a593Smuzhiyun #define lpfc_vport_param_show(attr)	\
2491*4882a593Smuzhiyun static ssize_t \
2492*4882a593Smuzhiyun lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
2493*4882a593Smuzhiyun 		   char *buf) \
2494*4882a593Smuzhiyun { \
2495*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);\
2496*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\
2497*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "%d\n", vport->cfg_##attr);\
2498*4882a593Smuzhiyun }
2499*4882a593Smuzhiyun 
2500*4882a593Smuzhiyun /**
2501*4882a593Smuzhiyun  * lpfc_vport_param_hex_show - Return hex formatted attribute value
2502*4882a593Smuzhiyun  *
2503*4882a593Smuzhiyun  * Description:
2504*4882a593Smuzhiyun  * Macro that given an attr e.g.
2505*4882a593Smuzhiyun  * hba_queue_depth expands into a function with the name
2506*4882a593Smuzhiyun  * lpfc_hba_queue_depth_show
2507*4882a593Smuzhiyun  *
2508*4882a593Smuzhiyun  * lpfc_##attr##_show: prints the attribute value in hexadecimal.
2509*4882a593Smuzhiyun  * @dev: class device that is converted into a Scsi_host.
2510*4882a593Smuzhiyun  * @attr: device attribute, not used.
2511*4882a593Smuzhiyun  * @buf: on return contains the attribute value in hexadecimal.
2512*4882a593Smuzhiyun  *
2513*4882a593Smuzhiyun  * Returns: length of formatted string.
2514*4882a593Smuzhiyun  **/
2515*4882a593Smuzhiyun #define lpfc_vport_param_hex_show(attr)	\
2516*4882a593Smuzhiyun static ssize_t \
2517*4882a593Smuzhiyun lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
2518*4882a593Smuzhiyun 		   char *buf) \
2519*4882a593Smuzhiyun { \
2520*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);\
2521*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\
2522*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "%#x\n", vport->cfg_##attr);\
2523*4882a593Smuzhiyun }
2524*4882a593Smuzhiyun 
2525*4882a593Smuzhiyun /**
2526*4882a593Smuzhiyun  * lpfc_vport_param_init - Initialize a vport cfg attribute
2527*4882a593Smuzhiyun  *
2528*4882a593Smuzhiyun  * Description:
2529*4882a593Smuzhiyun  * Macro that given an attr e.g. hba_queue_depth expands
2530*4882a593Smuzhiyun  * into a function with the name lpfc_hba_queue_depth_init. The macro also
2531*4882a593Smuzhiyun  * takes a default argument, a minimum and maximum argument.
2532*4882a593Smuzhiyun  *
2533*4882a593Smuzhiyun  * lpfc_##attr##_init: validates the min and max values then sets the
2534*4882a593Smuzhiyun  * adapter config field accordingly, or uses the default if out of range
2535*4882a593Smuzhiyun  * and prints an error message.
2536*4882a593Smuzhiyun  * @phba: pointer the the adapter structure.
2537*4882a593Smuzhiyun  * @val: integer attribute value.
2538*4882a593Smuzhiyun  *
2539*4882a593Smuzhiyun  * Returns:
2540*4882a593Smuzhiyun  * zero on success
2541*4882a593Smuzhiyun  * -EINVAL if default used
2542*4882a593Smuzhiyun  **/
2543*4882a593Smuzhiyun #define lpfc_vport_param_init(attr, default, minval, maxval)	\
2544*4882a593Smuzhiyun static int \
2545*4882a593Smuzhiyun lpfc_##attr##_init(struct lpfc_vport *vport, uint val) \
2546*4882a593Smuzhiyun { \
2547*4882a593Smuzhiyun 	if (lpfc_rangecheck(val, minval, maxval)) {\
2548*4882a593Smuzhiyun 		vport->cfg_##attr = val;\
2549*4882a593Smuzhiyun 		return 0;\
2550*4882a593Smuzhiyun 	}\
2551*4882a593Smuzhiyun 	lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, \
2552*4882a593Smuzhiyun 			 "0423 lpfc_"#attr" attribute cannot be set to %d, "\
2553*4882a593Smuzhiyun 			 "allowed range is ["#minval", "#maxval"]\n", val); \
2554*4882a593Smuzhiyun 	vport->cfg_##attr = default;\
2555*4882a593Smuzhiyun 	return -EINVAL;\
2556*4882a593Smuzhiyun }
2557*4882a593Smuzhiyun 
2558*4882a593Smuzhiyun /**
2559*4882a593Smuzhiyun  * lpfc_vport_param_set - Set a vport cfg attribute
2560*4882a593Smuzhiyun  *
2561*4882a593Smuzhiyun  * Description:
2562*4882a593Smuzhiyun  * Macro that given an attr e.g. hba_queue_depth expands
2563*4882a593Smuzhiyun  * into a function with the name lpfc_hba_queue_depth_set
2564*4882a593Smuzhiyun  *
2565*4882a593Smuzhiyun  * lpfc_##attr##_set: validates the min and max values then sets the
2566*4882a593Smuzhiyun  * adapter config field if in the valid range. prints error message
2567*4882a593Smuzhiyun  * and does not set the parameter if invalid.
2568*4882a593Smuzhiyun  * @phba: pointer the the adapter structure.
2569*4882a593Smuzhiyun  * @val:	integer attribute value.
2570*4882a593Smuzhiyun  *
2571*4882a593Smuzhiyun  * Returns:
2572*4882a593Smuzhiyun  * zero on success
2573*4882a593Smuzhiyun  * -EINVAL if val is invalid
2574*4882a593Smuzhiyun  **/
2575*4882a593Smuzhiyun #define lpfc_vport_param_set(attr, default, minval, maxval)	\
2576*4882a593Smuzhiyun static int \
2577*4882a593Smuzhiyun lpfc_##attr##_set(struct lpfc_vport *vport, uint val) \
2578*4882a593Smuzhiyun { \
2579*4882a593Smuzhiyun 	if (lpfc_rangecheck(val, minval, maxval)) {\
2580*4882a593Smuzhiyun 		lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, \
2581*4882a593Smuzhiyun 			"3053 lpfc_" #attr \
2582*4882a593Smuzhiyun 			" changed from %d (x%x) to %d (x%x)\n", \
2583*4882a593Smuzhiyun 			vport->cfg_##attr, vport->cfg_##attr, \
2584*4882a593Smuzhiyun 			val, val); \
2585*4882a593Smuzhiyun 		vport->cfg_##attr = val;\
2586*4882a593Smuzhiyun 		return 0;\
2587*4882a593Smuzhiyun 	}\
2588*4882a593Smuzhiyun 	lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, \
2589*4882a593Smuzhiyun 			 "0424 lpfc_"#attr" attribute cannot be set to %d, "\
2590*4882a593Smuzhiyun 			 "allowed range is ["#minval", "#maxval"]\n", val); \
2591*4882a593Smuzhiyun 	return -EINVAL;\
2592*4882a593Smuzhiyun }
2593*4882a593Smuzhiyun 
2594*4882a593Smuzhiyun /**
2595*4882a593Smuzhiyun  * lpfc_vport_param_store - Set a vport attribute
2596*4882a593Smuzhiyun  *
2597*4882a593Smuzhiyun  * Description:
2598*4882a593Smuzhiyun  * Macro that given an attr e.g. hba_queue_depth
2599*4882a593Smuzhiyun  * expands into a function with the name lpfc_hba_queue_depth_store
2600*4882a593Smuzhiyun  *
2601*4882a593Smuzhiyun  * lpfc_##attr##_store: convert the ascii text number to an integer, then
2602*4882a593Smuzhiyun  * use the lpfc_##attr##_set function to set the value.
2603*4882a593Smuzhiyun  * @cdev: class device that is converted into a Scsi_host.
2604*4882a593Smuzhiyun  * @buf:	contains the attribute value in decimal.
2605*4882a593Smuzhiyun  * @count: not used.
2606*4882a593Smuzhiyun  *
2607*4882a593Smuzhiyun  * Returns:
2608*4882a593Smuzhiyun  * -EINVAL if val is invalid or lpfc_##attr##_set() fails
2609*4882a593Smuzhiyun  * length of buffer upon success.
2610*4882a593Smuzhiyun  **/
2611*4882a593Smuzhiyun #define lpfc_vport_param_store(attr)	\
2612*4882a593Smuzhiyun static ssize_t \
2613*4882a593Smuzhiyun lpfc_##attr##_store(struct device *dev, struct device_attribute *attr, \
2614*4882a593Smuzhiyun 		    const char *buf, size_t count) \
2615*4882a593Smuzhiyun { \
2616*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);\
2617*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\
2618*4882a593Smuzhiyun 	uint val = 0;\
2619*4882a593Smuzhiyun 	if (!isdigit(buf[0]))\
2620*4882a593Smuzhiyun 		return -EINVAL;\
2621*4882a593Smuzhiyun 	if (sscanf(buf, "%i", &val) != 1)\
2622*4882a593Smuzhiyun 		return -EINVAL;\
2623*4882a593Smuzhiyun 	if (lpfc_##attr##_set(vport, val) == 0) \
2624*4882a593Smuzhiyun 		return strlen(buf);\
2625*4882a593Smuzhiyun 	else \
2626*4882a593Smuzhiyun 		return -EINVAL;\
2627*4882a593Smuzhiyun }
2628*4882a593Smuzhiyun 
2629*4882a593Smuzhiyun 
2630*4882a593Smuzhiyun static DEVICE_ATTR(nvme_info, 0444, lpfc_nvme_info_show, NULL);
2631*4882a593Smuzhiyun static DEVICE_ATTR(scsi_stat, 0444, lpfc_scsi_stat_show, NULL);
2632*4882a593Smuzhiyun static DEVICE_ATTR(bg_info, S_IRUGO, lpfc_bg_info_show, NULL);
2633*4882a593Smuzhiyun static DEVICE_ATTR(bg_guard_err, S_IRUGO, lpfc_bg_guard_err_show, NULL);
2634*4882a593Smuzhiyun static DEVICE_ATTR(bg_apptag_err, S_IRUGO, lpfc_bg_apptag_err_show, NULL);
2635*4882a593Smuzhiyun static DEVICE_ATTR(bg_reftag_err, S_IRUGO, lpfc_bg_reftag_err_show, NULL);
2636*4882a593Smuzhiyun static DEVICE_ATTR(info, S_IRUGO, lpfc_info_show, NULL);
2637*4882a593Smuzhiyun static DEVICE_ATTR(serialnum, S_IRUGO, lpfc_serialnum_show, NULL);
2638*4882a593Smuzhiyun static DEVICE_ATTR(modeldesc, S_IRUGO, lpfc_modeldesc_show, NULL);
2639*4882a593Smuzhiyun static DEVICE_ATTR(modelname, S_IRUGO, lpfc_modelname_show, NULL);
2640*4882a593Smuzhiyun static DEVICE_ATTR(programtype, S_IRUGO, lpfc_programtype_show, NULL);
2641*4882a593Smuzhiyun static DEVICE_ATTR(portnum, S_IRUGO, lpfc_vportnum_show, NULL);
2642*4882a593Smuzhiyun static DEVICE_ATTR(fwrev, S_IRUGO, lpfc_fwrev_show, NULL);
2643*4882a593Smuzhiyun static DEVICE_ATTR(hdw, S_IRUGO, lpfc_hdw_show, NULL);
2644*4882a593Smuzhiyun static DEVICE_ATTR(link_state, S_IRUGO | S_IWUSR, lpfc_link_state_show,
2645*4882a593Smuzhiyun 		lpfc_link_state_store);
2646*4882a593Smuzhiyun static DEVICE_ATTR(option_rom_version, S_IRUGO,
2647*4882a593Smuzhiyun 		   lpfc_option_rom_version_show, NULL);
2648*4882a593Smuzhiyun static DEVICE_ATTR(num_discovered_ports, S_IRUGO,
2649*4882a593Smuzhiyun 		   lpfc_num_discovered_ports_show, NULL);
2650*4882a593Smuzhiyun static DEVICE_ATTR(menlo_mgmt_mode, S_IRUGO, lpfc_mlomgmt_show, NULL);
2651*4882a593Smuzhiyun static DEVICE_ATTR(nport_evt_cnt, S_IRUGO, lpfc_nport_evt_cnt_show, NULL);
2652*4882a593Smuzhiyun static DEVICE_ATTR_RO(lpfc_drvr_version);
2653*4882a593Smuzhiyun static DEVICE_ATTR_RO(lpfc_enable_fip);
2654*4882a593Smuzhiyun static DEVICE_ATTR(board_mode, S_IRUGO | S_IWUSR,
2655*4882a593Smuzhiyun 		   lpfc_board_mode_show, lpfc_board_mode_store);
2656*4882a593Smuzhiyun static DEVICE_ATTR(issue_reset, S_IWUSR, NULL, lpfc_issue_reset);
2657*4882a593Smuzhiyun static DEVICE_ATTR(max_vpi, S_IRUGO, lpfc_max_vpi_show, NULL);
2658*4882a593Smuzhiyun static DEVICE_ATTR(used_vpi, S_IRUGO, lpfc_used_vpi_show, NULL);
2659*4882a593Smuzhiyun static DEVICE_ATTR(max_rpi, S_IRUGO, lpfc_max_rpi_show, NULL);
2660*4882a593Smuzhiyun static DEVICE_ATTR(used_rpi, S_IRUGO, lpfc_used_rpi_show, NULL);
2661*4882a593Smuzhiyun static DEVICE_ATTR(max_xri, S_IRUGO, lpfc_max_xri_show, NULL);
2662*4882a593Smuzhiyun static DEVICE_ATTR(used_xri, S_IRUGO, lpfc_used_xri_show, NULL);
2663*4882a593Smuzhiyun static DEVICE_ATTR(npiv_info, S_IRUGO, lpfc_npiv_info_show, NULL);
2664*4882a593Smuzhiyun static DEVICE_ATTR_RO(lpfc_temp_sensor);
2665*4882a593Smuzhiyun static DEVICE_ATTR_RO(lpfc_sriov_hw_max_virtfn);
2666*4882a593Smuzhiyun static DEVICE_ATTR(protocol, S_IRUGO, lpfc_sli4_protocol_show, NULL);
2667*4882a593Smuzhiyun static DEVICE_ATTR(lpfc_xlane_supported, S_IRUGO, lpfc_oas_supported_show,
2668*4882a593Smuzhiyun 		   NULL);
2669*4882a593Smuzhiyun 
2670*4882a593Smuzhiyun static char *lpfc_soft_wwn_key = "C99G71SL8032A";
2671*4882a593Smuzhiyun #define WWN_SZ 8
2672*4882a593Smuzhiyun /**
2673*4882a593Smuzhiyun  * lpfc_wwn_set - Convert string to the 8 byte WWN value.
2674*4882a593Smuzhiyun  * @buf: WWN string.
2675*4882a593Smuzhiyun  * @cnt: Length of string.
2676*4882a593Smuzhiyun  * @wwn: Array to receive converted wwn value.
2677*4882a593Smuzhiyun  *
2678*4882a593Smuzhiyun  * Returns:
2679*4882a593Smuzhiyun  * -EINVAL if the buffer does not contain a valid wwn
2680*4882a593Smuzhiyun  * 0 success
2681*4882a593Smuzhiyun  **/
2682*4882a593Smuzhiyun static size_t
lpfc_wwn_set(const char * buf,size_t cnt,char wwn[])2683*4882a593Smuzhiyun lpfc_wwn_set(const char *buf, size_t cnt, char wwn[])
2684*4882a593Smuzhiyun {
2685*4882a593Smuzhiyun 	unsigned int i, j;
2686*4882a593Smuzhiyun 
2687*4882a593Smuzhiyun 	/* Count may include a LF at end of string */
2688*4882a593Smuzhiyun 	if (buf[cnt-1] == '\n')
2689*4882a593Smuzhiyun 		cnt--;
2690*4882a593Smuzhiyun 
2691*4882a593Smuzhiyun 	if ((cnt < 16) || (cnt > 18) || ((cnt == 17) && (*buf++ != 'x')) ||
2692*4882a593Smuzhiyun 	    ((cnt == 18) && ((*buf++ != '0') || (*buf++ != 'x'))))
2693*4882a593Smuzhiyun 		return -EINVAL;
2694*4882a593Smuzhiyun 
2695*4882a593Smuzhiyun 	memset(wwn, 0, WWN_SZ);
2696*4882a593Smuzhiyun 
2697*4882a593Smuzhiyun 	/* Validate and store the new name */
2698*4882a593Smuzhiyun 	for (i = 0, j = 0; i < 16; i++) {
2699*4882a593Smuzhiyun 		if ((*buf >= 'a') && (*buf <= 'f'))
2700*4882a593Smuzhiyun 			j = ((j << 4) | ((*buf++ - 'a') + 10));
2701*4882a593Smuzhiyun 		else if ((*buf >= 'A') && (*buf <= 'F'))
2702*4882a593Smuzhiyun 			j = ((j << 4) | ((*buf++ - 'A') + 10));
2703*4882a593Smuzhiyun 		else if ((*buf >= '0') && (*buf <= '9'))
2704*4882a593Smuzhiyun 			j = ((j << 4) | (*buf++ - '0'));
2705*4882a593Smuzhiyun 		else
2706*4882a593Smuzhiyun 			return -EINVAL;
2707*4882a593Smuzhiyun 		if (i % 2) {
2708*4882a593Smuzhiyun 			wwn[i/2] = j & 0xff;
2709*4882a593Smuzhiyun 			j = 0;
2710*4882a593Smuzhiyun 		}
2711*4882a593Smuzhiyun 	}
2712*4882a593Smuzhiyun 	return 0;
2713*4882a593Smuzhiyun }
2714*4882a593Smuzhiyun /**
2715*4882a593Smuzhiyun  * lpfc_soft_wwn_enable_store - Allows setting of the wwn if the key is valid
2716*4882a593Smuzhiyun  * @dev: class device that is converted into a Scsi_host.
2717*4882a593Smuzhiyun  * @attr: device attribute, not used.
2718*4882a593Smuzhiyun  * @buf: containing the string lpfc_soft_wwn_key.
2719*4882a593Smuzhiyun  * @count: must be size of lpfc_soft_wwn_key.
2720*4882a593Smuzhiyun  *
2721*4882a593Smuzhiyun  * Returns:
2722*4882a593Smuzhiyun  * -EINVAL if the buffer does not contain lpfc_soft_wwn_key
2723*4882a593Smuzhiyun  * length of buf indicates success
2724*4882a593Smuzhiyun  **/
2725*4882a593Smuzhiyun static ssize_t
lpfc_soft_wwn_enable_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)2726*4882a593Smuzhiyun lpfc_soft_wwn_enable_store(struct device *dev, struct device_attribute *attr,
2727*4882a593Smuzhiyun 			   const char *buf, size_t count)
2728*4882a593Smuzhiyun {
2729*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
2730*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
2731*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
2732*4882a593Smuzhiyun 	unsigned int cnt = count;
2733*4882a593Smuzhiyun 	uint8_t vvvl = vport->fc_sparam.cmn.valid_vendor_ver_level;
2734*4882a593Smuzhiyun 	u32 *fawwpn_key = (uint32_t *)&vport->fc_sparam.un.vendorVersion[0];
2735*4882a593Smuzhiyun 
2736*4882a593Smuzhiyun 	/*
2737*4882a593Smuzhiyun 	 * We're doing a simple sanity check for soft_wwpn setting.
2738*4882a593Smuzhiyun 	 * We require that the user write a specific key to enable
2739*4882a593Smuzhiyun 	 * the soft_wwpn attribute to be settable. Once the attribute
2740*4882a593Smuzhiyun 	 * is written, the enable key resets. If further updates are
2741*4882a593Smuzhiyun 	 * desired, the key must be written again to re-enable the
2742*4882a593Smuzhiyun 	 * attribute.
2743*4882a593Smuzhiyun 	 *
2744*4882a593Smuzhiyun 	 * The "key" is not secret - it is a hardcoded string shown
2745*4882a593Smuzhiyun 	 * here. The intent is to protect against the random user or
2746*4882a593Smuzhiyun 	 * application that is just writing attributes.
2747*4882a593Smuzhiyun 	 */
2748*4882a593Smuzhiyun 	if (vvvl == 1 && cpu_to_be32(*fawwpn_key) == FAPWWN_KEY_VENDOR) {
2749*4882a593Smuzhiyun 		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
2750*4882a593Smuzhiyun 				 "0051 "LPFC_DRIVER_NAME" soft wwpn can not"
2751*4882a593Smuzhiyun 				 " be enabled: fawwpn is enabled\n");
2752*4882a593Smuzhiyun 		return -EINVAL;
2753*4882a593Smuzhiyun 	}
2754*4882a593Smuzhiyun 
2755*4882a593Smuzhiyun 	/* count may include a LF at end of string */
2756*4882a593Smuzhiyun 	if (buf[cnt-1] == '\n')
2757*4882a593Smuzhiyun 		cnt--;
2758*4882a593Smuzhiyun 
2759*4882a593Smuzhiyun 	if ((cnt != strlen(lpfc_soft_wwn_key)) ||
2760*4882a593Smuzhiyun 	    (strncmp(buf, lpfc_soft_wwn_key, strlen(lpfc_soft_wwn_key)) != 0))
2761*4882a593Smuzhiyun 		return -EINVAL;
2762*4882a593Smuzhiyun 
2763*4882a593Smuzhiyun 	phba->soft_wwn_enable = 1;
2764*4882a593Smuzhiyun 
2765*4882a593Smuzhiyun 	dev_printk(KERN_WARNING, &phba->pcidev->dev,
2766*4882a593Smuzhiyun 		   "lpfc%d: soft_wwpn assignment has been enabled.\n",
2767*4882a593Smuzhiyun 		   phba->brd_no);
2768*4882a593Smuzhiyun 	dev_printk(KERN_WARNING, &phba->pcidev->dev,
2769*4882a593Smuzhiyun 		   "  The soft_wwpn feature is not supported by Broadcom.");
2770*4882a593Smuzhiyun 
2771*4882a593Smuzhiyun 	return count;
2772*4882a593Smuzhiyun }
2773*4882a593Smuzhiyun static DEVICE_ATTR_WO(lpfc_soft_wwn_enable);
2774*4882a593Smuzhiyun 
2775*4882a593Smuzhiyun /**
2776*4882a593Smuzhiyun  * lpfc_soft_wwpn_show - Return the cfg soft ww port name of the adapter
2777*4882a593Smuzhiyun  * @dev: class device that is converted into a Scsi_host.
2778*4882a593Smuzhiyun  * @attr: device attribute, not used.
2779*4882a593Smuzhiyun  * @buf: on return contains the wwpn in hexadecimal.
2780*4882a593Smuzhiyun  *
2781*4882a593Smuzhiyun  * Returns: size of formatted string.
2782*4882a593Smuzhiyun  **/
2783*4882a593Smuzhiyun static ssize_t
lpfc_soft_wwpn_show(struct device * dev,struct device_attribute * attr,char * buf)2784*4882a593Smuzhiyun lpfc_soft_wwpn_show(struct device *dev, struct device_attribute *attr,
2785*4882a593Smuzhiyun 		    char *buf)
2786*4882a593Smuzhiyun {
2787*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
2788*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
2789*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
2790*4882a593Smuzhiyun 
2791*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "0x%llx\n",
2792*4882a593Smuzhiyun 			(unsigned long long)phba->cfg_soft_wwpn);
2793*4882a593Smuzhiyun }
2794*4882a593Smuzhiyun 
2795*4882a593Smuzhiyun /**
2796*4882a593Smuzhiyun  * lpfc_soft_wwpn_store - Set the ww port name of the adapter
2797*4882a593Smuzhiyun  * @dev class device that is converted into a Scsi_host.
2798*4882a593Smuzhiyun  * @attr: device attribute, not used.
2799*4882a593Smuzhiyun  * @buf: contains the wwpn in hexadecimal.
2800*4882a593Smuzhiyun  * @count: number of wwpn bytes in buf
2801*4882a593Smuzhiyun  *
2802*4882a593Smuzhiyun  * Returns:
2803*4882a593Smuzhiyun  * -EACCES hba reset not enabled, adapter over temp
2804*4882a593Smuzhiyun  * -EINVAL soft wwn not enabled, count is invalid, invalid wwpn byte invalid
2805*4882a593Smuzhiyun  * -EIO error taking adapter offline or online
2806*4882a593Smuzhiyun  * value of count on success
2807*4882a593Smuzhiyun  **/
2808*4882a593Smuzhiyun static ssize_t
lpfc_soft_wwpn_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)2809*4882a593Smuzhiyun lpfc_soft_wwpn_store(struct device *dev, struct device_attribute *attr,
2810*4882a593Smuzhiyun 		     const char *buf, size_t count)
2811*4882a593Smuzhiyun {
2812*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
2813*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
2814*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
2815*4882a593Smuzhiyun 	struct completion online_compl;
2816*4882a593Smuzhiyun 	int stat1 = 0, stat2 = 0;
2817*4882a593Smuzhiyun 	unsigned int cnt = count;
2818*4882a593Smuzhiyun 	u8 wwpn[WWN_SZ];
2819*4882a593Smuzhiyun 	int rc;
2820*4882a593Smuzhiyun 
2821*4882a593Smuzhiyun 	if (!phba->cfg_enable_hba_reset)
2822*4882a593Smuzhiyun 		return -EACCES;
2823*4882a593Smuzhiyun 	spin_lock_irq(&phba->hbalock);
2824*4882a593Smuzhiyun 	if (phba->over_temp_state == HBA_OVER_TEMP) {
2825*4882a593Smuzhiyun 		spin_unlock_irq(&phba->hbalock);
2826*4882a593Smuzhiyun 		return -EACCES;
2827*4882a593Smuzhiyun 	}
2828*4882a593Smuzhiyun 	spin_unlock_irq(&phba->hbalock);
2829*4882a593Smuzhiyun 	/* count may include a LF at end of string */
2830*4882a593Smuzhiyun 	if (buf[cnt-1] == '\n')
2831*4882a593Smuzhiyun 		cnt--;
2832*4882a593Smuzhiyun 
2833*4882a593Smuzhiyun 	if (!phba->soft_wwn_enable)
2834*4882a593Smuzhiyun 		return -EINVAL;
2835*4882a593Smuzhiyun 
2836*4882a593Smuzhiyun 	/* lock setting wwpn, wwnn down */
2837*4882a593Smuzhiyun 	phba->soft_wwn_enable = 0;
2838*4882a593Smuzhiyun 
2839*4882a593Smuzhiyun 	rc = lpfc_wwn_set(buf, cnt, wwpn);
2840*4882a593Smuzhiyun 	if (rc) {
2841*4882a593Smuzhiyun 		/* not able to set wwpn, unlock it */
2842*4882a593Smuzhiyun 		phba->soft_wwn_enable = 1;
2843*4882a593Smuzhiyun 		return rc;
2844*4882a593Smuzhiyun 	}
2845*4882a593Smuzhiyun 
2846*4882a593Smuzhiyun 	phba->cfg_soft_wwpn = wwn_to_u64(wwpn);
2847*4882a593Smuzhiyun 	fc_host_port_name(shost) = phba->cfg_soft_wwpn;
2848*4882a593Smuzhiyun 	if (phba->cfg_soft_wwnn)
2849*4882a593Smuzhiyun 		fc_host_node_name(shost) = phba->cfg_soft_wwnn;
2850*4882a593Smuzhiyun 
2851*4882a593Smuzhiyun 	dev_printk(KERN_NOTICE, &phba->pcidev->dev,
2852*4882a593Smuzhiyun 		   "lpfc%d: Reinitializing to use soft_wwpn\n", phba->brd_no);
2853*4882a593Smuzhiyun 
2854*4882a593Smuzhiyun 	stat1 = lpfc_do_offline(phba, LPFC_EVT_OFFLINE);
2855*4882a593Smuzhiyun 	if (stat1)
2856*4882a593Smuzhiyun 		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
2857*4882a593Smuzhiyun 				"0463 lpfc_soft_wwpn attribute set failed to "
2858*4882a593Smuzhiyun 				"reinit adapter - %d\n", stat1);
2859*4882a593Smuzhiyun 	init_completion(&online_compl);
2860*4882a593Smuzhiyun 	rc = lpfc_workq_post_event(phba, &stat2, &online_compl,
2861*4882a593Smuzhiyun 				   LPFC_EVT_ONLINE);
2862*4882a593Smuzhiyun 	if (rc == 0)
2863*4882a593Smuzhiyun 		return -ENOMEM;
2864*4882a593Smuzhiyun 
2865*4882a593Smuzhiyun 	wait_for_completion(&online_compl);
2866*4882a593Smuzhiyun 	if (stat2)
2867*4882a593Smuzhiyun 		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
2868*4882a593Smuzhiyun 				"0464 lpfc_soft_wwpn attribute set failed to "
2869*4882a593Smuzhiyun 				"reinit adapter - %d\n", stat2);
2870*4882a593Smuzhiyun 	return (stat1 || stat2) ? -EIO : count;
2871*4882a593Smuzhiyun }
2872*4882a593Smuzhiyun static DEVICE_ATTR_RW(lpfc_soft_wwpn);
2873*4882a593Smuzhiyun 
2874*4882a593Smuzhiyun /**
2875*4882a593Smuzhiyun  * lpfc_soft_wwnn_show - Return the cfg soft ww node name for the adapter
2876*4882a593Smuzhiyun  * @dev: class device that is converted into a Scsi_host.
2877*4882a593Smuzhiyun  * @attr: device attribute, not used.
2878*4882a593Smuzhiyun  * @buf: on return contains the wwnn in hexadecimal.
2879*4882a593Smuzhiyun  *
2880*4882a593Smuzhiyun  * Returns: size of formatted string.
2881*4882a593Smuzhiyun  **/
2882*4882a593Smuzhiyun static ssize_t
lpfc_soft_wwnn_show(struct device * dev,struct device_attribute * attr,char * buf)2883*4882a593Smuzhiyun lpfc_soft_wwnn_show(struct device *dev, struct device_attribute *attr,
2884*4882a593Smuzhiyun 		    char *buf)
2885*4882a593Smuzhiyun {
2886*4882a593Smuzhiyun 	struct Scsi_Host *shost = class_to_shost(dev);
2887*4882a593Smuzhiyun 	struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
2888*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "0x%llx\n",
2889*4882a593Smuzhiyun 			(unsigned long long)phba->cfg_soft_wwnn);
2890*4882a593Smuzhiyun }
2891*4882a593Smuzhiyun 
2892*4882a593Smuzhiyun /**
2893*4882a593Smuzhiyun  * lpfc_soft_wwnn_store - sets the ww node name of the adapter
2894*4882a593Smuzhiyun  * @cdev: class device that is converted into a Scsi_host.
2895*4882a593Smuzhiyun  * @buf: contains the ww node name in hexadecimal.
2896*4882a593Smuzhiyun  * @count: number of wwnn bytes in buf.
2897*4882a593Smuzhiyun  *
2898*4882a593Smuzhiyun  * Returns:
2899*4882a593Smuzhiyun  * -EINVAL soft wwn not enabled, count is invalid, invalid wwnn byte invalid
2900*4882a593Smuzhiyun  * value of count on success
2901*4882a593Smuzhiyun  **/
2902*4882a593Smuzhiyun static ssize_t
lpfc_soft_wwnn_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)2903*4882a593Smuzhiyun lpfc_soft_wwnn_store(struct device *dev, struct device_attribute *attr,
2904*4882a593Smuzhiyun 		     const char *buf, size_t count)
2905*4882a593Smuzhiyun {
2906*4882a593Smuzhiyun 	struct Scsi_Host *shost = class_to_shost(dev);
2907*4882a593Smuzhiyun 	struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
2908*4882a593Smuzhiyun 	unsigned int cnt = count;
2909*4882a593Smuzhiyun 	u8 wwnn[WWN_SZ];
2910*4882a593Smuzhiyun 	int rc;
2911*4882a593Smuzhiyun 
2912*4882a593Smuzhiyun 	/* count may include a LF at end of string */
2913*4882a593Smuzhiyun 	if (buf[cnt-1] == '\n')
2914*4882a593Smuzhiyun 		cnt--;
2915*4882a593Smuzhiyun 
2916*4882a593Smuzhiyun 	if (!phba->soft_wwn_enable)
2917*4882a593Smuzhiyun 		return -EINVAL;
2918*4882a593Smuzhiyun 
2919*4882a593Smuzhiyun 	rc = lpfc_wwn_set(buf, cnt, wwnn);
2920*4882a593Smuzhiyun 	if (rc) {
2921*4882a593Smuzhiyun 		/* Allow wwnn to be set many times, as long as the enable
2922*4882a593Smuzhiyun 		 * is set. However, once the wwpn is set, everything locks.
2923*4882a593Smuzhiyun 		 */
2924*4882a593Smuzhiyun 		return rc;
2925*4882a593Smuzhiyun 	}
2926*4882a593Smuzhiyun 
2927*4882a593Smuzhiyun 	phba->cfg_soft_wwnn = wwn_to_u64(wwnn);
2928*4882a593Smuzhiyun 
2929*4882a593Smuzhiyun 	dev_printk(KERN_NOTICE, &phba->pcidev->dev,
2930*4882a593Smuzhiyun 		   "lpfc%d: soft_wwnn set. Value will take effect upon "
2931*4882a593Smuzhiyun 		   "setting of the soft_wwpn\n", phba->brd_no);
2932*4882a593Smuzhiyun 
2933*4882a593Smuzhiyun 	return count;
2934*4882a593Smuzhiyun }
2935*4882a593Smuzhiyun static DEVICE_ATTR_RW(lpfc_soft_wwnn);
2936*4882a593Smuzhiyun 
2937*4882a593Smuzhiyun /**
2938*4882a593Smuzhiyun  * lpfc_oas_tgt_show - Return wwpn of target whose luns maybe enabled for
2939*4882a593Smuzhiyun  *		      Optimized Access Storage (OAS) operations.
2940*4882a593Smuzhiyun  * @dev: class device that is converted into a Scsi_host.
2941*4882a593Smuzhiyun  * @attr: device attribute, not used.
2942*4882a593Smuzhiyun  * @buf: buffer for passing information.
2943*4882a593Smuzhiyun  *
2944*4882a593Smuzhiyun  * Returns:
2945*4882a593Smuzhiyun  * value of count
2946*4882a593Smuzhiyun  **/
2947*4882a593Smuzhiyun static ssize_t
lpfc_oas_tgt_show(struct device * dev,struct device_attribute * attr,char * buf)2948*4882a593Smuzhiyun lpfc_oas_tgt_show(struct device *dev, struct device_attribute *attr,
2949*4882a593Smuzhiyun 		  char *buf)
2950*4882a593Smuzhiyun {
2951*4882a593Smuzhiyun 	struct Scsi_Host *shost = class_to_shost(dev);
2952*4882a593Smuzhiyun 	struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
2953*4882a593Smuzhiyun 
2954*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "0x%llx\n",
2955*4882a593Smuzhiyun 			wwn_to_u64(phba->cfg_oas_tgt_wwpn));
2956*4882a593Smuzhiyun }
2957*4882a593Smuzhiyun 
2958*4882a593Smuzhiyun /**
2959*4882a593Smuzhiyun  * lpfc_oas_tgt_store - Store wwpn of target whose luns maybe enabled for
2960*4882a593Smuzhiyun  *		      Optimized Access Storage (OAS) operations.
2961*4882a593Smuzhiyun  * @dev: class device that is converted into a Scsi_host.
2962*4882a593Smuzhiyun  * @attr: device attribute, not used.
2963*4882a593Smuzhiyun  * @buf: buffer for passing information.
2964*4882a593Smuzhiyun  * @count: Size of the data buffer.
2965*4882a593Smuzhiyun  *
2966*4882a593Smuzhiyun  * Returns:
2967*4882a593Smuzhiyun  * -EINVAL count is invalid, invalid wwpn byte invalid
2968*4882a593Smuzhiyun  * -EPERM oas is not supported by hba
2969*4882a593Smuzhiyun  * value of count on success
2970*4882a593Smuzhiyun  **/
2971*4882a593Smuzhiyun static ssize_t
lpfc_oas_tgt_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)2972*4882a593Smuzhiyun lpfc_oas_tgt_store(struct device *dev, struct device_attribute *attr,
2973*4882a593Smuzhiyun 		   const char *buf, size_t count)
2974*4882a593Smuzhiyun {
2975*4882a593Smuzhiyun 	struct Scsi_Host *shost = class_to_shost(dev);
2976*4882a593Smuzhiyun 	struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
2977*4882a593Smuzhiyun 	unsigned int cnt = count;
2978*4882a593Smuzhiyun 	uint8_t wwpn[WWN_SZ];
2979*4882a593Smuzhiyun 	int rc;
2980*4882a593Smuzhiyun 
2981*4882a593Smuzhiyun 	if (!phba->cfg_fof)
2982*4882a593Smuzhiyun 		return -EPERM;
2983*4882a593Smuzhiyun 
2984*4882a593Smuzhiyun 	/* count may include a LF at end of string */
2985*4882a593Smuzhiyun 	if (buf[cnt-1] == '\n')
2986*4882a593Smuzhiyun 		cnt--;
2987*4882a593Smuzhiyun 
2988*4882a593Smuzhiyun 	rc = lpfc_wwn_set(buf, cnt, wwpn);
2989*4882a593Smuzhiyun 	if (rc)
2990*4882a593Smuzhiyun 		return rc;
2991*4882a593Smuzhiyun 
2992*4882a593Smuzhiyun 	memcpy(phba->cfg_oas_tgt_wwpn, wwpn, (8 * sizeof(uint8_t)));
2993*4882a593Smuzhiyun 	memcpy(phba->sli4_hba.oas_next_tgt_wwpn, wwpn, (8 * sizeof(uint8_t)));
2994*4882a593Smuzhiyun 	if (wwn_to_u64(wwpn) == 0)
2995*4882a593Smuzhiyun 		phba->cfg_oas_flags |= OAS_FIND_ANY_TARGET;
2996*4882a593Smuzhiyun 	else
2997*4882a593Smuzhiyun 		phba->cfg_oas_flags &= ~OAS_FIND_ANY_TARGET;
2998*4882a593Smuzhiyun 	phba->cfg_oas_flags &= ~OAS_LUN_VALID;
2999*4882a593Smuzhiyun 	phba->sli4_hba.oas_next_lun = FIND_FIRST_OAS_LUN;
3000*4882a593Smuzhiyun 	return count;
3001*4882a593Smuzhiyun }
3002*4882a593Smuzhiyun static DEVICE_ATTR(lpfc_xlane_tgt, S_IRUGO | S_IWUSR,
3003*4882a593Smuzhiyun 		   lpfc_oas_tgt_show, lpfc_oas_tgt_store);
3004*4882a593Smuzhiyun 
3005*4882a593Smuzhiyun /**
3006*4882a593Smuzhiyun  * lpfc_oas_priority_show - Return wwpn of target whose luns maybe enabled for
3007*4882a593Smuzhiyun  *		      Optimized Access Storage (OAS) operations.
3008*4882a593Smuzhiyun  * @dev: class device that is converted into a Scsi_host.
3009*4882a593Smuzhiyun  * @attr: device attribute, not used.
3010*4882a593Smuzhiyun  * @buf: buffer for passing information.
3011*4882a593Smuzhiyun  *
3012*4882a593Smuzhiyun  * Returns:
3013*4882a593Smuzhiyun  * value of count
3014*4882a593Smuzhiyun  **/
3015*4882a593Smuzhiyun static ssize_t
lpfc_oas_priority_show(struct device * dev,struct device_attribute * attr,char * buf)3016*4882a593Smuzhiyun lpfc_oas_priority_show(struct device *dev, struct device_attribute *attr,
3017*4882a593Smuzhiyun 		       char *buf)
3018*4882a593Smuzhiyun {
3019*4882a593Smuzhiyun 	struct Scsi_Host *shost = class_to_shost(dev);
3020*4882a593Smuzhiyun 	struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
3021*4882a593Smuzhiyun 
3022*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "%d\n", phba->cfg_oas_priority);
3023*4882a593Smuzhiyun }
3024*4882a593Smuzhiyun 
3025*4882a593Smuzhiyun /**
3026*4882a593Smuzhiyun  * lpfc_oas_priority_store - Store wwpn of target whose luns maybe enabled for
3027*4882a593Smuzhiyun  *		      Optimized Access Storage (OAS) operations.
3028*4882a593Smuzhiyun  * @dev: class device that is converted into a Scsi_host.
3029*4882a593Smuzhiyun  * @attr: device attribute, not used.
3030*4882a593Smuzhiyun  * @buf: buffer for passing information.
3031*4882a593Smuzhiyun  * @count: Size of the data buffer.
3032*4882a593Smuzhiyun  *
3033*4882a593Smuzhiyun  * Returns:
3034*4882a593Smuzhiyun  * -EINVAL count is invalid, invalid wwpn byte invalid
3035*4882a593Smuzhiyun  * -EPERM oas is not supported by hba
3036*4882a593Smuzhiyun  * value of count on success
3037*4882a593Smuzhiyun  **/
3038*4882a593Smuzhiyun static ssize_t
lpfc_oas_priority_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)3039*4882a593Smuzhiyun lpfc_oas_priority_store(struct device *dev, struct device_attribute *attr,
3040*4882a593Smuzhiyun 			const char *buf, size_t count)
3041*4882a593Smuzhiyun {
3042*4882a593Smuzhiyun 	struct Scsi_Host *shost = class_to_shost(dev);
3043*4882a593Smuzhiyun 	struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
3044*4882a593Smuzhiyun 	unsigned int cnt = count;
3045*4882a593Smuzhiyun 	unsigned long val;
3046*4882a593Smuzhiyun 	int ret;
3047*4882a593Smuzhiyun 
3048*4882a593Smuzhiyun 	if (!phba->cfg_fof)
3049*4882a593Smuzhiyun 		return -EPERM;
3050*4882a593Smuzhiyun 
3051*4882a593Smuzhiyun 	/* count may include a LF at end of string */
3052*4882a593Smuzhiyun 	if (buf[cnt-1] == '\n')
3053*4882a593Smuzhiyun 		cnt--;
3054*4882a593Smuzhiyun 
3055*4882a593Smuzhiyun 	ret = kstrtoul(buf, 0, &val);
3056*4882a593Smuzhiyun 	if (ret || (val > 0x7f))
3057*4882a593Smuzhiyun 		return -EINVAL;
3058*4882a593Smuzhiyun 
3059*4882a593Smuzhiyun 	if (val)
3060*4882a593Smuzhiyun 		phba->cfg_oas_priority = (uint8_t)val;
3061*4882a593Smuzhiyun 	else
3062*4882a593Smuzhiyun 		phba->cfg_oas_priority = phba->cfg_XLanePriority;
3063*4882a593Smuzhiyun 	return count;
3064*4882a593Smuzhiyun }
3065*4882a593Smuzhiyun static DEVICE_ATTR(lpfc_xlane_priority, S_IRUGO | S_IWUSR,
3066*4882a593Smuzhiyun 		   lpfc_oas_priority_show, lpfc_oas_priority_store);
3067*4882a593Smuzhiyun 
3068*4882a593Smuzhiyun /**
3069*4882a593Smuzhiyun  * lpfc_oas_vpt_show - Return wwpn of vport whose targets maybe enabled
3070*4882a593Smuzhiyun  *		      for Optimized Access Storage (OAS) operations.
3071*4882a593Smuzhiyun  * @dev: class device that is converted into a Scsi_host.
3072*4882a593Smuzhiyun  * @attr: device attribute, not used.
3073*4882a593Smuzhiyun  * @buf: buffer for passing information.
3074*4882a593Smuzhiyun  *
3075*4882a593Smuzhiyun  * Returns:
3076*4882a593Smuzhiyun  * value of count on success
3077*4882a593Smuzhiyun  **/
3078*4882a593Smuzhiyun static ssize_t
lpfc_oas_vpt_show(struct device * dev,struct device_attribute * attr,char * buf)3079*4882a593Smuzhiyun lpfc_oas_vpt_show(struct device *dev, struct device_attribute *attr,
3080*4882a593Smuzhiyun 		  char *buf)
3081*4882a593Smuzhiyun {
3082*4882a593Smuzhiyun 	struct Scsi_Host *shost = class_to_shost(dev);
3083*4882a593Smuzhiyun 	struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
3084*4882a593Smuzhiyun 
3085*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "0x%llx\n",
3086*4882a593Smuzhiyun 			wwn_to_u64(phba->cfg_oas_vpt_wwpn));
3087*4882a593Smuzhiyun }
3088*4882a593Smuzhiyun 
3089*4882a593Smuzhiyun /**
3090*4882a593Smuzhiyun  * lpfc_oas_vpt_store - Store wwpn of vport whose targets maybe enabled
3091*4882a593Smuzhiyun  *		      for Optimized Access Storage (OAS) operations.
3092*4882a593Smuzhiyun  * @dev: class device that is converted into a Scsi_host.
3093*4882a593Smuzhiyun  * @attr: device attribute, not used.
3094*4882a593Smuzhiyun  * @buf: buffer for passing information.
3095*4882a593Smuzhiyun  * @count: Size of the data buffer.
3096*4882a593Smuzhiyun  *
3097*4882a593Smuzhiyun  * Returns:
3098*4882a593Smuzhiyun  * -EINVAL count is invalid, invalid wwpn byte invalid
3099*4882a593Smuzhiyun  * -EPERM oas is not supported by hba
3100*4882a593Smuzhiyun  * value of count on success
3101*4882a593Smuzhiyun  **/
3102*4882a593Smuzhiyun static ssize_t
lpfc_oas_vpt_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)3103*4882a593Smuzhiyun lpfc_oas_vpt_store(struct device *dev, struct device_attribute *attr,
3104*4882a593Smuzhiyun 		   const char *buf, size_t count)
3105*4882a593Smuzhiyun {
3106*4882a593Smuzhiyun 	struct Scsi_Host *shost = class_to_shost(dev);
3107*4882a593Smuzhiyun 	struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
3108*4882a593Smuzhiyun 	unsigned int cnt = count;
3109*4882a593Smuzhiyun 	uint8_t wwpn[WWN_SZ];
3110*4882a593Smuzhiyun 	int rc;
3111*4882a593Smuzhiyun 
3112*4882a593Smuzhiyun 	if (!phba->cfg_fof)
3113*4882a593Smuzhiyun 		return -EPERM;
3114*4882a593Smuzhiyun 
3115*4882a593Smuzhiyun 	/* count may include a LF at end of string */
3116*4882a593Smuzhiyun 	if (buf[cnt-1] == '\n')
3117*4882a593Smuzhiyun 		cnt--;
3118*4882a593Smuzhiyun 
3119*4882a593Smuzhiyun 	rc = lpfc_wwn_set(buf, cnt, wwpn);
3120*4882a593Smuzhiyun 	if (rc)
3121*4882a593Smuzhiyun 		return rc;
3122*4882a593Smuzhiyun 
3123*4882a593Smuzhiyun 	memcpy(phba->cfg_oas_vpt_wwpn, wwpn, (8 * sizeof(uint8_t)));
3124*4882a593Smuzhiyun 	memcpy(phba->sli4_hba.oas_next_vpt_wwpn, wwpn, (8 * sizeof(uint8_t)));
3125*4882a593Smuzhiyun 	if (wwn_to_u64(wwpn) == 0)
3126*4882a593Smuzhiyun 		phba->cfg_oas_flags |= OAS_FIND_ANY_VPORT;
3127*4882a593Smuzhiyun 	else
3128*4882a593Smuzhiyun 		phba->cfg_oas_flags &= ~OAS_FIND_ANY_VPORT;
3129*4882a593Smuzhiyun 	phba->cfg_oas_flags &= ~OAS_LUN_VALID;
3130*4882a593Smuzhiyun 	if (phba->cfg_oas_priority == 0)
3131*4882a593Smuzhiyun 		phba->cfg_oas_priority = phba->cfg_XLanePriority;
3132*4882a593Smuzhiyun 	phba->sli4_hba.oas_next_lun = FIND_FIRST_OAS_LUN;
3133*4882a593Smuzhiyun 	return count;
3134*4882a593Smuzhiyun }
3135*4882a593Smuzhiyun static DEVICE_ATTR(lpfc_xlane_vpt, S_IRUGO | S_IWUSR,
3136*4882a593Smuzhiyun 		   lpfc_oas_vpt_show, lpfc_oas_vpt_store);
3137*4882a593Smuzhiyun 
3138*4882a593Smuzhiyun /**
3139*4882a593Smuzhiyun  * lpfc_oas_lun_state_show - Return the current state (enabled or disabled)
3140*4882a593Smuzhiyun  *			    of whether luns will be enabled or disabled
3141*4882a593Smuzhiyun  *			    for Optimized Access Storage (OAS) operations.
3142*4882a593Smuzhiyun  * @dev: class device that is converted into a Scsi_host.
3143*4882a593Smuzhiyun  * @attr: device attribute, not used.
3144*4882a593Smuzhiyun  * @buf: buffer for passing information.
3145*4882a593Smuzhiyun  *
3146*4882a593Smuzhiyun  * Returns:
3147*4882a593Smuzhiyun  * size of formatted string.
3148*4882a593Smuzhiyun  **/
3149*4882a593Smuzhiyun static ssize_t
lpfc_oas_lun_state_show(struct device * dev,struct device_attribute * attr,char * buf)3150*4882a593Smuzhiyun lpfc_oas_lun_state_show(struct device *dev, struct device_attribute *attr,
3151*4882a593Smuzhiyun 			char *buf)
3152*4882a593Smuzhiyun {
3153*4882a593Smuzhiyun 	struct Scsi_Host *shost = class_to_shost(dev);
3154*4882a593Smuzhiyun 	struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
3155*4882a593Smuzhiyun 
3156*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "%d\n", phba->cfg_oas_lun_state);
3157*4882a593Smuzhiyun }
3158*4882a593Smuzhiyun 
3159*4882a593Smuzhiyun /**
3160*4882a593Smuzhiyun  * lpfc_oas_lun_state_store - Store the state (enabled or disabled)
3161*4882a593Smuzhiyun  *			    of whether luns will be enabled or disabled
3162*4882a593Smuzhiyun  *			    for Optimized Access Storage (OAS) operations.
3163*4882a593Smuzhiyun  * @dev: class device that is converted into a Scsi_host.
3164*4882a593Smuzhiyun  * @attr: device attribute, not used.
3165*4882a593Smuzhiyun  * @buf: buffer for passing information.
3166*4882a593Smuzhiyun  * @count: Size of the data buffer.
3167*4882a593Smuzhiyun  *
3168*4882a593Smuzhiyun  * Returns:
3169*4882a593Smuzhiyun  * -EINVAL count is invalid, invalid wwpn byte invalid
3170*4882a593Smuzhiyun  * -EPERM oas is not supported by hba
3171*4882a593Smuzhiyun  * value of count on success
3172*4882a593Smuzhiyun  **/
3173*4882a593Smuzhiyun static ssize_t
lpfc_oas_lun_state_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)3174*4882a593Smuzhiyun lpfc_oas_lun_state_store(struct device *dev, struct device_attribute *attr,
3175*4882a593Smuzhiyun 			 const char *buf, size_t count)
3176*4882a593Smuzhiyun {
3177*4882a593Smuzhiyun 	struct Scsi_Host *shost = class_to_shost(dev);
3178*4882a593Smuzhiyun 	struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
3179*4882a593Smuzhiyun 	int val = 0;
3180*4882a593Smuzhiyun 
3181*4882a593Smuzhiyun 	if (!phba->cfg_fof)
3182*4882a593Smuzhiyun 		return -EPERM;
3183*4882a593Smuzhiyun 
3184*4882a593Smuzhiyun 	if (!isdigit(buf[0]))
3185*4882a593Smuzhiyun 		return -EINVAL;
3186*4882a593Smuzhiyun 
3187*4882a593Smuzhiyun 	if (sscanf(buf, "%i", &val) != 1)
3188*4882a593Smuzhiyun 		return -EINVAL;
3189*4882a593Smuzhiyun 
3190*4882a593Smuzhiyun 	if ((val != 0) && (val != 1))
3191*4882a593Smuzhiyun 		return -EINVAL;
3192*4882a593Smuzhiyun 
3193*4882a593Smuzhiyun 	phba->cfg_oas_lun_state = val;
3194*4882a593Smuzhiyun 	return strlen(buf);
3195*4882a593Smuzhiyun }
3196*4882a593Smuzhiyun static DEVICE_ATTR(lpfc_xlane_lun_state, S_IRUGO | S_IWUSR,
3197*4882a593Smuzhiyun 		   lpfc_oas_lun_state_show, lpfc_oas_lun_state_store);
3198*4882a593Smuzhiyun 
3199*4882a593Smuzhiyun /**
3200*4882a593Smuzhiyun  * lpfc_oas_lun_status_show - Return the status of the Optimized Access
3201*4882a593Smuzhiyun  *                          Storage (OAS) lun returned by the
3202*4882a593Smuzhiyun  *                          lpfc_oas_lun_show function.
3203*4882a593Smuzhiyun  * @dev: class device that is converted into a Scsi_host.
3204*4882a593Smuzhiyun  * @attr: device attribute, not used.
3205*4882a593Smuzhiyun  * @buf: buffer for passing information.
3206*4882a593Smuzhiyun  *
3207*4882a593Smuzhiyun  * Returns:
3208*4882a593Smuzhiyun  * size of formatted string.
3209*4882a593Smuzhiyun  **/
3210*4882a593Smuzhiyun static ssize_t
lpfc_oas_lun_status_show(struct device * dev,struct device_attribute * attr,char * buf)3211*4882a593Smuzhiyun lpfc_oas_lun_status_show(struct device *dev, struct device_attribute *attr,
3212*4882a593Smuzhiyun 			 char *buf)
3213*4882a593Smuzhiyun {
3214*4882a593Smuzhiyun 	struct Scsi_Host *shost = class_to_shost(dev);
3215*4882a593Smuzhiyun 	struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
3216*4882a593Smuzhiyun 
3217*4882a593Smuzhiyun 	if (!(phba->cfg_oas_flags & OAS_LUN_VALID))
3218*4882a593Smuzhiyun 		return -EFAULT;
3219*4882a593Smuzhiyun 
3220*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "%d\n", phba->cfg_oas_lun_status);
3221*4882a593Smuzhiyun }
3222*4882a593Smuzhiyun static DEVICE_ATTR(lpfc_xlane_lun_status, S_IRUGO,
3223*4882a593Smuzhiyun 		   lpfc_oas_lun_status_show, NULL);
3224*4882a593Smuzhiyun 
3225*4882a593Smuzhiyun 
3226*4882a593Smuzhiyun /**
3227*4882a593Smuzhiyun  * lpfc_oas_lun_state_set - enable or disable a lun for Optimized Access Storage
3228*4882a593Smuzhiyun  *			   (OAS) operations.
3229*4882a593Smuzhiyun  * @phba: lpfc_hba pointer.
3230*4882a593Smuzhiyun  * @ndlp: pointer to fcp target node.
3231*4882a593Smuzhiyun  * @lun: the fc lun for setting oas state.
3232*4882a593Smuzhiyun  * @oas_state: the oas state to be set to the lun.
3233*4882a593Smuzhiyun  *
3234*4882a593Smuzhiyun  * Returns:
3235*4882a593Smuzhiyun  * SUCCESS : 0
3236*4882a593Smuzhiyun  * -EPERM OAS is not enabled or not supported by this port.
3237*4882a593Smuzhiyun  *
3238*4882a593Smuzhiyun  */
3239*4882a593Smuzhiyun static size_t
lpfc_oas_lun_state_set(struct lpfc_hba * phba,uint8_t vpt_wwpn[],uint8_t tgt_wwpn[],uint64_t lun,uint32_t oas_state,uint8_t pri)3240*4882a593Smuzhiyun lpfc_oas_lun_state_set(struct lpfc_hba *phba, uint8_t vpt_wwpn[],
3241*4882a593Smuzhiyun 		       uint8_t tgt_wwpn[], uint64_t lun,
3242*4882a593Smuzhiyun 		       uint32_t oas_state, uint8_t pri)
3243*4882a593Smuzhiyun {
3244*4882a593Smuzhiyun 
3245*4882a593Smuzhiyun 	int rc = 0;
3246*4882a593Smuzhiyun 
3247*4882a593Smuzhiyun 	if (!phba->cfg_fof)
3248*4882a593Smuzhiyun 		return -EPERM;
3249*4882a593Smuzhiyun 
3250*4882a593Smuzhiyun 	if (oas_state) {
3251*4882a593Smuzhiyun 		if (!lpfc_enable_oas_lun(phba, (struct lpfc_name *)vpt_wwpn,
3252*4882a593Smuzhiyun 					 (struct lpfc_name *)tgt_wwpn,
3253*4882a593Smuzhiyun 					 lun, pri))
3254*4882a593Smuzhiyun 			rc = -ENOMEM;
3255*4882a593Smuzhiyun 	} else {
3256*4882a593Smuzhiyun 		lpfc_disable_oas_lun(phba, (struct lpfc_name *)vpt_wwpn,
3257*4882a593Smuzhiyun 				     (struct lpfc_name *)tgt_wwpn, lun, pri);
3258*4882a593Smuzhiyun 	}
3259*4882a593Smuzhiyun 	return rc;
3260*4882a593Smuzhiyun 
3261*4882a593Smuzhiyun }
3262*4882a593Smuzhiyun 
3263*4882a593Smuzhiyun /**
3264*4882a593Smuzhiyun  * lpfc_oas_lun_get_next - get the next lun that has been enabled for Optimized
3265*4882a593Smuzhiyun  *			  Access Storage (OAS) operations.
3266*4882a593Smuzhiyun  * @phba: lpfc_hba pointer.
3267*4882a593Smuzhiyun  * @vpt_wwpn: wwpn of the vport associated with the returned lun
3268*4882a593Smuzhiyun  * @tgt_wwpn: wwpn of the target associated with the returned lun
3269*4882a593Smuzhiyun  * @lun_status: status of the lun returned lun
3270*4882a593Smuzhiyun  *
3271*4882a593Smuzhiyun  * Returns the first or next lun enabled for OAS operations for the vport/target
3272*4882a593Smuzhiyun  * specified.  If a lun is found, its vport wwpn, target wwpn and status is
3273*4882a593Smuzhiyun  * returned.  If the lun is not found, NOT_OAS_ENABLED_LUN is returned.
3274*4882a593Smuzhiyun  *
3275*4882a593Smuzhiyun  * Return:
3276*4882a593Smuzhiyun  * lun that is OAS enabled for the vport/target
3277*4882a593Smuzhiyun  * NOT_OAS_ENABLED_LUN when no oas enabled lun found.
3278*4882a593Smuzhiyun  */
3279*4882a593Smuzhiyun static uint64_t
lpfc_oas_lun_get_next(struct lpfc_hba * phba,uint8_t vpt_wwpn[],uint8_t tgt_wwpn[],uint32_t * lun_status,uint32_t * lun_pri)3280*4882a593Smuzhiyun lpfc_oas_lun_get_next(struct lpfc_hba *phba, uint8_t vpt_wwpn[],
3281*4882a593Smuzhiyun 		      uint8_t tgt_wwpn[], uint32_t *lun_status,
3282*4882a593Smuzhiyun 		      uint32_t *lun_pri)
3283*4882a593Smuzhiyun {
3284*4882a593Smuzhiyun 	uint64_t found_lun;
3285*4882a593Smuzhiyun 
3286*4882a593Smuzhiyun 	if (unlikely(!phba) || !vpt_wwpn || !tgt_wwpn)
3287*4882a593Smuzhiyun 		return NOT_OAS_ENABLED_LUN;
3288*4882a593Smuzhiyun 	if (lpfc_find_next_oas_lun(phba, (struct lpfc_name *)
3289*4882a593Smuzhiyun 				   phba->sli4_hba.oas_next_vpt_wwpn,
3290*4882a593Smuzhiyun 				   (struct lpfc_name *)
3291*4882a593Smuzhiyun 				   phba->sli4_hba.oas_next_tgt_wwpn,
3292*4882a593Smuzhiyun 				   &phba->sli4_hba.oas_next_lun,
3293*4882a593Smuzhiyun 				   (struct lpfc_name *)vpt_wwpn,
3294*4882a593Smuzhiyun 				   (struct lpfc_name *)tgt_wwpn,
3295*4882a593Smuzhiyun 				   &found_lun, lun_status, lun_pri))
3296*4882a593Smuzhiyun 		return found_lun;
3297*4882a593Smuzhiyun 	else
3298*4882a593Smuzhiyun 		return NOT_OAS_ENABLED_LUN;
3299*4882a593Smuzhiyun }
3300*4882a593Smuzhiyun 
3301*4882a593Smuzhiyun /**
3302*4882a593Smuzhiyun  * lpfc_oas_lun_state_change - enable/disable a lun for OAS operations
3303*4882a593Smuzhiyun  * @phba: lpfc_hba pointer.
3304*4882a593Smuzhiyun  * @vpt_wwpn: vport wwpn by reference.
3305*4882a593Smuzhiyun  * @tgt_wwpn: target wwpn by reference.
3306*4882a593Smuzhiyun  * @lun: the fc lun for setting oas state.
3307*4882a593Smuzhiyun  * @oas_state: the oas state to be set to the oas_lun.
3308*4882a593Smuzhiyun  *
3309*4882a593Smuzhiyun  * This routine enables (OAS_LUN_ENABLE) or disables (OAS_LUN_DISABLE)
3310*4882a593Smuzhiyun  * a lun for OAS operations.
3311*4882a593Smuzhiyun  *
3312*4882a593Smuzhiyun  * Return:
3313*4882a593Smuzhiyun  * SUCCESS: 0
3314*4882a593Smuzhiyun  * -ENOMEM: failed to enable an lun for OAS operations
3315*4882a593Smuzhiyun  * -EPERM: OAS is not enabled
3316*4882a593Smuzhiyun  */
3317*4882a593Smuzhiyun static ssize_t
lpfc_oas_lun_state_change(struct lpfc_hba * phba,uint8_t vpt_wwpn[],uint8_t tgt_wwpn[],uint64_t lun,uint32_t oas_state,uint8_t pri)3318*4882a593Smuzhiyun lpfc_oas_lun_state_change(struct lpfc_hba *phba, uint8_t vpt_wwpn[],
3319*4882a593Smuzhiyun 			  uint8_t tgt_wwpn[], uint64_t lun,
3320*4882a593Smuzhiyun 			  uint32_t oas_state, uint8_t pri)
3321*4882a593Smuzhiyun {
3322*4882a593Smuzhiyun 
3323*4882a593Smuzhiyun 	int rc;
3324*4882a593Smuzhiyun 
3325*4882a593Smuzhiyun 	rc = lpfc_oas_lun_state_set(phba, vpt_wwpn, tgt_wwpn, lun,
3326*4882a593Smuzhiyun 				    oas_state, pri);
3327*4882a593Smuzhiyun 	return rc;
3328*4882a593Smuzhiyun }
3329*4882a593Smuzhiyun 
3330*4882a593Smuzhiyun /**
3331*4882a593Smuzhiyun  * lpfc_oas_lun_show - Return oas enabled luns from a chosen target
3332*4882a593Smuzhiyun  * @dev: class device that is converted into a Scsi_host.
3333*4882a593Smuzhiyun  * @attr: device attribute, not used.
3334*4882a593Smuzhiyun  * @buf: buffer for passing information.
3335*4882a593Smuzhiyun  *
3336*4882a593Smuzhiyun  * This routine returns a lun enabled for OAS each time the function
3337*4882a593Smuzhiyun  * is called.
3338*4882a593Smuzhiyun  *
3339*4882a593Smuzhiyun  * Returns:
3340*4882a593Smuzhiyun  * SUCCESS: size of formatted string.
3341*4882a593Smuzhiyun  * -EFAULT: target or vport wwpn was not set properly.
3342*4882a593Smuzhiyun  * -EPERM: oas is not enabled.
3343*4882a593Smuzhiyun  **/
3344*4882a593Smuzhiyun static ssize_t
lpfc_oas_lun_show(struct device * dev,struct device_attribute * attr,char * buf)3345*4882a593Smuzhiyun lpfc_oas_lun_show(struct device *dev, struct device_attribute *attr,
3346*4882a593Smuzhiyun 		  char *buf)
3347*4882a593Smuzhiyun {
3348*4882a593Smuzhiyun 	struct Scsi_Host *shost = class_to_shost(dev);
3349*4882a593Smuzhiyun 	struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
3350*4882a593Smuzhiyun 
3351*4882a593Smuzhiyun 	uint64_t oas_lun;
3352*4882a593Smuzhiyun 	int len = 0;
3353*4882a593Smuzhiyun 
3354*4882a593Smuzhiyun 	if (!phba->cfg_fof)
3355*4882a593Smuzhiyun 		return -EPERM;
3356*4882a593Smuzhiyun 
3357*4882a593Smuzhiyun 	if (wwn_to_u64(phba->cfg_oas_vpt_wwpn) == 0)
3358*4882a593Smuzhiyun 		if (!(phba->cfg_oas_flags & OAS_FIND_ANY_VPORT))
3359*4882a593Smuzhiyun 			return -EFAULT;
3360*4882a593Smuzhiyun 
3361*4882a593Smuzhiyun 	if (wwn_to_u64(phba->cfg_oas_tgt_wwpn) == 0)
3362*4882a593Smuzhiyun 		if (!(phba->cfg_oas_flags & OAS_FIND_ANY_TARGET))
3363*4882a593Smuzhiyun 			return -EFAULT;
3364*4882a593Smuzhiyun 
3365*4882a593Smuzhiyun 	oas_lun = lpfc_oas_lun_get_next(phba, phba->cfg_oas_vpt_wwpn,
3366*4882a593Smuzhiyun 					phba->cfg_oas_tgt_wwpn,
3367*4882a593Smuzhiyun 					&phba->cfg_oas_lun_status,
3368*4882a593Smuzhiyun 					&phba->cfg_oas_priority);
3369*4882a593Smuzhiyun 	if (oas_lun != NOT_OAS_ENABLED_LUN)
3370*4882a593Smuzhiyun 		phba->cfg_oas_flags |= OAS_LUN_VALID;
3371*4882a593Smuzhiyun 
3372*4882a593Smuzhiyun 	len += scnprintf(buf + len, PAGE_SIZE-len, "0x%llx", oas_lun);
3373*4882a593Smuzhiyun 
3374*4882a593Smuzhiyun 	return len;
3375*4882a593Smuzhiyun }
3376*4882a593Smuzhiyun 
3377*4882a593Smuzhiyun /**
3378*4882a593Smuzhiyun  * lpfc_oas_lun_store - Sets the OAS state for lun
3379*4882a593Smuzhiyun  * @dev: class device that is converted into a Scsi_host.
3380*4882a593Smuzhiyun  * @attr: device attribute, not used.
3381*4882a593Smuzhiyun  * @buf: buffer for passing information.
3382*4882a593Smuzhiyun  *
3383*4882a593Smuzhiyun  * This function sets the OAS state for lun.  Before this function is called,
3384*4882a593Smuzhiyun  * the vport wwpn, target wwpn, and oas state need to be set.
3385*4882a593Smuzhiyun  *
3386*4882a593Smuzhiyun  * Returns:
3387*4882a593Smuzhiyun  * SUCCESS: size of formatted string.
3388*4882a593Smuzhiyun  * -EFAULT: target or vport wwpn was not set properly.
3389*4882a593Smuzhiyun  * -EPERM: oas is not enabled.
3390*4882a593Smuzhiyun  * size of formatted string.
3391*4882a593Smuzhiyun  **/
3392*4882a593Smuzhiyun static ssize_t
lpfc_oas_lun_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)3393*4882a593Smuzhiyun lpfc_oas_lun_store(struct device *dev, struct device_attribute *attr,
3394*4882a593Smuzhiyun 		   const char *buf, size_t count)
3395*4882a593Smuzhiyun {
3396*4882a593Smuzhiyun 	struct Scsi_Host *shost = class_to_shost(dev);
3397*4882a593Smuzhiyun 	struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
3398*4882a593Smuzhiyun 	uint64_t scsi_lun;
3399*4882a593Smuzhiyun 	uint32_t pri;
3400*4882a593Smuzhiyun 	ssize_t rc;
3401*4882a593Smuzhiyun 
3402*4882a593Smuzhiyun 	if (!phba->cfg_fof)
3403*4882a593Smuzhiyun 		return -EPERM;
3404*4882a593Smuzhiyun 
3405*4882a593Smuzhiyun 	if (wwn_to_u64(phba->cfg_oas_vpt_wwpn) == 0)
3406*4882a593Smuzhiyun 		return -EFAULT;
3407*4882a593Smuzhiyun 
3408*4882a593Smuzhiyun 	if (wwn_to_u64(phba->cfg_oas_tgt_wwpn) == 0)
3409*4882a593Smuzhiyun 		return -EFAULT;
3410*4882a593Smuzhiyun 
3411*4882a593Smuzhiyun 	if (!isdigit(buf[0]))
3412*4882a593Smuzhiyun 		return -EINVAL;
3413*4882a593Smuzhiyun 
3414*4882a593Smuzhiyun 	if (sscanf(buf, "0x%llx", &scsi_lun) != 1)
3415*4882a593Smuzhiyun 		return -EINVAL;
3416*4882a593Smuzhiyun 
3417*4882a593Smuzhiyun 	pri = phba->cfg_oas_priority;
3418*4882a593Smuzhiyun 	if (pri == 0)
3419*4882a593Smuzhiyun 		pri = phba->cfg_XLanePriority;
3420*4882a593Smuzhiyun 
3421*4882a593Smuzhiyun 	lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
3422*4882a593Smuzhiyun 			"3372 Try to set vport 0x%llx target 0x%llx lun:0x%llx "
3423*4882a593Smuzhiyun 			"priority 0x%x with oas state %d\n",
3424*4882a593Smuzhiyun 			wwn_to_u64(phba->cfg_oas_vpt_wwpn),
3425*4882a593Smuzhiyun 			wwn_to_u64(phba->cfg_oas_tgt_wwpn), scsi_lun,
3426*4882a593Smuzhiyun 			pri, phba->cfg_oas_lun_state);
3427*4882a593Smuzhiyun 
3428*4882a593Smuzhiyun 	rc = lpfc_oas_lun_state_change(phba, phba->cfg_oas_vpt_wwpn,
3429*4882a593Smuzhiyun 				       phba->cfg_oas_tgt_wwpn, scsi_lun,
3430*4882a593Smuzhiyun 				       phba->cfg_oas_lun_state, pri);
3431*4882a593Smuzhiyun 	if (rc)
3432*4882a593Smuzhiyun 		return rc;
3433*4882a593Smuzhiyun 
3434*4882a593Smuzhiyun 	return count;
3435*4882a593Smuzhiyun }
3436*4882a593Smuzhiyun static DEVICE_ATTR(lpfc_xlane_lun, S_IRUGO | S_IWUSR,
3437*4882a593Smuzhiyun 		   lpfc_oas_lun_show, lpfc_oas_lun_store);
3438*4882a593Smuzhiyun 
3439*4882a593Smuzhiyun int lpfc_enable_nvmet_cnt;
3440*4882a593Smuzhiyun unsigned long long lpfc_enable_nvmet[LPFC_NVMET_MAX_PORTS] = {
3441*4882a593Smuzhiyun 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3442*4882a593Smuzhiyun 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
3443*4882a593Smuzhiyun module_param_array(lpfc_enable_nvmet, ullong, &lpfc_enable_nvmet_cnt, 0444);
3444*4882a593Smuzhiyun MODULE_PARM_DESC(lpfc_enable_nvmet, "Enable HBA port(s) WWPN as a NVME Target");
3445*4882a593Smuzhiyun 
3446*4882a593Smuzhiyun static int lpfc_poll = 0;
3447*4882a593Smuzhiyun module_param(lpfc_poll, int, S_IRUGO);
3448*4882a593Smuzhiyun MODULE_PARM_DESC(lpfc_poll, "FCP ring polling mode control:"
3449*4882a593Smuzhiyun 		 " 0 - none,"
3450*4882a593Smuzhiyun 		 " 1 - poll with interrupts enabled"
3451*4882a593Smuzhiyun 		 " 3 - poll and disable FCP ring interrupts");
3452*4882a593Smuzhiyun 
3453*4882a593Smuzhiyun static DEVICE_ATTR_RW(lpfc_poll);
3454*4882a593Smuzhiyun 
3455*4882a593Smuzhiyun int lpfc_no_hba_reset_cnt;
3456*4882a593Smuzhiyun unsigned long lpfc_no_hba_reset[MAX_HBAS_NO_RESET] = {
3457*4882a593Smuzhiyun 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
3458*4882a593Smuzhiyun module_param_array(lpfc_no_hba_reset, ulong, &lpfc_no_hba_reset_cnt, 0444);
3459*4882a593Smuzhiyun MODULE_PARM_DESC(lpfc_no_hba_reset, "WWPN of HBAs that should not be reset");
3460*4882a593Smuzhiyun 
3461*4882a593Smuzhiyun LPFC_ATTR(sli_mode, 0, 0, 3,
3462*4882a593Smuzhiyun 	"SLI mode selector:"
3463*4882a593Smuzhiyun 	" 0 - auto (SLI-3 if supported),"
3464*4882a593Smuzhiyun 	" 2 - select SLI-2 even on SLI-3 capable HBAs,"
3465*4882a593Smuzhiyun 	" 3 - select SLI-3");
3466*4882a593Smuzhiyun 
3467*4882a593Smuzhiyun LPFC_ATTR_R(enable_npiv, 1, 0, 1,
3468*4882a593Smuzhiyun 	"Enable NPIV functionality");
3469*4882a593Smuzhiyun 
3470*4882a593Smuzhiyun LPFC_ATTR_R(fcf_failover_policy, 1, 1, 2,
3471*4882a593Smuzhiyun 	"FCF Fast failover=1 Priority failover=2");
3472*4882a593Smuzhiyun 
3473*4882a593Smuzhiyun /*
3474*4882a593Smuzhiyun # lpfc_enable_rrq: Track XRI/OXID reuse after IO failures
3475*4882a593Smuzhiyun #	0x0 = disabled, XRI/OXID use not tracked.
3476*4882a593Smuzhiyun #	0x1 = XRI/OXID reuse is timed with ratov, RRQ sent.
3477*4882a593Smuzhiyun #	0x2 = XRI/OXID reuse is timed with ratov, No RRQ sent.
3478*4882a593Smuzhiyun */
3479*4882a593Smuzhiyun LPFC_ATTR_R(enable_rrq, 2, 0, 2,
3480*4882a593Smuzhiyun 	"Enable RRQ functionality");
3481*4882a593Smuzhiyun 
3482*4882a593Smuzhiyun /*
3483*4882a593Smuzhiyun # lpfc_suppress_link_up:  Bring link up at initialization
3484*4882a593Smuzhiyun #            0x0  = bring link up (issue MBX_INIT_LINK)
3485*4882a593Smuzhiyun #            0x1  = do NOT bring link up at initialization(MBX_INIT_LINK)
3486*4882a593Smuzhiyun #            0x2  = never bring up link
3487*4882a593Smuzhiyun # Default value is 0.
3488*4882a593Smuzhiyun */
3489*4882a593Smuzhiyun LPFC_ATTR_R(suppress_link_up, LPFC_INITIALIZE_LINK, LPFC_INITIALIZE_LINK,
3490*4882a593Smuzhiyun 		LPFC_DELAY_INIT_LINK_INDEFINITELY,
3491*4882a593Smuzhiyun 		"Suppress Link Up at initialization");
3492*4882a593Smuzhiyun 
3493*4882a593Smuzhiyun static ssize_t
lpfc_pls_show(struct device * dev,struct device_attribute * attr,char * buf)3494*4882a593Smuzhiyun lpfc_pls_show(struct device *dev, struct device_attribute *attr, char *buf)
3495*4882a593Smuzhiyun {
3496*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
3497*4882a593Smuzhiyun 	struct lpfc_hba   *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
3498*4882a593Smuzhiyun 
3499*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "%d\n",
3500*4882a593Smuzhiyun 			 phba->sli4_hba.pc_sli4_params.pls);
3501*4882a593Smuzhiyun }
3502*4882a593Smuzhiyun static DEVICE_ATTR(pls, 0444,
3503*4882a593Smuzhiyun 			 lpfc_pls_show, NULL);
3504*4882a593Smuzhiyun 
3505*4882a593Smuzhiyun static ssize_t
lpfc_pt_show(struct device * dev,struct device_attribute * attr,char * buf)3506*4882a593Smuzhiyun lpfc_pt_show(struct device *dev, struct device_attribute *attr, char *buf)
3507*4882a593Smuzhiyun {
3508*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
3509*4882a593Smuzhiyun 	struct lpfc_hba   *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
3510*4882a593Smuzhiyun 
3511*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "%d\n",
3512*4882a593Smuzhiyun 			 (phba->hba_flag & HBA_PERSISTENT_TOPO) ? 1 : 0);
3513*4882a593Smuzhiyun }
3514*4882a593Smuzhiyun static DEVICE_ATTR(pt, 0444,
3515*4882a593Smuzhiyun 			 lpfc_pt_show, NULL);
3516*4882a593Smuzhiyun 
3517*4882a593Smuzhiyun /*
3518*4882a593Smuzhiyun # lpfc_cnt: Number of IOCBs allocated for ELS, CT, and ABTS
3519*4882a593Smuzhiyun #       1 - (1024)
3520*4882a593Smuzhiyun #       2 - (2048)
3521*4882a593Smuzhiyun #       3 - (3072)
3522*4882a593Smuzhiyun #       4 - (4096)
3523*4882a593Smuzhiyun #       5 - (5120)
3524*4882a593Smuzhiyun */
3525*4882a593Smuzhiyun static ssize_t
lpfc_iocb_hw_show(struct device * dev,struct device_attribute * attr,char * buf)3526*4882a593Smuzhiyun lpfc_iocb_hw_show(struct device *dev, struct device_attribute *attr, char *buf)
3527*4882a593Smuzhiyun {
3528*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
3529*4882a593Smuzhiyun 	struct lpfc_hba   *phba = ((struct lpfc_vport *) shost->hostdata)->phba;
3530*4882a593Smuzhiyun 
3531*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "%d\n", phba->iocb_max);
3532*4882a593Smuzhiyun }
3533*4882a593Smuzhiyun 
3534*4882a593Smuzhiyun static DEVICE_ATTR(iocb_hw, S_IRUGO,
3535*4882a593Smuzhiyun 			 lpfc_iocb_hw_show, NULL);
3536*4882a593Smuzhiyun static ssize_t
lpfc_txq_hw_show(struct device * dev,struct device_attribute * attr,char * buf)3537*4882a593Smuzhiyun lpfc_txq_hw_show(struct device *dev, struct device_attribute *attr, char *buf)
3538*4882a593Smuzhiyun {
3539*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
3540*4882a593Smuzhiyun 	struct lpfc_hba   *phba = ((struct lpfc_vport *) shost->hostdata)->phba;
3541*4882a593Smuzhiyun 	struct lpfc_sli_ring *pring = lpfc_phba_elsring(phba);
3542*4882a593Smuzhiyun 
3543*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "%d\n",
3544*4882a593Smuzhiyun 			pring ? pring->txq_max : 0);
3545*4882a593Smuzhiyun }
3546*4882a593Smuzhiyun 
3547*4882a593Smuzhiyun static DEVICE_ATTR(txq_hw, S_IRUGO,
3548*4882a593Smuzhiyun 			 lpfc_txq_hw_show, NULL);
3549*4882a593Smuzhiyun static ssize_t
lpfc_txcmplq_hw_show(struct device * dev,struct device_attribute * attr,char * buf)3550*4882a593Smuzhiyun lpfc_txcmplq_hw_show(struct device *dev, struct device_attribute *attr,
3551*4882a593Smuzhiyun  char *buf)
3552*4882a593Smuzhiyun {
3553*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
3554*4882a593Smuzhiyun 	struct lpfc_hba   *phba = ((struct lpfc_vport *) shost->hostdata)->phba;
3555*4882a593Smuzhiyun 	struct lpfc_sli_ring *pring = lpfc_phba_elsring(phba);
3556*4882a593Smuzhiyun 
3557*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "%d\n",
3558*4882a593Smuzhiyun 			pring ? pring->txcmplq_max : 0);
3559*4882a593Smuzhiyun }
3560*4882a593Smuzhiyun 
3561*4882a593Smuzhiyun static DEVICE_ATTR(txcmplq_hw, S_IRUGO,
3562*4882a593Smuzhiyun 			 lpfc_txcmplq_hw_show, NULL);
3563*4882a593Smuzhiyun 
3564*4882a593Smuzhiyun /*
3565*4882a593Smuzhiyun # lpfc_nodev_tmo: If set, it will hold all I/O errors on devices that disappear
3566*4882a593Smuzhiyun # until the timer expires. Value range is [0,255]. Default value is 30.
3567*4882a593Smuzhiyun */
3568*4882a593Smuzhiyun static int lpfc_nodev_tmo = LPFC_DEF_DEVLOSS_TMO;
3569*4882a593Smuzhiyun static int lpfc_devloss_tmo = LPFC_DEF_DEVLOSS_TMO;
3570*4882a593Smuzhiyun module_param(lpfc_nodev_tmo, int, 0);
3571*4882a593Smuzhiyun MODULE_PARM_DESC(lpfc_nodev_tmo,
3572*4882a593Smuzhiyun 		 "Seconds driver will hold I/O waiting "
3573*4882a593Smuzhiyun 		 "for a device to come back");
3574*4882a593Smuzhiyun 
3575*4882a593Smuzhiyun /**
3576*4882a593Smuzhiyun  * lpfc_nodev_tmo_show - Return the hba dev loss timeout value
3577*4882a593Smuzhiyun  * @dev: class converted to a Scsi_host structure.
3578*4882a593Smuzhiyun  * @attr: device attribute, not used.
3579*4882a593Smuzhiyun  * @buf: on return contains the dev loss timeout in decimal.
3580*4882a593Smuzhiyun  *
3581*4882a593Smuzhiyun  * Returns: size of formatted string.
3582*4882a593Smuzhiyun  **/
3583*4882a593Smuzhiyun static ssize_t
lpfc_nodev_tmo_show(struct device * dev,struct device_attribute * attr,char * buf)3584*4882a593Smuzhiyun lpfc_nodev_tmo_show(struct device *dev, struct device_attribute *attr,
3585*4882a593Smuzhiyun 		    char *buf)
3586*4882a593Smuzhiyun {
3587*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
3588*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
3589*4882a593Smuzhiyun 
3590*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "%d\n",	vport->cfg_devloss_tmo);
3591*4882a593Smuzhiyun }
3592*4882a593Smuzhiyun 
3593*4882a593Smuzhiyun /**
3594*4882a593Smuzhiyun  * lpfc_nodev_tmo_init - Set the hba nodev timeout value
3595*4882a593Smuzhiyun  * @vport: lpfc vport structure pointer.
3596*4882a593Smuzhiyun  * @val: contains the nodev timeout value.
3597*4882a593Smuzhiyun  *
3598*4882a593Smuzhiyun  * Description:
3599*4882a593Smuzhiyun  * If the devloss tmo is already set then nodev tmo is set to devloss tmo,
3600*4882a593Smuzhiyun  * a kernel error message is printed and zero is returned.
3601*4882a593Smuzhiyun  * Else if val is in range then nodev tmo and devloss tmo are set to val.
3602*4882a593Smuzhiyun  * Otherwise nodev tmo is set to the default value.
3603*4882a593Smuzhiyun  *
3604*4882a593Smuzhiyun  * Returns:
3605*4882a593Smuzhiyun  * zero if already set or if val is in range
3606*4882a593Smuzhiyun  * -EINVAL val out of range
3607*4882a593Smuzhiyun  **/
3608*4882a593Smuzhiyun static int
lpfc_nodev_tmo_init(struct lpfc_vport * vport,int val)3609*4882a593Smuzhiyun lpfc_nodev_tmo_init(struct lpfc_vport *vport, int val)
3610*4882a593Smuzhiyun {
3611*4882a593Smuzhiyun 	if (vport->cfg_devloss_tmo != LPFC_DEF_DEVLOSS_TMO) {
3612*4882a593Smuzhiyun 		vport->cfg_nodev_tmo = vport->cfg_devloss_tmo;
3613*4882a593Smuzhiyun 		if (val != LPFC_DEF_DEVLOSS_TMO)
3614*4882a593Smuzhiyun 			lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
3615*4882a593Smuzhiyun 					 "0407 Ignoring lpfc_nodev_tmo module "
3616*4882a593Smuzhiyun 					 "parameter because lpfc_devloss_tmo "
3617*4882a593Smuzhiyun 					 "is set.\n");
3618*4882a593Smuzhiyun 		return 0;
3619*4882a593Smuzhiyun 	}
3620*4882a593Smuzhiyun 
3621*4882a593Smuzhiyun 	if (val >= LPFC_MIN_DEVLOSS_TMO && val <= LPFC_MAX_DEVLOSS_TMO) {
3622*4882a593Smuzhiyun 		vport->cfg_nodev_tmo = val;
3623*4882a593Smuzhiyun 		vport->cfg_devloss_tmo = val;
3624*4882a593Smuzhiyun 		return 0;
3625*4882a593Smuzhiyun 	}
3626*4882a593Smuzhiyun 	lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
3627*4882a593Smuzhiyun 			 "0400 lpfc_nodev_tmo attribute cannot be set to"
3628*4882a593Smuzhiyun 			 " %d, allowed range is [%d, %d]\n",
3629*4882a593Smuzhiyun 			 val, LPFC_MIN_DEVLOSS_TMO, LPFC_MAX_DEVLOSS_TMO);
3630*4882a593Smuzhiyun 	vport->cfg_nodev_tmo = LPFC_DEF_DEVLOSS_TMO;
3631*4882a593Smuzhiyun 	return -EINVAL;
3632*4882a593Smuzhiyun }
3633*4882a593Smuzhiyun 
3634*4882a593Smuzhiyun /**
3635*4882a593Smuzhiyun  * lpfc_update_rport_devloss_tmo - Update dev loss tmo value
3636*4882a593Smuzhiyun  * @vport: lpfc vport structure pointer.
3637*4882a593Smuzhiyun  *
3638*4882a593Smuzhiyun  * Description:
3639*4882a593Smuzhiyun  * Update all the ndlp's dev loss tmo with the vport devloss tmo value.
3640*4882a593Smuzhiyun  **/
3641*4882a593Smuzhiyun static void
lpfc_update_rport_devloss_tmo(struct lpfc_vport * vport)3642*4882a593Smuzhiyun lpfc_update_rport_devloss_tmo(struct lpfc_vport *vport)
3643*4882a593Smuzhiyun {
3644*4882a593Smuzhiyun 	struct Scsi_Host  *shost;
3645*4882a593Smuzhiyun 	struct lpfc_nodelist  *ndlp;
3646*4882a593Smuzhiyun #if (IS_ENABLED(CONFIG_NVME_FC))
3647*4882a593Smuzhiyun 	struct lpfc_nvme_rport *rport;
3648*4882a593Smuzhiyun 	struct nvme_fc_remote_port *remoteport = NULL;
3649*4882a593Smuzhiyun #endif
3650*4882a593Smuzhiyun 
3651*4882a593Smuzhiyun 	shost = lpfc_shost_from_vport(vport);
3652*4882a593Smuzhiyun 	spin_lock_irq(shost->host_lock);
3653*4882a593Smuzhiyun 	list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
3654*4882a593Smuzhiyun 		if (!NLP_CHK_NODE_ACT(ndlp))
3655*4882a593Smuzhiyun 			continue;
3656*4882a593Smuzhiyun 		if (ndlp->rport)
3657*4882a593Smuzhiyun 			ndlp->rport->dev_loss_tmo = vport->cfg_devloss_tmo;
3658*4882a593Smuzhiyun #if (IS_ENABLED(CONFIG_NVME_FC))
3659*4882a593Smuzhiyun 		spin_lock(&vport->phba->hbalock);
3660*4882a593Smuzhiyun 		rport = lpfc_ndlp_get_nrport(ndlp);
3661*4882a593Smuzhiyun 		if (rport)
3662*4882a593Smuzhiyun 			remoteport = rport->remoteport;
3663*4882a593Smuzhiyun 		spin_unlock(&vport->phba->hbalock);
3664*4882a593Smuzhiyun 		if (rport && remoteport)
3665*4882a593Smuzhiyun 			nvme_fc_set_remoteport_devloss(remoteport,
3666*4882a593Smuzhiyun 						       vport->cfg_devloss_tmo);
3667*4882a593Smuzhiyun #endif
3668*4882a593Smuzhiyun 	}
3669*4882a593Smuzhiyun 	spin_unlock_irq(shost->host_lock);
3670*4882a593Smuzhiyun }
3671*4882a593Smuzhiyun 
3672*4882a593Smuzhiyun /**
3673*4882a593Smuzhiyun  * lpfc_nodev_tmo_set - Set the vport nodev tmo and devloss tmo values
3674*4882a593Smuzhiyun  * @vport: lpfc vport structure pointer.
3675*4882a593Smuzhiyun  * @val: contains the tmo value.
3676*4882a593Smuzhiyun  *
3677*4882a593Smuzhiyun  * Description:
3678*4882a593Smuzhiyun  * If the devloss tmo is already set or the vport dev loss tmo has changed
3679*4882a593Smuzhiyun  * then a kernel error message is printed and zero is returned.
3680*4882a593Smuzhiyun  * Else if val is in range then nodev tmo and devloss tmo are set to val.
3681*4882a593Smuzhiyun  * Otherwise nodev tmo is set to the default value.
3682*4882a593Smuzhiyun  *
3683*4882a593Smuzhiyun  * Returns:
3684*4882a593Smuzhiyun  * zero if already set or if val is in range
3685*4882a593Smuzhiyun  * -EINVAL val out of range
3686*4882a593Smuzhiyun  **/
3687*4882a593Smuzhiyun static int
lpfc_nodev_tmo_set(struct lpfc_vport * vport,int val)3688*4882a593Smuzhiyun lpfc_nodev_tmo_set(struct lpfc_vport *vport, int val)
3689*4882a593Smuzhiyun {
3690*4882a593Smuzhiyun 	if (vport->dev_loss_tmo_changed ||
3691*4882a593Smuzhiyun 	    (lpfc_devloss_tmo != LPFC_DEF_DEVLOSS_TMO)) {
3692*4882a593Smuzhiyun 		lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
3693*4882a593Smuzhiyun 				 "0401 Ignoring change to lpfc_nodev_tmo "
3694*4882a593Smuzhiyun 				 "because lpfc_devloss_tmo is set.\n");
3695*4882a593Smuzhiyun 		return 0;
3696*4882a593Smuzhiyun 	}
3697*4882a593Smuzhiyun 	if (val >= LPFC_MIN_DEVLOSS_TMO && val <= LPFC_MAX_DEVLOSS_TMO) {
3698*4882a593Smuzhiyun 		vport->cfg_nodev_tmo = val;
3699*4882a593Smuzhiyun 		vport->cfg_devloss_tmo = val;
3700*4882a593Smuzhiyun 		/*
3701*4882a593Smuzhiyun 		 * For compat: set the fc_host dev loss so new rports
3702*4882a593Smuzhiyun 		 * will get the value.
3703*4882a593Smuzhiyun 		 */
3704*4882a593Smuzhiyun 		fc_host_dev_loss_tmo(lpfc_shost_from_vport(vport)) = val;
3705*4882a593Smuzhiyun 		lpfc_update_rport_devloss_tmo(vport);
3706*4882a593Smuzhiyun 		return 0;
3707*4882a593Smuzhiyun 	}
3708*4882a593Smuzhiyun 	lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
3709*4882a593Smuzhiyun 			 "0403 lpfc_nodev_tmo attribute cannot be set to "
3710*4882a593Smuzhiyun 			 "%d, allowed range is [%d, %d]\n",
3711*4882a593Smuzhiyun 			 val, LPFC_MIN_DEVLOSS_TMO, LPFC_MAX_DEVLOSS_TMO);
3712*4882a593Smuzhiyun 	return -EINVAL;
3713*4882a593Smuzhiyun }
3714*4882a593Smuzhiyun 
3715*4882a593Smuzhiyun lpfc_vport_param_store(nodev_tmo)
3716*4882a593Smuzhiyun 
3717*4882a593Smuzhiyun static DEVICE_ATTR_RW(lpfc_nodev_tmo);
3718*4882a593Smuzhiyun 
3719*4882a593Smuzhiyun /*
3720*4882a593Smuzhiyun # lpfc_devloss_tmo: If set, it will hold all I/O errors on devices that
3721*4882a593Smuzhiyun # disappear until the timer expires. Value range is [0,255]. Default
3722*4882a593Smuzhiyun # value is 30.
3723*4882a593Smuzhiyun */
3724*4882a593Smuzhiyun module_param(lpfc_devloss_tmo, int, S_IRUGO);
3725*4882a593Smuzhiyun MODULE_PARM_DESC(lpfc_devloss_tmo,
3726*4882a593Smuzhiyun 		 "Seconds driver will hold I/O waiting "
3727*4882a593Smuzhiyun 		 "for a device to come back");
lpfc_vport_param_init(devloss_tmo,LPFC_DEF_DEVLOSS_TMO,LPFC_MIN_DEVLOSS_TMO,LPFC_MAX_DEVLOSS_TMO)3728*4882a593Smuzhiyun lpfc_vport_param_init(devloss_tmo, LPFC_DEF_DEVLOSS_TMO,
3729*4882a593Smuzhiyun 		      LPFC_MIN_DEVLOSS_TMO, LPFC_MAX_DEVLOSS_TMO)
3730*4882a593Smuzhiyun lpfc_vport_param_show(devloss_tmo)
3731*4882a593Smuzhiyun 
3732*4882a593Smuzhiyun /**
3733*4882a593Smuzhiyun  * lpfc_devloss_tmo_set - Sets vport nodev tmo, devloss tmo values, changed bit
3734*4882a593Smuzhiyun  * @vport: lpfc vport structure pointer.
3735*4882a593Smuzhiyun  * @val: contains the tmo value.
3736*4882a593Smuzhiyun  *
3737*4882a593Smuzhiyun  * Description:
3738*4882a593Smuzhiyun  * If val is in a valid range then set the vport nodev tmo,
3739*4882a593Smuzhiyun  * devloss tmo, also set the vport dev loss tmo changed flag.
3740*4882a593Smuzhiyun  * Else a kernel error message is printed.
3741*4882a593Smuzhiyun  *
3742*4882a593Smuzhiyun  * Returns:
3743*4882a593Smuzhiyun  * zero if val is in range
3744*4882a593Smuzhiyun  * -EINVAL val out of range
3745*4882a593Smuzhiyun  **/
3746*4882a593Smuzhiyun static int
3747*4882a593Smuzhiyun lpfc_devloss_tmo_set(struct lpfc_vport *vport, int val)
3748*4882a593Smuzhiyun {
3749*4882a593Smuzhiyun 	if (val >= LPFC_MIN_DEVLOSS_TMO && val <= LPFC_MAX_DEVLOSS_TMO) {
3750*4882a593Smuzhiyun 		vport->cfg_nodev_tmo = val;
3751*4882a593Smuzhiyun 		vport->cfg_devloss_tmo = val;
3752*4882a593Smuzhiyun 		vport->dev_loss_tmo_changed = 1;
3753*4882a593Smuzhiyun 		fc_host_dev_loss_tmo(lpfc_shost_from_vport(vport)) = val;
3754*4882a593Smuzhiyun 		lpfc_update_rport_devloss_tmo(vport);
3755*4882a593Smuzhiyun 		return 0;
3756*4882a593Smuzhiyun 	}
3757*4882a593Smuzhiyun 
3758*4882a593Smuzhiyun 	lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
3759*4882a593Smuzhiyun 			 "0404 lpfc_devloss_tmo attribute cannot be set to "
3760*4882a593Smuzhiyun 			 "%d, allowed range is [%d, %d]\n",
3761*4882a593Smuzhiyun 			 val, LPFC_MIN_DEVLOSS_TMO, LPFC_MAX_DEVLOSS_TMO);
3762*4882a593Smuzhiyun 	return -EINVAL;
3763*4882a593Smuzhiyun }
3764*4882a593Smuzhiyun 
3765*4882a593Smuzhiyun lpfc_vport_param_store(devloss_tmo)
3766*4882a593Smuzhiyun static DEVICE_ATTR_RW(lpfc_devloss_tmo);
3767*4882a593Smuzhiyun 
3768*4882a593Smuzhiyun /*
3769*4882a593Smuzhiyun  * lpfc_suppress_rsp: Enable suppress rsp feature is firmware supports it
3770*4882a593Smuzhiyun  * lpfc_suppress_rsp = 0  Disable
3771*4882a593Smuzhiyun  * lpfc_suppress_rsp = 1  Enable (default)
3772*4882a593Smuzhiyun  *
3773*4882a593Smuzhiyun  */
3774*4882a593Smuzhiyun LPFC_ATTR_R(suppress_rsp, 1, 0, 1,
3775*4882a593Smuzhiyun 	    "Enable suppress rsp feature is firmware supports it");
3776*4882a593Smuzhiyun 
3777*4882a593Smuzhiyun /*
3778*4882a593Smuzhiyun  * lpfc_nvmet_mrq: Specify number of RQ pairs for processing NVMET cmds
3779*4882a593Smuzhiyun  * lpfc_nvmet_mrq = 0  driver will calcualte optimal number of RQ pairs
3780*4882a593Smuzhiyun  * lpfc_nvmet_mrq = 1  use a single RQ pair
3781*4882a593Smuzhiyun  * lpfc_nvmet_mrq >= 2  use specified RQ pairs for MRQ
3782*4882a593Smuzhiyun  *
3783*4882a593Smuzhiyun  */
3784*4882a593Smuzhiyun LPFC_ATTR_R(nvmet_mrq,
3785*4882a593Smuzhiyun 	    LPFC_NVMET_MRQ_AUTO, LPFC_NVMET_MRQ_AUTO, LPFC_NVMET_MRQ_MAX,
3786*4882a593Smuzhiyun 	    "Specify number of RQ pairs for processing NVMET cmds");
3787*4882a593Smuzhiyun 
3788*4882a593Smuzhiyun /*
3789*4882a593Smuzhiyun  * lpfc_nvmet_mrq_post: Specify number of RQ buffer to initially post
3790*4882a593Smuzhiyun  * to each NVMET RQ. Range 64 to 2048, default is 512.
3791*4882a593Smuzhiyun  */
3792*4882a593Smuzhiyun LPFC_ATTR_R(nvmet_mrq_post,
3793*4882a593Smuzhiyun 	    LPFC_NVMET_RQE_DEF_POST, LPFC_NVMET_RQE_MIN_POST,
3794*4882a593Smuzhiyun 	    LPFC_NVMET_RQE_DEF_COUNT,
3795*4882a593Smuzhiyun 	    "Specify number of RQ buffers to initially post");
3796*4882a593Smuzhiyun 
3797*4882a593Smuzhiyun /*
3798*4882a593Smuzhiyun  * lpfc_enable_fc4_type: Defines what FC4 types are supported.
3799*4882a593Smuzhiyun  * Supported Values:  1 - register just FCP
3800*4882a593Smuzhiyun  *                    3 - register both FCP and NVME
3801*4882a593Smuzhiyun  * Supported values are [1,3]. Default value is 3
3802*4882a593Smuzhiyun  */
3803*4882a593Smuzhiyun LPFC_ATTR_R(enable_fc4_type, LPFC_DEF_ENBL_FC4_TYPE,
3804*4882a593Smuzhiyun 	    LPFC_ENABLE_FCP, LPFC_MAX_ENBL_FC4_TYPE,
3805*4882a593Smuzhiyun 	    "Enable FC4 Protocol support - FCP / NVME");
3806*4882a593Smuzhiyun 
3807*4882a593Smuzhiyun /*
3808*4882a593Smuzhiyun # lpfc_log_verbose: Only turn this flag on if you are willing to risk being
3809*4882a593Smuzhiyun # deluged with LOTS of information.
3810*4882a593Smuzhiyun # You can set a bit mask to record specific types of verbose messages:
3811*4882a593Smuzhiyun # See lpfc_logmsh.h for definitions.
3812*4882a593Smuzhiyun */
3813*4882a593Smuzhiyun LPFC_VPORT_ATTR_HEX_RW(log_verbose, 0x0, 0x0, 0xffffffff,
3814*4882a593Smuzhiyun 		       "Verbose logging bit-mask");
3815*4882a593Smuzhiyun 
3816*4882a593Smuzhiyun /*
3817*4882a593Smuzhiyun # lpfc_enable_da_id: This turns on the DA_ID CT command that deregisters
3818*4882a593Smuzhiyun # objects that have been registered with the nameserver after login.
3819*4882a593Smuzhiyun */
3820*4882a593Smuzhiyun LPFC_VPORT_ATTR_R(enable_da_id, 1, 0, 1,
3821*4882a593Smuzhiyun 		  "Deregister nameserver objects before LOGO");
3822*4882a593Smuzhiyun 
3823*4882a593Smuzhiyun /*
3824*4882a593Smuzhiyun # lun_queue_depth:  This parameter is used to limit the number of outstanding
3825*4882a593Smuzhiyun # commands per FCP LUN.
3826*4882a593Smuzhiyun */
3827*4882a593Smuzhiyun LPFC_VPORT_ATTR_R(lun_queue_depth, 64, 1, 512,
3828*4882a593Smuzhiyun 		  "Max number of FCP commands we can queue to a specific LUN");
3829*4882a593Smuzhiyun 
3830*4882a593Smuzhiyun /*
3831*4882a593Smuzhiyun # tgt_queue_depth:  This parameter is used to limit the number of outstanding
3832*4882a593Smuzhiyun # commands per target port. Value range is [10,65535]. Default value is 65535.
3833*4882a593Smuzhiyun */
3834*4882a593Smuzhiyun static uint lpfc_tgt_queue_depth = LPFC_MAX_TGT_QDEPTH;
3835*4882a593Smuzhiyun module_param(lpfc_tgt_queue_depth, uint, 0444);
3836*4882a593Smuzhiyun MODULE_PARM_DESC(lpfc_tgt_queue_depth, "Set max Target queue depth");
3837*4882a593Smuzhiyun lpfc_vport_param_show(tgt_queue_depth);
3838*4882a593Smuzhiyun lpfc_vport_param_init(tgt_queue_depth, LPFC_MAX_TGT_QDEPTH,
3839*4882a593Smuzhiyun 		      LPFC_MIN_TGT_QDEPTH, LPFC_MAX_TGT_QDEPTH);
3840*4882a593Smuzhiyun 
3841*4882a593Smuzhiyun /**
3842*4882a593Smuzhiyun  * lpfc_tgt_queue_depth_store: Sets an attribute value.
3843*4882a593Smuzhiyun  * @phba: pointer the the adapter structure.
3844*4882a593Smuzhiyun  * @val: integer attribute value.
3845*4882a593Smuzhiyun  *
3846*4882a593Smuzhiyun  * Description: Sets the parameter to the new value.
3847*4882a593Smuzhiyun  *
3848*4882a593Smuzhiyun  * Returns:
3849*4882a593Smuzhiyun  * zero on success
3850*4882a593Smuzhiyun  * -EINVAL if val is invalid
3851*4882a593Smuzhiyun  */
3852*4882a593Smuzhiyun static int
lpfc_tgt_queue_depth_set(struct lpfc_vport * vport,uint val)3853*4882a593Smuzhiyun lpfc_tgt_queue_depth_set(struct lpfc_vport *vport, uint val)
3854*4882a593Smuzhiyun {
3855*4882a593Smuzhiyun 	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
3856*4882a593Smuzhiyun 	struct lpfc_nodelist *ndlp;
3857*4882a593Smuzhiyun 
3858*4882a593Smuzhiyun 	if (!lpfc_rangecheck(val, LPFC_MIN_TGT_QDEPTH, LPFC_MAX_TGT_QDEPTH))
3859*4882a593Smuzhiyun 		return -EINVAL;
3860*4882a593Smuzhiyun 
3861*4882a593Smuzhiyun 	if (val == vport->cfg_tgt_queue_depth)
3862*4882a593Smuzhiyun 		return 0;
3863*4882a593Smuzhiyun 
3864*4882a593Smuzhiyun 	spin_lock_irq(shost->host_lock);
3865*4882a593Smuzhiyun 	vport->cfg_tgt_queue_depth = val;
3866*4882a593Smuzhiyun 
3867*4882a593Smuzhiyun 	/* Next loop thru nodelist and change cmd_qdepth */
3868*4882a593Smuzhiyun 	list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp)
3869*4882a593Smuzhiyun 		ndlp->cmd_qdepth = vport->cfg_tgt_queue_depth;
3870*4882a593Smuzhiyun 
3871*4882a593Smuzhiyun 	spin_unlock_irq(shost->host_lock);
3872*4882a593Smuzhiyun 	return 0;
3873*4882a593Smuzhiyun }
3874*4882a593Smuzhiyun 
3875*4882a593Smuzhiyun lpfc_vport_param_store(tgt_queue_depth);
3876*4882a593Smuzhiyun static DEVICE_ATTR_RW(lpfc_tgt_queue_depth);
3877*4882a593Smuzhiyun 
3878*4882a593Smuzhiyun /*
3879*4882a593Smuzhiyun # hba_queue_depth:  This parameter is used to limit the number of outstanding
3880*4882a593Smuzhiyun # commands per lpfc HBA. Value range is [32,8192]. If this parameter
3881*4882a593Smuzhiyun # value is greater than the maximum number of exchanges supported by the HBA,
3882*4882a593Smuzhiyun # then maximum number of exchanges supported by the HBA is used to determine
3883*4882a593Smuzhiyun # the hba_queue_depth.
3884*4882a593Smuzhiyun */
3885*4882a593Smuzhiyun LPFC_ATTR_R(hba_queue_depth, 8192, 32, 8192,
3886*4882a593Smuzhiyun 	    "Max number of FCP commands we can queue to a lpfc HBA");
3887*4882a593Smuzhiyun 
3888*4882a593Smuzhiyun /*
3889*4882a593Smuzhiyun # peer_port_login:  This parameter allows/prevents logins
3890*4882a593Smuzhiyun # between peer ports hosted on the same physical port.
3891*4882a593Smuzhiyun # When this parameter is set 0 peer ports of same physical port
3892*4882a593Smuzhiyun # are not allowed to login to each other.
3893*4882a593Smuzhiyun # When this parameter is set 1 peer ports of same physical port
3894*4882a593Smuzhiyun # are allowed to login to each other.
3895*4882a593Smuzhiyun # Default value of this parameter is 0.
3896*4882a593Smuzhiyun */
3897*4882a593Smuzhiyun LPFC_VPORT_ATTR_R(peer_port_login, 0, 0, 1,
3898*4882a593Smuzhiyun 		  "Allow peer ports on the same physical port to login to each "
3899*4882a593Smuzhiyun 		  "other.");
3900*4882a593Smuzhiyun 
3901*4882a593Smuzhiyun /*
3902*4882a593Smuzhiyun # restrict_login:  This parameter allows/prevents logins
3903*4882a593Smuzhiyun # between Virtual Ports and remote initiators.
3904*4882a593Smuzhiyun # When this parameter is not set (0) Virtual Ports will accept PLOGIs from
3905*4882a593Smuzhiyun # other initiators and will attempt to PLOGI all remote ports.
3906*4882a593Smuzhiyun # When this parameter is set (1) Virtual Ports will reject PLOGIs from
3907*4882a593Smuzhiyun # remote ports and will not attempt to PLOGI to other initiators.
3908*4882a593Smuzhiyun # This parameter does not restrict to the physical port.
3909*4882a593Smuzhiyun # This parameter does not restrict logins to Fabric resident remote ports.
3910*4882a593Smuzhiyun # Default value of this parameter is 1.
3911*4882a593Smuzhiyun */
3912*4882a593Smuzhiyun static int lpfc_restrict_login = 1;
3913*4882a593Smuzhiyun module_param(lpfc_restrict_login, int, S_IRUGO);
3914*4882a593Smuzhiyun MODULE_PARM_DESC(lpfc_restrict_login,
3915*4882a593Smuzhiyun 		 "Restrict virtual ports login to remote initiators.");
3916*4882a593Smuzhiyun lpfc_vport_param_show(restrict_login);
3917*4882a593Smuzhiyun 
3918*4882a593Smuzhiyun /**
3919*4882a593Smuzhiyun  * lpfc_restrict_login_init - Set the vport restrict login flag
3920*4882a593Smuzhiyun  * @vport: lpfc vport structure pointer.
3921*4882a593Smuzhiyun  * @val: contains the restrict login value.
3922*4882a593Smuzhiyun  *
3923*4882a593Smuzhiyun  * Description:
3924*4882a593Smuzhiyun  * If val is not in a valid range then log a kernel error message and set
3925*4882a593Smuzhiyun  * the vport restrict login to one.
3926*4882a593Smuzhiyun  * If the port type is physical clear the restrict login flag and return.
3927*4882a593Smuzhiyun  * Else set the restrict login flag to val.
3928*4882a593Smuzhiyun  *
3929*4882a593Smuzhiyun  * Returns:
3930*4882a593Smuzhiyun  * zero if val is in range
3931*4882a593Smuzhiyun  * -EINVAL val out of range
3932*4882a593Smuzhiyun  **/
3933*4882a593Smuzhiyun static int
lpfc_restrict_login_init(struct lpfc_vport * vport,int val)3934*4882a593Smuzhiyun lpfc_restrict_login_init(struct lpfc_vport *vport, int val)
3935*4882a593Smuzhiyun {
3936*4882a593Smuzhiyun 	if (val < 0 || val > 1) {
3937*4882a593Smuzhiyun 		lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
3938*4882a593Smuzhiyun 				 "0422 lpfc_restrict_login attribute cannot "
3939*4882a593Smuzhiyun 				 "be set to %d, allowed range is [0, 1]\n",
3940*4882a593Smuzhiyun 				 val);
3941*4882a593Smuzhiyun 		vport->cfg_restrict_login = 1;
3942*4882a593Smuzhiyun 		return -EINVAL;
3943*4882a593Smuzhiyun 	}
3944*4882a593Smuzhiyun 	if (vport->port_type == LPFC_PHYSICAL_PORT) {
3945*4882a593Smuzhiyun 		vport->cfg_restrict_login = 0;
3946*4882a593Smuzhiyun 		return 0;
3947*4882a593Smuzhiyun 	}
3948*4882a593Smuzhiyun 	vport->cfg_restrict_login = val;
3949*4882a593Smuzhiyun 	return 0;
3950*4882a593Smuzhiyun }
3951*4882a593Smuzhiyun 
3952*4882a593Smuzhiyun /**
3953*4882a593Smuzhiyun  * lpfc_restrict_login_set - Set the vport restrict login flag
3954*4882a593Smuzhiyun  * @vport: lpfc vport structure pointer.
3955*4882a593Smuzhiyun  * @val: contains the restrict login value.
3956*4882a593Smuzhiyun  *
3957*4882a593Smuzhiyun  * Description:
3958*4882a593Smuzhiyun  * If val is not in a valid range then log a kernel error message and set
3959*4882a593Smuzhiyun  * the vport restrict login to one.
3960*4882a593Smuzhiyun  * If the port type is physical and the val is not zero log a kernel
3961*4882a593Smuzhiyun  * error message, clear the restrict login flag and return zero.
3962*4882a593Smuzhiyun  * Else set the restrict login flag to val.
3963*4882a593Smuzhiyun  *
3964*4882a593Smuzhiyun  * Returns:
3965*4882a593Smuzhiyun  * zero if val is in range
3966*4882a593Smuzhiyun  * -EINVAL val out of range
3967*4882a593Smuzhiyun  **/
3968*4882a593Smuzhiyun static int
lpfc_restrict_login_set(struct lpfc_vport * vport,int val)3969*4882a593Smuzhiyun lpfc_restrict_login_set(struct lpfc_vport *vport, int val)
3970*4882a593Smuzhiyun {
3971*4882a593Smuzhiyun 	if (val < 0 || val > 1) {
3972*4882a593Smuzhiyun 		lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
3973*4882a593Smuzhiyun 				 "0425 lpfc_restrict_login attribute cannot "
3974*4882a593Smuzhiyun 				 "be set to %d, allowed range is [0, 1]\n",
3975*4882a593Smuzhiyun 				 val);
3976*4882a593Smuzhiyun 		vport->cfg_restrict_login = 1;
3977*4882a593Smuzhiyun 		return -EINVAL;
3978*4882a593Smuzhiyun 	}
3979*4882a593Smuzhiyun 	if (vport->port_type == LPFC_PHYSICAL_PORT && val != 0) {
3980*4882a593Smuzhiyun 		lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
3981*4882a593Smuzhiyun 				 "0468 lpfc_restrict_login must be 0 for "
3982*4882a593Smuzhiyun 				 "Physical ports.\n");
3983*4882a593Smuzhiyun 		vport->cfg_restrict_login = 0;
3984*4882a593Smuzhiyun 		return 0;
3985*4882a593Smuzhiyun 	}
3986*4882a593Smuzhiyun 	vport->cfg_restrict_login = val;
3987*4882a593Smuzhiyun 	return 0;
3988*4882a593Smuzhiyun }
3989*4882a593Smuzhiyun lpfc_vport_param_store(restrict_login);
3990*4882a593Smuzhiyun static DEVICE_ATTR_RW(lpfc_restrict_login);
3991*4882a593Smuzhiyun 
3992*4882a593Smuzhiyun /*
3993*4882a593Smuzhiyun # Some disk devices have a "select ID" or "select Target" capability.
3994*4882a593Smuzhiyun # From a protocol standpoint "select ID" usually means select the
3995*4882a593Smuzhiyun # Fibre channel "ALPA".  In the FC-AL Profile there is an "informative
3996*4882a593Smuzhiyun # annex" which contains a table that maps a "select ID" (a number
3997*4882a593Smuzhiyun # between 0 and 7F) to an ALPA.  By default, for compatibility with
3998*4882a593Smuzhiyun # older drivers, the lpfc driver scans this table from low ALPA to high
3999*4882a593Smuzhiyun # ALPA.
4000*4882a593Smuzhiyun #
4001*4882a593Smuzhiyun # Turning on the scan-down variable (on  = 1, off = 0) will
4002*4882a593Smuzhiyun # cause the lpfc driver to use an inverted table, effectively
4003*4882a593Smuzhiyun # scanning ALPAs from high to low. Value range is [0,1]. Default value is 1.
4004*4882a593Smuzhiyun #
4005*4882a593Smuzhiyun # (Note: This "select ID" functionality is a LOOP ONLY characteristic
4006*4882a593Smuzhiyun # and will not work across a fabric. Also this parameter will take
4007*4882a593Smuzhiyun # effect only in the case when ALPA map is not available.)
4008*4882a593Smuzhiyun */
4009*4882a593Smuzhiyun LPFC_VPORT_ATTR_R(scan_down, 1, 0, 1,
4010*4882a593Smuzhiyun 		  "Start scanning for devices from highest ALPA to lowest");
4011*4882a593Smuzhiyun 
4012*4882a593Smuzhiyun /*
4013*4882a593Smuzhiyun # lpfc_topology:  link topology for init link
4014*4882a593Smuzhiyun #            0x0  = attempt loop mode then point-to-point
4015*4882a593Smuzhiyun #            0x01 = internal loopback mode
4016*4882a593Smuzhiyun #            0x02 = attempt point-to-point mode only
4017*4882a593Smuzhiyun #            0x04 = attempt loop mode only
4018*4882a593Smuzhiyun #            0x06 = attempt point-to-point mode then loop
4019*4882a593Smuzhiyun # Set point-to-point mode if you want to run as an N_Port.
4020*4882a593Smuzhiyun # Set loop mode if you want to run as an NL_Port. Value range is [0,0x6].
4021*4882a593Smuzhiyun # Default value is 0.
4022*4882a593Smuzhiyun */
4023*4882a593Smuzhiyun LPFC_ATTR(topology, 0, 0, 6,
4024*4882a593Smuzhiyun 	"Select Fibre Channel topology");
4025*4882a593Smuzhiyun 
4026*4882a593Smuzhiyun /**
4027*4882a593Smuzhiyun  * lpfc_topology_set - Set the adapters topology field
4028*4882a593Smuzhiyun  * @phba: lpfc_hba pointer.
4029*4882a593Smuzhiyun  * @val: topology value.
4030*4882a593Smuzhiyun  *
4031*4882a593Smuzhiyun  * Description:
4032*4882a593Smuzhiyun  * If val is in a valid range then set the adapter's topology field and
4033*4882a593Smuzhiyun  * issue a lip; if the lip fails reset the topology to the old value.
4034*4882a593Smuzhiyun  *
4035*4882a593Smuzhiyun  * If the value is not in range log a kernel error message and return an error.
4036*4882a593Smuzhiyun  *
4037*4882a593Smuzhiyun  * Returns:
4038*4882a593Smuzhiyun  * zero if val is in range and lip okay
4039*4882a593Smuzhiyun  * non-zero return value from lpfc_issue_lip()
4040*4882a593Smuzhiyun  * -EINVAL val out of range
4041*4882a593Smuzhiyun  **/
4042*4882a593Smuzhiyun static ssize_t
lpfc_topology_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)4043*4882a593Smuzhiyun lpfc_topology_store(struct device *dev, struct device_attribute *attr,
4044*4882a593Smuzhiyun 			const char *buf, size_t count)
4045*4882a593Smuzhiyun {
4046*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
4047*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
4048*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
4049*4882a593Smuzhiyun 	int val = 0;
4050*4882a593Smuzhiyun 	int nolip = 0;
4051*4882a593Smuzhiyun 	const char *val_buf = buf;
4052*4882a593Smuzhiyun 	int err;
4053*4882a593Smuzhiyun 	uint32_t prev_val;
4054*4882a593Smuzhiyun 
4055*4882a593Smuzhiyun 	if (!strncmp(buf, "nolip ", strlen("nolip "))) {
4056*4882a593Smuzhiyun 		nolip = 1;
4057*4882a593Smuzhiyun 		val_buf = &buf[strlen("nolip ")];
4058*4882a593Smuzhiyun 	}
4059*4882a593Smuzhiyun 
4060*4882a593Smuzhiyun 	if (!isdigit(val_buf[0]))
4061*4882a593Smuzhiyun 		return -EINVAL;
4062*4882a593Smuzhiyun 	if (sscanf(val_buf, "%i", &val) != 1)
4063*4882a593Smuzhiyun 		return -EINVAL;
4064*4882a593Smuzhiyun 
4065*4882a593Smuzhiyun 	if (val >= 0 && val <= 6) {
4066*4882a593Smuzhiyun 		prev_val = phba->cfg_topology;
4067*4882a593Smuzhiyun 		if (phba->cfg_link_speed == LPFC_USER_LINK_SPEED_16G &&
4068*4882a593Smuzhiyun 			val == 4) {
4069*4882a593Smuzhiyun 			lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
4070*4882a593Smuzhiyun 				"3113 Loop mode not supported at speed %d\n",
4071*4882a593Smuzhiyun 				val);
4072*4882a593Smuzhiyun 			return -EINVAL;
4073*4882a593Smuzhiyun 		}
4074*4882a593Smuzhiyun 		/*
4075*4882a593Smuzhiyun 		 * The 'topology' is not a configurable parameter if :
4076*4882a593Smuzhiyun 		 *   - persistent topology enabled
4077*4882a593Smuzhiyun 		 *   - G7/G6 with no private loop support
4078*4882a593Smuzhiyun 		 */
4079*4882a593Smuzhiyun 
4080*4882a593Smuzhiyun 		if ((phba->hba_flag & HBA_PERSISTENT_TOPO ||
4081*4882a593Smuzhiyun 		     (!phba->sli4_hba.pc_sli4_params.pls &&
4082*4882a593Smuzhiyun 		     (phba->pcidev->device == PCI_DEVICE_ID_LANCER_G6_FC ||
4083*4882a593Smuzhiyun 		     phba->pcidev->device == PCI_DEVICE_ID_LANCER_G7_FC))) &&
4084*4882a593Smuzhiyun 		    val == 4) {
4085*4882a593Smuzhiyun 			lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
4086*4882a593Smuzhiyun 				"3114 Loop mode not supported\n");
4087*4882a593Smuzhiyun 			return -EINVAL;
4088*4882a593Smuzhiyun 		}
4089*4882a593Smuzhiyun 		phba->cfg_topology = val;
4090*4882a593Smuzhiyun 		if (nolip)
4091*4882a593Smuzhiyun 			return strlen(buf);
4092*4882a593Smuzhiyun 
4093*4882a593Smuzhiyun 		lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
4094*4882a593Smuzhiyun 			"3054 lpfc_topology changed from %d to %d\n",
4095*4882a593Smuzhiyun 			prev_val, val);
4096*4882a593Smuzhiyun 		if (prev_val != val && phba->sli_rev == LPFC_SLI_REV4)
4097*4882a593Smuzhiyun 			phba->fc_topology_changed = 1;
4098*4882a593Smuzhiyun 		err = lpfc_issue_lip(lpfc_shost_from_vport(phba->pport));
4099*4882a593Smuzhiyun 		if (err) {
4100*4882a593Smuzhiyun 			phba->cfg_topology = prev_val;
4101*4882a593Smuzhiyun 			return -EINVAL;
4102*4882a593Smuzhiyun 		} else
4103*4882a593Smuzhiyun 			return strlen(buf);
4104*4882a593Smuzhiyun 	}
4105*4882a593Smuzhiyun 	lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
4106*4882a593Smuzhiyun 		"%d:0467 lpfc_topology attribute cannot be set to %d, "
4107*4882a593Smuzhiyun 		"allowed range is [0, 6]\n",
4108*4882a593Smuzhiyun 		phba->brd_no, val);
4109*4882a593Smuzhiyun 	return -EINVAL;
4110*4882a593Smuzhiyun }
4111*4882a593Smuzhiyun 
4112*4882a593Smuzhiyun lpfc_param_show(topology)
4113*4882a593Smuzhiyun static DEVICE_ATTR_RW(lpfc_topology);
4114*4882a593Smuzhiyun 
4115*4882a593Smuzhiyun /**
4116*4882a593Smuzhiyun  * lpfc_static_vport_show: Read callback function for
4117*4882a593Smuzhiyun  *   lpfc_static_vport sysfs file.
4118*4882a593Smuzhiyun  * @dev: Pointer to class device object.
4119*4882a593Smuzhiyun  * @attr: device attribute structure.
4120*4882a593Smuzhiyun  * @buf: Data buffer.
4121*4882a593Smuzhiyun  *
4122*4882a593Smuzhiyun  * This function is the read call back function for
4123*4882a593Smuzhiyun  * lpfc_static_vport sysfs file. The lpfc_static_vport
4124*4882a593Smuzhiyun  * sysfs file report the mageability of the vport.
4125*4882a593Smuzhiyun  **/
4126*4882a593Smuzhiyun static ssize_t
lpfc_static_vport_show(struct device * dev,struct device_attribute * attr,char * buf)4127*4882a593Smuzhiyun lpfc_static_vport_show(struct device *dev, struct device_attribute *attr,
4128*4882a593Smuzhiyun 			 char *buf)
4129*4882a593Smuzhiyun {
4130*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
4131*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
4132*4882a593Smuzhiyun 	if (vport->vport_flag & STATIC_VPORT)
4133*4882a593Smuzhiyun 		sprintf(buf, "1\n");
4134*4882a593Smuzhiyun 	else
4135*4882a593Smuzhiyun 		sprintf(buf, "0\n");
4136*4882a593Smuzhiyun 
4137*4882a593Smuzhiyun 	return strlen(buf);
4138*4882a593Smuzhiyun }
4139*4882a593Smuzhiyun 
4140*4882a593Smuzhiyun /*
4141*4882a593Smuzhiyun  * Sysfs attribute to control the statistical data collection.
4142*4882a593Smuzhiyun  */
4143*4882a593Smuzhiyun static DEVICE_ATTR_RO(lpfc_static_vport);
4144*4882a593Smuzhiyun 
4145*4882a593Smuzhiyun /**
4146*4882a593Smuzhiyun  * lpfc_stat_data_ctrl_store - write call back for lpfc_stat_data_ctrl sysfs file
4147*4882a593Smuzhiyun  * @dev: Pointer to class device.
4148*4882a593Smuzhiyun  * @buf: Data buffer.
4149*4882a593Smuzhiyun  * @count: Size of the data buffer.
4150*4882a593Smuzhiyun  *
4151*4882a593Smuzhiyun  * This function get called when a user write to the lpfc_stat_data_ctrl
4152*4882a593Smuzhiyun  * sysfs file. This function parse the command written to the sysfs file
4153*4882a593Smuzhiyun  * and take appropriate action. These commands are used for controlling
4154*4882a593Smuzhiyun  * driver statistical data collection.
4155*4882a593Smuzhiyun  * Following are the command this function handles.
4156*4882a593Smuzhiyun  *
4157*4882a593Smuzhiyun  *    setbucket <bucket_type> <base> <step>
4158*4882a593Smuzhiyun  *			       = Set the latency buckets.
4159*4882a593Smuzhiyun  *    destroybucket            = destroy all the buckets.
4160*4882a593Smuzhiyun  *    start                    = start data collection
4161*4882a593Smuzhiyun  *    stop                     = stop data collection
4162*4882a593Smuzhiyun  *    reset                    = reset the collected data
4163*4882a593Smuzhiyun  **/
4164*4882a593Smuzhiyun static ssize_t
lpfc_stat_data_ctrl_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)4165*4882a593Smuzhiyun lpfc_stat_data_ctrl_store(struct device *dev, struct device_attribute *attr,
4166*4882a593Smuzhiyun 			  const char *buf, size_t count)
4167*4882a593Smuzhiyun {
4168*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
4169*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
4170*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
4171*4882a593Smuzhiyun #define LPFC_MAX_DATA_CTRL_LEN 1024
4172*4882a593Smuzhiyun 	static char bucket_data[LPFC_MAX_DATA_CTRL_LEN];
4173*4882a593Smuzhiyun 	unsigned long i;
4174*4882a593Smuzhiyun 	char *str_ptr, *token;
4175*4882a593Smuzhiyun 	struct lpfc_vport **vports;
4176*4882a593Smuzhiyun 	struct Scsi_Host *v_shost;
4177*4882a593Smuzhiyun 	char *bucket_type_str, *base_str, *step_str;
4178*4882a593Smuzhiyun 	unsigned long base, step, bucket_type;
4179*4882a593Smuzhiyun 
4180*4882a593Smuzhiyun 	if (!strncmp(buf, "setbucket", strlen("setbucket"))) {
4181*4882a593Smuzhiyun 		if (strlen(buf) > (LPFC_MAX_DATA_CTRL_LEN - 1))
4182*4882a593Smuzhiyun 			return -EINVAL;
4183*4882a593Smuzhiyun 
4184*4882a593Smuzhiyun 		strncpy(bucket_data, buf, LPFC_MAX_DATA_CTRL_LEN);
4185*4882a593Smuzhiyun 		str_ptr = &bucket_data[0];
4186*4882a593Smuzhiyun 		/* Ignore this token - this is command token */
4187*4882a593Smuzhiyun 		token = strsep(&str_ptr, "\t ");
4188*4882a593Smuzhiyun 		if (!token)
4189*4882a593Smuzhiyun 			return -EINVAL;
4190*4882a593Smuzhiyun 
4191*4882a593Smuzhiyun 		bucket_type_str = strsep(&str_ptr, "\t ");
4192*4882a593Smuzhiyun 		if (!bucket_type_str)
4193*4882a593Smuzhiyun 			return -EINVAL;
4194*4882a593Smuzhiyun 
4195*4882a593Smuzhiyun 		if (!strncmp(bucket_type_str, "linear", strlen("linear")))
4196*4882a593Smuzhiyun 			bucket_type = LPFC_LINEAR_BUCKET;
4197*4882a593Smuzhiyun 		else if (!strncmp(bucket_type_str, "power2", strlen("power2")))
4198*4882a593Smuzhiyun 			bucket_type = LPFC_POWER2_BUCKET;
4199*4882a593Smuzhiyun 		else
4200*4882a593Smuzhiyun 			return -EINVAL;
4201*4882a593Smuzhiyun 
4202*4882a593Smuzhiyun 		base_str = strsep(&str_ptr, "\t ");
4203*4882a593Smuzhiyun 		if (!base_str)
4204*4882a593Smuzhiyun 			return -EINVAL;
4205*4882a593Smuzhiyun 		base = simple_strtoul(base_str, NULL, 0);
4206*4882a593Smuzhiyun 
4207*4882a593Smuzhiyun 		step_str = strsep(&str_ptr, "\t ");
4208*4882a593Smuzhiyun 		if (!step_str)
4209*4882a593Smuzhiyun 			return -EINVAL;
4210*4882a593Smuzhiyun 		step = simple_strtoul(step_str, NULL, 0);
4211*4882a593Smuzhiyun 		if (!step)
4212*4882a593Smuzhiyun 			return -EINVAL;
4213*4882a593Smuzhiyun 
4214*4882a593Smuzhiyun 		/* Block the data collection for every vport */
4215*4882a593Smuzhiyun 		vports = lpfc_create_vport_work_array(phba);
4216*4882a593Smuzhiyun 		if (vports == NULL)
4217*4882a593Smuzhiyun 			return -ENOMEM;
4218*4882a593Smuzhiyun 
4219*4882a593Smuzhiyun 		for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) {
4220*4882a593Smuzhiyun 			v_shost = lpfc_shost_from_vport(vports[i]);
4221*4882a593Smuzhiyun 			spin_lock_irq(v_shost->host_lock);
4222*4882a593Smuzhiyun 			/* Block and reset data collection */
4223*4882a593Smuzhiyun 			vports[i]->stat_data_blocked = 1;
4224*4882a593Smuzhiyun 			if (vports[i]->stat_data_enabled)
4225*4882a593Smuzhiyun 				lpfc_vport_reset_stat_data(vports[i]);
4226*4882a593Smuzhiyun 			spin_unlock_irq(v_shost->host_lock);
4227*4882a593Smuzhiyun 		}
4228*4882a593Smuzhiyun 
4229*4882a593Smuzhiyun 		/* Set the bucket attributes */
4230*4882a593Smuzhiyun 		phba->bucket_type = bucket_type;
4231*4882a593Smuzhiyun 		phba->bucket_base = base;
4232*4882a593Smuzhiyun 		phba->bucket_step = step;
4233*4882a593Smuzhiyun 
4234*4882a593Smuzhiyun 		for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) {
4235*4882a593Smuzhiyun 			v_shost = lpfc_shost_from_vport(vports[i]);
4236*4882a593Smuzhiyun 
4237*4882a593Smuzhiyun 			/* Unblock data collection */
4238*4882a593Smuzhiyun 			spin_lock_irq(v_shost->host_lock);
4239*4882a593Smuzhiyun 			vports[i]->stat_data_blocked = 0;
4240*4882a593Smuzhiyun 			spin_unlock_irq(v_shost->host_lock);
4241*4882a593Smuzhiyun 		}
4242*4882a593Smuzhiyun 		lpfc_destroy_vport_work_array(phba, vports);
4243*4882a593Smuzhiyun 		return strlen(buf);
4244*4882a593Smuzhiyun 	}
4245*4882a593Smuzhiyun 
4246*4882a593Smuzhiyun 	if (!strncmp(buf, "destroybucket", strlen("destroybucket"))) {
4247*4882a593Smuzhiyun 		vports = lpfc_create_vport_work_array(phba);
4248*4882a593Smuzhiyun 		if (vports == NULL)
4249*4882a593Smuzhiyun 			return -ENOMEM;
4250*4882a593Smuzhiyun 
4251*4882a593Smuzhiyun 		for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) {
4252*4882a593Smuzhiyun 			v_shost = lpfc_shost_from_vport(vports[i]);
4253*4882a593Smuzhiyun 			spin_lock_irq(shost->host_lock);
4254*4882a593Smuzhiyun 			vports[i]->stat_data_blocked = 1;
4255*4882a593Smuzhiyun 			lpfc_free_bucket(vport);
4256*4882a593Smuzhiyun 			vport->stat_data_enabled = 0;
4257*4882a593Smuzhiyun 			vports[i]->stat_data_blocked = 0;
4258*4882a593Smuzhiyun 			spin_unlock_irq(shost->host_lock);
4259*4882a593Smuzhiyun 		}
4260*4882a593Smuzhiyun 		lpfc_destroy_vport_work_array(phba, vports);
4261*4882a593Smuzhiyun 		phba->bucket_type = LPFC_NO_BUCKET;
4262*4882a593Smuzhiyun 		phba->bucket_base = 0;
4263*4882a593Smuzhiyun 		phba->bucket_step = 0;
4264*4882a593Smuzhiyun 		return strlen(buf);
4265*4882a593Smuzhiyun 	}
4266*4882a593Smuzhiyun 
4267*4882a593Smuzhiyun 	if (!strncmp(buf, "start", strlen("start"))) {
4268*4882a593Smuzhiyun 		/* If no buckets configured return error */
4269*4882a593Smuzhiyun 		if (phba->bucket_type == LPFC_NO_BUCKET)
4270*4882a593Smuzhiyun 			return -EINVAL;
4271*4882a593Smuzhiyun 		spin_lock_irq(shost->host_lock);
4272*4882a593Smuzhiyun 		if (vport->stat_data_enabled) {
4273*4882a593Smuzhiyun 			spin_unlock_irq(shost->host_lock);
4274*4882a593Smuzhiyun 			return strlen(buf);
4275*4882a593Smuzhiyun 		}
4276*4882a593Smuzhiyun 		lpfc_alloc_bucket(vport);
4277*4882a593Smuzhiyun 		vport->stat_data_enabled = 1;
4278*4882a593Smuzhiyun 		spin_unlock_irq(shost->host_lock);
4279*4882a593Smuzhiyun 		return strlen(buf);
4280*4882a593Smuzhiyun 	}
4281*4882a593Smuzhiyun 
4282*4882a593Smuzhiyun 	if (!strncmp(buf, "stop", strlen("stop"))) {
4283*4882a593Smuzhiyun 		spin_lock_irq(shost->host_lock);
4284*4882a593Smuzhiyun 		if (vport->stat_data_enabled == 0) {
4285*4882a593Smuzhiyun 			spin_unlock_irq(shost->host_lock);
4286*4882a593Smuzhiyun 			return strlen(buf);
4287*4882a593Smuzhiyun 		}
4288*4882a593Smuzhiyun 		lpfc_free_bucket(vport);
4289*4882a593Smuzhiyun 		vport->stat_data_enabled = 0;
4290*4882a593Smuzhiyun 		spin_unlock_irq(shost->host_lock);
4291*4882a593Smuzhiyun 		return strlen(buf);
4292*4882a593Smuzhiyun 	}
4293*4882a593Smuzhiyun 
4294*4882a593Smuzhiyun 	if (!strncmp(buf, "reset", strlen("reset"))) {
4295*4882a593Smuzhiyun 		if ((phba->bucket_type == LPFC_NO_BUCKET)
4296*4882a593Smuzhiyun 			|| !vport->stat_data_enabled)
4297*4882a593Smuzhiyun 			return strlen(buf);
4298*4882a593Smuzhiyun 		spin_lock_irq(shost->host_lock);
4299*4882a593Smuzhiyun 		vport->stat_data_blocked = 1;
4300*4882a593Smuzhiyun 		lpfc_vport_reset_stat_data(vport);
4301*4882a593Smuzhiyun 		vport->stat_data_blocked = 0;
4302*4882a593Smuzhiyun 		spin_unlock_irq(shost->host_lock);
4303*4882a593Smuzhiyun 		return strlen(buf);
4304*4882a593Smuzhiyun 	}
4305*4882a593Smuzhiyun 	return -EINVAL;
4306*4882a593Smuzhiyun }
4307*4882a593Smuzhiyun 
4308*4882a593Smuzhiyun 
4309*4882a593Smuzhiyun /**
4310*4882a593Smuzhiyun  * lpfc_stat_data_ctrl_show - Read function for lpfc_stat_data_ctrl sysfs file
4311*4882a593Smuzhiyun  * @dev: Pointer to class device object.
4312*4882a593Smuzhiyun  * @buf: Data buffer.
4313*4882a593Smuzhiyun  *
4314*4882a593Smuzhiyun  * This function is the read call back function for
4315*4882a593Smuzhiyun  * lpfc_stat_data_ctrl sysfs file. This function report the
4316*4882a593Smuzhiyun  * current statistical data collection state.
4317*4882a593Smuzhiyun  **/
4318*4882a593Smuzhiyun static ssize_t
lpfc_stat_data_ctrl_show(struct device * dev,struct device_attribute * attr,char * buf)4319*4882a593Smuzhiyun lpfc_stat_data_ctrl_show(struct device *dev, struct device_attribute *attr,
4320*4882a593Smuzhiyun 			 char *buf)
4321*4882a593Smuzhiyun {
4322*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
4323*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
4324*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
4325*4882a593Smuzhiyun 	int index = 0;
4326*4882a593Smuzhiyun 	int i;
4327*4882a593Smuzhiyun 	char *bucket_type;
4328*4882a593Smuzhiyun 	unsigned long bucket_value;
4329*4882a593Smuzhiyun 
4330*4882a593Smuzhiyun 	switch (phba->bucket_type) {
4331*4882a593Smuzhiyun 	case LPFC_LINEAR_BUCKET:
4332*4882a593Smuzhiyun 		bucket_type = "linear";
4333*4882a593Smuzhiyun 		break;
4334*4882a593Smuzhiyun 	case LPFC_POWER2_BUCKET:
4335*4882a593Smuzhiyun 		bucket_type = "power2";
4336*4882a593Smuzhiyun 		break;
4337*4882a593Smuzhiyun 	default:
4338*4882a593Smuzhiyun 		bucket_type = "No Bucket";
4339*4882a593Smuzhiyun 		break;
4340*4882a593Smuzhiyun 	}
4341*4882a593Smuzhiyun 
4342*4882a593Smuzhiyun 	sprintf(&buf[index], "Statistical Data enabled :%d, "
4343*4882a593Smuzhiyun 		"blocked :%d, Bucket type :%s, Bucket base :%d,"
4344*4882a593Smuzhiyun 		" Bucket step :%d\nLatency Ranges :",
4345*4882a593Smuzhiyun 		vport->stat_data_enabled, vport->stat_data_blocked,
4346*4882a593Smuzhiyun 		bucket_type, phba->bucket_base, phba->bucket_step);
4347*4882a593Smuzhiyun 	index = strlen(buf);
4348*4882a593Smuzhiyun 	if (phba->bucket_type != LPFC_NO_BUCKET) {
4349*4882a593Smuzhiyun 		for (i = 0; i < LPFC_MAX_BUCKET_COUNT; i++) {
4350*4882a593Smuzhiyun 			if (phba->bucket_type == LPFC_LINEAR_BUCKET)
4351*4882a593Smuzhiyun 				bucket_value = phba->bucket_base +
4352*4882a593Smuzhiyun 					phba->bucket_step * i;
4353*4882a593Smuzhiyun 			else
4354*4882a593Smuzhiyun 				bucket_value = phba->bucket_base +
4355*4882a593Smuzhiyun 				(1 << i) * phba->bucket_step;
4356*4882a593Smuzhiyun 
4357*4882a593Smuzhiyun 			if (index + 10 > PAGE_SIZE)
4358*4882a593Smuzhiyun 				break;
4359*4882a593Smuzhiyun 			sprintf(&buf[index], "%08ld ", bucket_value);
4360*4882a593Smuzhiyun 			index = strlen(buf);
4361*4882a593Smuzhiyun 		}
4362*4882a593Smuzhiyun 	}
4363*4882a593Smuzhiyun 	sprintf(&buf[index], "\n");
4364*4882a593Smuzhiyun 	return strlen(buf);
4365*4882a593Smuzhiyun }
4366*4882a593Smuzhiyun 
4367*4882a593Smuzhiyun /*
4368*4882a593Smuzhiyun  * Sysfs attribute to control the statistical data collection.
4369*4882a593Smuzhiyun  */
4370*4882a593Smuzhiyun static DEVICE_ATTR_RW(lpfc_stat_data_ctrl);
4371*4882a593Smuzhiyun 
4372*4882a593Smuzhiyun /*
4373*4882a593Smuzhiyun  * lpfc_drvr_stat_data: sysfs attr to get driver statistical data.
4374*4882a593Smuzhiyun  */
4375*4882a593Smuzhiyun 
4376*4882a593Smuzhiyun /*
4377*4882a593Smuzhiyun  * Each Bucket takes 11 characters and 1 new line + 17 bytes WWN
4378*4882a593Smuzhiyun  * for each target.
4379*4882a593Smuzhiyun  */
4380*4882a593Smuzhiyun #define STAT_DATA_SIZE_PER_TARGET(NUM_BUCKETS) ((NUM_BUCKETS) * 11 + 18)
4381*4882a593Smuzhiyun #define MAX_STAT_DATA_SIZE_PER_TARGET \
4382*4882a593Smuzhiyun 	STAT_DATA_SIZE_PER_TARGET(LPFC_MAX_BUCKET_COUNT)
4383*4882a593Smuzhiyun 
4384*4882a593Smuzhiyun 
4385*4882a593Smuzhiyun /**
4386*4882a593Smuzhiyun  * sysfs_drvr_stat_data_read - Read function for lpfc_drvr_stat_data attribute
4387*4882a593Smuzhiyun  * @filp: sysfs file
4388*4882a593Smuzhiyun  * @kobj: Pointer to the kernel object
4389*4882a593Smuzhiyun  * @bin_attr: Attribute object
4390*4882a593Smuzhiyun  * @buff: Buffer pointer
4391*4882a593Smuzhiyun  * @off: File offset
4392*4882a593Smuzhiyun  * @count: Buffer size
4393*4882a593Smuzhiyun  *
4394*4882a593Smuzhiyun  * This function is the read call back function for lpfc_drvr_stat_data
4395*4882a593Smuzhiyun  * sysfs file. This function export the statistical data to user
4396*4882a593Smuzhiyun  * applications.
4397*4882a593Smuzhiyun  **/
4398*4882a593Smuzhiyun static ssize_t
sysfs_drvr_stat_data_read(struct file * filp,struct kobject * kobj,struct bin_attribute * bin_attr,char * buf,loff_t off,size_t count)4399*4882a593Smuzhiyun sysfs_drvr_stat_data_read(struct file *filp, struct kobject *kobj,
4400*4882a593Smuzhiyun 		struct bin_attribute *bin_attr,
4401*4882a593Smuzhiyun 		char *buf, loff_t off, size_t count)
4402*4882a593Smuzhiyun {
4403*4882a593Smuzhiyun 	struct device *dev = container_of(kobj, struct device,
4404*4882a593Smuzhiyun 		kobj);
4405*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
4406*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
4407*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
4408*4882a593Smuzhiyun 	int i = 0, index = 0;
4409*4882a593Smuzhiyun 	unsigned long nport_index;
4410*4882a593Smuzhiyun 	struct lpfc_nodelist *ndlp = NULL;
4411*4882a593Smuzhiyun 	nport_index = (unsigned long)off /
4412*4882a593Smuzhiyun 		MAX_STAT_DATA_SIZE_PER_TARGET;
4413*4882a593Smuzhiyun 
4414*4882a593Smuzhiyun 	if (!vport->stat_data_enabled || vport->stat_data_blocked
4415*4882a593Smuzhiyun 		|| (phba->bucket_type == LPFC_NO_BUCKET))
4416*4882a593Smuzhiyun 		return 0;
4417*4882a593Smuzhiyun 
4418*4882a593Smuzhiyun 	spin_lock_irq(shost->host_lock);
4419*4882a593Smuzhiyun 	list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
4420*4882a593Smuzhiyun 		if (!NLP_CHK_NODE_ACT(ndlp) || !ndlp->lat_data)
4421*4882a593Smuzhiyun 			continue;
4422*4882a593Smuzhiyun 
4423*4882a593Smuzhiyun 		if (nport_index > 0) {
4424*4882a593Smuzhiyun 			nport_index--;
4425*4882a593Smuzhiyun 			continue;
4426*4882a593Smuzhiyun 		}
4427*4882a593Smuzhiyun 
4428*4882a593Smuzhiyun 		if ((index + MAX_STAT_DATA_SIZE_PER_TARGET)
4429*4882a593Smuzhiyun 			> count)
4430*4882a593Smuzhiyun 			break;
4431*4882a593Smuzhiyun 
4432*4882a593Smuzhiyun 		if (!ndlp->lat_data)
4433*4882a593Smuzhiyun 			continue;
4434*4882a593Smuzhiyun 
4435*4882a593Smuzhiyun 		/* Print the WWN */
4436*4882a593Smuzhiyun 		sprintf(&buf[index], "%02x%02x%02x%02x%02x%02x%02x%02x:",
4437*4882a593Smuzhiyun 			ndlp->nlp_portname.u.wwn[0],
4438*4882a593Smuzhiyun 			ndlp->nlp_portname.u.wwn[1],
4439*4882a593Smuzhiyun 			ndlp->nlp_portname.u.wwn[2],
4440*4882a593Smuzhiyun 			ndlp->nlp_portname.u.wwn[3],
4441*4882a593Smuzhiyun 			ndlp->nlp_portname.u.wwn[4],
4442*4882a593Smuzhiyun 			ndlp->nlp_portname.u.wwn[5],
4443*4882a593Smuzhiyun 			ndlp->nlp_portname.u.wwn[6],
4444*4882a593Smuzhiyun 			ndlp->nlp_portname.u.wwn[7]);
4445*4882a593Smuzhiyun 
4446*4882a593Smuzhiyun 		index = strlen(buf);
4447*4882a593Smuzhiyun 
4448*4882a593Smuzhiyun 		for (i = 0; i < LPFC_MAX_BUCKET_COUNT; i++) {
4449*4882a593Smuzhiyun 			sprintf(&buf[index], "%010u,",
4450*4882a593Smuzhiyun 				ndlp->lat_data[i].cmd_count);
4451*4882a593Smuzhiyun 			index = strlen(buf);
4452*4882a593Smuzhiyun 		}
4453*4882a593Smuzhiyun 		sprintf(&buf[index], "\n");
4454*4882a593Smuzhiyun 		index = strlen(buf);
4455*4882a593Smuzhiyun 	}
4456*4882a593Smuzhiyun 	spin_unlock_irq(shost->host_lock);
4457*4882a593Smuzhiyun 	return index;
4458*4882a593Smuzhiyun }
4459*4882a593Smuzhiyun 
4460*4882a593Smuzhiyun static struct bin_attribute sysfs_drvr_stat_data_attr = {
4461*4882a593Smuzhiyun 	.attr = {
4462*4882a593Smuzhiyun 		.name = "lpfc_drvr_stat_data",
4463*4882a593Smuzhiyun 		.mode = S_IRUSR,
4464*4882a593Smuzhiyun 	},
4465*4882a593Smuzhiyun 	.size = LPFC_MAX_TARGET * MAX_STAT_DATA_SIZE_PER_TARGET,
4466*4882a593Smuzhiyun 	.read = sysfs_drvr_stat_data_read,
4467*4882a593Smuzhiyun 	.write = NULL,
4468*4882a593Smuzhiyun };
4469*4882a593Smuzhiyun 
4470*4882a593Smuzhiyun /*
4471*4882a593Smuzhiyun # lpfc_link_speed: Link speed selection for initializing the Fibre Channel
4472*4882a593Smuzhiyun # connection.
4473*4882a593Smuzhiyun # Value range is [0,16]. Default value is 0.
4474*4882a593Smuzhiyun */
4475*4882a593Smuzhiyun /**
4476*4882a593Smuzhiyun  * lpfc_link_speed_set - Set the adapters link speed
4477*4882a593Smuzhiyun  * @phba: lpfc_hba pointer.
4478*4882a593Smuzhiyun  * @val: link speed value.
4479*4882a593Smuzhiyun  *
4480*4882a593Smuzhiyun  * Description:
4481*4882a593Smuzhiyun  * If val is in a valid range then set the adapter's link speed field and
4482*4882a593Smuzhiyun  * issue a lip; if the lip fails reset the link speed to the old value.
4483*4882a593Smuzhiyun  *
4484*4882a593Smuzhiyun  * Notes:
4485*4882a593Smuzhiyun  * If the value is not in range log a kernel error message and return an error.
4486*4882a593Smuzhiyun  *
4487*4882a593Smuzhiyun  * Returns:
4488*4882a593Smuzhiyun  * zero if val is in range and lip okay.
4489*4882a593Smuzhiyun  * non-zero return value from lpfc_issue_lip()
4490*4882a593Smuzhiyun  * -EINVAL val out of range
4491*4882a593Smuzhiyun  **/
4492*4882a593Smuzhiyun static ssize_t
lpfc_link_speed_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)4493*4882a593Smuzhiyun lpfc_link_speed_store(struct device *dev, struct device_attribute *attr,
4494*4882a593Smuzhiyun 		const char *buf, size_t count)
4495*4882a593Smuzhiyun {
4496*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
4497*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
4498*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
4499*4882a593Smuzhiyun 	int val = LPFC_USER_LINK_SPEED_AUTO;
4500*4882a593Smuzhiyun 	int nolip = 0;
4501*4882a593Smuzhiyun 	const char *val_buf = buf;
4502*4882a593Smuzhiyun 	int err;
4503*4882a593Smuzhiyun 	uint32_t prev_val, if_type;
4504*4882a593Smuzhiyun 
4505*4882a593Smuzhiyun 	if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf);
4506*4882a593Smuzhiyun 	if (if_type >= LPFC_SLI_INTF_IF_TYPE_2 &&
4507*4882a593Smuzhiyun 	    phba->hba_flag & HBA_FORCED_LINK_SPEED)
4508*4882a593Smuzhiyun 		return -EPERM;
4509*4882a593Smuzhiyun 
4510*4882a593Smuzhiyun 	if (!strncmp(buf, "nolip ", strlen("nolip "))) {
4511*4882a593Smuzhiyun 		nolip = 1;
4512*4882a593Smuzhiyun 		val_buf = &buf[strlen("nolip ")];
4513*4882a593Smuzhiyun 	}
4514*4882a593Smuzhiyun 
4515*4882a593Smuzhiyun 	if (!isdigit(val_buf[0]))
4516*4882a593Smuzhiyun 		return -EINVAL;
4517*4882a593Smuzhiyun 	if (sscanf(val_buf, "%i", &val) != 1)
4518*4882a593Smuzhiyun 		return -EINVAL;
4519*4882a593Smuzhiyun 
4520*4882a593Smuzhiyun 	lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
4521*4882a593Smuzhiyun 		"3055 lpfc_link_speed changed from %d to %d %s\n",
4522*4882a593Smuzhiyun 		phba->cfg_link_speed, val, nolip ? "(nolip)" : "(lip)");
4523*4882a593Smuzhiyun 
4524*4882a593Smuzhiyun 	if (((val == LPFC_USER_LINK_SPEED_1G) && !(phba->lmt & LMT_1Gb)) ||
4525*4882a593Smuzhiyun 	    ((val == LPFC_USER_LINK_SPEED_2G) && !(phba->lmt & LMT_2Gb)) ||
4526*4882a593Smuzhiyun 	    ((val == LPFC_USER_LINK_SPEED_4G) && !(phba->lmt & LMT_4Gb)) ||
4527*4882a593Smuzhiyun 	    ((val == LPFC_USER_LINK_SPEED_8G) && !(phba->lmt & LMT_8Gb)) ||
4528*4882a593Smuzhiyun 	    ((val == LPFC_USER_LINK_SPEED_10G) && !(phba->lmt & LMT_10Gb)) ||
4529*4882a593Smuzhiyun 	    ((val == LPFC_USER_LINK_SPEED_16G) && !(phba->lmt & LMT_16Gb)) ||
4530*4882a593Smuzhiyun 	    ((val == LPFC_USER_LINK_SPEED_32G) && !(phba->lmt & LMT_32Gb)) ||
4531*4882a593Smuzhiyun 	    ((val == LPFC_USER_LINK_SPEED_64G) && !(phba->lmt & LMT_64Gb))) {
4532*4882a593Smuzhiyun 		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
4533*4882a593Smuzhiyun 				"2879 lpfc_link_speed attribute cannot be set "
4534*4882a593Smuzhiyun 				"to %d. Speed is not supported by this port.\n",
4535*4882a593Smuzhiyun 				val);
4536*4882a593Smuzhiyun 		return -EINVAL;
4537*4882a593Smuzhiyun 	}
4538*4882a593Smuzhiyun 	if (val >= LPFC_USER_LINK_SPEED_16G &&
4539*4882a593Smuzhiyun 	    phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
4540*4882a593Smuzhiyun 		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
4541*4882a593Smuzhiyun 				"3112 lpfc_link_speed attribute cannot be set "
4542*4882a593Smuzhiyun 				"to %d. Speed is not supported in loop mode.\n",
4543*4882a593Smuzhiyun 				val);
4544*4882a593Smuzhiyun 		return -EINVAL;
4545*4882a593Smuzhiyun 	}
4546*4882a593Smuzhiyun 
4547*4882a593Smuzhiyun 	switch (val) {
4548*4882a593Smuzhiyun 	case LPFC_USER_LINK_SPEED_AUTO:
4549*4882a593Smuzhiyun 	case LPFC_USER_LINK_SPEED_1G:
4550*4882a593Smuzhiyun 	case LPFC_USER_LINK_SPEED_2G:
4551*4882a593Smuzhiyun 	case LPFC_USER_LINK_SPEED_4G:
4552*4882a593Smuzhiyun 	case LPFC_USER_LINK_SPEED_8G:
4553*4882a593Smuzhiyun 	case LPFC_USER_LINK_SPEED_16G:
4554*4882a593Smuzhiyun 	case LPFC_USER_LINK_SPEED_32G:
4555*4882a593Smuzhiyun 	case LPFC_USER_LINK_SPEED_64G:
4556*4882a593Smuzhiyun 		prev_val = phba->cfg_link_speed;
4557*4882a593Smuzhiyun 		phba->cfg_link_speed = val;
4558*4882a593Smuzhiyun 		if (nolip)
4559*4882a593Smuzhiyun 			return strlen(buf);
4560*4882a593Smuzhiyun 
4561*4882a593Smuzhiyun 		err = lpfc_issue_lip(lpfc_shost_from_vport(phba->pport));
4562*4882a593Smuzhiyun 		if (err) {
4563*4882a593Smuzhiyun 			phba->cfg_link_speed = prev_val;
4564*4882a593Smuzhiyun 			return -EINVAL;
4565*4882a593Smuzhiyun 		}
4566*4882a593Smuzhiyun 		return strlen(buf);
4567*4882a593Smuzhiyun 	default:
4568*4882a593Smuzhiyun 		break;
4569*4882a593Smuzhiyun 	}
4570*4882a593Smuzhiyun 
4571*4882a593Smuzhiyun 	lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
4572*4882a593Smuzhiyun 			"0469 lpfc_link_speed attribute cannot be set to %d, "
4573*4882a593Smuzhiyun 			"allowed values are [%s]\n",
4574*4882a593Smuzhiyun 			val, LPFC_LINK_SPEED_STRING);
4575*4882a593Smuzhiyun 	return -EINVAL;
4576*4882a593Smuzhiyun 
4577*4882a593Smuzhiyun }
4578*4882a593Smuzhiyun 
4579*4882a593Smuzhiyun static int lpfc_link_speed = 0;
4580*4882a593Smuzhiyun module_param(lpfc_link_speed, int, S_IRUGO);
4581*4882a593Smuzhiyun MODULE_PARM_DESC(lpfc_link_speed, "Select link speed");
lpfc_param_show(link_speed)4582*4882a593Smuzhiyun lpfc_param_show(link_speed)
4583*4882a593Smuzhiyun 
4584*4882a593Smuzhiyun /**
4585*4882a593Smuzhiyun  * lpfc_link_speed_init - Set the adapters link speed
4586*4882a593Smuzhiyun  * @phba: lpfc_hba pointer.
4587*4882a593Smuzhiyun  * @val: link speed value.
4588*4882a593Smuzhiyun  *
4589*4882a593Smuzhiyun  * Description:
4590*4882a593Smuzhiyun  * If val is in a valid range then set the adapter's link speed field.
4591*4882a593Smuzhiyun  *
4592*4882a593Smuzhiyun  * Notes:
4593*4882a593Smuzhiyun  * If the value is not in range log a kernel error message, clear the link
4594*4882a593Smuzhiyun  * speed and return an error.
4595*4882a593Smuzhiyun  *
4596*4882a593Smuzhiyun  * Returns:
4597*4882a593Smuzhiyun  * zero if val saved.
4598*4882a593Smuzhiyun  * -EINVAL val out of range
4599*4882a593Smuzhiyun  **/
4600*4882a593Smuzhiyun static int
4601*4882a593Smuzhiyun lpfc_link_speed_init(struct lpfc_hba *phba, int val)
4602*4882a593Smuzhiyun {
4603*4882a593Smuzhiyun 	if (val >= LPFC_USER_LINK_SPEED_16G && phba->cfg_topology == 4) {
4604*4882a593Smuzhiyun 		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
4605*4882a593Smuzhiyun 			"3111 lpfc_link_speed of %d cannot "
4606*4882a593Smuzhiyun 			"support loop mode, setting topology to default.\n",
4607*4882a593Smuzhiyun 			 val);
4608*4882a593Smuzhiyun 		phba->cfg_topology = 0;
4609*4882a593Smuzhiyun 	}
4610*4882a593Smuzhiyun 
4611*4882a593Smuzhiyun 	switch (val) {
4612*4882a593Smuzhiyun 	case LPFC_USER_LINK_SPEED_AUTO:
4613*4882a593Smuzhiyun 	case LPFC_USER_LINK_SPEED_1G:
4614*4882a593Smuzhiyun 	case LPFC_USER_LINK_SPEED_2G:
4615*4882a593Smuzhiyun 	case LPFC_USER_LINK_SPEED_4G:
4616*4882a593Smuzhiyun 	case LPFC_USER_LINK_SPEED_8G:
4617*4882a593Smuzhiyun 	case LPFC_USER_LINK_SPEED_16G:
4618*4882a593Smuzhiyun 	case LPFC_USER_LINK_SPEED_32G:
4619*4882a593Smuzhiyun 	case LPFC_USER_LINK_SPEED_64G:
4620*4882a593Smuzhiyun 		phba->cfg_link_speed = val;
4621*4882a593Smuzhiyun 		return 0;
4622*4882a593Smuzhiyun 	default:
4623*4882a593Smuzhiyun 		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
4624*4882a593Smuzhiyun 				"0405 lpfc_link_speed attribute cannot "
4625*4882a593Smuzhiyun 				"be set to %d, allowed values are "
4626*4882a593Smuzhiyun 				"["LPFC_LINK_SPEED_STRING"]\n", val);
4627*4882a593Smuzhiyun 		phba->cfg_link_speed = LPFC_USER_LINK_SPEED_AUTO;
4628*4882a593Smuzhiyun 		return -EINVAL;
4629*4882a593Smuzhiyun 	}
4630*4882a593Smuzhiyun }
4631*4882a593Smuzhiyun 
4632*4882a593Smuzhiyun static DEVICE_ATTR_RW(lpfc_link_speed);
4633*4882a593Smuzhiyun 
4634*4882a593Smuzhiyun /*
4635*4882a593Smuzhiyun # lpfc_aer_support: Support PCIe device Advanced Error Reporting (AER)
4636*4882a593Smuzhiyun #       0  = aer disabled or not supported
4637*4882a593Smuzhiyun #       1  = aer supported and enabled (default)
4638*4882a593Smuzhiyun # Value range is [0,1]. Default value is 1.
4639*4882a593Smuzhiyun */
4640*4882a593Smuzhiyun LPFC_ATTR(aer_support, 1, 0, 1,
4641*4882a593Smuzhiyun 	"Enable PCIe device AER support");
lpfc_param_show(aer_support)4642*4882a593Smuzhiyun lpfc_param_show(aer_support)
4643*4882a593Smuzhiyun 
4644*4882a593Smuzhiyun /**
4645*4882a593Smuzhiyun  * lpfc_aer_support_store - Set the adapter for aer support
4646*4882a593Smuzhiyun  *
4647*4882a593Smuzhiyun  * @dev: class device that is converted into a Scsi_host.
4648*4882a593Smuzhiyun  * @attr: device attribute, not used.
4649*4882a593Smuzhiyun  * @buf: containing enable or disable aer flag.
4650*4882a593Smuzhiyun  * @count: unused variable.
4651*4882a593Smuzhiyun  *
4652*4882a593Smuzhiyun  * Description:
4653*4882a593Smuzhiyun  * If the val is 1 and currently the device's AER capability was not
4654*4882a593Smuzhiyun  * enabled, invoke the kernel's enable AER helper routine, trying to
4655*4882a593Smuzhiyun  * enable the device's AER capability. If the helper routine enabling
4656*4882a593Smuzhiyun  * AER returns success, update the device's cfg_aer_support flag to
4657*4882a593Smuzhiyun  * indicate AER is supported by the device; otherwise, if the device
4658*4882a593Smuzhiyun  * AER capability is already enabled to support AER, then do nothing.
4659*4882a593Smuzhiyun  *
4660*4882a593Smuzhiyun  * If the val is 0 and currently the device's AER support was enabled,
4661*4882a593Smuzhiyun  * invoke the kernel's disable AER helper routine. After that, update
4662*4882a593Smuzhiyun  * the device's cfg_aer_support flag to indicate AER is not supported
4663*4882a593Smuzhiyun  * by the device; otherwise, if the device AER capability is already
4664*4882a593Smuzhiyun  * disabled from supporting AER, then do nothing.
4665*4882a593Smuzhiyun  *
4666*4882a593Smuzhiyun  * Returns:
4667*4882a593Smuzhiyun  * length of the buf on success if val is in range the intended mode
4668*4882a593Smuzhiyun  * is supported.
4669*4882a593Smuzhiyun  * -EINVAL if val out of range or intended mode is not supported.
4670*4882a593Smuzhiyun  **/
4671*4882a593Smuzhiyun static ssize_t
4672*4882a593Smuzhiyun lpfc_aer_support_store(struct device *dev, struct device_attribute *attr,
4673*4882a593Smuzhiyun 		       const char *buf, size_t count)
4674*4882a593Smuzhiyun {
4675*4882a593Smuzhiyun 	struct Scsi_Host *shost = class_to_shost(dev);
4676*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata;
4677*4882a593Smuzhiyun 	struct lpfc_hba *phba = vport->phba;
4678*4882a593Smuzhiyun 	int val = 0, rc = -EINVAL;
4679*4882a593Smuzhiyun 
4680*4882a593Smuzhiyun 	if (!isdigit(buf[0]))
4681*4882a593Smuzhiyun 		return -EINVAL;
4682*4882a593Smuzhiyun 	if (sscanf(buf, "%i", &val) != 1)
4683*4882a593Smuzhiyun 		return -EINVAL;
4684*4882a593Smuzhiyun 
4685*4882a593Smuzhiyun 	switch (val) {
4686*4882a593Smuzhiyun 	case 0:
4687*4882a593Smuzhiyun 		if (phba->hba_flag & HBA_AER_ENABLED) {
4688*4882a593Smuzhiyun 			rc = pci_disable_pcie_error_reporting(phba->pcidev);
4689*4882a593Smuzhiyun 			if (!rc) {
4690*4882a593Smuzhiyun 				spin_lock_irq(&phba->hbalock);
4691*4882a593Smuzhiyun 				phba->hba_flag &= ~HBA_AER_ENABLED;
4692*4882a593Smuzhiyun 				spin_unlock_irq(&phba->hbalock);
4693*4882a593Smuzhiyun 				phba->cfg_aer_support = 0;
4694*4882a593Smuzhiyun 				rc = strlen(buf);
4695*4882a593Smuzhiyun 			} else
4696*4882a593Smuzhiyun 				rc = -EPERM;
4697*4882a593Smuzhiyun 		} else {
4698*4882a593Smuzhiyun 			phba->cfg_aer_support = 0;
4699*4882a593Smuzhiyun 			rc = strlen(buf);
4700*4882a593Smuzhiyun 		}
4701*4882a593Smuzhiyun 		break;
4702*4882a593Smuzhiyun 	case 1:
4703*4882a593Smuzhiyun 		if (!(phba->hba_flag & HBA_AER_ENABLED)) {
4704*4882a593Smuzhiyun 			rc = pci_enable_pcie_error_reporting(phba->pcidev);
4705*4882a593Smuzhiyun 			if (!rc) {
4706*4882a593Smuzhiyun 				spin_lock_irq(&phba->hbalock);
4707*4882a593Smuzhiyun 				phba->hba_flag |= HBA_AER_ENABLED;
4708*4882a593Smuzhiyun 				spin_unlock_irq(&phba->hbalock);
4709*4882a593Smuzhiyun 				phba->cfg_aer_support = 1;
4710*4882a593Smuzhiyun 				rc = strlen(buf);
4711*4882a593Smuzhiyun 			} else
4712*4882a593Smuzhiyun 				 rc = -EPERM;
4713*4882a593Smuzhiyun 		} else {
4714*4882a593Smuzhiyun 			phba->cfg_aer_support = 1;
4715*4882a593Smuzhiyun 			rc = strlen(buf);
4716*4882a593Smuzhiyun 		}
4717*4882a593Smuzhiyun 		break;
4718*4882a593Smuzhiyun 	default:
4719*4882a593Smuzhiyun 		rc = -EINVAL;
4720*4882a593Smuzhiyun 		break;
4721*4882a593Smuzhiyun 	}
4722*4882a593Smuzhiyun 	return rc;
4723*4882a593Smuzhiyun }
4724*4882a593Smuzhiyun 
4725*4882a593Smuzhiyun static DEVICE_ATTR_RW(lpfc_aer_support);
4726*4882a593Smuzhiyun 
4727*4882a593Smuzhiyun /**
4728*4882a593Smuzhiyun  * lpfc_aer_cleanup_state - Clean up aer state to the aer enabled device
4729*4882a593Smuzhiyun  * @dev: class device that is converted into a Scsi_host.
4730*4882a593Smuzhiyun  * @attr: device attribute, not used.
4731*4882a593Smuzhiyun  * @buf: containing flag 1 for aer cleanup state.
4732*4882a593Smuzhiyun  * @count: unused variable.
4733*4882a593Smuzhiyun  *
4734*4882a593Smuzhiyun  * Description:
4735*4882a593Smuzhiyun  * If the @buf contains 1 and the device currently has the AER support
4736*4882a593Smuzhiyun  * enabled, then invokes the kernel AER helper routine
4737*4882a593Smuzhiyun  * pci_aer_clear_nonfatal_status() to clean up the uncorrectable
4738*4882a593Smuzhiyun  * error status register.
4739*4882a593Smuzhiyun  *
4740*4882a593Smuzhiyun  * Notes:
4741*4882a593Smuzhiyun  *
4742*4882a593Smuzhiyun  * Returns:
4743*4882a593Smuzhiyun  * -EINVAL if the buf does not contain the 1 or the device is not currently
4744*4882a593Smuzhiyun  * enabled with the AER support.
4745*4882a593Smuzhiyun  **/
4746*4882a593Smuzhiyun static ssize_t
lpfc_aer_cleanup_state(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)4747*4882a593Smuzhiyun lpfc_aer_cleanup_state(struct device *dev, struct device_attribute *attr,
4748*4882a593Smuzhiyun 		       const char *buf, size_t count)
4749*4882a593Smuzhiyun {
4750*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
4751*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
4752*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
4753*4882a593Smuzhiyun 	int val, rc = -1;
4754*4882a593Smuzhiyun 
4755*4882a593Smuzhiyun 	if (!isdigit(buf[0]))
4756*4882a593Smuzhiyun 		return -EINVAL;
4757*4882a593Smuzhiyun 	if (sscanf(buf, "%i", &val) != 1)
4758*4882a593Smuzhiyun 		return -EINVAL;
4759*4882a593Smuzhiyun 	if (val != 1)
4760*4882a593Smuzhiyun 		return -EINVAL;
4761*4882a593Smuzhiyun 
4762*4882a593Smuzhiyun 	if (phba->hba_flag & HBA_AER_ENABLED)
4763*4882a593Smuzhiyun 		rc = pci_aer_clear_nonfatal_status(phba->pcidev);
4764*4882a593Smuzhiyun 
4765*4882a593Smuzhiyun 	if (rc == 0)
4766*4882a593Smuzhiyun 		return strlen(buf);
4767*4882a593Smuzhiyun 	else
4768*4882a593Smuzhiyun 		return -EPERM;
4769*4882a593Smuzhiyun }
4770*4882a593Smuzhiyun 
4771*4882a593Smuzhiyun static DEVICE_ATTR(lpfc_aer_state_cleanup, S_IWUSR, NULL,
4772*4882a593Smuzhiyun 		   lpfc_aer_cleanup_state);
4773*4882a593Smuzhiyun 
4774*4882a593Smuzhiyun /**
4775*4882a593Smuzhiyun  * lpfc_sriov_nr_virtfn_store - Enable the adapter for sr-iov virtual functions
4776*4882a593Smuzhiyun  *
4777*4882a593Smuzhiyun  * @dev: class device that is converted into a Scsi_host.
4778*4882a593Smuzhiyun  * @attr: device attribute, not used.
4779*4882a593Smuzhiyun  * @buf: containing the string the number of vfs to be enabled.
4780*4882a593Smuzhiyun  * @count: unused variable.
4781*4882a593Smuzhiyun  *
4782*4882a593Smuzhiyun  * Description:
4783*4882a593Smuzhiyun  * When this api is called either through user sysfs, the driver shall
4784*4882a593Smuzhiyun  * try to enable or disable SR-IOV virtual functions according to the
4785*4882a593Smuzhiyun  * following:
4786*4882a593Smuzhiyun  *
4787*4882a593Smuzhiyun  * If zero virtual function has been enabled to the physical function,
4788*4882a593Smuzhiyun  * the driver shall invoke the pci enable virtual function api trying
4789*4882a593Smuzhiyun  * to enable the virtual functions. If the nr_vfn provided is greater
4790*4882a593Smuzhiyun  * than the maximum supported, the maximum virtual function number will
4791*4882a593Smuzhiyun  * be used for invoking the api; otherwise, the nr_vfn provided shall
4792*4882a593Smuzhiyun  * be used for invoking the api. If the api call returned success, the
4793*4882a593Smuzhiyun  * actual number of virtual functions enabled will be set to the driver
4794*4882a593Smuzhiyun  * cfg_sriov_nr_virtfn; otherwise, -EINVAL shall be returned and driver
4795*4882a593Smuzhiyun  * cfg_sriov_nr_virtfn remains zero.
4796*4882a593Smuzhiyun  *
4797*4882a593Smuzhiyun  * If none-zero virtual functions have already been enabled to the
4798*4882a593Smuzhiyun  * physical function, as reflected by the driver's cfg_sriov_nr_virtfn,
4799*4882a593Smuzhiyun  * -EINVAL will be returned and the driver does nothing;
4800*4882a593Smuzhiyun  *
4801*4882a593Smuzhiyun  * If the nr_vfn provided is zero and none-zero virtual functions have
4802*4882a593Smuzhiyun  * been enabled, as indicated by the driver's cfg_sriov_nr_virtfn, the
4803*4882a593Smuzhiyun  * disabling virtual function api shall be invoded to disable all the
4804*4882a593Smuzhiyun  * virtual functions and driver's cfg_sriov_nr_virtfn shall be set to
4805*4882a593Smuzhiyun  * zero. Otherwise, if zero virtual function has been enabled, do
4806*4882a593Smuzhiyun  * nothing.
4807*4882a593Smuzhiyun  *
4808*4882a593Smuzhiyun  * Returns:
4809*4882a593Smuzhiyun  * length of the buf on success if val is in range the intended mode
4810*4882a593Smuzhiyun  * is supported.
4811*4882a593Smuzhiyun  * -EINVAL if val out of range or intended mode is not supported.
4812*4882a593Smuzhiyun  **/
4813*4882a593Smuzhiyun static ssize_t
lpfc_sriov_nr_virtfn_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)4814*4882a593Smuzhiyun lpfc_sriov_nr_virtfn_store(struct device *dev, struct device_attribute *attr,
4815*4882a593Smuzhiyun 			 const char *buf, size_t count)
4816*4882a593Smuzhiyun {
4817*4882a593Smuzhiyun 	struct Scsi_Host *shost = class_to_shost(dev);
4818*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata;
4819*4882a593Smuzhiyun 	struct lpfc_hba *phba = vport->phba;
4820*4882a593Smuzhiyun 	struct pci_dev *pdev = phba->pcidev;
4821*4882a593Smuzhiyun 	int val = 0, rc = -EINVAL;
4822*4882a593Smuzhiyun 
4823*4882a593Smuzhiyun 	/* Sanity check on user data */
4824*4882a593Smuzhiyun 	if (!isdigit(buf[0]))
4825*4882a593Smuzhiyun 		return -EINVAL;
4826*4882a593Smuzhiyun 	if (sscanf(buf, "%i", &val) != 1)
4827*4882a593Smuzhiyun 		return -EINVAL;
4828*4882a593Smuzhiyun 	if (val < 0)
4829*4882a593Smuzhiyun 		return -EINVAL;
4830*4882a593Smuzhiyun 
4831*4882a593Smuzhiyun 	/* Request disabling virtual functions */
4832*4882a593Smuzhiyun 	if (val == 0) {
4833*4882a593Smuzhiyun 		if (phba->cfg_sriov_nr_virtfn > 0) {
4834*4882a593Smuzhiyun 			pci_disable_sriov(pdev);
4835*4882a593Smuzhiyun 			phba->cfg_sriov_nr_virtfn = 0;
4836*4882a593Smuzhiyun 		}
4837*4882a593Smuzhiyun 		return strlen(buf);
4838*4882a593Smuzhiyun 	}
4839*4882a593Smuzhiyun 
4840*4882a593Smuzhiyun 	/* Request enabling virtual functions */
4841*4882a593Smuzhiyun 	if (phba->cfg_sriov_nr_virtfn > 0) {
4842*4882a593Smuzhiyun 		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
4843*4882a593Smuzhiyun 				"3018 There are %d virtual functions "
4844*4882a593Smuzhiyun 				"enabled on physical function.\n",
4845*4882a593Smuzhiyun 				phba->cfg_sriov_nr_virtfn);
4846*4882a593Smuzhiyun 		return -EEXIST;
4847*4882a593Smuzhiyun 	}
4848*4882a593Smuzhiyun 
4849*4882a593Smuzhiyun 	if (val <= LPFC_MAX_VFN_PER_PFN)
4850*4882a593Smuzhiyun 		phba->cfg_sriov_nr_virtfn = val;
4851*4882a593Smuzhiyun 	else {
4852*4882a593Smuzhiyun 		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
4853*4882a593Smuzhiyun 				"3019 Enabling %d virtual functions is not "
4854*4882a593Smuzhiyun 				"allowed.\n", val);
4855*4882a593Smuzhiyun 		return -EINVAL;
4856*4882a593Smuzhiyun 	}
4857*4882a593Smuzhiyun 
4858*4882a593Smuzhiyun 	rc = lpfc_sli_probe_sriov_nr_virtfn(phba, phba->cfg_sriov_nr_virtfn);
4859*4882a593Smuzhiyun 	if (rc) {
4860*4882a593Smuzhiyun 		phba->cfg_sriov_nr_virtfn = 0;
4861*4882a593Smuzhiyun 		rc = -EPERM;
4862*4882a593Smuzhiyun 	} else
4863*4882a593Smuzhiyun 		rc = strlen(buf);
4864*4882a593Smuzhiyun 
4865*4882a593Smuzhiyun 	return rc;
4866*4882a593Smuzhiyun }
4867*4882a593Smuzhiyun 
4868*4882a593Smuzhiyun LPFC_ATTR(sriov_nr_virtfn, LPFC_DEF_VFN_PER_PFN, 0, LPFC_MAX_VFN_PER_PFN,
4869*4882a593Smuzhiyun 	"Enable PCIe device SR-IOV virtual fn");
4870*4882a593Smuzhiyun 
4871*4882a593Smuzhiyun lpfc_param_show(sriov_nr_virtfn)
4872*4882a593Smuzhiyun static DEVICE_ATTR_RW(lpfc_sriov_nr_virtfn);
4873*4882a593Smuzhiyun 
4874*4882a593Smuzhiyun /**
4875*4882a593Smuzhiyun  * lpfc_request_firmware_store - Request for Linux generic firmware upgrade
4876*4882a593Smuzhiyun  *
4877*4882a593Smuzhiyun  * @dev: class device that is converted into a Scsi_host.
4878*4882a593Smuzhiyun  * @attr: device attribute, not used.
4879*4882a593Smuzhiyun  * @buf: containing the string the number of vfs to be enabled.
4880*4882a593Smuzhiyun  * @count: unused variable.
4881*4882a593Smuzhiyun  *
4882*4882a593Smuzhiyun  * Description:
4883*4882a593Smuzhiyun  *
4884*4882a593Smuzhiyun  * Returns:
4885*4882a593Smuzhiyun  * length of the buf on success if val is in range the intended mode
4886*4882a593Smuzhiyun  * is supported.
4887*4882a593Smuzhiyun  * -EINVAL if val out of range or intended mode is not supported.
4888*4882a593Smuzhiyun  **/
4889*4882a593Smuzhiyun static ssize_t
lpfc_request_firmware_upgrade_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)4890*4882a593Smuzhiyun lpfc_request_firmware_upgrade_store(struct device *dev,
4891*4882a593Smuzhiyun 				    struct device_attribute *attr,
4892*4882a593Smuzhiyun 				    const char *buf, size_t count)
4893*4882a593Smuzhiyun {
4894*4882a593Smuzhiyun 	struct Scsi_Host *shost = class_to_shost(dev);
4895*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata;
4896*4882a593Smuzhiyun 	struct lpfc_hba *phba = vport->phba;
4897*4882a593Smuzhiyun 	int val = 0, rc;
4898*4882a593Smuzhiyun 
4899*4882a593Smuzhiyun 	/* Sanity check on user data */
4900*4882a593Smuzhiyun 	if (!isdigit(buf[0]))
4901*4882a593Smuzhiyun 		return -EINVAL;
4902*4882a593Smuzhiyun 	if (sscanf(buf, "%i", &val) != 1)
4903*4882a593Smuzhiyun 		return -EINVAL;
4904*4882a593Smuzhiyun 	if (val != 1)
4905*4882a593Smuzhiyun 		return -EINVAL;
4906*4882a593Smuzhiyun 
4907*4882a593Smuzhiyun 	rc = lpfc_sli4_request_firmware_update(phba, RUN_FW_UPGRADE);
4908*4882a593Smuzhiyun 	if (rc)
4909*4882a593Smuzhiyun 		rc = -EPERM;
4910*4882a593Smuzhiyun 	else
4911*4882a593Smuzhiyun 		rc = strlen(buf);
4912*4882a593Smuzhiyun 	return rc;
4913*4882a593Smuzhiyun }
4914*4882a593Smuzhiyun 
4915*4882a593Smuzhiyun static int lpfc_req_fw_upgrade;
4916*4882a593Smuzhiyun module_param(lpfc_req_fw_upgrade, int, S_IRUGO|S_IWUSR);
4917*4882a593Smuzhiyun MODULE_PARM_DESC(lpfc_req_fw_upgrade, "Enable Linux generic firmware upgrade");
lpfc_param_show(request_firmware_upgrade)4918*4882a593Smuzhiyun lpfc_param_show(request_firmware_upgrade)
4919*4882a593Smuzhiyun 
4920*4882a593Smuzhiyun /**
4921*4882a593Smuzhiyun  * lpfc_request_firmware_upgrade_init - Enable initial linux generic fw upgrade
4922*4882a593Smuzhiyun  * @phba: lpfc_hba pointer.
4923*4882a593Smuzhiyun  * @val: 0 or 1.
4924*4882a593Smuzhiyun  *
4925*4882a593Smuzhiyun  * Description:
4926*4882a593Smuzhiyun  * Set the initial Linux generic firmware upgrade enable or disable flag.
4927*4882a593Smuzhiyun  *
4928*4882a593Smuzhiyun  * Returns:
4929*4882a593Smuzhiyun  * zero if val saved.
4930*4882a593Smuzhiyun  * -EINVAL val out of range
4931*4882a593Smuzhiyun  **/
4932*4882a593Smuzhiyun static int
4933*4882a593Smuzhiyun lpfc_request_firmware_upgrade_init(struct lpfc_hba *phba, int val)
4934*4882a593Smuzhiyun {
4935*4882a593Smuzhiyun 	if (val >= 0 && val <= 1) {
4936*4882a593Smuzhiyun 		phba->cfg_request_firmware_upgrade = val;
4937*4882a593Smuzhiyun 		return 0;
4938*4882a593Smuzhiyun 	}
4939*4882a593Smuzhiyun 	return -EINVAL;
4940*4882a593Smuzhiyun }
4941*4882a593Smuzhiyun static DEVICE_ATTR(lpfc_req_fw_upgrade, S_IRUGO | S_IWUSR,
4942*4882a593Smuzhiyun 		   lpfc_request_firmware_upgrade_show,
4943*4882a593Smuzhiyun 		   lpfc_request_firmware_upgrade_store);
4944*4882a593Smuzhiyun 
4945*4882a593Smuzhiyun /**
4946*4882a593Smuzhiyun  * lpfc_force_rscn_store
4947*4882a593Smuzhiyun  *
4948*4882a593Smuzhiyun  * @dev: class device that is converted into a Scsi_host.
4949*4882a593Smuzhiyun  * @attr: device attribute, not used.
4950*4882a593Smuzhiyun  * @buf: unused string
4951*4882a593Smuzhiyun  * @count: unused variable.
4952*4882a593Smuzhiyun  *
4953*4882a593Smuzhiyun  * Description:
4954*4882a593Smuzhiyun  * Force the switch to send a RSCN to all other NPorts in our zone
4955*4882a593Smuzhiyun  * If we are direct connect pt2pt, build the RSCN command ourself
4956*4882a593Smuzhiyun  * and send to the other NPort. Not supported for private loop.
4957*4882a593Smuzhiyun  *
4958*4882a593Smuzhiyun  * Returns:
4959*4882a593Smuzhiyun  * 0      - on success
4960*4882a593Smuzhiyun  * -EIO   - if command is not sent
4961*4882a593Smuzhiyun  **/
4962*4882a593Smuzhiyun static ssize_t
lpfc_force_rscn_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)4963*4882a593Smuzhiyun lpfc_force_rscn_store(struct device *dev, struct device_attribute *attr,
4964*4882a593Smuzhiyun 		      const char *buf, size_t count)
4965*4882a593Smuzhiyun {
4966*4882a593Smuzhiyun 	struct Scsi_Host *shost = class_to_shost(dev);
4967*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata;
4968*4882a593Smuzhiyun 	int i;
4969*4882a593Smuzhiyun 
4970*4882a593Smuzhiyun 	i = lpfc_issue_els_rscn(vport, 0);
4971*4882a593Smuzhiyun 	if (i)
4972*4882a593Smuzhiyun 		return -EIO;
4973*4882a593Smuzhiyun 	return strlen(buf);
4974*4882a593Smuzhiyun }
4975*4882a593Smuzhiyun 
4976*4882a593Smuzhiyun /*
4977*4882a593Smuzhiyun  * lpfc_force_rscn: Force an RSCN to be sent to all remote NPorts
4978*4882a593Smuzhiyun  * connected to  the HBA.
4979*4882a593Smuzhiyun  *
4980*4882a593Smuzhiyun  * Value range is any ascii value
4981*4882a593Smuzhiyun  */
4982*4882a593Smuzhiyun static int lpfc_force_rscn;
4983*4882a593Smuzhiyun module_param(lpfc_force_rscn, int, 0644);
4984*4882a593Smuzhiyun MODULE_PARM_DESC(lpfc_force_rscn,
4985*4882a593Smuzhiyun 		 "Force an RSCN to be sent to all remote NPorts");
lpfc_param_show(force_rscn)4986*4882a593Smuzhiyun lpfc_param_show(force_rscn)
4987*4882a593Smuzhiyun 
4988*4882a593Smuzhiyun /**
4989*4882a593Smuzhiyun  * lpfc_force_rscn_init - Force an RSCN to be sent to all remote NPorts
4990*4882a593Smuzhiyun  * @phba: lpfc_hba pointer.
4991*4882a593Smuzhiyun  * @val: unused value.
4992*4882a593Smuzhiyun  *
4993*4882a593Smuzhiyun  * Returns:
4994*4882a593Smuzhiyun  * zero if val saved.
4995*4882a593Smuzhiyun  **/
4996*4882a593Smuzhiyun static int
4997*4882a593Smuzhiyun lpfc_force_rscn_init(struct lpfc_hba *phba, int val)
4998*4882a593Smuzhiyun {
4999*4882a593Smuzhiyun 	return 0;
5000*4882a593Smuzhiyun }
5001*4882a593Smuzhiyun static DEVICE_ATTR_RW(lpfc_force_rscn);
5002*4882a593Smuzhiyun 
5003*4882a593Smuzhiyun /**
5004*4882a593Smuzhiyun  * lpfc_fcp_imax_store
5005*4882a593Smuzhiyun  *
5006*4882a593Smuzhiyun  * @dev: class device that is converted into a Scsi_host.
5007*4882a593Smuzhiyun  * @attr: device attribute, not used.
5008*4882a593Smuzhiyun  * @buf: string with the number of fast-path FCP interrupts per second.
5009*4882a593Smuzhiyun  * @count: unused variable.
5010*4882a593Smuzhiyun  *
5011*4882a593Smuzhiyun  * Description:
5012*4882a593Smuzhiyun  * If val is in a valid range [636,651042], then set the adapter's
5013*4882a593Smuzhiyun  * maximum number of fast-path FCP interrupts per second.
5014*4882a593Smuzhiyun  *
5015*4882a593Smuzhiyun  * Returns:
5016*4882a593Smuzhiyun  * length of the buf on success if val is in range the intended mode
5017*4882a593Smuzhiyun  * is supported.
5018*4882a593Smuzhiyun  * -EINVAL if val out of range or intended mode is not supported.
5019*4882a593Smuzhiyun  **/
5020*4882a593Smuzhiyun static ssize_t
lpfc_fcp_imax_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)5021*4882a593Smuzhiyun lpfc_fcp_imax_store(struct device *dev, struct device_attribute *attr,
5022*4882a593Smuzhiyun 			 const char *buf, size_t count)
5023*4882a593Smuzhiyun {
5024*4882a593Smuzhiyun 	struct Scsi_Host *shost = class_to_shost(dev);
5025*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata;
5026*4882a593Smuzhiyun 	struct lpfc_hba *phba = vport->phba;
5027*4882a593Smuzhiyun 	struct lpfc_eq_intr_info *eqi;
5028*4882a593Smuzhiyun 	uint32_t usdelay;
5029*4882a593Smuzhiyun 	int val = 0, i;
5030*4882a593Smuzhiyun 
5031*4882a593Smuzhiyun 	/* fcp_imax is only valid for SLI4 */
5032*4882a593Smuzhiyun 	if (phba->sli_rev != LPFC_SLI_REV4)
5033*4882a593Smuzhiyun 		return -EINVAL;
5034*4882a593Smuzhiyun 
5035*4882a593Smuzhiyun 	/* Sanity check on user data */
5036*4882a593Smuzhiyun 	if (!isdigit(buf[0]))
5037*4882a593Smuzhiyun 		return -EINVAL;
5038*4882a593Smuzhiyun 	if (sscanf(buf, "%i", &val) != 1)
5039*4882a593Smuzhiyun 		return -EINVAL;
5040*4882a593Smuzhiyun 
5041*4882a593Smuzhiyun 	/*
5042*4882a593Smuzhiyun 	 * Value range for the HBA is [5000,5000000]
5043*4882a593Smuzhiyun 	 * The value for each EQ depends on how many EQs are configured.
5044*4882a593Smuzhiyun 	 * Allow value == 0
5045*4882a593Smuzhiyun 	 */
5046*4882a593Smuzhiyun 	if (val && (val < LPFC_MIN_IMAX || val > LPFC_MAX_IMAX))
5047*4882a593Smuzhiyun 		return -EINVAL;
5048*4882a593Smuzhiyun 
5049*4882a593Smuzhiyun 	phba->cfg_auto_imax = (val) ? 0 : 1;
5050*4882a593Smuzhiyun 	if (phba->cfg_fcp_imax && !val) {
5051*4882a593Smuzhiyun 		queue_delayed_work(phba->wq, &phba->eq_delay_work,
5052*4882a593Smuzhiyun 				   msecs_to_jiffies(LPFC_EQ_DELAY_MSECS));
5053*4882a593Smuzhiyun 
5054*4882a593Smuzhiyun 		for_each_present_cpu(i) {
5055*4882a593Smuzhiyun 			eqi = per_cpu_ptr(phba->sli4_hba.eq_info, i);
5056*4882a593Smuzhiyun 			eqi->icnt = 0;
5057*4882a593Smuzhiyun 		}
5058*4882a593Smuzhiyun 	}
5059*4882a593Smuzhiyun 
5060*4882a593Smuzhiyun 	phba->cfg_fcp_imax = (uint32_t)val;
5061*4882a593Smuzhiyun 
5062*4882a593Smuzhiyun 	if (phba->cfg_fcp_imax)
5063*4882a593Smuzhiyun 		usdelay = LPFC_SEC_TO_USEC / phba->cfg_fcp_imax;
5064*4882a593Smuzhiyun 	else
5065*4882a593Smuzhiyun 		usdelay = 0;
5066*4882a593Smuzhiyun 
5067*4882a593Smuzhiyun 	for (i = 0; i < phba->cfg_irq_chann; i += LPFC_MAX_EQ_DELAY_EQID_CNT)
5068*4882a593Smuzhiyun 		lpfc_modify_hba_eq_delay(phba, i, LPFC_MAX_EQ_DELAY_EQID_CNT,
5069*4882a593Smuzhiyun 					 usdelay);
5070*4882a593Smuzhiyun 
5071*4882a593Smuzhiyun 	return strlen(buf);
5072*4882a593Smuzhiyun }
5073*4882a593Smuzhiyun 
5074*4882a593Smuzhiyun /*
5075*4882a593Smuzhiyun # lpfc_fcp_imax: The maximum number of fast-path FCP interrupts per second
5076*4882a593Smuzhiyun # for the HBA.
5077*4882a593Smuzhiyun #
5078*4882a593Smuzhiyun # Value range is [5,000 to 5,000,000]. Default value is 50,000.
5079*4882a593Smuzhiyun */
5080*4882a593Smuzhiyun static int lpfc_fcp_imax = LPFC_DEF_IMAX;
5081*4882a593Smuzhiyun module_param(lpfc_fcp_imax, int, S_IRUGO|S_IWUSR);
5082*4882a593Smuzhiyun MODULE_PARM_DESC(lpfc_fcp_imax,
5083*4882a593Smuzhiyun 	    "Set the maximum number of FCP interrupts per second per HBA");
lpfc_param_show(fcp_imax)5084*4882a593Smuzhiyun lpfc_param_show(fcp_imax)
5085*4882a593Smuzhiyun 
5086*4882a593Smuzhiyun /**
5087*4882a593Smuzhiyun  * lpfc_fcp_imax_init - Set the initial sr-iov virtual function enable
5088*4882a593Smuzhiyun  * @phba: lpfc_hba pointer.
5089*4882a593Smuzhiyun  * @val: link speed value.
5090*4882a593Smuzhiyun  *
5091*4882a593Smuzhiyun  * Description:
5092*4882a593Smuzhiyun  * If val is in a valid range [636,651042], then initialize the adapter's
5093*4882a593Smuzhiyun  * maximum number of fast-path FCP interrupts per second.
5094*4882a593Smuzhiyun  *
5095*4882a593Smuzhiyun  * Returns:
5096*4882a593Smuzhiyun  * zero if val saved.
5097*4882a593Smuzhiyun  * -EINVAL val out of range
5098*4882a593Smuzhiyun  **/
5099*4882a593Smuzhiyun static int
5100*4882a593Smuzhiyun lpfc_fcp_imax_init(struct lpfc_hba *phba, int val)
5101*4882a593Smuzhiyun {
5102*4882a593Smuzhiyun 	if (phba->sli_rev != LPFC_SLI_REV4) {
5103*4882a593Smuzhiyun 		phba->cfg_fcp_imax = 0;
5104*4882a593Smuzhiyun 		return 0;
5105*4882a593Smuzhiyun 	}
5106*4882a593Smuzhiyun 
5107*4882a593Smuzhiyun 	if ((val >= LPFC_MIN_IMAX && val <= LPFC_MAX_IMAX) ||
5108*4882a593Smuzhiyun 	    (val == 0)) {
5109*4882a593Smuzhiyun 		phba->cfg_fcp_imax = val;
5110*4882a593Smuzhiyun 		return 0;
5111*4882a593Smuzhiyun 	}
5112*4882a593Smuzhiyun 
5113*4882a593Smuzhiyun 	lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
5114*4882a593Smuzhiyun 			"3016 lpfc_fcp_imax: %d out of range, using default\n",
5115*4882a593Smuzhiyun 			val);
5116*4882a593Smuzhiyun 	phba->cfg_fcp_imax = LPFC_DEF_IMAX;
5117*4882a593Smuzhiyun 
5118*4882a593Smuzhiyun 	return 0;
5119*4882a593Smuzhiyun }
5120*4882a593Smuzhiyun 
5121*4882a593Smuzhiyun static DEVICE_ATTR_RW(lpfc_fcp_imax);
5122*4882a593Smuzhiyun 
5123*4882a593Smuzhiyun /**
5124*4882a593Smuzhiyun  * lpfc_cq_max_proc_limit_store
5125*4882a593Smuzhiyun  *
5126*4882a593Smuzhiyun  * @dev: class device that is converted into a Scsi_host.
5127*4882a593Smuzhiyun  * @attr: device attribute, not used.
5128*4882a593Smuzhiyun  * @buf: string with the cq max processing limit of cqes
5129*4882a593Smuzhiyun  * @count: unused variable.
5130*4882a593Smuzhiyun  *
5131*4882a593Smuzhiyun  * Description:
5132*4882a593Smuzhiyun  * If val is in a valid range, then set value on each cq
5133*4882a593Smuzhiyun  *
5134*4882a593Smuzhiyun  * Returns:
5135*4882a593Smuzhiyun  * The length of the buf: if successful
5136*4882a593Smuzhiyun  * -ERANGE: if val is not in the valid range
5137*4882a593Smuzhiyun  * -EINVAL: if bad value format or intended mode is not supported.
5138*4882a593Smuzhiyun  **/
5139*4882a593Smuzhiyun static ssize_t
lpfc_cq_max_proc_limit_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)5140*4882a593Smuzhiyun lpfc_cq_max_proc_limit_store(struct device *dev, struct device_attribute *attr,
5141*4882a593Smuzhiyun 			 const char *buf, size_t count)
5142*4882a593Smuzhiyun {
5143*4882a593Smuzhiyun 	struct Scsi_Host *shost = class_to_shost(dev);
5144*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata;
5145*4882a593Smuzhiyun 	struct lpfc_hba *phba = vport->phba;
5146*4882a593Smuzhiyun 	struct lpfc_queue *eq, *cq;
5147*4882a593Smuzhiyun 	unsigned long val;
5148*4882a593Smuzhiyun 	int i;
5149*4882a593Smuzhiyun 
5150*4882a593Smuzhiyun 	/* cq_max_proc_limit is only valid for SLI4 */
5151*4882a593Smuzhiyun 	if (phba->sli_rev != LPFC_SLI_REV4)
5152*4882a593Smuzhiyun 		return -EINVAL;
5153*4882a593Smuzhiyun 
5154*4882a593Smuzhiyun 	/* Sanity check on user data */
5155*4882a593Smuzhiyun 	if (!isdigit(buf[0]))
5156*4882a593Smuzhiyun 		return -EINVAL;
5157*4882a593Smuzhiyun 	if (kstrtoul(buf, 0, &val))
5158*4882a593Smuzhiyun 		return -EINVAL;
5159*4882a593Smuzhiyun 
5160*4882a593Smuzhiyun 	if (val < LPFC_CQ_MIN_PROC_LIMIT || val > LPFC_CQ_MAX_PROC_LIMIT)
5161*4882a593Smuzhiyun 		return -ERANGE;
5162*4882a593Smuzhiyun 
5163*4882a593Smuzhiyun 	phba->cfg_cq_max_proc_limit = (uint32_t)val;
5164*4882a593Smuzhiyun 
5165*4882a593Smuzhiyun 	/* set the values on the cq's */
5166*4882a593Smuzhiyun 	for (i = 0; i < phba->cfg_irq_chann; i++) {
5167*4882a593Smuzhiyun 		/* Get the EQ corresponding to the IRQ vector */
5168*4882a593Smuzhiyun 		eq = phba->sli4_hba.hba_eq_hdl[i].eq;
5169*4882a593Smuzhiyun 		if (!eq)
5170*4882a593Smuzhiyun 			continue;
5171*4882a593Smuzhiyun 
5172*4882a593Smuzhiyun 		list_for_each_entry(cq, &eq->child_list, list)
5173*4882a593Smuzhiyun 			cq->max_proc_limit = min(phba->cfg_cq_max_proc_limit,
5174*4882a593Smuzhiyun 						 cq->entry_count);
5175*4882a593Smuzhiyun 	}
5176*4882a593Smuzhiyun 
5177*4882a593Smuzhiyun 	return strlen(buf);
5178*4882a593Smuzhiyun }
5179*4882a593Smuzhiyun 
5180*4882a593Smuzhiyun /*
5181*4882a593Smuzhiyun  * lpfc_cq_max_proc_limit: The maximum number CQE entries processed in an
5182*4882a593Smuzhiyun  *   itteration of CQ processing.
5183*4882a593Smuzhiyun  */
5184*4882a593Smuzhiyun static int lpfc_cq_max_proc_limit = LPFC_CQ_DEF_MAX_PROC_LIMIT;
5185*4882a593Smuzhiyun module_param(lpfc_cq_max_proc_limit, int, 0644);
5186*4882a593Smuzhiyun MODULE_PARM_DESC(lpfc_cq_max_proc_limit,
5187*4882a593Smuzhiyun 	    "Set the maximum number CQEs processed in an iteration of "
5188*4882a593Smuzhiyun 	    "CQ processing");
5189*4882a593Smuzhiyun lpfc_param_show(cq_max_proc_limit)
5190*4882a593Smuzhiyun 
5191*4882a593Smuzhiyun /*
5192*4882a593Smuzhiyun  * lpfc_cq_poll_threshold: Set the threshold of CQE completions in a
5193*4882a593Smuzhiyun  *   single handler call which should request a polled completion rather
5194*4882a593Smuzhiyun  *   than re-enabling interrupts.
5195*4882a593Smuzhiyun  */
5196*4882a593Smuzhiyun LPFC_ATTR_RW(cq_poll_threshold, LPFC_CQ_DEF_THRESHOLD_TO_POLL,
5197*4882a593Smuzhiyun 	     LPFC_CQ_MIN_THRESHOLD_TO_POLL,
5198*4882a593Smuzhiyun 	     LPFC_CQ_MAX_THRESHOLD_TO_POLL,
5199*4882a593Smuzhiyun 	     "CQE Processing Threshold to enable Polling");
5200*4882a593Smuzhiyun 
5201*4882a593Smuzhiyun /**
5202*4882a593Smuzhiyun  * lpfc_cq_max_proc_limit_init - Set the initial cq max_proc_limit
5203*4882a593Smuzhiyun  * @phba: lpfc_hba pointer.
5204*4882a593Smuzhiyun  * @val: entry limit
5205*4882a593Smuzhiyun  *
5206*4882a593Smuzhiyun  * Description:
5207*4882a593Smuzhiyun  * If val is in a valid range, then initialize the adapter's maximum
5208*4882a593Smuzhiyun  * value.
5209*4882a593Smuzhiyun  *
5210*4882a593Smuzhiyun  * Returns:
5211*4882a593Smuzhiyun  *  Always returns 0 for success, even if value not always set to
5212*4882a593Smuzhiyun  *  requested value. If value out of range or not supported, will fall
5213*4882a593Smuzhiyun  *  back to default.
5214*4882a593Smuzhiyun  **/
5215*4882a593Smuzhiyun static int
lpfc_cq_max_proc_limit_init(struct lpfc_hba * phba,int val)5216*4882a593Smuzhiyun lpfc_cq_max_proc_limit_init(struct lpfc_hba *phba, int val)
5217*4882a593Smuzhiyun {
5218*4882a593Smuzhiyun 	phba->cfg_cq_max_proc_limit = LPFC_CQ_DEF_MAX_PROC_LIMIT;
5219*4882a593Smuzhiyun 
5220*4882a593Smuzhiyun 	if (phba->sli_rev != LPFC_SLI_REV4)
5221*4882a593Smuzhiyun 		return 0;
5222*4882a593Smuzhiyun 
5223*4882a593Smuzhiyun 	if (val >= LPFC_CQ_MIN_PROC_LIMIT && val <= LPFC_CQ_MAX_PROC_LIMIT) {
5224*4882a593Smuzhiyun 		phba->cfg_cq_max_proc_limit = val;
5225*4882a593Smuzhiyun 		return 0;
5226*4882a593Smuzhiyun 	}
5227*4882a593Smuzhiyun 
5228*4882a593Smuzhiyun 	lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
5229*4882a593Smuzhiyun 			"0371 "LPFC_DRIVER_NAME"_cq_max_proc_limit: "
5230*4882a593Smuzhiyun 			"%d out of range, using default\n",
5231*4882a593Smuzhiyun 			phba->cfg_cq_max_proc_limit);
5232*4882a593Smuzhiyun 
5233*4882a593Smuzhiyun 	return 0;
5234*4882a593Smuzhiyun }
5235*4882a593Smuzhiyun 
5236*4882a593Smuzhiyun static DEVICE_ATTR_RW(lpfc_cq_max_proc_limit);
5237*4882a593Smuzhiyun 
5238*4882a593Smuzhiyun /**
5239*4882a593Smuzhiyun  * lpfc_state_show - Display current driver CPU affinity
5240*4882a593Smuzhiyun  * @dev: class converted to a Scsi_host structure.
5241*4882a593Smuzhiyun  * @attr: device attribute, not used.
5242*4882a593Smuzhiyun  * @buf: on return contains text describing the state of the link.
5243*4882a593Smuzhiyun  *
5244*4882a593Smuzhiyun  * Returns: size of formatted string.
5245*4882a593Smuzhiyun  **/
5246*4882a593Smuzhiyun static ssize_t
lpfc_fcp_cpu_map_show(struct device * dev,struct device_attribute * attr,char * buf)5247*4882a593Smuzhiyun lpfc_fcp_cpu_map_show(struct device *dev, struct device_attribute *attr,
5248*4882a593Smuzhiyun 		      char *buf)
5249*4882a593Smuzhiyun {
5250*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
5251*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata;
5252*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
5253*4882a593Smuzhiyun 	struct lpfc_vector_map_info *cpup;
5254*4882a593Smuzhiyun 	int  len = 0;
5255*4882a593Smuzhiyun 
5256*4882a593Smuzhiyun 	if ((phba->sli_rev != LPFC_SLI_REV4) ||
5257*4882a593Smuzhiyun 	    (phba->intr_type != MSIX))
5258*4882a593Smuzhiyun 		return len;
5259*4882a593Smuzhiyun 
5260*4882a593Smuzhiyun 	switch (phba->cfg_fcp_cpu_map) {
5261*4882a593Smuzhiyun 	case 0:
5262*4882a593Smuzhiyun 		len += scnprintf(buf + len, PAGE_SIZE-len,
5263*4882a593Smuzhiyun 				"fcp_cpu_map: No mapping (%d)\n",
5264*4882a593Smuzhiyun 				phba->cfg_fcp_cpu_map);
5265*4882a593Smuzhiyun 		return len;
5266*4882a593Smuzhiyun 	case 1:
5267*4882a593Smuzhiyun 		len += scnprintf(buf + len, PAGE_SIZE-len,
5268*4882a593Smuzhiyun 				"fcp_cpu_map: HBA centric mapping (%d): "
5269*4882a593Smuzhiyun 				"%d of %d CPUs online from %d possible CPUs\n",
5270*4882a593Smuzhiyun 				phba->cfg_fcp_cpu_map, num_online_cpus(),
5271*4882a593Smuzhiyun 				num_present_cpus(),
5272*4882a593Smuzhiyun 				phba->sli4_hba.num_possible_cpu);
5273*4882a593Smuzhiyun 		break;
5274*4882a593Smuzhiyun 	}
5275*4882a593Smuzhiyun 
5276*4882a593Smuzhiyun 	while (phba->sli4_hba.curr_disp_cpu <
5277*4882a593Smuzhiyun 	       phba->sli4_hba.num_possible_cpu) {
5278*4882a593Smuzhiyun 		cpup = &phba->sli4_hba.cpu_map[phba->sli4_hba.curr_disp_cpu];
5279*4882a593Smuzhiyun 
5280*4882a593Smuzhiyun 		if (!cpu_present(phba->sli4_hba.curr_disp_cpu))
5281*4882a593Smuzhiyun 			len += scnprintf(buf + len, PAGE_SIZE - len,
5282*4882a593Smuzhiyun 					"CPU %02d not present\n",
5283*4882a593Smuzhiyun 					phba->sli4_hba.curr_disp_cpu);
5284*4882a593Smuzhiyun 		else if (cpup->eq == LPFC_VECTOR_MAP_EMPTY) {
5285*4882a593Smuzhiyun 			if (cpup->hdwq == LPFC_VECTOR_MAP_EMPTY)
5286*4882a593Smuzhiyun 				len += scnprintf(
5287*4882a593Smuzhiyun 					buf + len, PAGE_SIZE - len,
5288*4882a593Smuzhiyun 					"CPU %02d hdwq None "
5289*4882a593Smuzhiyun 					"physid %d coreid %d ht %d ua %d\n",
5290*4882a593Smuzhiyun 					phba->sli4_hba.curr_disp_cpu,
5291*4882a593Smuzhiyun 					cpup->phys_id, cpup->core_id,
5292*4882a593Smuzhiyun 					(cpup->flag & LPFC_CPU_MAP_HYPER),
5293*4882a593Smuzhiyun 					(cpup->flag & LPFC_CPU_MAP_UNASSIGN));
5294*4882a593Smuzhiyun 			else
5295*4882a593Smuzhiyun 				len += scnprintf(
5296*4882a593Smuzhiyun 					buf + len, PAGE_SIZE - len,
5297*4882a593Smuzhiyun 					"CPU %02d EQ None hdwq %04d "
5298*4882a593Smuzhiyun 					"physid %d coreid %d ht %d ua %d\n",
5299*4882a593Smuzhiyun 					phba->sli4_hba.curr_disp_cpu,
5300*4882a593Smuzhiyun 					cpup->hdwq, cpup->phys_id,
5301*4882a593Smuzhiyun 					cpup->core_id,
5302*4882a593Smuzhiyun 					(cpup->flag & LPFC_CPU_MAP_HYPER),
5303*4882a593Smuzhiyun 					(cpup->flag & LPFC_CPU_MAP_UNASSIGN));
5304*4882a593Smuzhiyun 		} else {
5305*4882a593Smuzhiyun 			if (cpup->hdwq == LPFC_VECTOR_MAP_EMPTY)
5306*4882a593Smuzhiyun 				len += scnprintf(
5307*4882a593Smuzhiyun 					buf + len, PAGE_SIZE - len,
5308*4882a593Smuzhiyun 					"CPU %02d hdwq None "
5309*4882a593Smuzhiyun 					"physid %d coreid %d ht %d ua %d IRQ %d\n",
5310*4882a593Smuzhiyun 					phba->sli4_hba.curr_disp_cpu,
5311*4882a593Smuzhiyun 					cpup->phys_id,
5312*4882a593Smuzhiyun 					cpup->core_id,
5313*4882a593Smuzhiyun 					(cpup->flag & LPFC_CPU_MAP_HYPER),
5314*4882a593Smuzhiyun 					(cpup->flag & LPFC_CPU_MAP_UNASSIGN),
5315*4882a593Smuzhiyun 					lpfc_get_irq(cpup->eq));
5316*4882a593Smuzhiyun 			else
5317*4882a593Smuzhiyun 				len += scnprintf(
5318*4882a593Smuzhiyun 					buf + len, PAGE_SIZE - len,
5319*4882a593Smuzhiyun 					"CPU %02d EQ %04d hdwq %04d "
5320*4882a593Smuzhiyun 					"physid %d coreid %d ht %d ua %d IRQ %d\n",
5321*4882a593Smuzhiyun 					phba->sli4_hba.curr_disp_cpu,
5322*4882a593Smuzhiyun 					cpup->eq, cpup->hdwq, cpup->phys_id,
5323*4882a593Smuzhiyun 					cpup->core_id,
5324*4882a593Smuzhiyun 					(cpup->flag & LPFC_CPU_MAP_HYPER),
5325*4882a593Smuzhiyun 					(cpup->flag & LPFC_CPU_MAP_UNASSIGN),
5326*4882a593Smuzhiyun 					lpfc_get_irq(cpup->eq));
5327*4882a593Smuzhiyun 		}
5328*4882a593Smuzhiyun 
5329*4882a593Smuzhiyun 		phba->sli4_hba.curr_disp_cpu++;
5330*4882a593Smuzhiyun 
5331*4882a593Smuzhiyun 		/* display max number of CPUs keeping some margin */
5332*4882a593Smuzhiyun 		if (phba->sli4_hba.curr_disp_cpu <
5333*4882a593Smuzhiyun 				phba->sli4_hba.num_possible_cpu &&
5334*4882a593Smuzhiyun 				(len >= (PAGE_SIZE - 64))) {
5335*4882a593Smuzhiyun 			len += scnprintf(buf + len,
5336*4882a593Smuzhiyun 					PAGE_SIZE - len, "more...\n");
5337*4882a593Smuzhiyun 			break;
5338*4882a593Smuzhiyun 		}
5339*4882a593Smuzhiyun 	}
5340*4882a593Smuzhiyun 
5341*4882a593Smuzhiyun 	if (phba->sli4_hba.curr_disp_cpu == phba->sli4_hba.num_possible_cpu)
5342*4882a593Smuzhiyun 		phba->sli4_hba.curr_disp_cpu = 0;
5343*4882a593Smuzhiyun 
5344*4882a593Smuzhiyun 	return len;
5345*4882a593Smuzhiyun }
5346*4882a593Smuzhiyun 
5347*4882a593Smuzhiyun /**
5348*4882a593Smuzhiyun  * lpfc_fcp_cpu_map_store - Change CPU affinity of driver vectors
5349*4882a593Smuzhiyun  * @dev: class device that is converted into a Scsi_host.
5350*4882a593Smuzhiyun  * @attr: device attribute, not used.
5351*4882a593Smuzhiyun  * @buf: one or more lpfc_polling_flags values.
5352*4882a593Smuzhiyun  * @count: not used.
5353*4882a593Smuzhiyun  *
5354*4882a593Smuzhiyun  * Returns:
5355*4882a593Smuzhiyun  * -EINVAL  - Not implemented yet.
5356*4882a593Smuzhiyun  **/
5357*4882a593Smuzhiyun static ssize_t
lpfc_fcp_cpu_map_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)5358*4882a593Smuzhiyun lpfc_fcp_cpu_map_store(struct device *dev, struct device_attribute *attr,
5359*4882a593Smuzhiyun 		       const char *buf, size_t count)
5360*4882a593Smuzhiyun {
5361*4882a593Smuzhiyun 	return -EINVAL;
5362*4882a593Smuzhiyun }
5363*4882a593Smuzhiyun 
5364*4882a593Smuzhiyun /*
5365*4882a593Smuzhiyun # lpfc_fcp_cpu_map: Defines how to map CPUs to IRQ vectors
5366*4882a593Smuzhiyun # for the HBA.
5367*4882a593Smuzhiyun #
5368*4882a593Smuzhiyun # Value range is [0 to 1]. Default value is LPFC_HBA_CPU_MAP (1).
5369*4882a593Smuzhiyun #	0 - Do not affinitze IRQ vectors
5370*4882a593Smuzhiyun #	1 - Affintize HBA vectors with respect to each HBA
5371*4882a593Smuzhiyun #	    (start with CPU0 for each HBA)
5372*4882a593Smuzhiyun # This also defines how Hardware Queues are mapped to specific CPUs.
5373*4882a593Smuzhiyun */
5374*4882a593Smuzhiyun static int lpfc_fcp_cpu_map = LPFC_HBA_CPU_MAP;
5375*4882a593Smuzhiyun module_param(lpfc_fcp_cpu_map, int, S_IRUGO|S_IWUSR);
5376*4882a593Smuzhiyun MODULE_PARM_DESC(lpfc_fcp_cpu_map,
5377*4882a593Smuzhiyun 		 "Defines how to map CPUs to IRQ vectors per HBA");
5378*4882a593Smuzhiyun 
5379*4882a593Smuzhiyun /**
5380*4882a593Smuzhiyun  * lpfc_fcp_cpu_map_init - Set the initial sr-iov virtual function enable
5381*4882a593Smuzhiyun  * @phba: lpfc_hba pointer.
5382*4882a593Smuzhiyun  * @val: link speed value.
5383*4882a593Smuzhiyun  *
5384*4882a593Smuzhiyun  * Description:
5385*4882a593Smuzhiyun  * If val is in a valid range [0-2], then affinitze the adapter's
5386*4882a593Smuzhiyun  * MSIX vectors.
5387*4882a593Smuzhiyun  *
5388*4882a593Smuzhiyun  * Returns:
5389*4882a593Smuzhiyun  * zero if val saved.
5390*4882a593Smuzhiyun  * -EINVAL val out of range
5391*4882a593Smuzhiyun  **/
5392*4882a593Smuzhiyun static int
lpfc_fcp_cpu_map_init(struct lpfc_hba * phba,int val)5393*4882a593Smuzhiyun lpfc_fcp_cpu_map_init(struct lpfc_hba *phba, int val)
5394*4882a593Smuzhiyun {
5395*4882a593Smuzhiyun 	if (phba->sli_rev != LPFC_SLI_REV4) {
5396*4882a593Smuzhiyun 		phba->cfg_fcp_cpu_map = 0;
5397*4882a593Smuzhiyun 		return 0;
5398*4882a593Smuzhiyun 	}
5399*4882a593Smuzhiyun 
5400*4882a593Smuzhiyun 	if (val >= LPFC_MIN_CPU_MAP && val <= LPFC_MAX_CPU_MAP) {
5401*4882a593Smuzhiyun 		phba->cfg_fcp_cpu_map = val;
5402*4882a593Smuzhiyun 		return 0;
5403*4882a593Smuzhiyun 	}
5404*4882a593Smuzhiyun 
5405*4882a593Smuzhiyun 	lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
5406*4882a593Smuzhiyun 			"3326 lpfc_fcp_cpu_map: %d out of range, using "
5407*4882a593Smuzhiyun 			"default\n", val);
5408*4882a593Smuzhiyun 	phba->cfg_fcp_cpu_map = LPFC_HBA_CPU_MAP;
5409*4882a593Smuzhiyun 
5410*4882a593Smuzhiyun 	return 0;
5411*4882a593Smuzhiyun }
5412*4882a593Smuzhiyun 
5413*4882a593Smuzhiyun static DEVICE_ATTR_RW(lpfc_fcp_cpu_map);
5414*4882a593Smuzhiyun 
5415*4882a593Smuzhiyun /*
5416*4882a593Smuzhiyun # lpfc_fcp_class:  Determines FC class to use for the FCP protocol.
5417*4882a593Smuzhiyun # Value range is [2,3]. Default value is 3.
5418*4882a593Smuzhiyun */
5419*4882a593Smuzhiyun LPFC_VPORT_ATTR_R(fcp_class, 3, 2, 3,
5420*4882a593Smuzhiyun 		  "Select Fibre Channel class of service for FCP sequences");
5421*4882a593Smuzhiyun 
5422*4882a593Smuzhiyun /*
5423*4882a593Smuzhiyun # lpfc_use_adisc: Use ADISC for FCP rediscovery instead of PLOGI. Value range
5424*4882a593Smuzhiyun # is [0,1]. Default value is 0.
5425*4882a593Smuzhiyun */
5426*4882a593Smuzhiyun LPFC_VPORT_ATTR_RW(use_adisc, 0, 0, 1,
5427*4882a593Smuzhiyun 		   "Use ADISC on rediscovery to authenticate FCP devices");
5428*4882a593Smuzhiyun 
5429*4882a593Smuzhiyun /*
5430*4882a593Smuzhiyun # lpfc_first_burst_size: First burst size to use on the NPorts
5431*4882a593Smuzhiyun # that support first burst.
5432*4882a593Smuzhiyun # Value range is [0,65536]. Default value is 0.
5433*4882a593Smuzhiyun */
5434*4882a593Smuzhiyun LPFC_VPORT_ATTR_RW(first_burst_size, 0, 0, 65536,
5435*4882a593Smuzhiyun 		   "First burst size for Targets that support first burst");
5436*4882a593Smuzhiyun 
5437*4882a593Smuzhiyun /*
5438*4882a593Smuzhiyun * lpfc_nvmet_fb_size: NVME Target mode supported first burst size.
5439*4882a593Smuzhiyun * When the driver is configured as an NVME target, this value is
5440*4882a593Smuzhiyun * communicated to the NVME initiator in the PRLI response.  It is
5441*4882a593Smuzhiyun * used only when the lpfc_nvme_enable_fb and lpfc_nvmet_support
5442*4882a593Smuzhiyun * parameters are set and the target is sending the PRLI RSP.
5443*4882a593Smuzhiyun * Parameter supported on physical port only - no NPIV support.
5444*4882a593Smuzhiyun * Value range is [0,65536]. Default value is 0.
5445*4882a593Smuzhiyun */
5446*4882a593Smuzhiyun LPFC_ATTR_RW(nvmet_fb_size, 0, 0, 65536,
5447*4882a593Smuzhiyun 	     "NVME Target mode first burst size in 512B increments.");
5448*4882a593Smuzhiyun 
5449*4882a593Smuzhiyun /*
5450*4882a593Smuzhiyun  * lpfc_nvme_enable_fb: Enable NVME first burst on I and T functions.
5451*4882a593Smuzhiyun  * For the Initiator (I), enabling this parameter means that an NVMET
5452*4882a593Smuzhiyun  * PRLI response with FBA enabled and an FB_SIZE set to a nonzero value will be
5453*4882a593Smuzhiyun  * processed by the initiator for subsequent NVME FCP IO.
5454*4882a593Smuzhiyun  * Currently, this feature is not supported on the NVME target
5455*4882a593Smuzhiyun  * Value range is [0,1]. Default value is 0 (disabled).
5456*4882a593Smuzhiyun  */
5457*4882a593Smuzhiyun LPFC_ATTR_RW(nvme_enable_fb, 0, 0, 1,
5458*4882a593Smuzhiyun 	     "Enable First Burst feature for NVME Initiator.");
5459*4882a593Smuzhiyun 
5460*4882a593Smuzhiyun /*
5461*4882a593Smuzhiyun # lpfc_max_scsicmpl_time: Use scsi command completion time to control I/O queue
5462*4882a593Smuzhiyun # depth. Default value is 0. When the value of this parameter is zero the
5463*4882a593Smuzhiyun # SCSI command completion time is not used for controlling I/O queue depth. When
5464*4882a593Smuzhiyun # the parameter is set to a non-zero value, the I/O queue depth is controlled
5465*4882a593Smuzhiyun # to limit the I/O completion time to the parameter value.
5466*4882a593Smuzhiyun # The value is set in milliseconds.
5467*4882a593Smuzhiyun */
5468*4882a593Smuzhiyun LPFC_VPORT_ATTR(max_scsicmpl_time, 0, 0, 60000,
5469*4882a593Smuzhiyun 	"Use command completion time to control queue depth");
5470*4882a593Smuzhiyun 
5471*4882a593Smuzhiyun lpfc_vport_param_show(max_scsicmpl_time);
5472*4882a593Smuzhiyun static int
lpfc_max_scsicmpl_time_set(struct lpfc_vport * vport,int val)5473*4882a593Smuzhiyun lpfc_max_scsicmpl_time_set(struct lpfc_vport *vport, int val)
5474*4882a593Smuzhiyun {
5475*4882a593Smuzhiyun 	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
5476*4882a593Smuzhiyun 	struct lpfc_nodelist *ndlp, *next_ndlp;
5477*4882a593Smuzhiyun 
5478*4882a593Smuzhiyun 	if (val == vport->cfg_max_scsicmpl_time)
5479*4882a593Smuzhiyun 		return 0;
5480*4882a593Smuzhiyun 	if ((val < 0) || (val > 60000))
5481*4882a593Smuzhiyun 		return -EINVAL;
5482*4882a593Smuzhiyun 	vport->cfg_max_scsicmpl_time = val;
5483*4882a593Smuzhiyun 
5484*4882a593Smuzhiyun 	spin_lock_irq(shost->host_lock);
5485*4882a593Smuzhiyun 	list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
5486*4882a593Smuzhiyun 		if (!NLP_CHK_NODE_ACT(ndlp))
5487*4882a593Smuzhiyun 			continue;
5488*4882a593Smuzhiyun 		if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
5489*4882a593Smuzhiyun 			continue;
5490*4882a593Smuzhiyun 		ndlp->cmd_qdepth = vport->cfg_tgt_queue_depth;
5491*4882a593Smuzhiyun 	}
5492*4882a593Smuzhiyun 	spin_unlock_irq(shost->host_lock);
5493*4882a593Smuzhiyun 	return 0;
5494*4882a593Smuzhiyun }
5495*4882a593Smuzhiyun lpfc_vport_param_store(max_scsicmpl_time);
5496*4882a593Smuzhiyun static DEVICE_ATTR_RW(lpfc_max_scsicmpl_time);
5497*4882a593Smuzhiyun 
5498*4882a593Smuzhiyun /*
5499*4882a593Smuzhiyun # lpfc_ack0: Use ACK0, instead of ACK1 for class 2 acknowledgement. Value
5500*4882a593Smuzhiyun # range is [0,1]. Default value is 0.
5501*4882a593Smuzhiyun */
5502*4882a593Smuzhiyun LPFC_ATTR_R(ack0, 0, 0, 1, "Enable ACK0 support");
5503*4882a593Smuzhiyun 
5504*4882a593Smuzhiyun /*
5505*4882a593Smuzhiyun # lpfc_xri_rebalancing: enable or disable XRI rebalancing feature
5506*4882a593Smuzhiyun # range is [0,1]. Default value is 1.
5507*4882a593Smuzhiyun */
5508*4882a593Smuzhiyun LPFC_ATTR_R(xri_rebalancing, 1, 0, 1, "Enable/Disable XRI rebalancing");
5509*4882a593Smuzhiyun 
5510*4882a593Smuzhiyun /*
5511*4882a593Smuzhiyun  * lpfc_io_sched: Determine scheduling algrithmn for issuing FCP cmds
5512*4882a593Smuzhiyun  * range is [0,1]. Default value is 0.
5513*4882a593Smuzhiyun  * For [0], FCP commands are issued to Work Queues based on upper layer
5514*4882a593Smuzhiyun  * hardware queue index.
5515*4882a593Smuzhiyun  * For [1], FCP commands are issued to a Work Queue associated with the
5516*4882a593Smuzhiyun  *          current CPU.
5517*4882a593Smuzhiyun  *
5518*4882a593Smuzhiyun  * LPFC_FCP_SCHED_BY_HDWQ == 0
5519*4882a593Smuzhiyun  * LPFC_FCP_SCHED_BY_CPU == 1
5520*4882a593Smuzhiyun  *
5521*4882a593Smuzhiyun  * The driver dynamically sets this to 1 (BY_CPU) if it's able to set up cpu
5522*4882a593Smuzhiyun  * affinity for FCP/NVME I/Os through Work Queues associated with the current
5523*4882a593Smuzhiyun  * CPU. Otherwise, the default 0 (Round Robin) scheduling of FCP/NVME I/Os
5524*4882a593Smuzhiyun  * through WQs will be used.
5525*4882a593Smuzhiyun  */
5526*4882a593Smuzhiyun LPFC_ATTR_RW(fcp_io_sched, LPFC_FCP_SCHED_BY_CPU,
5527*4882a593Smuzhiyun 	     LPFC_FCP_SCHED_BY_HDWQ,
5528*4882a593Smuzhiyun 	     LPFC_FCP_SCHED_BY_CPU,
5529*4882a593Smuzhiyun 	     "Determine scheduling algorithm for "
5530*4882a593Smuzhiyun 	     "issuing commands [0] - Hardware Queue, [1] - Current CPU");
5531*4882a593Smuzhiyun 
5532*4882a593Smuzhiyun /*
5533*4882a593Smuzhiyun  * lpfc_ns_query: Determine algrithmn for NameServer queries after RSCN
5534*4882a593Smuzhiyun  * range is [0,1]. Default value is 0.
5535*4882a593Smuzhiyun  * For [0], GID_FT is used for NameServer queries after RSCN (default)
5536*4882a593Smuzhiyun  * For [1], GID_PT is used for NameServer queries after RSCN
5537*4882a593Smuzhiyun  *
5538*4882a593Smuzhiyun  */
5539*4882a593Smuzhiyun LPFC_ATTR_RW(ns_query, LPFC_NS_QUERY_GID_FT,
5540*4882a593Smuzhiyun 	     LPFC_NS_QUERY_GID_FT, LPFC_NS_QUERY_GID_PT,
5541*4882a593Smuzhiyun 	     "Determine algorithm NameServer queries after RSCN "
5542*4882a593Smuzhiyun 	     "[0] - GID_FT, [1] - GID_PT");
5543*4882a593Smuzhiyun 
5544*4882a593Smuzhiyun /*
5545*4882a593Smuzhiyun # lpfc_fcp2_no_tgt_reset: Determine bus reset behavior
5546*4882a593Smuzhiyun # range is [0,1]. Default value is 0.
5547*4882a593Smuzhiyun # For [0], bus reset issues target reset to ALL devices
5548*4882a593Smuzhiyun # For [1], bus reset issues target reset to non-FCP2 devices
5549*4882a593Smuzhiyun */
5550*4882a593Smuzhiyun LPFC_ATTR_RW(fcp2_no_tgt_reset, 0, 0, 1, "Determine bus reset behavior for "
5551*4882a593Smuzhiyun 	     "FCP2 devices [0] - issue tgt reset, [1] - no tgt reset");
5552*4882a593Smuzhiyun 
5553*4882a593Smuzhiyun 
5554*4882a593Smuzhiyun /*
5555*4882a593Smuzhiyun # lpfc_cr_delay & lpfc_cr_count: Default values for I/O colaesing
5556*4882a593Smuzhiyun # cr_delay (msec) or cr_count outstanding commands. cr_delay can take
5557*4882a593Smuzhiyun # value [0,63]. cr_count can take value [1,255]. Default value of cr_delay
5558*4882a593Smuzhiyun # is 0. Default value of cr_count is 1. The cr_count feature is disabled if
5559*4882a593Smuzhiyun # cr_delay is set to 0.
5560*4882a593Smuzhiyun */
5561*4882a593Smuzhiyun LPFC_ATTR_RW(cr_delay, 0, 0, 63, "A count of milliseconds after which an "
5562*4882a593Smuzhiyun 		"interrupt response is generated");
5563*4882a593Smuzhiyun 
5564*4882a593Smuzhiyun LPFC_ATTR_RW(cr_count, 1, 1, 255, "A count of I/O completions after which an "
5565*4882a593Smuzhiyun 		"interrupt response is generated");
5566*4882a593Smuzhiyun 
5567*4882a593Smuzhiyun /*
5568*4882a593Smuzhiyun # lpfc_multi_ring_support:  Determines how many rings to spread available
5569*4882a593Smuzhiyun # cmd/rsp IOCB entries across.
5570*4882a593Smuzhiyun # Value range is [1,2]. Default value is 1.
5571*4882a593Smuzhiyun */
5572*4882a593Smuzhiyun LPFC_ATTR_R(multi_ring_support, 1, 1, 2, "Determines number of primary "
5573*4882a593Smuzhiyun 		"SLI rings to spread IOCB entries across");
5574*4882a593Smuzhiyun 
5575*4882a593Smuzhiyun /*
5576*4882a593Smuzhiyun # lpfc_multi_ring_rctl:  If lpfc_multi_ring_support is enabled, this
5577*4882a593Smuzhiyun # identifies what rctl value to configure the additional ring for.
5578*4882a593Smuzhiyun # Value range is [1,0xff]. Default value is 4 (Unsolicated Data).
5579*4882a593Smuzhiyun */
5580*4882a593Smuzhiyun LPFC_ATTR_R(multi_ring_rctl, FC_RCTL_DD_UNSOL_DATA, 1,
5581*4882a593Smuzhiyun 	     255, "Identifies RCTL for additional ring configuration");
5582*4882a593Smuzhiyun 
5583*4882a593Smuzhiyun /*
5584*4882a593Smuzhiyun # lpfc_multi_ring_type:  If lpfc_multi_ring_support is enabled, this
5585*4882a593Smuzhiyun # identifies what type value to configure the additional ring for.
5586*4882a593Smuzhiyun # Value range is [1,0xff]. Default value is 5 (LLC/SNAP).
5587*4882a593Smuzhiyun */
5588*4882a593Smuzhiyun LPFC_ATTR_R(multi_ring_type, FC_TYPE_IP, 1,
5589*4882a593Smuzhiyun 	     255, "Identifies TYPE for additional ring configuration");
5590*4882a593Smuzhiyun 
5591*4882a593Smuzhiyun /*
5592*4882a593Smuzhiyun # lpfc_enable_SmartSAN: Sets up FDMI support for SmartSAN
5593*4882a593Smuzhiyun #       0  = SmartSAN functionality disabled (default)
5594*4882a593Smuzhiyun #       1  = SmartSAN functionality enabled
5595*4882a593Smuzhiyun # This parameter will override the value of lpfc_fdmi_on module parameter.
5596*4882a593Smuzhiyun # Value range is [0,1]. Default value is 0.
5597*4882a593Smuzhiyun */
5598*4882a593Smuzhiyun LPFC_ATTR_R(enable_SmartSAN, 0, 0, 1, "Enable SmartSAN functionality");
5599*4882a593Smuzhiyun 
5600*4882a593Smuzhiyun /*
5601*4882a593Smuzhiyun # lpfc_fdmi_on: Controls FDMI support.
5602*4882a593Smuzhiyun #       0       No FDMI support
5603*4882a593Smuzhiyun #       1       Traditional FDMI support (default)
5604*4882a593Smuzhiyun # Traditional FDMI support means the driver will assume FDMI-2 support;
5605*4882a593Smuzhiyun # however, if that fails, it will fallback to FDMI-1.
5606*4882a593Smuzhiyun # If lpfc_enable_SmartSAN is set to 1, the driver ignores lpfc_fdmi_on.
5607*4882a593Smuzhiyun # If lpfc_enable_SmartSAN is set 0, the driver uses the current value of
5608*4882a593Smuzhiyun # lpfc_fdmi_on.
5609*4882a593Smuzhiyun # Value range [0,1]. Default value is 1.
5610*4882a593Smuzhiyun */
5611*4882a593Smuzhiyun LPFC_ATTR_R(fdmi_on, 1, 0, 1, "Enable FDMI support");
5612*4882a593Smuzhiyun 
5613*4882a593Smuzhiyun /*
5614*4882a593Smuzhiyun # Specifies the maximum number of ELS cmds we can have outstanding (for
5615*4882a593Smuzhiyun # discovery). Value range is [1,64]. Default value = 32.
5616*4882a593Smuzhiyun */
5617*4882a593Smuzhiyun LPFC_VPORT_ATTR(discovery_threads, 32, 1, 64, "Maximum number of ELS commands "
5618*4882a593Smuzhiyun 		 "during discovery");
5619*4882a593Smuzhiyun 
5620*4882a593Smuzhiyun /*
5621*4882a593Smuzhiyun # lpfc_max_luns: maximum allowed LUN ID. This is the highest LUN ID that
5622*4882a593Smuzhiyun #    will be scanned by the SCSI midlayer when sequential scanning is
5623*4882a593Smuzhiyun #    used; and is also the highest LUN ID allowed when the SCSI midlayer
5624*4882a593Smuzhiyun #    parses REPORT_LUN responses. The lpfc driver has no LUN count or
5625*4882a593Smuzhiyun #    LUN ID limit, but the SCSI midlayer requires this field for the uses
5626*4882a593Smuzhiyun #    above. The lpfc driver limits the default value to 255 for two reasons.
5627*4882a593Smuzhiyun #    As it bounds the sequential scan loop, scanning for thousands of luns
5628*4882a593Smuzhiyun #    on a target can take minutes of wall clock time.  Additionally,
5629*4882a593Smuzhiyun #    there are FC targets, such as JBODs, that only recognize 8-bits of
5630*4882a593Smuzhiyun #    LUN ID. When they receive a value greater than 8 bits, they chop off
5631*4882a593Smuzhiyun #    the high order bits. In other words, they see LUN IDs 0, 256, 512,
5632*4882a593Smuzhiyun #    and so on all as LUN ID 0. This causes the linux kernel, which sees
5633*4882a593Smuzhiyun #    valid responses at each of the LUN IDs, to believe there are multiple
5634*4882a593Smuzhiyun #    devices present, when in fact, there is only 1.
5635*4882a593Smuzhiyun #    A customer that is aware of their target behaviors, and the results as
5636*4882a593Smuzhiyun #    indicated above, is welcome to increase the lpfc_max_luns value.
5637*4882a593Smuzhiyun #    As mentioned, this value is not used by the lpfc driver, only the
5638*4882a593Smuzhiyun #    SCSI midlayer.
5639*4882a593Smuzhiyun # Value range is [0,65535]. Default value is 255.
5640*4882a593Smuzhiyun # NOTE: The SCSI layer might probe all allowed LUN on some old targets.
5641*4882a593Smuzhiyun */
5642*4882a593Smuzhiyun LPFC_VPORT_ULL_ATTR_R(max_luns, 255, 0, 65535, "Maximum allowed LUN ID");
5643*4882a593Smuzhiyun 
5644*4882a593Smuzhiyun /*
5645*4882a593Smuzhiyun # lpfc_poll_tmo: .Milliseconds driver will wait between polling FCP ring.
5646*4882a593Smuzhiyun # Value range is [1,255], default value is 10.
5647*4882a593Smuzhiyun */
5648*4882a593Smuzhiyun LPFC_ATTR_RW(poll_tmo, 10, 1, 255,
5649*4882a593Smuzhiyun 	     "Milliseconds driver will wait between polling FCP ring");
5650*4882a593Smuzhiyun 
5651*4882a593Smuzhiyun /*
5652*4882a593Smuzhiyun # lpfc_task_mgmt_tmo: Maximum time to wait for task management commands
5653*4882a593Smuzhiyun # to complete in seconds. Value range is [5,180], default value is 60.
5654*4882a593Smuzhiyun */
5655*4882a593Smuzhiyun LPFC_ATTR_RW(task_mgmt_tmo, 60, 5, 180,
5656*4882a593Smuzhiyun 	     "Maximum time to wait for task management commands to complete");
5657*4882a593Smuzhiyun /*
5658*4882a593Smuzhiyun # lpfc_use_msi: Use MSI (Message Signaled Interrupts) in systems that
5659*4882a593Smuzhiyun #		support this feature
5660*4882a593Smuzhiyun #       0  = MSI disabled
5661*4882a593Smuzhiyun #       1  = MSI enabled
5662*4882a593Smuzhiyun #       2  = MSI-X enabled (default)
5663*4882a593Smuzhiyun # Value range is [0,2]. Default value is 2.
5664*4882a593Smuzhiyun */
5665*4882a593Smuzhiyun LPFC_ATTR_R(use_msi, 2, 0, 2, "Use Message Signaled Interrupts (1) or "
5666*4882a593Smuzhiyun 	    "MSI-X (2), if possible");
5667*4882a593Smuzhiyun 
5668*4882a593Smuzhiyun /*
5669*4882a593Smuzhiyun  * lpfc_nvme_oas: Use the oas bit when sending NVME/NVMET IOs
5670*4882a593Smuzhiyun  *
5671*4882a593Smuzhiyun  *      0  = NVME OAS disabled
5672*4882a593Smuzhiyun  *      1  = NVME OAS enabled
5673*4882a593Smuzhiyun  *
5674*4882a593Smuzhiyun  * Value range is [0,1]. Default value is 0.
5675*4882a593Smuzhiyun  */
5676*4882a593Smuzhiyun LPFC_ATTR_RW(nvme_oas, 0, 0, 1,
5677*4882a593Smuzhiyun 	     "Use OAS bit on NVME IOs");
5678*4882a593Smuzhiyun 
5679*4882a593Smuzhiyun /*
5680*4882a593Smuzhiyun  * lpfc_nvme_embed_cmd: Use the oas bit when sending NVME/NVMET IOs
5681*4882a593Smuzhiyun  *
5682*4882a593Smuzhiyun  *      0  = Put NVME Command in SGL
5683*4882a593Smuzhiyun  *      1  = Embed NVME Command in WQE (unless G7)
5684*4882a593Smuzhiyun  *      2 =  Embed NVME Command in WQE (force)
5685*4882a593Smuzhiyun  *
5686*4882a593Smuzhiyun  * Value range is [0,2]. Default value is 1.
5687*4882a593Smuzhiyun  */
5688*4882a593Smuzhiyun LPFC_ATTR_RW(nvme_embed_cmd, 1, 0, 2,
5689*4882a593Smuzhiyun 	     "Embed NVME Command in WQE");
5690*4882a593Smuzhiyun 
5691*4882a593Smuzhiyun /*
5692*4882a593Smuzhiyun  * lpfc_fcp_mq_threshold: Set the maximum number of Hardware Queues
5693*4882a593Smuzhiyun  * the driver will advertise it supports to the SCSI layer.
5694*4882a593Smuzhiyun  *
5695*4882a593Smuzhiyun  *      0    = Set nr_hw_queues by the number of CPUs or HW queues.
5696*4882a593Smuzhiyun  *      1,256 = Manually specify nr_hw_queue value to be advertised,
5697*4882a593Smuzhiyun  *
5698*4882a593Smuzhiyun  * Value range is [0,256]. Default value is 8.
5699*4882a593Smuzhiyun  */
5700*4882a593Smuzhiyun LPFC_ATTR_R(fcp_mq_threshold, LPFC_FCP_MQ_THRESHOLD_DEF,
5701*4882a593Smuzhiyun 	    LPFC_FCP_MQ_THRESHOLD_MIN, LPFC_FCP_MQ_THRESHOLD_MAX,
5702*4882a593Smuzhiyun 	    "Set the number of SCSI Queues advertised");
5703*4882a593Smuzhiyun 
5704*4882a593Smuzhiyun /*
5705*4882a593Smuzhiyun  * lpfc_hdw_queue: Set the number of Hardware Queues the driver
5706*4882a593Smuzhiyun  * will advertise it supports to the NVME and  SCSI layers. This also
5707*4882a593Smuzhiyun  * will map to the number of CQ/WQ pairs the driver will create.
5708*4882a593Smuzhiyun  *
5709*4882a593Smuzhiyun  * The NVME Layer will try to create this many, plus 1 administrative
5710*4882a593Smuzhiyun  * hardware queue. The administrative queue will always map to WQ 0
5711*4882a593Smuzhiyun  * A hardware IO queue maps (qidx) to a specific driver CQ/WQ.
5712*4882a593Smuzhiyun  *
5713*4882a593Smuzhiyun  *      0    = Configure the number of hdw queues to the number of active CPUs.
5714*4882a593Smuzhiyun  *      1,256 = Manually specify how many hdw queues to use.
5715*4882a593Smuzhiyun  *
5716*4882a593Smuzhiyun  * Value range is [0,256]. Default value is 0.
5717*4882a593Smuzhiyun  */
5718*4882a593Smuzhiyun LPFC_ATTR_R(hdw_queue,
5719*4882a593Smuzhiyun 	    LPFC_HBA_HDWQ_DEF,
5720*4882a593Smuzhiyun 	    LPFC_HBA_HDWQ_MIN, LPFC_HBA_HDWQ_MAX,
5721*4882a593Smuzhiyun 	    "Set the number of I/O Hardware Queues");
5722*4882a593Smuzhiyun 
5723*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_X86)
5724*4882a593Smuzhiyun /**
5725*4882a593Smuzhiyun  * lpfc_cpumask_irq_mode_init - initalizes cpumask of phba based on
5726*4882a593Smuzhiyun  *				irq_chann_mode
5727*4882a593Smuzhiyun  * @phba: Pointer to HBA context object.
5728*4882a593Smuzhiyun  **/
5729*4882a593Smuzhiyun static void
lpfc_cpumask_irq_mode_init(struct lpfc_hba * phba)5730*4882a593Smuzhiyun lpfc_cpumask_irq_mode_init(struct lpfc_hba *phba)
5731*4882a593Smuzhiyun {
5732*4882a593Smuzhiyun 	unsigned int cpu, first_cpu, numa_node = NUMA_NO_NODE;
5733*4882a593Smuzhiyun 	const struct cpumask *sibling_mask;
5734*4882a593Smuzhiyun 	struct cpumask *aff_mask = &phba->sli4_hba.irq_aff_mask;
5735*4882a593Smuzhiyun 
5736*4882a593Smuzhiyun 	cpumask_clear(aff_mask);
5737*4882a593Smuzhiyun 
5738*4882a593Smuzhiyun 	if (phba->irq_chann_mode == NUMA_MODE) {
5739*4882a593Smuzhiyun 		/* Check if we're a NUMA architecture */
5740*4882a593Smuzhiyun 		numa_node = dev_to_node(&phba->pcidev->dev);
5741*4882a593Smuzhiyun 		if (numa_node == NUMA_NO_NODE) {
5742*4882a593Smuzhiyun 			phba->irq_chann_mode = NORMAL_MODE;
5743*4882a593Smuzhiyun 			return;
5744*4882a593Smuzhiyun 		}
5745*4882a593Smuzhiyun 	}
5746*4882a593Smuzhiyun 
5747*4882a593Smuzhiyun 	for_each_possible_cpu(cpu) {
5748*4882a593Smuzhiyun 		switch (phba->irq_chann_mode) {
5749*4882a593Smuzhiyun 		case NUMA_MODE:
5750*4882a593Smuzhiyun 			if (cpu_to_node(cpu) == numa_node)
5751*4882a593Smuzhiyun 				cpumask_set_cpu(cpu, aff_mask);
5752*4882a593Smuzhiyun 			break;
5753*4882a593Smuzhiyun 		case NHT_MODE:
5754*4882a593Smuzhiyun 			sibling_mask = topology_sibling_cpumask(cpu);
5755*4882a593Smuzhiyun 			first_cpu = cpumask_first(sibling_mask);
5756*4882a593Smuzhiyun 			if (first_cpu < nr_cpu_ids)
5757*4882a593Smuzhiyun 				cpumask_set_cpu(first_cpu, aff_mask);
5758*4882a593Smuzhiyun 			break;
5759*4882a593Smuzhiyun 		default:
5760*4882a593Smuzhiyun 			break;
5761*4882a593Smuzhiyun 		}
5762*4882a593Smuzhiyun 	}
5763*4882a593Smuzhiyun }
5764*4882a593Smuzhiyun #endif
5765*4882a593Smuzhiyun 
5766*4882a593Smuzhiyun static void
lpfc_assign_default_irq_chann(struct lpfc_hba * phba)5767*4882a593Smuzhiyun lpfc_assign_default_irq_chann(struct lpfc_hba *phba)
5768*4882a593Smuzhiyun {
5769*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_X86)
5770*4882a593Smuzhiyun 	switch (boot_cpu_data.x86_vendor) {
5771*4882a593Smuzhiyun 	case X86_VENDOR_AMD:
5772*4882a593Smuzhiyun 		/* If AMD architecture, then default is NUMA_MODE */
5773*4882a593Smuzhiyun 		phba->irq_chann_mode = NUMA_MODE;
5774*4882a593Smuzhiyun 		break;
5775*4882a593Smuzhiyun 	case X86_VENDOR_INTEL:
5776*4882a593Smuzhiyun 		/* If Intel architecture, then default is no hyperthread mode */
5777*4882a593Smuzhiyun 		phba->irq_chann_mode = NHT_MODE;
5778*4882a593Smuzhiyun 		break;
5779*4882a593Smuzhiyun 	default:
5780*4882a593Smuzhiyun 		phba->irq_chann_mode = NORMAL_MODE;
5781*4882a593Smuzhiyun 		break;
5782*4882a593Smuzhiyun 	}
5783*4882a593Smuzhiyun 	lpfc_cpumask_irq_mode_init(phba);
5784*4882a593Smuzhiyun #else
5785*4882a593Smuzhiyun 	phba->irq_chann_mode = NORMAL_MODE;
5786*4882a593Smuzhiyun #endif
5787*4882a593Smuzhiyun }
5788*4882a593Smuzhiyun 
5789*4882a593Smuzhiyun /*
5790*4882a593Smuzhiyun  * lpfc_irq_chann: Set the number of IRQ vectors that are available
5791*4882a593Smuzhiyun  * for Hardware Queues to utilize.  This also will map to the number
5792*4882a593Smuzhiyun  * of EQ / MSI-X vectors the driver will create. This should never be
5793*4882a593Smuzhiyun  * more than the number of Hardware Queues
5794*4882a593Smuzhiyun  *
5795*4882a593Smuzhiyun  *	0		= Configure number of IRQ Channels to:
5796*4882a593Smuzhiyun  *			  if AMD architecture, number of CPUs on HBA's NUMA node
5797*4882a593Smuzhiyun  *			  if Intel architecture, number of physical CPUs.
5798*4882a593Smuzhiyun  *			  otherwise, number of active CPUs.
5799*4882a593Smuzhiyun  *	[1,256]		= Manually specify how many IRQ Channels to use.
5800*4882a593Smuzhiyun  *
5801*4882a593Smuzhiyun  * Value range is [0,256]. Default value is [0].
5802*4882a593Smuzhiyun  */
5803*4882a593Smuzhiyun static uint lpfc_irq_chann = LPFC_IRQ_CHANN_DEF;
5804*4882a593Smuzhiyun module_param(lpfc_irq_chann, uint, 0444);
5805*4882a593Smuzhiyun MODULE_PARM_DESC(lpfc_irq_chann, "Set number of interrupt vectors to allocate");
5806*4882a593Smuzhiyun 
5807*4882a593Smuzhiyun /* lpfc_irq_chann_init - Set the hba irq_chann initial value
5808*4882a593Smuzhiyun  * @phba: lpfc_hba pointer.
5809*4882a593Smuzhiyun  * @val: contains the initial value
5810*4882a593Smuzhiyun  *
5811*4882a593Smuzhiyun  * Description:
5812*4882a593Smuzhiyun  * Validates the initial value is within range and assigns it to the
5813*4882a593Smuzhiyun  * adapter. If not in range, an error message is posted and the
5814*4882a593Smuzhiyun  * default value is assigned.
5815*4882a593Smuzhiyun  *
5816*4882a593Smuzhiyun  * Returns:
5817*4882a593Smuzhiyun  * zero if value is in range and is set
5818*4882a593Smuzhiyun  * -EINVAL if value was out of range
5819*4882a593Smuzhiyun  **/
5820*4882a593Smuzhiyun static int
lpfc_irq_chann_init(struct lpfc_hba * phba,uint32_t val)5821*4882a593Smuzhiyun lpfc_irq_chann_init(struct lpfc_hba *phba, uint32_t val)
5822*4882a593Smuzhiyun {
5823*4882a593Smuzhiyun 	const struct cpumask *aff_mask;
5824*4882a593Smuzhiyun 
5825*4882a593Smuzhiyun 	if (phba->cfg_use_msi != 2) {
5826*4882a593Smuzhiyun 		lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
5827*4882a593Smuzhiyun 				"8532 use_msi = %u ignoring cfg_irq_numa\n",
5828*4882a593Smuzhiyun 				phba->cfg_use_msi);
5829*4882a593Smuzhiyun 		phba->irq_chann_mode = NORMAL_MODE;
5830*4882a593Smuzhiyun 		phba->cfg_irq_chann = LPFC_IRQ_CHANN_DEF;
5831*4882a593Smuzhiyun 		return 0;
5832*4882a593Smuzhiyun 	}
5833*4882a593Smuzhiyun 
5834*4882a593Smuzhiyun 	/* Check if default setting was passed */
5835*4882a593Smuzhiyun 	if (val == LPFC_IRQ_CHANN_DEF)
5836*4882a593Smuzhiyun 		lpfc_assign_default_irq_chann(phba);
5837*4882a593Smuzhiyun 
5838*4882a593Smuzhiyun 	if (phba->irq_chann_mode != NORMAL_MODE) {
5839*4882a593Smuzhiyun 		aff_mask = &phba->sli4_hba.irq_aff_mask;
5840*4882a593Smuzhiyun 
5841*4882a593Smuzhiyun 		if (cpumask_empty(aff_mask)) {
5842*4882a593Smuzhiyun 			lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
5843*4882a593Smuzhiyun 					"8533 Could not identify CPUS for "
5844*4882a593Smuzhiyun 					"mode %d, ignoring\n",
5845*4882a593Smuzhiyun 					phba->irq_chann_mode);
5846*4882a593Smuzhiyun 			phba->irq_chann_mode = NORMAL_MODE;
5847*4882a593Smuzhiyun 			phba->cfg_irq_chann = LPFC_IRQ_CHANN_DEF;
5848*4882a593Smuzhiyun 		} else {
5849*4882a593Smuzhiyun 			phba->cfg_irq_chann = cpumask_weight(aff_mask);
5850*4882a593Smuzhiyun 
5851*4882a593Smuzhiyun 			/* If no hyperthread mode, then set hdwq count to
5852*4882a593Smuzhiyun 			 * aff_mask weight as well
5853*4882a593Smuzhiyun 			 */
5854*4882a593Smuzhiyun 			if (phba->irq_chann_mode == NHT_MODE)
5855*4882a593Smuzhiyun 				phba->cfg_hdw_queue = phba->cfg_irq_chann;
5856*4882a593Smuzhiyun 
5857*4882a593Smuzhiyun 			lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
5858*4882a593Smuzhiyun 					"8543 lpfc_irq_chann set to %u "
5859*4882a593Smuzhiyun 					"(mode: %d)\n", phba->cfg_irq_chann,
5860*4882a593Smuzhiyun 					phba->irq_chann_mode);
5861*4882a593Smuzhiyun 		}
5862*4882a593Smuzhiyun 	} else {
5863*4882a593Smuzhiyun 		if (val > LPFC_IRQ_CHANN_MAX) {
5864*4882a593Smuzhiyun 			lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
5865*4882a593Smuzhiyun 					"8545 lpfc_irq_chann attribute cannot "
5866*4882a593Smuzhiyun 					"be set to %u, allowed range is "
5867*4882a593Smuzhiyun 					"[%u,%u]\n",
5868*4882a593Smuzhiyun 					val,
5869*4882a593Smuzhiyun 					LPFC_IRQ_CHANN_MIN,
5870*4882a593Smuzhiyun 					LPFC_IRQ_CHANN_MAX);
5871*4882a593Smuzhiyun 			phba->cfg_irq_chann = LPFC_IRQ_CHANN_DEF;
5872*4882a593Smuzhiyun 			return -EINVAL;
5873*4882a593Smuzhiyun 		}
5874*4882a593Smuzhiyun 		phba->cfg_irq_chann = val;
5875*4882a593Smuzhiyun 	}
5876*4882a593Smuzhiyun 
5877*4882a593Smuzhiyun 	return 0;
5878*4882a593Smuzhiyun }
5879*4882a593Smuzhiyun 
5880*4882a593Smuzhiyun /**
5881*4882a593Smuzhiyun  * lpfc_irq_chann_show - Display value of irq_chann
5882*4882a593Smuzhiyun  * @dev: class converted to a Scsi_host structure.
5883*4882a593Smuzhiyun  * @attr: device attribute, not used.
5884*4882a593Smuzhiyun  * @buf: on return contains a string with the list sizes
5885*4882a593Smuzhiyun  *
5886*4882a593Smuzhiyun  * Returns: size of formatted string.
5887*4882a593Smuzhiyun  **/
5888*4882a593Smuzhiyun static ssize_t
lpfc_irq_chann_show(struct device * dev,struct device_attribute * attr,char * buf)5889*4882a593Smuzhiyun lpfc_irq_chann_show(struct device *dev, struct device_attribute *attr,
5890*4882a593Smuzhiyun 		    char *buf)
5891*4882a593Smuzhiyun {
5892*4882a593Smuzhiyun 	struct Scsi_Host *shost = class_to_shost(dev);
5893*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata;
5894*4882a593Smuzhiyun 	struct lpfc_hba *phba = vport->phba;
5895*4882a593Smuzhiyun 
5896*4882a593Smuzhiyun 	return scnprintf(buf, PAGE_SIZE, "%u\n", phba->cfg_irq_chann);
5897*4882a593Smuzhiyun }
5898*4882a593Smuzhiyun 
5899*4882a593Smuzhiyun static DEVICE_ATTR_RO(lpfc_irq_chann);
5900*4882a593Smuzhiyun 
5901*4882a593Smuzhiyun /*
5902*4882a593Smuzhiyun # lpfc_enable_hba_reset: Allow or prevent HBA resets to the hardware.
5903*4882a593Smuzhiyun #       0  = HBA resets disabled
5904*4882a593Smuzhiyun #       1  = HBA resets enabled (default)
5905*4882a593Smuzhiyun #       2  = HBA reset via PCI bus reset enabled
5906*4882a593Smuzhiyun # Value range is [0,2]. Default value is 1.
5907*4882a593Smuzhiyun */
5908*4882a593Smuzhiyun LPFC_ATTR_RW(enable_hba_reset, 1, 0, 2, "Enable HBA resets from the driver.");
5909*4882a593Smuzhiyun 
5910*4882a593Smuzhiyun /*
5911*4882a593Smuzhiyun # lpfc_enable_hba_heartbeat: Disable HBA heartbeat timer..
5912*4882a593Smuzhiyun #       0  = HBA Heartbeat disabled
5913*4882a593Smuzhiyun #       1  = HBA Heartbeat enabled (default)
5914*4882a593Smuzhiyun # Value range is [0,1]. Default value is 1.
5915*4882a593Smuzhiyun */
5916*4882a593Smuzhiyun LPFC_ATTR_R(enable_hba_heartbeat, 0, 0, 1, "Enable HBA Heartbeat.");
5917*4882a593Smuzhiyun 
5918*4882a593Smuzhiyun /*
5919*4882a593Smuzhiyun # lpfc_EnableXLane: Enable Express Lane Feature
5920*4882a593Smuzhiyun #      0x0   Express Lane Feature disabled
5921*4882a593Smuzhiyun #      0x1   Express Lane Feature enabled
5922*4882a593Smuzhiyun # Value range is [0,1]. Default value is 0.
5923*4882a593Smuzhiyun */
5924*4882a593Smuzhiyun LPFC_ATTR_R(EnableXLane, 0, 0, 1, "Enable Express Lane Feature.");
5925*4882a593Smuzhiyun 
5926*4882a593Smuzhiyun /*
5927*4882a593Smuzhiyun # lpfc_XLanePriority:  Define CS_CTL priority for Express Lane Feature
5928*4882a593Smuzhiyun #       0x0 - 0x7f  = CS_CTL field in FC header (high 7 bits)
5929*4882a593Smuzhiyun # Value range is [0x0,0x7f]. Default value is 0
5930*4882a593Smuzhiyun */
5931*4882a593Smuzhiyun LPFC_ATTR_RW(XLanePriority, 0, 0x0, 0x7f, "CS_CTL for Express Lane Feature.");
5932*4882a593Smuzhiyun 
5933*4882a593Smuzhiyun /*
5934*4882a593Smuzhiyun # lpfc_enable_bg: Enable BlockGuard (Emulex's Implementation of T10-DIF)
5935*4882a593Smuzhiyun #       0  = BlockGuard disabled (default)
5936*4882a593Smuzhiyun #       1  = BlockGuard enabled
5937*4882a593Smuzhiyun # Value range is [0,1]. Default value is 0.
5938*4882a593Smuzhiyun */
5939*4882a593Smuzhiyun LPFC_ATTR_R(enable_bg, 0, 0, 1, "Enable BlockGuard Support");
5940*4882a593Smuzhiyun 
5941*4882a593Smuzhiyun /*
5942*4882a593Smuzhiyun # lpfc_prot_mask: i
5943*4882a593Smuzhiyun #	- Bit mask of host protection capabilities used to register with the
5944*4882a593Smuzhiyun #	  SCSI mid-layer
5945*4882a593Smuzhiyun # 	- Only meaningful if BG is turned on (lpfc_enable_bg=1).
5946*4882a593Smuzhiyun #	- Allows you to ultimately specify which profiles to use
5947*4882a593Smuzhiyun #	- Default will result in registering capabilities for all profiles.
5948*4882a593Smuzhiyun #	- SHOST_DIF_TYPE1_PROTECTION	1
5949*4882a593Smuzhiyun #		HBA supports T10 DIF Type 1: HBA to Target Type 1 Protection
5950*4882a593Smuzhiyun #	- SHOST_DIX_TYPE0_PROTECTION	8
5951*4882a593Smuzhiyun #		HBA supports DIX Type 0: Host to HBA protection only
5952*4882a593Smuzhiyun #	- SHOST_DIX_TYPE1_PROTECTION	16
5953*4882a593Smuzhiyun #		HBA supports DIX Type 1: Host to HBA  Type 1 protection
5954*4882a593Smuzhiyun #
5955*4882a593Smuzhiyun */
5956*4882a593Smuzhiyun LPFC_ATTR(prot_mask,
5957*4882a593Smuzhiyun 	(SHOST_DIF_TYPE1_PROTECTION |
5958*4882a593Smuzhiyun 	SHOST_DIX_TYPE0_PROTECTION |
5959*4882a593Smuzhiyun 	SHOST_DIX_TYPE1_PROTECTION),
5960*4882a593Smuzhiyun 	0,
5961*4882a593Smuzhiyun 	(SHOST_DIF_TYPE1_PROTECTION |
5962*4882a593Smuzhiyun 	SHOST_DIX_TYPE0_PROTECTION |
5963*4882a593Smuzhiyun 	SHOST_DIX_TYPE1_PROTECTION),
5964*4882a593Smuzhiyun 	"T10-DIF host protection capabilities mask");
5965*4882a593Smuzhiyun 
5966*4882a593Smuzhiyun /*
5967*4882a593Smuzhiyun # lpfc_prot_guard: i
5968*4882a593Smuzhiyun #	- Bit mask of protection guard types to register with the SCSI mid-layer
5969*4882a593Smuzhiyun #	- Guard types are currently either 1) T10-DIF CRC 2) IP checksum
5970*4882a593Smuzhiyun #	- Allows you to ultimately specify which profiles to use
5971*4882a593Smuzhiyun #	- Default will result in registering capabilities for all guard types
5972*4882a593Smuzhiyun #
5973*4882a593Smuzhiyun */
5974*4882a593Smuzhiyun LPFC_ATTR(prot_guard,
5975*4882a593Smuzhiyun 	SHOST_DIX_GUARD_IP, SHOST_DIX_GUARD_CRC, SHOST_DIX_GUARD_IP,
5976*4882a593Smuzhiyun 	"T10-DIF host protection guard type");
5977*4882a593Smuzhiyun 
5978*4882a593Smuzhiyun /*
5979*4882a593Smuzhiyun  * Delay initial NPort discovery when Clean Address bit is cleared in
5980*4882a593Smuzhiyun  * FLOGI/FDISC accept and FCID/Fabric name/Fabric portname is changed.
5981*4882a593Smuzhiyun  * This parameter can have value 0 or 1.
5982*4882a593Smuzhiyun  * When this parameter is set to 0, no delay is added to the initial
5983*4882a593Smuzhiyun  * discovery.
5984*4882a593Smuzhiyun  * When this parameter is set to non-zero value, initial Nport discovery is
5985*4882a593Smuzhiyun  * delayed by ra_tov seconds when Clean Address bit is cleared in FLOGI/FDISC
5986*4882a593Smuzhiyun  * accept and FCID/Fabric name/Fabric portname is changed.
5987*4882a593Smuzhiyun  * Driver always delay Nport discovery for subsequent FLOGI/FDISC completion
5988*4882a593Smuzhiyun  * when Clean Address bit is cleared in FLOGI/FDISC
5989*4882a593Smuzhiyun  * accept and FCID/Fabric name/Fabric portname is changed.
5990*4882a593Smuzhiyun  * Default value is 0.
5991*4882a593Smuzhiyun  */
5992*4882a593Smuzhiyun LPFC_ATTR(delay_discovery, 0, 0, 1,
5993*4882a593Smuzhiyun 	"Delay NPort discovery when Clean Address bit is cleared.");
5994*4882a593Smuzhiyun 
5995*4882a593Smuzhiyun /*
5996*4882a593Smuzhiyun  * lpfc_sg_seg_cnt - Initial Maximum DMA Segment Count
5997*4882a593Smuzhiyun  * This value can be set to values between 64 and 4096. The default value
5998*4882a593Smuzhiyun  * is 64, but may be increased to allow for larger Max I/O sizes. The scsi
5999*4882a593Smuzhiyun  * and nvme layers will allow I/O sizes up to (MAX_SEG_COUNT * SEG_SIZE).
6000*4882a593Smuzhiyun  * Because of the additional overhead involved in setting up T10-DIF,
6001*4882a593Smuzhiyun  * this parameter will be limited to 128 if BlockGuard is enabled under SLI4
6002*4882a593Smuzhiyun  * and will be limited to 512 if BlockGuard is enabled under SLI3.
6003*4882a593Smuzhiyun  */
6004*4882a593Smuzhiyun static uint lpfc_sg_seg_cnt = LPFC_DEFAULT_SG_SEG_CNT;
6005*4882a593Smuzhiyun module_param(lpfc_sg_seg_cnt, uint, 0444);
6006*4882a593Smuzhiyun MODULE_PARM_DESC(lpfc_sg_seg_cnt, "Max Scatter Gather Segment Count");
6007*4882a593Smuzhiyun 
6008*4882a593Smuzhiyun /**
6009*4882a593Smuzhiyun  * lpfc_sg_seg_cnt_show - Display the scatter/gather list sizes
6010*4882a593Smuzhiyun  *    configured for the adapter
6011*4882a593Smuzhiyun  * @dev: class converted to a Scsi_host structure.
6012*4882a593Smuzhiyun  * @attr: device attribute, not used.
6013*4882a593Smuzhiyun  * @buf: on return contains a string with the list sizes
6014*4882a593Smuzhiyun  *
6015*4882a593Smuzhiyun  * Returns: size of formatted string.
6016*4882a593Smuzhiyun  **/
6017*4882a593Smuzhiyun static ssize_t
lpfc_sg_seg_cnt_show(struct device * dev,struct device_attribute * attr,char * buf)6018*4882a593Smuzhiyun lpfc_sg_seg_cnt_show(struct device *dev, struct device_attribute *attr,
6019*4882a593Smuzhiyun 		     char *buf)
6020*4882a593Smuzhiyun {
6021*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
6022*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata;
6023*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
6024*4882a593Smuzhiyun 	int len;
6025*4882a593Smuzhiyun 
6026*4882a593Smuzhiyun 	len = scnprintf(buf, PAGE_SIZE, "SGL sz: %d  total SGEs: %d\n",
6027*4882a593Smuzhiyun 		       phba->cfg_sg_dma_buf_size, phba->cfg_total_seg_cnt);
6028*4882a593Smuzhiyun 
6029*4882a593Smuzhiyun 	len += scnprintf(buf + len, PAGE_SIZE - len,
6030*4882a593Smuzhiyun 			"Cfg: %d  SCSI: %d  NVME: %d\n",
6031*4882a593Smuzhiyun 			phba->cfg_sg_seg_cnt, phba->cfg_scsi_seg_cnt,
6032*4882a593Smuzhiyun 			phba->cfg_nvme_seg_cnt);
6033*4882a593Smuzhiyun 	return len;
6034*4882a593Smuzhiyun }
6035*4882a593Smuzhiyun 
6036*4882a593Smuzhiyun static DEVICE_ATTR_RO(lpfc_sg_seg_cnt);
6037*4882a593Smuzhiyun 
6038*4882a593Smuzhiyun /**
6039*4882a593Smuzhiyun  * lpfc_sg_seg_cnt_init - Set the hba sg_seg_cnt initial value
6040*4882a593Smuzhiyun  * @phba: lpfc_hba pointer.
6041*4882a593Smuzhiyun  * @val: contains the initial value
6042*4882a593Smuzhiyun  *
6043*4882a593Smuzhiyun  * Description:
6044*4882a593Smuzhiyun  * Validates the initial value is within range and assigns it to the
6045*4882a593Smuzhiyun  * adapter. If not in range, an error message is posted and the
6046*4882a593Smuzhiyun  * default value is assigned.
6047*4882a593Smuzhiyun  *
6048*4882a593Smuzhiyun  * Returns:
6049*4882a593Smuzhiyun  * zero if value is in range and is set
6050*4882a593Smuzhiyun  * -EINVAL if value was out of range
6051*4882a593Smuzhiyun  **/
6052*4882a593Smuzhiyun static int
lpfc_sg_seg_cnt_init(struct lpfc_hba * phba,int val)6053*4882a593Smuzhiyun lpfc_sg_seg_cnt_init(struct lpfc_hba *phba, int val)
6054*4882a593Smuzhiyun {
6055*4882a593Smuzhiyun 	if (val >= LPFC_MIN_SG_SEG_CNT && val <= LPFC_MAX_SG_SEG_CNT) {
6056*4882a593Smuzhiyun 		phba->cfg_sg_seg_cnt = val;
6057*4882a593Smuzhiyun 		return 0;
6058*4882a593Smuzhiyun 	}
6059*4882a593Smuzhiyun 	lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
6060*4882a593Smuzhiyun 			"0409 "LPFC_DRIVER_NAME"_sg_seg_cnt attribute cannot "
6061*4882a593Smuzhiyun 			"be set to %d, allowed range is [%d, %d]\n",
6062*4882a593Smuzhiyun 			val, LPFC_MIN_SG_SEG_CNT, LPFC_MAX_SG_SEG_CNT);
6063*4882a593Smuzhiyun 	phba->cfg_sg_seg_cnt = LPFC_DEFAULT_SG_SEG_CNT;
6064*4882a593Smuzhiyun 	return -EINVAL;
6065*4882a593Smuzhiyun }
6066*4882a593Smuzhiyun 
6067*4882a593Smuzhiyun /*
6068*4882a593Smuzhiyun  * lpfc_enable_mds_diags: Enable MDS Diagnostics
6069*4882a593Smuzhiyun  *       0  = MDS Diagnostics disabled (default)
6070*4882a593Smuzhiyun  *       1  = MDS Diagnostics enabled
6071*4882a593Smuzhiyun  * Value range is [0,1]. Default value is 0.
6072*4882a593Smuzhiyun  */
6073*4882a593Smuzhiyun LPFC_ATTR_RW(enable_mds_diags, 0, 0, 1, "Enable MDS Diagnostics");
6074*4882a593Smuzhiyun 
6075*4882a593Smuzhiyun /*
6076*4882a593Smuzhiyun  * lpfc_ras_fwlog_buffsize: Firmware logging host buffer size
6077*4882a593Smuzhiyun  *	0 = Disable firmware logging (default)
6078*4882a593Smuzhiyun  *	[1-4] = Multiple of 1/4th Mb of host memory for FW logging
6079*4882a593Smuzhiyun  * Value range [0..4]. Default value is 0
6080*4882a593Smuzhiyun  */
6081*4882a593Smuzhiyun LPFC_ATTR(ras_fwlog_buffsize, 0, 0, 4, "Host memory for FW logging");
6082*4882a593Smuzhiyun lpfc_param_show(ras_fwlog_buffsize);
6083*4882a593Smuzhiyun 
6084*4882a593Smuzhiyun static ssize_t
lpfc_ras_fwlog_buffsize_set(struct lpfc_hba * phba,uint val)6085*4882a593Smuzhiyun lpfc_ras_fwlog_buffsize_set(struct lpfc_hba  *phba, uint val)
6086*4882a593Smuzhiyun {
6087*4882a593Smuzhiyun 	int ret = 0;
6088*4882a593Smuzhiyun 	enum ras_state state;
6089*4882a593Smuzhiyun 
6090*4882a593Smuzhiyun 	if (!lpfc_rangecheck(val, 0, 4))
6091*4882a593Smuzhiyun 		return -EINVAL;
6092*4882a593Smuzhiyun 
6093*4882a593Smuzhiyun 	if (phba->cfg_ras_fwlog_buffsize == val)
6094*4882a593Smuzhiyun 		return 0;
6095*4882a593Smuzhiyun 
6096*4882a593Smuzhiyun 	if (phba->cfg_ras_fwlog_func != PCI_FUNC(phba->pcidev->devfn))
6097*4882a593Smuzhiyun 		return -EINVAL;
6098*4882a593Smuzhiyun 
6099*4882a593Smuzhiyun 	spin_lock_irq(&phba->hbalock);
6100*4882a593Smuzhiyun 	state = phba->ras_fwlog.state;
6101*4882a593Smuzhiyun 	spin_unlock_irq(&phba->hbalock);
6102*4882a593Smuzhiyun 
6103*4882a593Smuzhiyun 	if (state == REG_INPROGRESS) {
6104*4882a593Smuzhiyun 		lpfc_printf_log(phba, KERN_ERR, LOG_SLI, "6147 RAS Logging "
6105*4882a593Smuzhiyun 				"registration is in progress\n");
6106*4882a593Smuzhiyun 		return -EBUSY;
6107*4882a593Smuzhiyun 	}
6108*4882a593Smuzhiyun 
6109*4882a593Smuzhiyun 	/* For disable logging: stop the logs and free the DMA.
6110*4882a593Smuzhiyun 	 * For ras_fwlog_buffsize size change we still need to free and
6111*4882a593Smuzhiyun 	 * reallocate the DMA in lpfc_sli4_ras_fwlog_init.
6112*4882a593Smuzhiyun 	 */
6113*4882a593Smuzhiyun 	phba->cfg_ras_fwlog_buffsize = val;
6114*4882a593Smuzhiyun 	if (state == ACTIVE) {
6115*4882a593Smuzhiyun 		lpfc_ras_stop_fwlog(phba);
6116*4882a593Smuzhiyun 		lpfc_sli4_ras_dma_free(phba);
6117*4882a593Smuzhiyun 	}
6118*4882a593Smuzhiyun 
6119*4882a593Smuzhiyun 	lpfc_sli4_ras_init(phba);
6120*4882a593Smuzhiyun 	if (phba->ras_fwlog.ras_enabled)
6121*4882a593Smuzhiyun 		ret = lpfc_sli4_ras_fwlog_init(phba, phba->cfg_ras_fwlog_level,
6122*4882a593Smuzhiyun 					       LPFC_RAS_ENABLE_LOGGING);
6123*4882a593Smuzhiyun 	return ret;
6124*4882a593Smuzhiyun }
6125*4882a593Smuzhiyun 
6126*4882a593Smuzhiyun lpfc_param_store(ras_fwlog_buffsize);
6127*4882a593Smuzhiyun static DEVICE_ATTR_RW(lpfc_ras_fwlog_buffsize);
6128*4882a593Smuzhiyun 
6129*4882a593Smuzhiyun /*
6130*4882a593Smuzhiyun  * lpfc_ras_fwlog_level: Firmware logging verbosity level
6131*4882a593Smuzhiyun  * Valid only if firmware logging is enabled
6132*4882a593Smuzhiyun  * 0(Least Verbosity) 4 (most verbosity)
6133*4882a593Smuzhiyun  * Value range is [0..4]. Default value is 0
6134*4882a593Smuzhiyun  */
6135*4882a593Smuzhiyun LPFC_ATTR_RW(ras_fwlog_level, 0, 0, 4, "Firmware Logging Level");
6136*4882a593Smuzhiyun 
6137*4882a593Smuzhiyun /*
6138*4882a593Smuzhiyun  * lpfc_ras_fwlog_func: Firmware logging enabled on function number
6139*4882a593Smuzhiyun  * Default function which has RAS support : 0
6140*4882a593Smuzhiyun  * Value Range is [0..7].
6141*4882a593Smuzhiyun  * FW logging is a global action and enablement is via a specific
6142*4882a593Smuzhiyun  * port.
6143*4882a593Smuzhiyun  */
6144*4882a593Smuzhiyun LPFC_ATTR_RW(ras_fwlog_func, 0, 0, 7, "Firmware Logging Enabled on Function");
6145*4882a593Smuzhiyun 
6146*4882a593Smuzhiyun /*
6147*4882a593Smuzhiyun  * lpfc_enable_bbcr: Enable BB Credit Recovery
6148*4882a593Smuzhiyun  *       0  = BB Credit Recovery disabled
6149*4882a593Smuzhiyun  *       1  = BB Credit Recovery enabled (default)
6150*4882a593Smuzhiyun  * Value range is [0,1]. Default value is 1.
6151*4882a593Smuzhiyun  */
6152*4882a593Smuzhiyun LPFC_BBCR_ATTR_RW(enable_bbcr, 1, 0, 1, "Enable BBC Recovery");
6153*4882a593Smuzhiyun 
6154*4882a593Smuzhiyun /*
6155*4882a593Smuzhiyun  * lpfc_enable_dpp: Enable DPP on G7
6156*4882a593Smuzhiyun  *       0  = DPP on G7 disabled
6157*4882a593Smuzhiyun  *       1  = DPP on G7 enabled (default)
6158*4882a593Smuzhiyun  * Value range is [0,1]. Default value is 1.
6159*4882a593Smuzhiyun  */
6160*4882a593Smuzhiyun LPFC_ATTR_RW(enable_dpp, 1, 0, 1, "Enable Direct Packet Push");
6161*4882a593Smuzhiyun 
6162*4882a593Smuzhiyun struct device_attribute *lpfc_hba_attrs[] = {
6163*4882a593Smuzhiyun 	&dev_attr_nvme_info,
6164*4882a593Smuzhiyun 	&dev_attr_scsi_stat,
6165*4882a593Smuzhiyun 	&dev_attr_bg_info,
6166*4882a593Smuzhiyun 	&dev_attr_bg_guard_err,
6167*4882a593Smuzhiyun 	&dev_attr_bg_apptag_err,
6168*4882a593Smuzhiyun 	&dev_attr_bg_reftag_err,
6169*4882a593Smuzhiyun 	&dev_attr_info,
6170*4882a593Smuzhiyun 	&dev_attr_serialnum,
6171*4882a593Smuzhiyun 	&dev_attr_modeldesc,
6172*4882a593Smuzhiyun 	&dev_attr_modelname,
6173*4882a593Smuzhiyun 	&dev_attr_programtype,
6174*4882a593Smuzhiyun 	&dev_attr_portnum,
6175*4882a593Smuzhiyun 	&dev_attr_fwrev,
6176*4882a593Smuzhiyun 	&dev_attr_hdw,
6177*4882a593Smuzhiyun 	&dev_attr_option_rom_version,
6178*4882a593Smuzhiyun 	&dev_attr_link_state,
6179*4882a593Smuzhiyun 	&dev_attr_num_discovered_ports,
6180*4882a593Smuzhiyun 	&dev_attr_menlo_mgmt_mode,
6181*4882a593Smuzhiyun 	&dev_attr_lpfc_drvr_version,
6182*4882a593Smuzhiyun 	&dev_attr_lpfc_enable_fip,
6183*4882a593Smuzhiyun 	&dev_attr_lpfc_temp_sensor,
6184*4882a593Smuzhiyun 	&dev_attr_lpfc_log_verbose,
6185*4882a593Smuzhiyun 	&dev_attr_lpfc_lun_queue_depth,
6186*4882a593Smuzhiyun 	&dev_attr_lpfc_tgt_queue_depth,
6187*4882a593Smuzhiyun 	&dev_attr_lpfc_hba_queue_depth,
6188*4882a593Smuzhiyun 	&dev_attr_lpfc_peer_port_login,
6189*4882a593Smuzhiyun 	&dev_attr_lpfc_nodev_tmo,
6190*4882a593Smuzhiyun 	&dev_attr_lpfc_devloss_tmo,
6191*4882a593Smuzhiyun 	&dev_attr_lpfc_enable_fc4_type,
6192*4882a593Smuzhiyun 	&dev_attr_lpfc_fcp_class,
6193*4882a593Smuzhiyun 	&dev_attr_lpfc_use_adisc,
6194*4882a593Smuzhiyun 	&dev_attr_lpfc_first_burst_size,
6195*4882a593Smuzhiyun 	&dev_attr_lpfc_ack0,
6196*4882a593Smuzhiyun 	&dev_attr_lpfc_xri_rebalancing,
6197*4882a593Smuzhiyun 	&dev_attr_lpfc_topology,
6198*4882a593Smuzhiyun 	&dev_attr_lpfc_scan_down,
6199*4882a593Smuzhiyun 	&dev_attr_lpfc_link_speed,
6200*4882a593Smuzhiyun 	&dev_attr_lpfc_fcp_io_sched,
6201*4882a593Smuzhiyun 	&dev_attr_lpfc_ns_query,
6202*4882a593Smuzhiyun 	&dev_attr_lpfc_fcp2_no_tgt_reset,
6203*4882a593Smuzhiyun 	&dev_attr_lpfc_cr_delay,
6204*4882a593Smuzhiyun 	&dev_attr_lpfc_cr_count,
6205*4882a593Smuzhiyun 	&dev_attr_lpfc_multi_ring_support,
6206*4882a593Smuzhiyun 	&dev_attr_lpfc_multi_ring_rctl,
6207*4882a593Smuzhiyun 	&dev_attr_lpfc_multi_ring_type,
6208*4882a593Smuzhiyun 	&dev_attr_lpfc_fdmi_on,
6209*4882a593Smuzhiyun 	&dev_attr_lpfc_enable_SmartSAN,
6210*4882a593Smuzhiyun 	&dev_attr_lpfc_max_luns,
6211*4882a593Smuzhiyun 	&dev_attr_lpfc_enable_npiv,
6212*4882a593Smuzhiyun 	&dev_attr_lpfc_fcf_failover_policy,
6213*4882a593Smuzhiyun 	&dev_attr_lpfc_enable_rrq,
6214*4882a593Smuzhiyun 	&dev_attr_nport_evt_cnt,
6215*4882a593Smuzhiyun 	&dev_attr_board_mode,
6216*4882a593Smuzhiyun 	&dev_attr_max_vpi,
6217*4882a593Smuzhiyun 	&dev_attr_used_vpi,
6218*4882a593Smuzhiyun 	&dev_attr_max_rpi,
6219*4882a593Smuzhiyun 	&dev_attr_used_rpi,
6220*4882a593Smuzhiyun 	&dev_attr_max_xri,
6221*4882a593Smuzhiyun 	&dev_attr_used_xri,
6222*4882a593Smuzhiyun 	&dev_attr_npiv_info,
6223*4882a593Smuzhiyun 	&dev_attr_issue_reset,
6224*4882a593Smuzhiyun 	&dev_attr_lpfc_poll,
6225*4882a593Smuzhiyun 	&dev_attr_lpfc_poll_tmo,
6226*4882a593Smuzhiyun 	&dev_attr_lpfc_task_mgmt_tmo,
6227*4882a593Smuzhiyun 	&dev_attr_lpfc_use_msi,
6228*4882a593Smuzhiyun 	&dev_attr_lpfc_nvme_oas,
6229*4882a593Smuzhiyun 	&dev_attr_lpfc_nvme_embed_cmd,
6230*4882a593Smuzhiyun 	&dev_attr_lpfc_fcp_imax,
6231*4882a593Smuzhiyun 	&dev_attr_lpfc_force_rscn,
6232*4882a593Smuzhiyun 	&dev_attr_lpfc_cq_poll_threshold,
6233*4882a593Smuzhiyun 	&dev_attr_lpfc_cq_max_proc_limit,
6234*4882a593Smuzhiyun 	&dev_attr_lpfc_fcp_cpu_map,
6235*4882a593Smuzhiyun 	&dev_attr_lpfc_fcp_mq_threshold,
6236*4882a593Smuzhiyun 	&dev_attr_lpfc_hdw_queue,
6237*4882a593Smuzhiyun 	&dev_attr_lpfc_irq_chann,
6238*4882a593Smuzhiyun 	&dev_attr_lpfc_suppress_rsp,
6239*4882a593Smuzhiyun 	&dev_attr_lpfc_nvmet_mrq,
6240*4882a593Smuzhiyun 	&dev_attr_lpfc_nvmet_mrq_post,
6241*4882a593Smuzhiyun 	&dev_attr_lpfc_nvme_enable_fb,
6242*4882a593Smuzhiyun 	&dev_attr_lpfc_nvmet_fb_size,
6243*4882a593Smuzhiyun 	&dev_attr_lpfc_enable_bg,
6244*4882a593Smuzhiyun 	&dev_attr_lpfc_soft_wwnn,
6245*4882a593Smuzhiyun 	&dev_attr_lpfc_soft_wwpn,
6246*4882a593Smuzhiyun 	&dev_attr_lpfc_soft_wwn_enable,
6247*4882a593Smuzhiyun 	&dev_attr_lpfc_enable_hba_reset,
6248*4882a593Smuzhiyun 	&dev_attr_lpfc_enable_hba_heartbeat,
6249*4882a593Smuzhiyun 	&dev_attr_lpfc_EnableXLane,
6250*4882a593Smuzhiyun 	&dev_attr_lpfc_XLanePriority,
6251*4882a593Smuzhiyun 	&dev_attr_lpfc_xlane_lun,
6252*4882a593Smuzhiyun 	&dev_attr_lpfc_xlane_tgt,
6253*4882a593Smuzhiyun 	&dev_attr_lpfc_xlane_vpt,
6254*4882a593Smuzhiyun 	&dev_attr_lpfc_xlane_lun_state,
6255*4882a593Smuzhiyun 	&dev_attr_lpfc_xlane_lun_status,
6256*4882a593Smuzhiyun 	&dev_attr_lpfc_xlane_priority,
6257*4882a593Smuzhiyun 	&dev_attr_lpfc_sg_seg_cnt,
6258*4882a593Smuzhiyun 	&dev_attr_lpfc_max_scsicmpl_time,
6259*4882a593Smuzhiyun 	&dev_attr_lpfc_stat_data_ctrl,
6260*4882a593Smuzhiyun 	&dev_attr_lpfc_aer_support,
6261*4882a593Smuzhiyun 	&dev_attr_lpfc_aer_state_cleanup,
6262*4882a593Smuzhiyun 	&dev_attr_lpfc_sriov_nr_virtfn,
6263*4882a593Smuzhiyun 	&dev_attr_lpfc_req_fw_upgrade,
6264*4882a593Smuzhiyun 	&dev_attr_lpfc_suppress_link_up,
6265*4882a593Smuzhiyun 	&dev_attr_iocb_hw,
6266*4882a593Smuzhiyun 	&dev_attr_pls,
6267*4882a593Smuzhiyun 	&dev_attr_pt,
6268*4882a593Smuzhiyun 	&dev_attr_txq_hw,
6269*4882a593Smuzhiyun 	&dev_attr_txcmplq_hw,
6270*4882a593Smuzhiyun 	&dev_attr_lpfc_sriov_hw_max_virtfn,
6271*4882a593Smuzhiyun 	&dev_attr_protocol,
6272*4882a593Smuzhiyun 	&dev_attr_lpfc_xlane_supported,
6273*4882a593Smuzhiyun 	&dev_attr_lpfc_enable_mds_diags,
6274*4882a593Smuzhiyun 	&dev_attr_lpfc_ras_fwlog_buffsize,
6275*4882a593Smuzhiyun 	&dev_attr_lpfc_ras_fwlog_level,
6276*4882a593Smuzhiyun 	&dev_attr_lpfc_ras_fwlog_func,
6277*4882a593Smuzhiyun 	&dev_attr_lpfc_enable_bbcr,
6278*4882a593Smuzhiyun 	&dev_attr_lpfc_enable_dpp,
6279*4882a593Smuzhiyun 	NULL,
6280*4882a593Smuzhiyun };
6281*4882a593Smuzhiyun 
6282*4882a593Smuzhiyun struct device_attribute *lpfc_vport_attrs[] = {
6283*4882a593Smuzhiyun 	&dev_attr_info,
6284*4882a593Smuzhiyun 	&dev_attr_link_state,
6285*4882a593Smuzhiyun 	&dev_attr_num_discovered_ports,
6286*4882a593Smuzhiyun 	&dev_attr_lpfc_drvr_version,
6287*4882a593Smuzhiyun 	&dev_attr_lpfc_log_verbose,
6288*4882a593Smuzhiyun 	&dev_attr_lpfc_lun_queue_depth,
6289*4882a593Smuzhiyun 	&dev_attr_lpfc_tgt_queue_depth,
6290*4882a593Smuzhiyun 	&dev_attr_lpfc_nodev_tmo,
6291*4882a593Smuzhiyun 	&dev_attr_lpfc_devloss_tmo,
6292*4882a593Smuzhiyun 	&dev_attr_lpfc_hba_queue_depth,
6293*4882a593Smuzhiyun 	&dev_attr_lpfc_peer_port_login,
6294*4882a593Smuzhiyun 	&dev_attr_lpfc_restrict_login,
6295*4882a593Smuzhiyun 	&dev_attr_lpfc_fcp_class,
6296*4882a593Smuzhiyun 	&dev_attr_lpfc_use_adisc,
6297*4882a593Smuzhiyun 	&dev_attr_lpfc_first_burst_size,
6298*4882a593Smuzhiyun 	&dev_attr_lpfc_max_luns,
6299*4882a593Smuzhiyun 	&dev_attr_nport_evt_cnt,
6300*4882a593Smuzhiyun 	&dev_attr_npiv_info,
6301*4882a593Smuzhiyun 	&dev_attr_lpfc_enable_da_id,
6302*4882a593Smuzhiyun 	&dev_attr_lpfc_max_scsicmpl_time,
6303*4882a593Smuzhiyun 	&dev_attr_lpfc_stat_data_ctrl,
6304*4882a593Smuzhiyun 	&dev_attr_lpfc_static_vport,
6305*4882a593Smuzhiyun 	NULL,
6306*4882a593Smuzhiyun };
6307*4882a593Smuzhiyun 
6308*4882a593Smuzhiyun /**
6309*4882a593Smuzhiyun  * sysfs_ctlreg_write - Write method for writing to ctlreg
6310*4882a593Smuzhiyun  * @filp: open sysfs file
6311*4882a593Smuzhiyun  * @kobj: kernel kobject that contains the kernel class device.
6312*4882a593Smuzhiyun  * @bin_attr: kernel attributes passed to us.
6313*4882a593Smuzhiyun  * @buf: contains the data to be written to the adapter IOREG space.
6314*4882a593Smuzhiyun  * @off: offset into buffer to beginning of data.
6315*4882a593Smuzhiyun  * @count: bytes to transfer.
6316*4882a593Smuzhiyun  *
6317*4882a593Smuzhiyun  * Description:
6318*4882a593Smuzhiyun  * Accessed via /sys/class/scsi_host/hostxxx/ctlreg.
6319*4882a593Smuzhiyun  * Uses the adapter io control registers to send buf contents to the adapter.
6320*4882a593Smuzhiyun  *
6321*4882a593Smuzhiyun  * Returns:
6322*4882a593Smuzhiyun  * -ERANGE off and count combo out of range
6323*4882a593Smuzhiyun  * -EINVAL off, count or buff address invalid
6324*4882a593Smuzhiyun  * -EPERM adapter is offline
6325*4882a593Smuzhiyun  * value of count, buf contents written
6326*4882a593Smuzhiyun  **/
6327*4882a593Smuzhiyun static ssize_t
sysfs_ctlreg_write(struct file * filp,struct kobject * kobj,struct bin_attribute * bin_attr,char * buf,loff_t off,size_t count)6328*4882a593Smuzhiyun sysfs_ctlreg_write(struct file *filp, struct kobject *kobj,
6329*4882a593Smuzhiyun 		   struct bin_attribute *bin_attr,
6330*4882a593Smuzhiyun 		   char *buf, loff_t off, size_t count)
6331*4882a593Smuzhiyun {
6332*4882a593Smuzhiyun 	size_t buf_off;
6333*4882a593Smuzhiyun 	struct device *dev = container_of(kobj, struct device, kobj);
6334*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
6335*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
6336*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
6337*4882a593Smuzhiyun 
6338*4882a593Smuzhiyun 	if (phba->sli_rev >= LPFC_SLI_REV4)
6339*4882a593Smuzhiyun 		return -EPERM;
6340*4882a593Smuzhiyun 
6341*4882a593Smuzhiyun 	if ((off + count) > FF_REG_AREA_SIZE)
6342*4882a593Smuzhiyun 		return -ERANGE;
6343*4882a593Smuzhiyun 
6344*4882a593Smuzhiyun 	if (count <= LPFC_REG_WRITE_KEY_SIZE)
6345*4882a593Smuzhiyun 		return 0;
6346*4882a593Smuzhiyun 
6347*4882a593Smuzhiyun 	if (off % 4 || count % 4 || (unsigned long)buf % 4)
6348*4882a593Smuzhiyun 		return -EINVAL;
6349*4882a593Smuzhiyun 
6350*4882a593Smuzhiyun 	/* This is to protect HBA registers from accidental writes. */
6351*4882a593Smuzhiyun 	if (memcmp(buf, LPFC_REG_WRITE_KEY, LPFC_REG_WRITE_KEY_SIZE))
6352*4882a593Smuzhiyun 		return -EINVAL;
6353*4882a593Smuzhiyun 
6354*4882a593Smuzhiyun 	if (!(vport->fc_flag & FC_OFFLINE_MODE))
6355*4882a593Smuzhiyun 		return -EPERM;
6356*4882a593Smuzhiyun 
6357*4882a593Smuzhiyun 	spin_lock_irq(&phba->hbalock);
6358*4882a593Smuzhiyun 	for (buf_off = 0; buf_off < count - LPFC_REG_WRITE_KEY_SIZE;
6359*4882a593Smuzhiyun 			buf_off += sizeof(uint32_t))
6360*4882a593Smuzhiyun 		writel(*((uint32_t *)(buf + buf_off + LPFC_REG_WRITE_KEY_SIZE)),
6361*4882a593Smuzhiyun 		       phba->ctrl_regs_memmap_p + off + buf_off);
6362*4882a593Smuzhiyun 
6363*4882a593Smuzhiyun 	spin_unlock_irq(&phba->hbalock);
6364*4882a593Smuzhiyun 
6365*4882a593Smuzhiyun 	return count;
6366*4882a593Smuzhiyun }
6367*4882a593Smuzhiyun 
6368*4882a593Smuzhiyun /**
6369*4882a593Smuzhiyun  * sysfs_ctlreg_read - Read method for reading from ctlreg
6370*4882a593Smuzhiyun  * @filp: open sysfs file
6371*4882a593Smuzhiyun  * @kobj: kernel kobject that contains the kernel class device.
6372*4882a593Smuzhiyun  * @bin_attr: kernel attributes passed to us.
6373*4882a593Smuzhiyun  * @buf: if successful contains the data from the adapter IOREG space.
6374*4882a593Smuzhiyun  * @off: offset into buffer to beginning of data.
6375*4882a593Smuzhiyun  * @count: bytes to transfer.
6376*4882a593Smuzhiyun  *
6377*4882a593Smuzhiyun  * Description:
6378*4882a593Smuzhiyun  * Accessed via /sys/class/scsi_host/hostxxx/ctlreg.
6379*4882a593Smuzhiyun  * Uses the adapter io control registers to read data into buf.
6380*4882a593Smuzhiyun  *
6381*4882a593Smuzhiyun  * Returns:
6382*4882a593Smuzhiyun  * -ERANGE off and count combo out of range
6383*4882a593Smuzhiyun  * -EINVAL off, count or buff address invalid
6384*4882a593Smuzhiyun  * value of count, buf contents read
6385*4882a593Smuzhiyun  **/
6386*4882a593Smuzhiyun static ssize_t
sysfs_ctlreg_read(struct file * filp,struct kobject * kobj,struct bin_attribute * bin_attr,char * buf,loff_t off,size_t count)6387*4882a593Smuzhiyun sysfs_ctlreg_read(struct file *filp, struct kobject *kobj,
6388*4882a593Smuzhiyun 		  struct bin_attribute *bin_attr,
6389*4882a593Smuzhiyun 		  char *buf, loff_t off, size_t count)
6390*4882a593Smuzhiyun {
6391*4882a593Smuzhiyun 	size_t buf_off;
6392*4882a593Smuzhiyun 	uint32_t * tmp_ptr;
6393*4882a593Smuzhiyun 	struct device *dev = container_of(kobj, struct device, kobj);
6394*4882a593Smuzhiyun 	struct Scsi_Host  *shost = class_to_shost(dev);
6395*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
6396*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
6397*4882a593Smuzhiyun 
6398*4882a593Smuzhiyun 	if (phba->sli_rev >= LPFC_SLI_REV4)
6399*4882a593Smuzhiyun 		return -EPERM;
6400*4882a593Smuzhiyun 
6401*4882a593Smuzhiyun 	if (off > FF_REG_AREA_SIZE)
6402*4882a593Smuzhiyun 		return -ERANGE;
6403*4882a593Smuzhiyun 
6404*4882a593Smuzhiyun 	if ((off + count) > FF_REG_AREA_SIZE)
6405*4882a593Smuzhiyun 		count = FF_REG_AREA_SIZE - off;
6406*4882a593Smuzhiyun 
6407*4882a593Smuzhiyun 	if (count == 0) return 0;
6408*4882a593Smuzhiyun 
6409*4882a593Smuzhiyun 	if (off % 4 || count % 4 || (unsigned long)buf % 4)
6410*4882a593Smuzhiyun 		return -EINVAL;
6411*4882a593Smuzhiyun 
6412*4882a593Smuzhiyun 	spin_lock_irq(&phba->hbalock);
6413*4882a593Smuzhiyun 
6414*4882a593Smuzhiyun 	for (buf_off = 0; buf_off < count; buf_off += sizeof(uint32_t)) {
6415*4882a593Smuzhiyun 		tmp_ptr = (uint32_t *)(buf + buf_off);
6416*4882a593Smuzhiyun 		*tmp_ptr = readl(phba->ctrl_regs_memmap_p + off + buf_off);
6417*4882a593Smuzhiyun 	}
6418*4882a593Smuzhiyun 
6419*4882a593Smuzhiyun 	spin_unlock_irq(&phba->hbalock);
6420*4882a593Smuzhiyun 
6421*4882a593Smuzhiyun 	return count;
6422*4882a593Smuzhiyun }
6423*4882a593Smuzhiyun 
6424*4882a593Smuzhiyun static struct bin_attribute sysfs_ctlreg_attr = {
6425*4882a593Smuzhiyun 	.attr = {
6426*4882a593Smuzhiyun 		.name = "ctlreg",
6427*4882a593Smuzhiyun 		.mode = S_IRUSR | S_IWUSR,
6428*4882a593Smuzhiyun 	},
6429*4882a593Smuzhiyun 	.size = 256,
6430*4882a593Smuzhiyun 	.read = sysfs_ctlreg_read,
6431*4882a593Smuzhiyun 	.write = sysfs_ctlreg_write,
6432*4882a593Smuzhiyun };
6433*4882a593Smuzhiyun 
6434*4882a593Smuzhiyun /**
6435*4882a593Smuzhiyun  * sysfs_mbox_write - Write method for writing information via mbox
6436*4882a593Smuzhiyun  * @filp: open sysfs file
6437*4882a593Smuzhiyun  * @kobj: kernel kobject that contains the kernel class device.
6438*4882a593Smuzhiyun  * @bin_attr: kernel attributes passed to us.
6439*4882a593Smuzhiyun  * @buf: contains the data to be written to sysfs mbox.
6440*4882a593Smuzhiyun  * @off: offset into buffer to beginning of data.
6441*4882a593Smuzhiyun  * @count: bytes to transfer.
6442*4882a593Smuzhiyun  *
6443*4882a593Smuzhiyun  * Description:
6444*4882a593Smuzhiyun  * Deprecated function. All mailbox access from user space is performed via the
6445*4882a593Smuzhiyun  * bsg interface.
6446*4882a593Smuzhiyun  *
6447*4882a593Smuzhiyun  * Returns:
6448*4882a593Smuzhiyun  * -EPERM operation not permitted
6449*4882a593Smuzhiyun  **/
6450*4882a593Smuzhiyun static ssize_t
sysfs_mbox_write(struct file * filp,struct kobject * kobj,struct bin_attribute * bin_attr,char * buf,loff_t off,size_t count)6451*4882a593Smuzhiyun sysfs_mbox_write(struct file *filp, struct kobject *kobj,
6452*4882a593Smuzhiyun 		 struct bin_attribute *bin_attr,
6453*4882a593Smuzhiyun 		 char *buf, loff_t off, size_t count)
6454*4882a593Smuzhiyun {
6455*4882a593Smuzhiyun 	return -EPERM;
6456*4882a593Smuzhiyun }
6457*4882a593Smuzhiyun 
6458*4882a593Smuzhiyun /**
6459*4882a593Smuzhiyun  * sysfs_mbox_read - Read method for reading information via mbox
6460*4882a593Smuzhiyun  * @filp: open sysfs file
6461*4882a593Smuzhiyun  * @kobj: kernel kobject that contains the kernel class device.
6462*4882a593Smuzhiyun  * @bin_attr: kernel attributes passed to us.
6463*4882a593Smuzhiyun  * @buf: contains the data to be read from sysfs mbox.
6464*4882a593Smuzhiyun  * @off: offset into buffer to beginning of data.
6465*4882a593Smuzhiyun  * @count: bytes to transfer.
6466*4882a593Smuzhiyun  *
6467*4882a593Smuzhiyun  * Description:
6468*4882a593Smuzhiyun  * Deprecated function. All mailbox access from user space is performed via the
6469*4882a593Smuzhiyun  * bsg interface.
6470*4882a593Smuzhiyun  *
6471*4882a593Smuzhiyun  * Returns:
6472*4882a593Smuzhiyun  * -EPERM operation not permitted
6473*4882a593Smuzhiyun  **/
6474*4882a593Smuzhiyun static ssize_t
sysfs_mbox_read(struct file * filp,struct kobject * kobj,struct bin_attribute * bin_attr,char * buf,loff_t off,size_t count)6475*4882a593Smuzhiyun sysfs_mbox_read(struct file *filp, struct kobject *kobj,
6476*4882a593Smuzhiyun 		struct bin_attribute *bin_attr,
6477*4882a593Smuzhiyun 		char *buf, loff_t off, size_t count)
6478*4882a593Smuzhiyun {
6479*4882a593Smuzhiyun 	return -EPERM;
6480*4882a593Smuzhiyun }
6481*4882a593Smuzhiyun 
6482*4882a593Smuzhiyun static struct bin_attribute sysfs_mbox_attr = {
6483*4882a593Smuzhiyun 	.attr = {
6484*4882a593Smuzhiyun 		.name = "mbox",
6485*4882a593Smuzhiyun 		.mode = S_IRUSR | S_IWUSR,
6486*4882a593Smuzhiyun 	},
6487*4882a593Smuzhiyun 	.size = MAILBOX_SYSFS_MAX,
6488*4882a593Smuzhiyun 	.read = sysfs_mbox_read,
6489*4882a593Smuzhiyun 	.write = sysfs_mbox_write,
6490*4882a593Smuzhiyun };
6491*4882a593Smuzhiyun 
6492*4882a593Smuzhiyun /**
6493*4882a593Smuzhiyun  * lpfc_alloc_sysfs_attr - Creates the ctlreg and mbox entries
6494*4882a593Smuzhiyun  * @vport: address of lpfc vport structure.
6495*4882a593Smuzhiyun  *
6496*4882a593Smuzhiyun  * Return codes:
6497*4882a593Smuzhiyun  * zero on success
6498*4882a593Smuzhiyun  * error return code from sysfs_create_bin_file()
6499*4882a593Smuzhiyun  **/
6500*4882a593Smuzhiyun int
lpfc_alloc_sysfs_attr(struct lpfc_vport * vport)6501*4882a593Smuzhiyun lpfc_alloc_sysfs_attr(struct lpfc_vport *vport)
6502*4882a593Smuzhiyun {
6503*4882a593Smuzhiyun 	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
6504*4882a593Smuzhiyun 	int error;
6505*4882a593Smuzhiyun 
6506*4882a593Smuzhiyun 	error = sysfs_create_bin_file(&shost->shost_dev.kobj,
6507*4882a593Smuzhiyun 				      &sysfs_drvr_stat_data_attr);
6508*4882a593Smuzhiyun 
6509*4882a593Smuzhiyun 	/* Virtual ports do not need ctrl_reg and mbox */
6510*4882a593Smuzhiyun 	if (error || vport->port_type == LPFC_NPIV_PORT)
6511*4882a593Smuzhiyun 		goto out;
6512*4882a593Smuzhiyun 
6513*4882a593Smuzhiyun 	error = sysfs_create_bin_file(&shost->shost_dev.kobj,
6514*4882a593Smuzhiyun 				      &sysfs_ctlreg_attr);
6515*4882a593Smuzhiyun 	if (error)
6516*4882a593Smuzhiyun 		goto out_remove_stat_attr;
6517*4882a593Smuzhiyun 
6518*4882a593Smuzhiyun 	error = sysfs_create_bin_file(&shost->shost_dev.kobj,
6519*4882a593Smuzhiyun 				      &sysfs_mbox_attr);
6520*4882a593Smuzhiyun 	if (error)
6521*4882a593Smuzhiyun 		goto out_remove_ctlreg_attr;
6522*4882a593Smuzhiyun 
6523*4882a593Smuzhiyun 	return 0;
6524*4882a593Smuzhiyun out_remove_ctlreg_attr:
6525*4882a593Smuzhiyun 	sysfs_remove_bin_file(&shost->shost_dev.kobj, &sysfs_ctlreg_attr);
6526*4882a593Smuzhiyun out_remove_stat_attr:
6527*4882a593Smuzhiyun 	sysfs_remove_bin_file(&shost->shost_dev.kobj,
6528*4882a593Smuzhiyun 			&sysfs_drvr_stat_data_attr);
6529*4882a593Smuzhiyun out:
6530*4882a593Smuzhiyun 	return error;
6531*4882a593Smuzhiyun }
6532*4882a593Smuzhiyun 
6533*4882a593Smuzhiyun /**
6534*4882a593Smuzhiyun  * lpfc_free_sysfs_attr - Removes the ctlreg and mbox entries
6535*4882a593Smuzhiyun  * @vport: address of lpfc vport structure.
6536*4882a593Smuzhiyun  **/
6537*4882a593Smuzhiyun void
lpfc_free_sysfs_attr(struct lpfc_vport * vport)6538*4882a593Smuzhiyun lpfc_free_sysfs_attr(struct lpfc_vport *vport)
6539*4882a593Smuzhiyun {
6540*4882a593Smuzhiyun 	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
6541*4882a593Smuzhiyun 	sysfs_remove_bin_file(&shost->shost_dev.kobj,
6542*4882a593Smuzhiyun 		&sysfs_drvr_stat_data_attr);
6543*4882a593Smuzhiyun 	/* Virtual ports do not need ctrl_reg and mbox */
6544*4882a593Smuzhiyun 	if (vport->port_type == LPFC_NPIV_PORT)
6545*4882a593Smuzhiyun 		return;
6546*4882a593Smuzhiyun 	sysfs_remove_bin_file(&shost->shost_dev.kobj, &sysfs_mbox_attr);
6547*4882a593Smuzhiyun 	sysfs_remove_bin_file(&shost->shost_dev.kobj, &sysfs_ctlreg_attr);
6548*4882a593Smuzhiyun }
6549*4882a593Smuzhiyun 
6550*4882a593Smuzhiyun /*
6551*4882a593Smuzhiyun  * Dynamic FC Host Attributes Support
6552*4882a593Smuzhiyun  */
6553*4882a593Smuzhiyun 
6554*4882a593Smuzhiyun /**
6555*4882a593Smuzhiyun  * lpfc_get_host_symbolic_name - Copy symbolic name into the scsi host
6556*4882a593Smuzhiyun  * @shost: kernel scsi host pointer.
6557*4882a593Smuzhiyun  **/
6558*4882a593Smuzhiyun static void
lpfc_get_host_symbolic_name(struct Scsi_Host * shost)6559*4882a593Smuzhiyun lpfc_get_host_symbolic_name(struct Scsi_Host *shost)
6560*4882a593Smuzhiyun {
6561*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata;
6562*4882a593Smuzhiyun 
6563*4882a593Smuzhiyun 	lpfc_vport_symbolic_node_name(vport, fc_host_symbolic_name(shost),
6564*4882a593Smuzhiyun 				      sizeof fc_host_symbolic_name(shost));
6565*4882a593Smuzhiyun }
6566*4882a593Smuzhiyun 
6567*4882a593Smuzhiyun /**
6568*4882a593Smuzhiyun  * lpfc_get_host_port_id - Copy the vport DID into the scsi host port id
6569*4882a593Smuzhiyun  * @shost: kernel scsi host pointer.
6570*4882a593Smuzhiyun  **/
6571*4882a593Smuzhiyun static void
lpfc_get_host_port_id(struct Scsi_Host * shost)6572*4882a593Smuzhiyun lpfc_get_host_port_id(struct Scsi_Host *shost)
6573*4882a593Smuzhiyun {
6574*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
6575*4882a593Smuzhiyun 
6576*4882a593Smuzhiyun 	/* note: fc_myDID already in cpu endianness */
6577*4882a593Smuzhiyun 	fc_host_port_id(shost) = vport->fc_myDID;
6578*4882a593Smuzhiyun }
6579*4882a593Smuzhiyun 
6580*4882a593Smuzhiyun /**
6581*4882a593Smuzhiyun  * lpfc_get_host_port_type - Set the value of the scsi host port type
6582*4882a593Smuzhiyun  * @shost: kernel scsi host pointer.
6583*4882a593Smuzhiyun  **/
6584*4882a593Smuzhiyun static void
lpfc_get_host_port_type(struct Scsi_Host * shost)6585*4882a593Smuzhiyun lpfc_get_host_port_type(struct Scsi_Host *shost)
6586*4882a593Smuzhiyun {
6587*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
6588*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
6589*4882a593Smuzhiyun 
6590*4882a593Smuzhiyun 	spin_lock_irq(shost->host_lock);
6591*4882a593Smuzhiyun 
6592*4882a593Smuzhiyun 	if (vport->port_type == LPFC_NPIV_PORT) {
6593*4882a593Smuzhiyun 		fc_host_port_type(shost) = FC_PORTTYPE_NPIV;
6594*4882a593Smuzhiyun 	} else if (lpfc_is_link_up(phba)) {
6595*4882a593Smuzhiyun 		if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
6596*4882a593Smuzhiyun 			if (vport->fc_flag & FC_PUBLIC_LOOP)
6597*4882a593Smuzhiyun 				fc_host_port_type(shost) = FC_PORTTYPE_NLPORT;
6598*4882a593Smuzhiyun 			else
6599*4882a593Smuzhiyun 				fc_host_port_type(shost) = FC_PORTTYPE_LPORT;
6600*4882a593Smuzhiyun 		} else {
6601*4882a593Smuzhiyun 			if (vport->fc_flag & FC_FABRIC)
6602*4882a593Smuzhiyun 				fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
6603*4882a593Smuzhiyun 			else
6604*4882a593Smuzhiyun 				fc_host_port_type(shost) = FC_PORTTYPE_PTP;
6605*4882a593Smuzhiyun 		}
6606*4882a593Smuzhiyun 	} else
6607*4882a593Smuzhiyun 		fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN;
6608*4882a593Smuzhiyun 
6609*4882a593Smuzhiyun 	spin_unlock_irq(shost->host_lock);
6610*4882a593Smuzhiyun }
6611*4882a593Smuzhiyun 
6612*4882a593Smuzhiyun /**
6613*4882a593Smuzhiyun  * lpfc_get_host_port_state - Set the value of the scsi host port state
6614*4882a593Smuzhiyun  * @shost: kernel scsi host pointer.
6615*4882a593Smuzhiyun  **/
6616*4882a593Smuzhiyun static void
lpfc_get_host_port_state(struct Scsi_Host * shost)6617*4882a593Smuzhiyun lpfc_get_host_port_state(struct Scsi_Host *shost)
6618*4882a593Smuzhiyun {
6619*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
6620*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
6621*4882a593Smuzhiyun 
6622*4882a593Smuzhiyun 	spin_lock_irq(shost->host_lock);
6623*4882a593Smuzhiyun 
6624*4882a593Smuzhiyun 	if (vport->fc_flag & FC_OFFLINE_MODE)
6625*4882a593Smuzhiyun 		fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE;
6626*4882a593Smuzhiyun 	else {
6627*4882a593Smuzhiyun 		switch (phba->link_state) {
6628*4882a593Smuzhiyun 		case LPFC_LINK_UNKNOWN:
6629*4882a593Smuzhiyun 		case LPFC_LINK_DOWN:
6630*4882a593Smuzhiyun 			fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN;
6631*4882a593Smuzhiyun 			break;
6632*4882a593Smuzhiyun 		case LPFC_LINK_UP:
6633*4882a593Smuzhiyun 		case LPFC_CLEAR_LA:
6634*4882a593Smuzhiyun 		case LPFC_HBA_READY:
6635*4882a593Smuzhiyun 			/* Links up, reports port state accordingly */
6636*4882a593Smuzhiyun 			if (vport->port_state < LPFC_VPORT_READY)
6637*4882a593Smuzhiyun 				fc_host_port_state(shost) =
6638*4882a593Smuzhiyun 							FC_PORTSTATE_BYPASSED;
6639*4882a593Smuzhiyun 			else
6640*4882a593Smuzhiyun 				fc_host_port_state(shost) =
6641*4882a593Smuzhiyun 							FC_PORTSTATE_ONLINE;
6642*4882a593Smuzhiyun 			break;
6643*4882a593Smuzhiyun 		case LPFC_HBA_ERROR:
6644*4882a593Smuzhiyun 			fc_host_port_state(shost) = FC_PORTSTATE_ERROR;
6645*4882a593Smuzhiyun 			break;
6646*4882a593Smuzhiyun 		default:
6647*4882a593Smuzhiyun 			fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN;
6648*4882a593Smuzhiyun 			break;
6649*4882a593Smuzhiyun 		}
6650*4882a593Smuzhiyun 	}
6651*4882a593Smuzhiyun 
6652*4882a593Smuzhiyun 	spin_unlock_irq(shost->host_lock);
6653*4882a593Smuzhiyun }
6654*4882a593Smuzhiyun 
6655*4882a593Smuzhiyun /**
6656*4882a593Smuzhiyun  * lpfc_get_host_speed - Set the value of the scsi host speed
6657*4882a593Smuzhiyun  * @shost: kernel scsi host pointer.
6658*4882a593Smuzhiyun  **/
6659*4882a593Smuzhiyun static void
lpfc_get_host_speed(struct Scsi_Host * shost)6660*4882a593Smuzhiyun lpfc_get_host_speed(struct Scsi_Host *shost)
6661*4882a593Smuzhiyun {
6662*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
6663*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
6664*4882a593Smuzhiyun 
6665*4882a593Smuzhiyun 	spin_lock_irq(shost->host_lock);
6666*4882a593Smuzhiyun 
6667*4882a593Smuzhiyun 	if ((lpfc_is_link_up(phba)) && (!(phba->hba_flag & HBA_FCOE_MODE))) {
6668*4882a593Smuzhiyun 		switch(phba->fc_linkspeed) {
6669*4882a593Smuzhiyun 		case LPFC_LINK_SPEED_1GHZ:
6670*4882a593Smuzhiyun 			fc_host_speed(shost) = FC_PORTSPEED_1GBIT;
6671*4882a593Smuzhiyun 			break;
6672*4882a593Smuzhiyun 		case LPFC_LINK_SPEED_2GHZ:
6673*4882a593Smuzhiyun 			fc_host_speed(shost) = FC_PORTSPEED_2GBIT;
6674*4882a593Smuzhiyun 			break;
6675*4882a593Smuzhiyun 		case LPFC_LINK_SPEED_4GHZ:
6676*4882a593Smuzhiyun 			fc_host_speed(shost) = FC_PORTSPEED_4GBIT;
6677*4882a593Smuzhiyun 			break;
6678*4882a593Smuzhiyun 		case LPFC_LINK_SPEED_8GHZ:
6679*4882a593Smuzhiyun 			fc_host_speed(shost) = FC_PORTSPEED_8GBIT;
6680*4882a593Smuzhiyun 			break;
6681*4882a593Smuzhiyun 		case LPFC_LINK_SPEED_10GHZ:
6682*4882a593Smuzhiyun 			fc_host_speed(shost) = FC_PORTSPEED_10GBIT;
6683*4882a593Smuzhiyun 			break;
6684*4882a593Smuzhiyun 		case LPFC_LINK_SPEED_16GHZ:
6685*4882a593Smuzhiyun 			fc_host_speed(shost) = FC_PORTSPEED_16GBIT;
6686*4882a593Smuzhiyun 			break;
6687*4882a593Smuzhiyun 		case LPFC_LINK_SPEED_32GHZ:
6688*4882a593Smuzhiyun 			fc_host_speed(shost) = FC_PORTSPEED_32GBIT;
6689*4882a593Smuzhiyun 			break;
6690*4882a593Smuzhiyun 		case LPFC_LINK_SPEED_64GHZ:
6691*4882a593Smuzhiyun 			fc_host_speed(shost) = FC_PORTSPEED_64GBIT;
6692*4882a593Smuzhiyun 			break;
6693*4882a593Smuzhiyun 		case LPFC_LINK_SPEED_128GHZ:
6694*4882a593Smuzhiyun 			fc_host_speed(shost) = FC_PORTSPEED_128GBIT;
6695*4882a593Smuzhiyun 			break;
6696*4882a593Smuzhiyun 		default:
6697*4882a593Smuzhiyun 			fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
6698*4882a593Smuzhiyun 			break;
6699*4882a593Smuzhiyun 		}
6700*4882a593Smuzhiyun 	} else if (lpfc_is_link_up(phba) && (phba->hba_flag & HBA_FCOE_MODE)) {
6701*4882a593Smuzhiyun 		switch (phba->fc_linkspeed) {
6702*4882a593Smuzhiyun 		case LPFC_ASYNC_LINK_SPEED_1GBPS:
6703*4882a593Smuzhiyun 			fc_host_speed(shost) = FC_PORTSPEED_1GBIT;
6704*4882a593Smuzhiyun 			break;
6705*4882a593Smuzhiyun 		case LPFC_ASYNC_LINK_SPEED_10GBPS:
6706*4882a593Smuzhiyun 			fc_host_speed(shost) = FC_PORTSPEED_10GBIT;
6707*4882a593Smuzhiyun 			break;
6708*4882a593Smuzhiyun 		case LPFC_ASYNC_LINK_SPEED_20GBPS:
6709*4882a593Smuzhiyun 			fc_host_speed(shost) = FC_PORTSPEED_20GBIT;
6710*4882a593Smuzhiyun 			break;
6711*4882a593Smuzhiyun 		case LPFC_ASYNC_LINK_SPEED_25GBPS:
6712*4882a593Smuzhiyun 			fc_host_speed(shost) = FC_PORTSPEED_25GBIT;
6713*4882a593Smuzhiyun 			break;
6714*4882a593Smuzhiyun 		case LPFC_ASYNC_LINK_SPEED_40GBPS:
6715*4882a593Smuzhiyun 			fc_host_speed(shost) = FC_PORTSPEED_40GBIT;
6716*4882a593Smuzhiyun 			break;
6717*4882a593Smuzhiyun 		case LPFC_ASYNC_LINK_SPEED_100GBPS:
6718*4882a593Smuzhiyun 			fc_host_speed(shost) = FC_PORTSPEED_100GBIT;
6719*4882a593Smuzhiyun 			break;
6720*4882a593Smuzhiyun 		default:
6721*4882a593Smuzhiyun 			fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
6722*4882a593Smuzhiyun 			break;
6723*4882a593Smuzhiyun 		}
6724*4882a593Smuzhiyun 	} else
6725*4882a593Smuzhiyun 		fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
6726*4882a593Smuzhiyun 
6727*4882a593Smuzhiyun 	spin_unlock_irq(shost->host_lock);
6728*4882a593Smuzhiyun }
6729*4882a593Smuzhiyun 
6730*4882a593Smuzhiyun /**
6731*4882a593Smuzhiyun  * lpfc_get_host_fabric_name - Set the value of the scsi host fabric name
6732*4882a593Smuzhiyun  * @shost: kernel scsi host pointer.
6733*4882a593Smuzhiyun  **/
6734*4882a593Smuzhiyun static void
lpfc_get_host_fabric_name(struct Scsi_Host * shost)6735*4882a593Smuzhiyun lpfc_get_host_fabric_name (struct Scsi_Host *shost)
6736*4882a593Smuzhiyun {
6737*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
6738*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
6739*4882a593Smuzhiyun 	u64 node_name;
6740*4882a593Smuzhiyun 
6741*4882a593Smuzhiyun 	spin_lock_irq(shost->host_lock);
6742*4882a593Smuzhiyun 
6743*4882a593Smuzhiyun 	if ((vport->port_state > LPFC_FLOGI) &&
6744*4882a593Smuzhiyun 	    ((vport->fc_flag & FC_FABRIC) ||
6745*4882a593Smuzhiyun 	     ((phba->fc_topology == LPFC_TOPOLOGY_LOOP) &&
6746*4882a593Smuzhiyun 	      (vport->fc_flag & FC_PUBLIC_LOOP))))
6747*4882a593Smuzhiyun 		node_name = wwn_to_u64(phba->fc_fabparam.nodeName.u.wwn);
6748*4882a593Smuzhiyun 	else
6749*4882a593Smuzhiyun 		/* fabric is local port if there is no F/FL_Port */
6750*4882a593Smuzhiyun 		node_name = 0;
6751*4882a593Smuzhiyun 
6752*4882a593Smuzhiyun 	spin_unlock_irq(shost->host_lock);
6753*4882a593Smuzhiyun 
6754*4882a593Smuzhiyun 	fc_host_fabric_name(shost) = node_name;
6755*4882a593Smuzhiyun }
6756*4882a593Smuzhiyun 
6757*4882a593Smuzhiyun /**
6758*4882a593Smuzhiyun  * lpfc_get_stats - Return statistical information about the adapter
6759*4882a593Smuzhiyun  * @shost: kernel scsi host pointer.
6760*4882a593Smuzhiyun  *
6761*4882a593Smuzhiyun  * Notes:
6762*4882a593Smuzhiyun  * NULL on error for link down, no mbox pool, sli2 active,
6763*4882a593Smuzhiyun  * management not allowed, memory allocation error, or mbox error.
6764*4882a593Smuzhiyun  *
6765*4882a593Smuzhiyun  * Returns:
6766*4882a593Smuzhiyun  * NULL for error
6767*4882a593Smuzhiyun  * address of the adapter host statistics
6768*4882a593Smuzhiyun  **/
6769*4882a593Smuzhiyun static struct fc_host_statistics *
lpfc_get_stats(struct Scsi_Host * shost)6770*4882a593Smuzhiyun lpfc_get_stats(struct Scsi_Host *shost)
6771*4882a593Smuzhiyun {
6772*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
6773*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
6774*4882a593Smuzhiyun 	struct lpfc_sli   *psli = &phba->sli;
6775*4882a593Smuzhiyun 	struct fc_host_statistics *hs = &phba->link_stats;
6776*4882a593Smuzhiyun 	struct lpfc_lnk_stat * lso = &psli->lnk_stat_offsets;
6777*4882a593Smuzhiyun 	LPFC_MBOXQ_t *pmboxq;
6778*4882a593Smuzhiyun 	MAILBOX_t *pmb;
6779*4882a593Smuzhiyun 	int rc = 0;
6780*4882a593Smuzhiyun 
6781*4882a593Smuzhiyun 	/*
6782*4882a593Smuzhiyun 	 * prevent udev from issuing mailbox commands until the port is
6783*4882a593Smuzhiyun 	 * configured.
6784*4882a593Smuzhiyun 	 */
6785*4882a593Smuzhiyun 	if (phba->link_state < LPFC_LINK_DOWN ||
6786*4882a593Smuzhiyun 	    !phba->mbox_mem_pool ||
6787*4882a593Smuzhiyun 	    (phba->sli.sli_flag & LPFC_SLI_ACTIVE) == 0)
6788*4882a593Smuzhiyun 		return NULL;
6789*4882a593Smuzhiyun 
6790*4882a593Smuzhiyun 	if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO)
6791*4882a593Smuzhiyun 		return NULL;
6792*4882a593Smuzhiyun 
6793*4882a593Smuzhiyun 	pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
6794*4882a593Smuzhiyun 	if (!pmboxq)
6795*4882a593Smuzhiyun 		return NULL;
6796*4882a593Smuzhiyun 	memset(pmboxq, 0, sizeof (LPFC_MBOXQ_t));
6797*4882a593Smuzhiyun 
6798*4882a593Smuzhiyun 	pmb = &pmboxq->u.mb;
6799*4882a593Smuzhiyun 	pmb->mbxCommand = MBX_READ_STATUS;
6800*4882a593Smuzhiyun 	pmb->mbxOwner = OWN_HOST;
6801*4882a593Smuzhiyun 	pmboxq->ctx_buf = NULL;
6802*4882a593Smuzhiyun 	pmboxq->vport = vport;
6803*4882a593Smuzhiyun 
6804*4882a593Smuzhiyun 	if (vport->fc_flag & FC_OFFLINE_MODE) {
6805*4882a593Smuzhiyun 		rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL);
6806*4882a593Smuzhiyun 		if (rc != MBX_SUCCESS) {
6807*4882a593Smuzhiyun 			mempool_free(pmboxq, phba->mbox_mem_pool);
6808*4882a593Smuzhiyun 			return NULL;
6809*4882a593Smuzhiyun 		}
6810*4882a593Smuzhiyun 	} else {
6811*4882a593Smuzhiyun 		rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
6812*4882a593Smuzhiyun 		if (rc != MBX_SUCCESS) {
6813*4882a593Smuzhiyun 			if (rc != MBX_TIMEOUT)
6814*4882a593Smuzhiyun 				mempool_free(pmboxq, phba->mbox_mem_pool);
6815*4882a593Smuzhiyun 			return NULL;
6816*4882a593Smuzhiyun 		}
6817*4882a593Smuzhiyun 	}
6818*4882a593Smuzhiyun 
6819*4882a593Smuzhiyun 	memset(hs, 0, sizeof (struct fc_host_statistics));
6820*4882a593Smuzhiyun 
6821*4882a593Smuzhiyun 	hs->tx_frames = pmb->un.varRdStatus.xmitFrameCnt;
6822*4882a593Smuzhiyun 	/*
6823*4882a593Smuzhiyun 	 * The MBX_READ_STATUS returns tx_k_bytes which has to
6824*4882a593Smuzhiyun 	 * converted to words
6825*4882a593Smuzhiyun 	 */
6826*4882a593Smuzhiyun 	hs->tx_words = (uint64_t)
6827*4882a593Smuzhiyun 			((uint64_t)pmb->un.varRdStatus.xmitByteCnt
6828*4882a593Smuzhiyun 			* (uint64_t)256);
6829*4882a593Smuzhiyun 	hs->rx_frames = pmb->un.varRdStatus.rcvFrameCnt;
6830*4882a593Smuzhiyun 	hs->rx_words = (uint64_t)
6831*4882a593Smuzhiyun 			((uint64_t)pmb->un.varRdStatus.rcvByteCnt
6832*4882a593Smuzhiyun 			 * (uint64_t)256);
6833*4882a593Smuzhiyun 
6834*4882a593Smuzhiyun 	memset(pmboxq, 0, sizeof (LPFC_MBOXQ_t));
6835*4882a593Smuzhiyun 	pmb->mbxCommand = MBX_READ_LNK_STAT;
6836*4882a593Smuzhiyun 	pmb->mbxOwner = OWN_HOST;
6837*4882a593Smuzhiyun 	pmboxq->ctx_buf = NULL;
6838*4882a593Smuzhiyun 	pmboxq->vport = vport;
6839*4882a593Smuzhiyun 
6840*4882a593Smuzhiyun 	if (vport->fc_flag & FC_OFFLINE_MODE) {
6841*4882a593Smuzhiyun 		rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL);
6842*4882a593Smuzhiyun 		if (rc != MBX_SUCCESS) {
6843*4882a593Smuzhiyun 			mempool_free(pmboxq, phba->mbox_mem_pool);
6844*4882a593Smuzhiyun 			return NULL;
6845*4882a593Smuzhiyun 		}
6846*4882a593Smuzhiyun 	} else {
6847*4882a593Smuzhiyun 		rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
6848*4882a593Smuzhiyun 		if (rc != MBX_SUCCESS) {
6849*4882a593Smuzhiyun 			if (rc != MBX_TIMEOUT)
6850*4882a593Smuzhiyun 				mempool_free(pmboxq, phba->mbox_mem_pool);
6851*4882a593Smuzhiyun 			return NULL;
6852*4882a593Smuzhiyun 		}
6853*4882a593Smuzhiyun 	}
6854*4882a593Smuzhiyun 
6855*4882a593Smuzhiyun 	hs->link_failure_count = pmb->un.varRdLnk.linkFailureCnt;
6856*4882a593Smuzhiyun 	hs->loss_of_sync_count = pmb->un.varRdLnk.lossSyncCnt;
6857*4882a593Smuzhiyun 	hs->loss_of_signal_count = pmb->un.varRdLnk.lossSignalCnt;
6858*4882a593Smuzhiyun 	hs->prim_seq_protocol_err_count = pmb->un.varRdLnk.primSeqErrCnt;
6859*4882a593Smuzhiyun 	hs->invalid_tx_word_count = pmb->un.varRdLnk.invalidXmitWord;
6860*4882a593Smuzhiyun 	hs->invalid_crc_count = pmb->un.varRdLnk.crcCnt;
6861*4882a593Smuzhiyun 	hs->error_frames = pmb->un.varRdLnk.crcCnt;
6862*4882a593Smuzhiyun 
6863*4882a593Smuzhiyun 	hs->link_failure_count -= lso->link_failure_count;
6864*4882a593Smuzhiyun 	hs->loss_of_sync_count -= lso->loss_of_sync_count;
6865*4882a593Smuzhiyun 	hs->loss_of_signal_count -= lso->loss_of_signal_count;
6866*4882a593Smuzhiyun 	hs->prim_seq_protocol_err_count -= lso->prim_seq_protocol_err_count;
6867*4882a593Smuzhiyun 	hs->invalid_tx_word_count -= lso->invalid_tx_word_count;
6868*4882a593Smuzhiyun 	hs->invalid_crc_count -= lso->invalid_crc_count;
6869*4882a593Smuzhiyun 	hs->error_frames -= lso->error_frames;
6870*4882a593Smuzhiyun 
6871*4882a593Smuzhiyun 	if (phba->hba_flag & HBA_FCOE_MODE) {
6872*4882a593Smuzhiyun 		hs->lip_count = -1;
6873*4882a593Smuzhiyun 		hs->nos_count = (phba->link_events >> 1);
6874*4882a593Smuzhiyun 		hs->nos_count -= lso->link_events;
6875*4882a593Smuzhiyun 	} else if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
6876*4882a593Smuzhiyun 		hs->lip_count = (phba->fc_eventTag >> 1);
6877*4882a593Smuzhiyun 		hs->lip_count -= lso->link_events;
6878*4882a593Smuzhiyun 		hs->nos_count = -1;
6879*4882a593Smuzhiyun 	} else {
6880*4882a593Smuzhiyun 		hs->lip_count = -1;
6881*4882a593Smuzhiyun 		hs->nos_count = (phba->fc_eventTag >> 1);
6882*4882a593Smuzhiyun 		hs->nos_count -= lso->link_events;
6883*4882a593Smuzhiyun 	}
6884*4882a593Smuzhiyun 
6885*4882a593Smuzhiyun 	hs->dumped_frames = -1;
6886*4882a593Smuzhiyun 
6887*4882a593Smuzhiyun 	hs->seconds_since_last_reset = ktime_get_seconds() - psli->stats_start;
6888*4882a593Smuzhiyun 
6889*4882a593Smuzhiyun 	mempool_free(pmboxq, phba->mbox_mem_pool);
6890*4882a593Smuzhiyun 
6891*4882a593Smuzhiyun 	return hs;
6892*4882a593Smuzhiyun }
6893*4882a593Smuzhiyun 
6894*4882a593Smuzhiyun /**
6895*4882a593Smuzhiyun  * lpfc_reset_stats - Copy the adapter link stats information
6896*4882a593Smuzhiyun  * @shost: kernel scsi host pointer.
6897*4882a593Smuzhiyun  **/
6898*4882a593Smuzhiyun static void
lpfc_reset_stats(struct Scsi_Host * shost)6899*4882a593Smuzhiyun lpfc_reset_stats(struct Scsi_Host *shost)
6900*4882a593Smuzhiyun {
6901*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
6902*4882a593Smuzhiyun 	struct lpfc_hba   *phba = vport->phba;
6903*4882a593Smuzhiyun 	struct lpfc_sli   *psli = &phba->sli;
6904*4882a593Smuzhiyun 	struct lpfc_lnk_stat *lso = &psli->lnk_stat_offsets;
6905*4882a593Smuzhiyun 	LPFC_MBOXQ_t *pmboxq;
6906*4882a593Smuzhiyun 	MAILBOX_t *pmb;
6907*4882a593Smuzhiyun 	int rc = 0;
6908*4882a593Smuzhiyun 
6909*4882a593Smuzhiyun 	if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO)
6910*4882a593Smuzhiyun 		return;
6911*4882a593Smuzhiyun 
6912*4882a593Smuzhiyun 	pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
6913*4882a593Smuzhiyun 	if (!pmboxq)
6914*4882a593Smuzhiyun 		return;
6915*4882a593Smuzhiyun 	memset(pmboxq, 0, sizeof(LPFC_MBOXQ_t));
6916*4882a593Smuzhiyun 
6917*4882a593Smuzhiyun 	pmb = &pmboxq->u.mb;
6918*4882a593Smuzhiyun 	pmb->mbxCommand = MBX_READ_STATUS;
6919*4882a593Smuzhiyun 	pmb->mbxOwner = OWN_HOST;
6920*4882a593Smuzhiyun 	pmb->un.varWords[0] = 0x1; /* reset request */
6921*4882a593Smuzhiyun 	pmboxq->ctx_buf = NULL;
6922*4882a593Smuzhiyun 	pmboxq->vport = vport;
6923*4882a593Smuzhiyun 
6924*4882a593Smuzhiyun 	if ((vport->fc_flag & FC_OFFLINE_MODE) ||
6925*4882a593Smuzhiyun 		(!(psli->sli_flag & LPFC_SLI_ACTIVE))) {
6926*4882a593Smuzhiyun 		rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL);
6927*4882a593Smuzhiyun 		if (rc != MBX_SUCCESS) {
6928*4882a593Smuzhiyun 			mempool_free(pmboxq, phba->mbox_mem_pool);
6929*4882a593Smuzhiyun 			return;
6930*4882a593Smuzhiyun 		}
6931*4882a593Smuzhiyun 	} else {
6932*4882a593Smuzhiyun 		rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
6933*4882a593Smuzhiyun 		if (rc != MBX_SUCCESS) {
6934*4882a593Smuzhiyun 			if (rc != MBX_TIMEOUT)
6935*4882a593Smuzhiyun 				mempool_free(pmboxq, phba->mbox_mem_pool);
6936*4882a593Smuzhiyun 			return;
6937*4882a593Smuzhiyun 		}
6938*4882a593Smuzhiyun 	}
6939*4882a593Smuzhiyun 
6940*4882a593Smuzhiyun 	memset(pmboxq, 0, sizeof(LPFC_MBOXQ_t));
6941*4882a593Smuzhiyun 	pmb->mbxCommand = MBX_READ_LNK_STAT;
6942*4882a593Smuzhiyun 	pmb->mbxOwner = OWN_HOST;
6943*4882a593Smuzhiyun 	pmboxq->ctx_buf = NULL;
6944*4882a593Smuzhiyun 	pmboxq->vport = vport;
6945*4882a593Smuzhiyun 
6946*4882a593Smuzhiyun 	if ((vport->fc_flag & FC_OFFLINE_MODE) ||
6947*4882a593Smuzhiyun 	    (!(psli->sli_flag & LPFC_SLI_ACTIVE))) {
6948*4882a593Smuzhiyun 		rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL);
6949*4882a593Smuzhiyun 		if (rc != MBX_SUCCESS) {
6950*4882a593Smuzhiyun 			mempool_free(pmboxq, phba->mbox_mem_pool);
6951*4882a593Smuzhiyun 			return;
6952*4882a593Smuzhiyun 		}
6953*4882a593Smuzhiyun 	} else {
6954*4882a593Smuzhiyun 		rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
6955*4882a593Smuzhiyun 		if (rc != MBX_SUCCESS) {
6956*4882a593Smuzhiyun 			if (rc != MBX_TIMEOUT)
6957*4882a593Smuzhiyun 				mempool_free(pmboxq, phba->mbox_mem_pool);
6958*4882a593Smuzhiyun 			return;
6959*4882a593Smuzhiyun 		}
6960*4882a593Smuzhiyun 	}
6961*4882a593Smuzhiyun 
6962*4882a593Smuzhiyun 	lso->link_failure_count = pmb->un.varRdLnk.linkFailureCnt;
6963*4882a593Smuzhiyun 	lso->loss_of_sync_count = pmb->un.varRdLnk.lossSyncCnt;
6964*4882a593Smuzhiyun 	lso->loss_of_signal_count = pmb->un.varRdLnk.lossSignalCnt;
6965*4882a593Smuzhiyun 	lso->prim_seq_protocol_err_count = pmb->un.varRdLnk.primSeqErrCnt;
6966*4882a593Smuzhiyun 	lso->invalid_tx_word_count = pmb->un.varRdLnk.invalidXmitWord;
6967*4882a593Smuzhiyun 	lso->invalid_crc_count = pmb->un.varRdLnk.crcCnt;
6968*4882a593Smuzhiyun 	lso->error_frames = pmb->un.varRdLnk.crcCnt;
6969*4882a593Smuzhiyun 	if (phba->hba_flag & HBA_FCOE_MODE)
6970*4882a593Smuzhiyun 		lso->link_events = (phba->link_events >> 1);
6971*4882a593Smuzhiyun 	else
6972*4882a593Smuzhiyun 		lso->link_events = (phba->fc_eventTag >> 1);
6973*4882a593Smuzhiyun 
6974*4882a593Smuzhiyun 	psli->stats_start = ktime_get_seconds();
6975*4882a593Smuzhiyun 
6976*4882a593Smuzhiyun 	mempool_free(pmboxq, phba->mbox_mem_pool);
6977*4882a593Smuzhiyun 
6978*4882a593Smuzhiyun 	return;
6979*4882a593Smuzhiyun }
6980*4882a593Smuzhiyun 
6981*4882a593Smuzhiyun /*
6982*4882a593Smuzhiyun  * The LPFC driver treats linkdown handling as target loss events so there
6983*4882a593Smuzhiyun  * are no sysfs handlers for link_down_tmo.
6984*4882a593Smuzhiyun  */
6985*4882a593Smuzhiyun 
6986*4882a593Smuzhiyun /**
6987*4882a593Smuzhiyun  * lpfc_get_node_by_target - Return the nodelist for a target
6988*4882a593Smuzhiyun  * @starget: kernel scsi target pointer.
6989*4882a593Smuzhiyun  *
6990*4882a593Smuzhiyun  * Returns:
6991*4882a593Smuzhiyun  * address of the node list if found
6992*4882a593Smuzhiyun  * NULL target not found
6993*4882a593Smuzhiyun  **/
6994*4882a593Smuzhiyun static struct lpfc_nodelist *
lpfc_get_node_by_target(struct scsi_target * starget)6995*4882a593Smuzhiyun lpfc_get_node_by_target(struct scsi_target *starget)
6996*4882a593Smuzhiyun {
6997*4882a593Smuzhiyun 	struct Scsi_Host  *shost = dev_to_shost(starget->dev.parent);
6998*4882a593Smuzhiyun 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
6999*4882a593Smuzhiyun 	struct lpfc_nodelist *ndlp;
7000*4882a593Smuzhiyun 
7001*4882a593Smuzhiyun 	spin_lock_irq(shost->host_lock);
7002*4882a593Smuzhiyun 	/* Search for this, mapped, target ID */
7003*4882a593Smuzhiyun 	list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
7004*4882a593Smuzhiyun 		if (NLP_CHK_NODE_ACT(ndlp) &&
7005*4882a593Smuzhiyun 		    ndlp->nlp_state == NLP_STE_MAPPED_NODE &&
7006*4882a593Smuzhiyun 		    starget->id == ndlp->nlp_sid) {
7007*4882a593Smuzhiyun 			spin_unlock_irq(shost->host_lock);
7008*4882a593Smuzhiyun 			return ndlp;
7009*4882a593Smuzhiyun 		}
7010*4882a593Smuzhiyun 	}
7011*4882a593Smuzhiyun 	spin_unlock_irq(shost->host_lock);
7012*4882a593Smuzhiyun 	return NULL;
7013*4882a593Smuzhiyun }
7014*4882a593Smuzhiyun 
7015*4882a593Smuzhiyun /**
7016*4882a593Smuzhiyun  * lpfc_get_starget_port_id - Set the target port id to the ndlp DID or -1
7017*4882a593Smuzhiyun  * @starget: kernel scsi target pointer.
7018*4882a593Smuzhiyun  **/
7019*4882a593Smuzhiyun static void
lpfc_get_starget_port_id(struct scsi_target * starget)7020*4882a593Smuzhiyun lpfc_get_starget_port_id(struct scsi_target *starget)
7021*4882a593Smuzhiyun {
7022*4882a593Smuzhiyun 	struct lpfc_nodelist *ndlp = lpfc_get_node_by_target(starget);
7023*4882a593Smuzhiyun 
7024*4882a593Smuzhiyun 	fc_starget_port_id(starget) = ndlp ? ndlp->nlp_DID : -1;
7025*4882a593Smuzhiyun }
7026*4882a593Smuzhiyun 
7027*4882a593Smuzhiyun /**
7028*4882a593Smuzhiyun  * lpfc_get_starget_node_name - Set the target node name
7029*4882a593Smuzhiyun  * @starget: kernel scsi target pointer.
7030*4882a593Smuzhiyun  *
7031*4882a593Smuzhiyun  * Description: Set the target node name to the ndlp node name wwn or zero.
7032*4882a593Smuzhiyun  **/
7033*4882a593Smuzhiyun static void
lpfc_get_starget_node_name(struct scsi_target * starget)7034*4882a593Smuzhiyun lpfc_get_starget_node_name(struct scsi_target *starget)
7035*4882a593Smuzhiyun {
7036*4882a593Smuzhiyun 	struct lpfc_nodelist *ndlp = lpfc_get_node_by_target(starget);
7037*4882a593Smuzhiyun 
7038*4882a593Smuzhiyun 	fc_starget_node_name(starget) =
7039*4882a593Smuzhiyun 		ndlp ? wwn_to_u64(ndlp->nlp_nodename.u.wwn) : 0;
7040*4882a593Smuzhiyun }
7041*4882a593Smuzhiyun 
7042*4882a593Smuzhiyun /**
7043*4882a593Smuzhiyun  * lpfc_get_starget_port_name - Set the target port name
7044*4882a593Smuzhiyun  * @starget: kernel scsi target pointer.
7045*4882a593Smuzhiyun  *
7046*4882a593Smuzhiyun  * Description:  set the target port name to the ndlp port name wwn or zero.
7047*4882a593Smuzhiyun  **/
7048*4882a593Smuzhiyun static void
lpfc_get_starget_port_name(struct scsi_target * starget)7049*4882a593Smuzhiyun lpfc_get_starget_port_name(struct scsi_target *starget)
7050*4882a593Smuzhiyun {
7051*4882a593Smuzhiyun 	struct lpfc_nodelist *ndlp = lpfc_get_node_by_target(starget);
7052*4882a593Smuzhiyun 
7053*4882a593Smuzhiyun 	fc_starget_port_name(starget) =
7054*4882a593Smuzhiyun 		ndlp ? wwn_to_u64(ndlp->nlp_portname.u.wwn) : 0;
7055*4882a593Smuzhiyun }
7056*4882a593Smuzhiyun 
7057*4882a593Smuzhiyun /**
7058*4882a593Smuzhiyun  * lpfc_set_rport_loss_tmo - Set the rport dev loss tmo
7059*4882a593Smuzhiyun  * @rport: fc rport address.
7060*4882a593Smuzhiyun  * @timeout: new value for dev loss tmo.
7061*4882a593Smuzhiyun  *
7062*4882a593Smuzhiyun  * Description:
7063*4882a593Smuzhiyun  * If timeout is non zero set the dev_loss_tmo to timeout, else set
7064*4882a593Smuzhiyun  * dev_loss_tmo to one.
7065*4882a593Smuzhiyun  **/
7066*4882a593Smuzhiyun static void
lpfc_set_rport_loss_tmo(struct fc_rport * rport,uint32_t timeout)7067*4882a593Smuzhiyun lpfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
7068*4882a593Smuzhiyun {
7069*4882a593Smuzhiyun 	struct lpfc_rport_data *rdata = rport->dd_data;
7070*4882a593Smuzhiyun 	struct lpfc_nodelist *ndlp = rdata->pnode;
7071*4882a593Smuzhiyun #if (IS_ENABLED(CONFIG_NVME_FC))
7072*4882a593Smuzhiyun 	struct lpfc_nvme_rport *nrport = NULL;
7073*4882a593Smuzhiyun #endif
7074*4882a593Smuzhiyun 
7075*4882a593Smuzhiyun 	if (timeout)
7076*4882a593Smuzhiyun 		rport->dev_loss_tmo = timeout;
7077*4882a593Smuzhiyun 	else
7078*4882a593Smuzhiyun 		rport->dev_loss_tmo = 1;
7079*4882a593Smuzhiyun 
7080*4882a593Smuzhiyun 	if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) {
7081*4882a593Smuzhiyun 		dev_info(&rport->dev, "Cannot find remote node to "
7082*4882a593Smuzhiyun 				      "set rport dev loss tmo, port_id x%x\n",
7083*4882a593Smuzhiyun 				      rport->port_id);
7084*4882a593Smuzhiyun 		return;
7085*4882a593Smuzhiyun 	}
7086*4882a593Smuzhiyun 
7087*4882a593Smuzhiyun #if (IS_ENABLED(CONFIG_NVME_FC))
7088*4882a593Smuzhiyun 	nrport = lpfc_ndlp_get_nrport(ndlp);
7089*4882a593Smuzhiyun 
7090*4882a593Smuzhiyun 	if (nrport && nrport->remoteport)
7091*4882a593Smuzhiyun 		nvme_fc_set_remoteport_devloss(nrport->remoteport,
7092*4882a593Smuzhiyun 					       rport->dev_loss_tmo);
7093*4882a593Smuzhiyun #endif
7094*4882a593Smuzhiyun }
7095*4882a593Smuzhiyun 
7096*4882a593Smuzhiyun /**
7097*4882a593Smuzhiyun  * lpfc_rport_show_function - Return rport target information
7098*4882a593Smuzhiyun  *
7099*4882a593Smuzhiyun  * Description:
7100*4882a593Smuzhiyun  * Macro that uses field to generate a function with the name lpfc_show_rport_
7101*4882a593Smuzhiyun  *
7102*4882a593Smuzhiyun  * lpfc_show_rport_##field: returns the bytes formatted in buf
7103*4882a593Smuzhiyun  * @cdev: class converted to an fc_rport.
7104*4882a593Smuzhiyun  * @buf: on return contains the target_field or zero.
7105*4882a593Smuzhiyun  *
7106*4882a593Smuzhiyun  * Returns: size of formatted string.
7107*4882a593Smuzhiyun  **/
7108*4882a593Smuzhiyun #define lpfc_rport_show_function(field, format_string, sz, cast)	\
7109*4882a593Smuzhiyun static ssize_t								\
7110*4882a593Smuzhiyun lpfc_show_rport_##field (struct device *dev,				\
7111*4882a593Smuzhiyun 			 struct device_attribute *attr,			\
7112*4882a593Smuzhiyun 			 char *buf)					\
7113*4882a593Smuzhiyun {									\
7114*4882a593Smuzhiyun 	struct fc_rport *rport = transport_class_to_rport(dev);		\
7115*4882a593Smuzhiyun 	struct lpfc_rport_data *rdata = rport->hostdata;		\
7116*4882a593Smuzhiyun 	return scnprintf(buf, sz, format_string,			\
7117*4882a593Smuzhiyun 		(rdata->target) ? cast rdata->target->field : 0);	\
7118*4882a593Smuzhiyun }
7119*4882a593Smuzhiyun 
7120*4882a593Smuzhiyun #define lpfc_rport_rd_attr(field, format_string, sz)			\
7121*4882a593Smuzhiyun 	lpfc_rport_show_function(field, format_string, sz, )		\
7122*4882a593Smuzhiyun static FC_RPORT_ATTR(field, S_IRUGO, lpfc_show_rport_##field, NULL)
7123*4882a593Smuzhiyun 
7124*4882a593Smuzhiyun /**
7125*4882a593Smuzhiyun  * lpfc_set_vport_symbolic_name - Set the vport's symbolic name
7126*4882a593Smuzhiyun  * @fc_vport: The fc_vport who's symbolic name has been changed.
7127*4882a593Smuzhiyun  *
7128*4882a593Smuzhiyun  * Description:
7129*4882a593Smuzhiyun  * This function is called by the transport after the @fc_vport's symbolic name
7130*4882a593Smuzhiyun  * has been changed. This function re-registers the symbolic name with the
7131*4882a593Smuzhiyun  * switch to propagate the change into the fabric if the vport is active.
7132*4882a593Smuzhiyun  **/
7133*4882a593Smuzhiyun static void
lpfc_set_vport_symbolic_name(struct fc_vport * fc_vport)7134*4882a593Smuzhiyun lpfc_set_vport_symbolic_name(struct fc_vport *fc_vport)
7135*4882a593Smuzhiyun {
7136*4882a593Smuzhiyun 	struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data;
7137*4882a593Smuzhiyun 
7138*4882a593Smuzhiyun 	if (vport->port_state == LPFC_VPORT_READY)
7139*4882a593Smuzhiyun 		lpfc_ns_cmd(vport, SLI_CTNS_RSPN_ID, 0, 0);
7140*4882a593Smuzhiyun }
7141*4882a593Smuzhiyun 
7142*4882a593Smuzhiyun /**
7143*4882a593Smuzhiyun  * lpfc_hba_log_verbose_init - Set hba's log verbose level
7144*4882a593Smuzhiyun  * @phba: Pointer to lpfc_hba struct.
7145*4882a593Smuzhiyun  *
7146*4882a593Smuzhiyun  * This function is called by the lpfc_get_cfgparam() routine to set the
7147*4882a593Smuzhiyun  * module lpfc_log_verbose into the @phba cfg_log_verbose for use with
7148*4882a593Smuzhiyun  * log message according to the module's lpfc_log_verbose parameter setting
7149*4882a593Smuzhiyun  * before hba port or vport created.
7150*4882a593Smuzhiyun  **/
7151*4882a593Smuzhiyun static void
lpfc_hba_log_verbose_init(struct lpfc_hba * phba,uint32_t verbose)7152*4882a593Smuzhiyun lpfc_hba_log_verbose_init(struct lpfc_hba *phba, uint32_t verbose)
7153*4882a593Smuzhiyun {
7154*4882a593Smuzhiyun 	phba->cfg_log_verbose = verbose;
7155*4882a593Smuzhiyun }
7156*4882a593Smuzhiyun 
7157*4882a593Smuzhiyun struct fc_function_template lpfc_transport_functions = {
7158*4882a593Smuzhiyun 	/* fixed attributes the driver supports */
7159*4882a593Smuzhiyun 	.show_host_node_name = 1,
7160*4882a593Smuzhiyun 	.show_host_port_name = 1,
7161*4882a593Smuzhiyun 	.show_host_supported_classes = 1,
7162*4882a593Smuzhiyun 	.show_host_supported_fc4s = 1,
7163*4882a593Smuzhiyun 	.show_host_supported_speeds = 1,
7164*4882a593Smuzhiyun 	.show_host_maxframe_size = 1,
7165*4882a593Smuzhiyun 
7166*4882a593Smuzhiyun 	.get_host_symbolic_name = lpfc_get_host_symbolic_name,
7167*4882a593Smuzhiyun 	.show_host_symbolic_name = 1,
7168*4882a593Smuzhiyun 
7169*4882a593Smuzhiyun 	/* dynamic attributes the driver supports */
7170*4882a593Smuzhiyun 	.get_host_port_id = lpfc_get_host_port_id,
7171*4882a593Smuzhiyun 	.show_host_port_id = 1,
7172*4882a593Smuzhiyun 
7173*4882a593Smuzhiyun 	.get_host_port_type = lpfc_get_host_port_type,
7174*4882a593Smuzhiyun 	.show_host_port_type = 1,
7175*4882a593Smuzhiyun 
7176*4882a593Smuzhiyun 	.get_host_port_state = lpfc_get_host_port_state,
7177*4882a593Smuzhiyun 	.show_host_port_state = 1,
7178*4882a593Smuzhiyun 
7179*4882a593Smuzhiyun 	/* active_fc4s is shown but doesn't change (thus no get function) */
7180*4882a593Smuzhiyun 	.show_host_active_fc4s = 1,
7181*4882a593Smuzhiyun 
7182*4882a593Smuzhiyun 	.get_host_speed = lpfc_get_host_speed,
7183*4882a593Smuzhiyun 	.show_host_speed = 1,
7184*4882a593Smuzhiyun 
7185*4882a593Smuzhiyun 	.get_host_fabric_name = lpfc_get_host_fabric_name,
7186*4882a593Smuzhiyun 	.show_host_fabric_name = 1,
7187*4882a593Smuzhiyun 
7188*4882a593Smuzhiyun 	/*
7189*4882a593Smuzhiyun 	 * The LPFC driver treats linkdown handling as target loss events
7190*4882a593Smuzhiyun 	 * so there are no sysfs handlers for link_down_tmo.
7191*4882a593Smuzhiyun 	 */
7192*4882a593Smuzhiyun 
7193*4882a593Smuzhiyun 	.get_fc_host_stats = lpfc_get_stats,
7194*4882a593Smuzhiyun 	.reset_fc_host_stats = lpfc_reset_stats,
7195*4882a593Smuzhiyun 
7196*4882a593Smuzhiyun 	.dd_fcrport_size = sizeof(struct lpfc_rport_data),
7197*4882a593Smuzhiyun 	.show_rport_maxframe_size = 1,
7198*4882a593Smuzhiyun 	.show_rport_supported_classes = 1,
7199*4882a593Smuzhiyun 
7200*4882a593Smuzhiyun 	.set_rport_dev_loss_tmo = lpfc_set_rport_loss_tmo,
7201*4882a593Smuzhiyun 	.show_rport_dev_loss_tmo = 1,
7202*4882a593Smuzhiyun 
7203*4882a593Smuzhiyun 	.get_starget_port_id  = lpfc_get_starget_port_id,
7204*4882a593Smuzhiyun 	.show_starget_port_id = 1,
7205*4882a593Smuzhiyun 
7206*4882a593Smuzhiyun 	.get_starget_node_name = lpfc_get_starget_node_name,
7207*4882a593Smuzhiyun 	.show_starget_node_name = 1,
7208*4882a593Smuzhiyun 
7209*4882a593Smuzhiyun 	.get_starget_port_name = lpfc_get_starget_port_name,
7210*4882a593Smuzhiyun 	.show_starget_port_name = 1,
7211*4882a593Smuzhiyun 
7212*4882a593Smuzhiyun 	.issue_fc_host_lip = lpfc_issue_lip,
7213*4882a593Smuzhiyun 	.dev_loss_tmo_callbk = lpfc_dev_loss_tmo_callbk,
7214*4882a593Smuzhiyun 	.terminate_rport_io = lpfc_terminate_rport_io,
7215*4882a593Smuzhiyun 
7216*4882a593Smuzhiyun 	.dd_fcvport_size = sizeof(struct lpfc_vport *),
7217*4882a593Smuzhiyun 
7218*4882a593Smuzhiyun 	.vport_disable = lpfc_vport_disable,
7219*4882a593Smuzhiyun 
7220*4882a593Smuzhiyun 	.set_vport_symbolic_name = lpfc_set_vport_symbolic_name,
7221*4882a593Smuzhiyun 
7222*4882a593Smuzhiyun 	.bsg_request = lpfc_bsg_request,
7223*4882a593Smuzhiyun 	.bsg_timeout = lpfc_bsg_timeout,
7224*4882a593Smuzhiyun };
7225*4882a593Smuzhiyun 
7226*4882a593Smuzhiyun struct fc_function_template lpfc_vport_transport_functions = {
7227*4882a593Smuzhiyun 	/* fixed attributes the driver supports */
7228*4882a593Smuzhiyun 	.show_host_node_name = 1,
7229*4882a593Smuzhiyun 	.show_host_port_name = 1,
7230*4882a593Smuzhiyun 	.show_host_supported_classes = 1,
7231*4882a593Smuzhiyun 	.show_host_supported_fc4s = 1,
7232*4882a593Smuzhiyun 	.show_host_supported_speeds = 1,
7233*4882a593Smuzhiyun 	.show_host_maxframe_size = 1,
7234*4882a593Smuzhiyun 
7235*4882a593Smuzhiyun 	.get_host_symbolic_name = lpfc_get_host_symbolic_name,
7236*4882a593Smuzhiyun 	.show_host_symbolic_name = 1,
7237*4882a593Smuzhiyun 
7238*4882a593Smuzhiyun 	/* dynamic attributes the driver supports */
7239*4882a593Smuzhiyun 	.get_host_port_id = lpfc_get_host_port_id,
7240*4882a593Smuzhiyun 	.show_host_port_id = 1,
7241*4882a593Smuzhiyun 
7242*4882a593Smuzhiyun 	.get_host_port_type = lpfc_get_host_port_type,
7243*4882a593Smuzhiyun 	.show_host_port_type = 1,
7244*4882a593Smuzhiyun 
7245*4882a593Smuzhiyun 	.get_host_port_state = lpfc_get_host_port_state,
7246*4882a593Smuzhiyun 	.show_host_port_state = 1,
7247*4882a593Smuzhiyun 
7248*4882a593Smuzhiyun 	/* active_fc4s is shown but doesn't change (thus no get function) */
7249*4882a593Smuzhiyun 	.show_host_active_fc4s = 1,
7250*4882a593Smuzhiyun 
7251*4882a593Smuzhiyun 	.get_host_speed = lpfc_get_host_speed,
7252*4882a593Smuzhiyun 	.show_host_speed = 1,
7253*4882a593Smuzhiyun 
7254*4882a593Smuzhiyun 	.get_host_fabric_name = lpfc_get_host_fabric_name,
7255*4882a593Smuzhiyun 	.show_host_fabric_name = 1,
7256*4882a593Smuzhiyun 
7257*4882a593Smuzhiyun 	/*
7258*4882a593Smuzhiyun 	 * The LPFC driver treats linkdown handling as target loss events
7259*4882a593Smuzhiyun 	 * so there are no sysfs handlers for link_down_tmo.
7260*4882a593Smuzhiyun 	 */
7261*4882a593Smuzhiyun 
7262*4882a593Smuzhiyun 	.get_fc_host_stats = lpfc_get_stats,
7263*4882a593Smuzhiyun 	.reset_fc_host_stats = lpfc_reset_stats,
7264*4882a593Smuzhiyun 
7265*4882a593Smuzhiyun 	.dd_fcrport_size = sizeof(struct lpfc_rport_data),
7266*4882a593Smuzhiyun 	.show_rport_maxframe_size = 1,
7267*4882a593Smuzhiyun 	.show_rport_supported_classes = 1,
7268*4882a593Smuzhiyun 
7269*4882a593Smuzhiyun 	.set_rport_dev_loss_tmo = lpfc_set_rport_loss_tmo,
7270*4882a593Smuzhiyun 	.show_rport_dev_loss_tmo = 1,
7271*4882a593Smuzhiyun 
7272*4882a593Smuzhiyun 	.get_starget_port_id  = lpfc_get_starget_port_id,
7273*4882a593Smuzhiyun 	.show_starget_port_id = 1,
7274*4882a593Smuzhiyun 
7275*4882a593Smuzhiyun 	.get_starget_node_name = lpfc_get_starget_node_name,
7276*4882a593Smuzhiyun 	.show_starget_node_name = 1,
7277*4882a593Smuzhiyun 
7278*4882a593Smuzhiyun 	.get_starget_port_name = lpfc_get_starget_port_name,
7279*4882a593Smuzhiyun 	.show_starget_port_name = 1,
7280*4882a593Smuzhiyun 
7281*4882a593Smuzhiyun 	.dev_loss_tmo_callbk = lpfc_dev_loss_tmo_callbk,
7282*4882a593Smuzhiyun 	.terminate_rport_io = lpfc_terminate_rport_io,
7283*4882a593Smuzhiyun 
7284*4882a593Smuzhiyun 	.vport_disable = lpfc_vport_disable,
7285*4882a593Smuzhiyun 
7286*4882a593Smuzhiyun 	.set_vport_symbolic_name = lpfc_set_vport_symbolic_name,
7287*4882a593Smuzhiyun };
7288*4882a593Smuzhiyun 
7289*4882a593Smuzhiyun /**
7290*4882a593Smuzhiyun  * lpfc_get_hba_function_mode - Used to determine the HBA function in FCoE
7291*4882a593Smuzhiyun  * Mode
7292*4882a593Smuzhiyun  * @phba: lpfc_hba pointer.
7293*4882a593Smuzhiyun  **/
7294*4882a593Smuzhiyun static void
lpfc_get_hba_function_mode(struct lpfc_hba * phba)7295*4882a593Smuzhiyun lpfc_get_hba_function_mode(struct lpfc_hba *phba)
7296*4882a593Smuzhiyun {
7297*4882a593Smuzhiyun 	/* If the adapter supports FCoE mode */
7298*4882a593Smuzhiyun 	switch (phba->pcidev->device) {
7299*4882a593Smuzhiyun 	case PCI_DEVICE_ID_SKYHAWK:
7300*4882a593Smuzhiyun 	case PCI_DEVICE_ID_SKYHAWK_VF:
7301*4882a593Smuzhiyun 	case PCI_DEVICE_ID_LANCER_FCOE:
7302*4882a593Smuzhiyun 	case PCI_DEVICE_ID_LANCER_FCOE_VF:
7303*4882a593Smuzhiyun 	case PCI_DEVICE_ID_ZEPHYR_DCSP:
7304*4882a593Smuzhiyun 	case PCI_DEVICE_ID_HORNET:
7305*4882a593Smuzhiyun 	case PCI_DEVICE_ID_TIGERSHARK:
7306*4882a593Smuzhiyun 	case PCI_DEVICE_ID_TOMCAT:
7307*4882a593Smuzhiyun 		phba->hba_flag |= HBA_FCOE_MODE;
7308*4882a593Smuzhiyun 		break;
7309*4882a593Smuzhiyun 	default:
7310*4882a593Smuzhiyun 	/* for others, clear the flag */
7311*4882a593Smuzhiyun 		phba->hba_flag &= ~HBA_FCOE_MODE;
7312*4882a593Smuzhiyun 	}
7313*4882a593Smuzhiyun }
7314*4882a593Smuzhiyun 
7315*4882a593Smuzhiyun /**
7316*4882a593Smuzhiyun  * lpfc_get_cfgparam - Used during probe_one to init the adapter structure
7317*4882a593Smuzhiyun  * @phba: lpfc_hba pointer.
7318*4882a593Smuzhiyun  **/
7319*4882a593Smuzhiyun void
lpfc_get_cfgparam(struct lpfc_hba * phba)7320*4882a593Smuzhiyun lpfc_get_cfgparam(struct lpfc_hba *phba)
7321*4882a593Smuzhiyun {
7322*4882a593Smuzhiyun 	lpfc_hba_log_verbose_init(phba, lpfc_log_verbose);
7323*4882a593Smuzhiyun 	lpfc_fcp_io_sched_init(phba, lpfc_fcp_io_sched);
7324*4882a593Smuzhiyun 	lpfc_ns_query_init(phba, lpfc_ns_query);
7325*4882a593Smuzhiyun 	lpfc_fcp2_no_tgt_reset_init(phba, lpfc_fcp2_no_tgt_reset);
7326*4882a593Smuzhiyun 	lpfc_cr_delay_init(phba, lpfc_cr_delay);
7327*4882a593Smuzhiyun 	lpfc_cr_count_init(phba, lpfc_cr_count);
7328*4882a593Smuzhiyun 	lpfc_multi_ring_support_init(phba, lpfc_multi_ring_support);
7329*4882a593Smuzhiyun 	lpfc_multi_ring_rctl_init(phba, lpfc_multi_ring_rctl);
7330*4882a593Smuzhiyun 	lpfc_multi_ring_type_init(phba, lpfc_multi_ring_type);
7331*4882a593Smuzhiyun 	lpfc_ack0_init(phba, lpfc_ack0);
7332*4882a593Smuzhiyun 	lpfc_xri_rebalancing_init(phba, lpfc_xri_rebalancing);
7333*4882a593Smuzhiyun 	lpfc_topology_init(phba, lpfc_topology);
7334*4882a593Smuzhiyun 	lpfc_link_speed_init(phba, lpfc_link_speed);
7335*4882a593Smuzhiyun 	lpfc_poll_tmo_init(phba, lpfc_poll_tmo);
7336*4882a593Smuzhiyun 	lpfc_task_mgmt_tmo_init(phba, lpfc_task_mgmt_tmo);
7337*4882a593Smuzhiyun 	lpfc_enable_npiv_init(phba, lpfc_enable_npiv);
7338*4882a593Smuzhiyun 	lpfc_fcf_failover_policy_init(phba, lpfc_fcf_failover_policy);
7339*4882a593Smuzhiyun 	lpfc_enable_rrq_init(phba, lpfc_enable_rrq);
7340*4882a593Smuzhiyun 	lpfc_fdmi_on_init(phba, lpfc_fdmi_on);
7341*4882a593Smuzhiyun 	lpfc_enable_SmartSAN_init(phba, lpfc_enable_SmartSAN);
7342*4882a593Smuzhiyun 	lpfc_use_msi_init(phba, lpfc_use_msi);
7343*4882a593Smuzhiyun 	lpfc_nvme_oas_init(phba, lpfc_nvme_oas);
7344*4882a593Smuzhiyun 	lpfc_nvme_embed_cmd_init(phba, lpfc_nvme_embed_cmd);
7345*4882a593Smuzhiyun 	lpfc_fcp_imax_init(phba, lpfc_fcp_imax);
7346*4882a593Smuzhiyun 	lpfc_force_rscn_init(phba, lpfc_force_rscn);
7347*4882a593Smuzhiyun 	lpfc_cq_poll_threshold_init(phba, lpfc_cq_poll_threshold);
7348*4882a593Smuzhiyun 	lpfc_cq_max_proc_limit_init(phba, lpfc_cq_max_proc_limit);
7349*4882a593Smuzhiyun 	lpfc_fcp_cpu_map_init(phba, lpfc_fcp_cpu_map);
7350*4882a593Smuzhiyun 	lpfc_enable_hba_reset_init(phba, lpfc_enable_hba_reset);
7351*4882a593Smuzhiyun 	lpfc_enable_hba_heartbeat_init(phba, lpfc_enable_hba_heartbeat);
7352*4882a593Smuzhiyun 
7353*4882a593Smuzhiyun 	lpfc_EnableXLane_init(phba, lpfc_EnableXLane);
7354*4882a593Smuzhiyun 	if (phba->sli_rev != LPFC_SLI_REV4)
7355*4882a593Smuzhiyun 		phba->cfg_EnableXLane = 0;
7356*4882a593Smuzhiyun 	lpfc_XLanePriority_init(phba, lpfc_XLanePriority);
7357*4882a593Smuzhiyun 
7358*4882a593Smuzhiyun 	memset(phba->cfg_oas_tgt_wwpn, 0, (8 * sizeof(uint8_t)));
7359*4882a593Smuzhiyun 	memset(phba->cfg_oas_vpt_wwpn, 0, (8 * sizeof(uint8_t)));
7360*4882a593Smuzhiyun 	phba->cfg_oas_lun_state = 0;
7361*4882a593Smuzhiyun 	phba->cfg_oas_lun_status = 0;
7362*4882a593Smuzhiyun 	phba->cfg_oas_flags = 0;
7363*4882a593Smuzhiyun 	phba->cfg_oas_priority = 0;
7364*4882a593Smuzhiyun 	lpfc_enable_bg_init(phba, lpfc_enable_bg);
7365*4882a593Smuzhiyun 	lpfc_prot_mask_init(phba, lpfc_prot_mask);
7366*4882a593Smuzhiyun 	lpfc_prot_guard_init(phba, lpfc_prot_guard);
7367*4882a593Smuzhiyun 	if (phba->sli_rev == LPFC_SLI_REV4)
7368*4882a593Smuzhiyun 		phba->cfg_poll = 0;
7369*4882a593Smuzhiyun 	else
7370*4882a593Smuzhiyun 		phba->cfg_poll = lpfc_poll;
7371*4882a593Smuzhiyun 
7372*4882a593Smuzhiyun 	/* Get the function mode */
7373*4882a593Smuzhiyun 	lpfc_get_hba_function_mode(phba);
7374*4882a593Smuzhiyun 
7375*4882a593Smuzhiyun 	/* BlockGuard allowed for FC only. */
7376*4882a593Smuzhiyun 	if (phba->cfg_enable_bg && phba->hba_flag & HBA_FCOE_MODE) {
7377*4882a593Smuzhiyun 		lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
7378*4882a593Smuzhiyun 				"0581 BlockGuard feature not supported\n");
7379*4882a593Smuzhiyun 		/* If set, clear the BlockGuard support param */
7380*4882a593Smuzhiyun 		phba->cfg_enable_bg = 0;
7381*4882a593Smuzhiyun 	} else if (phba->cfg_enable_bg) {
7382*4882a593Smuzhiyun 		phba->sli3_options |= LPFC_SLI3_BG_ENABLED;
7383*4882a593Smuzhiyun 	}
7384*4882a593Smuzhiyun 
7385*4882a593Smuzhiyun 	lpfc_suppress_rsp_init(phba, lpfc_suppress_rsp);
7386*4882a593Smuzhiyun 
7387*4882a593Smuzhiyun 	lpfc_enable_fc4_type_init(phba, lpfc_enable_fc4_type);
7388*4882a593Smuzhiyun 	lpfc_nvmet_mrq_init(phba, lpfc_nvmet_mrq);
7389*4882a593Smuzhiyun 	lpfc_nvmet_mrq_post_init(phba, lpfc_nvmet_mrq_post);
7390*4882a593Smuzhiyun 
7391*4882a593Smuzhiyun 	/* Initialize first burst. Target vs Initiator are different. */
7392*4882a593Smuzhiyun 	lpfc_nvme_enable_fb_init(phba, lpfc_nvme_enable_fb);
7393*4882a593Smuzhiyun 	lpfc_nvmet_fb_size_init(phba, lpfc_nvmet_fb_size);
7394*4882a593Smuzhiyun 	lpfc_fcp_mq_threshold_init(phba, lpfc_fcp_mq_threshold);
7395*4882a593Smuzhiyun 	lpfc_hdw_queue_init(phba, lpfc_hdw_queue);
7396*4882a593Smuzhiyun 	lpfc_irq_chann_init(phba, lpfc_irq_chann);
7397*4882a593Smuzhiyun 	lpfc_enable_bbcr_init(phba, lpfc_enable_bbcr);
7398*4882a593Smuzhiyun 	lpfc_enable_dpp_init(phba, lpfc_enable_dpp);
7399*4882a593Smuzhiyun 
7400*4882a593Smuzhiyun 	if (phba->sli_rev != LPFC_SLI_REV4) {
7401*4882a593Smuzhiyun 		/* NVME only supported on SLI4 */
7402*4882a593Smuzhiyun 		phba->nvmet_support = 0;
7403*4882a593Smuzhiyun 		phba->cfg_nvmet_mrq = 0;
7404*4882a593Smuzhiyun 		phba->cfg_enable_fc4_type = LPFC_ENABLE_FCP;
7405*4882a593Smuzhiyun 		phba->cfg_enable_bbcr = 0;
7406*4882a593Smuzhiyun 		phba->cfg_xri_rebalancing = 0;
7407*4882a593Smuzhiyun 	} else {
7408*4882a593Smuzhiyun 		/* We MUST have FCP support */
7409*4882a593Smuzhiyun 		if (!(phba->cfg_enable_fc4_type & LPFC_ENABLE_FCP))
7410*4882a593Smuzhiyun 			phba->cfg_enable_fc4_type |= LPFC_ENABLE_FCP;
7411*4882a593Smuzhiyun 	}
7412*4882a593Smuzhiyun 
7413*4882a593Smuzhiyun 	phba->cfg_auto_imax = (phba->cfg_fcp_imax) ? 0 : 1;
7414*4882a593Smuzhiyun 
7415*4882a593Smuzhiyun 	phba->cfg_enable_pbde = 0;
7416*4882a593Smuzhiyun 
7417*4882a593Smuzhiyun 	/* A value of 0 means use the number of CPUs found in the system */
7418*4882a593Smuzhiyun 	if (phba->cfg_hdw_queue == 0)
7419*4882a593Smuzhiyun 		phba->cfg_hdw_queue = phba->sli4_hba.num_present_cpu;
7420*4882a593Smuzhiyun 	if (phba->cfg_irq_chann == 0)
7421*4882a593Smuzhiyun 		phba->cfg_irq_chann = phba->sli4_hba.num_present_cpu;
7422*4882a593Smuzhiyun 	if (phba->cfg_irq_chann > phba->cfg_hdw_queue)
7423*4882a593Smuzhiyun 		phba->cfg_irq_chann = phba->cfg_hdw_queue;
7424*4882a593Smuzhiyun 
7425*4882a593Smuzhiyun 	phba->cfg_soft_wwnn = 0L;
7426*4882a593Smuzhiyun 	phba->cfg_soft_wwpn = 0L;
7427*4882a593Smuzhiyun 	lpfc_sg_seg_cnt_init(phba, lpfc_sg_seg_cnt);
7428*4882a593Smuzhiyun 	lpfc_hba_queue_depth_init(phba, lpfc_hba_queue_depth);
7429*4882a593Smuzhiyun 	lpfc_aer_support_init(phba, lpfc_aer_support);
7430*4882a593Smuzhiyun 	lpfc_sriov_nr_virtfn_init(phba, lpfc_sriov_nr_virtfn);
7431*4882a593Smuzhiyun 	lpfc_request_firmware_upgrade_init(phba, lpfc_req_fw_upgrade);
7432*4882a593Smuzhiyun 	lpfc_suppress_link_up_init(phba, lpfc_suppress_link_up);
7433*4882a593Smuzhiyun 	lpfc_delay_discovery_init(phba, lpfc_delay_discovery);
7434*4882a593Smuzhiyun 	lpfc_sli_mode_init(phba, lpfc_sli_mode);
7435*4882a593Smuzhiyun 	lpfc_enable_mds_diags_init(phba, lpfc_enable_mds_diags);
7436*4882a593Smuzhiyun 	lpfc_ras_fwlog_buffsize_init(phba, lpfc_ras_fwlog_buffsize);
7437*4882a593Smuzhiyun 	lpfc_ras_fwlog_level_init(phba, lpfc_ras_fwlog_level);
7438*4882a593Smuzhiyun 	lpfc_ras_fwlog_func_init(phba, lpfc_ras_fwlog_func);
7439*4882a593Smuzhiyun 
7440*4882a593Smuzhiyun 	return;
7441*4882a593Smuzhiyun }
7442*4882a593Smuzhiyun 
7443*4882a593Smuzhiyun /**
7444*4882a593Smuzhiyun  * lpfc_nvme_mod_param_dep - Adjust module parameter value based on
7445*4882a593Smuzhiyun  * dependencies between protocols and roles.
7446*4882a593Smuzhiyun  * @phba: lpfc_hba pointer.
7447*4882a593Smuzhiyun  **/
7448*4882a593Smuzhiyun void
lpfc_nvme_mod_param_dep(struct lpfc_hba * phba)7449*4882a593Smuzhiyun lpfc_nvme_mod_param_dep(struct lpfc_hba *phba)
7450*4882a593Smuzhiyun {
7451*4882a593Smuzhiyun 	int  logit = 0;
7452*4882a593Smuzhiyun 
7453*4882a593Smuzhiyun 	if (phba->cfg_hdw_queue > phba->sli4_hba.num_present_cpu) {
7454*4882a593Smuzhiyun 		phba->cfg_hdw_queue = phba->sli4_hba.num_present_cpu;
7455*4882a593Smuzhiyun 		logit = 1;
7456*4882a593Smuzhiyun 	}
7457*4882a593Smuzhiyun 	if (phba->cfg_irq_chann > phba->sli4_hba.num_present_cpu) {
7458*4882a593Smuzhiyun 		phba->cfg_irq_chann = phba->sli4_hba.num_present_cpu;
7459*4882a593Smuzhiyun 		logit = 1;
7460*4882a593Smuzhiyun 	}
7461*4882a593Smuzhiyun 	if (phba->cfg_irq_chann > phba->cfg_hdw_queue) {
7462*4882a593Smuzhiyun 		phba->cfg_irq_chann = phba->cfg_hdw_queue;
7463*4882a593Smuzhiyun 		logit = 1;
7464*4882a593Smuzhiyun 	}
7465*4882a593Smuzhiyun 	if (logit)
7466*4882a593Smuzhiyun 		lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
7467*4882a593Smuzhiyun 				"2006 Reducing Queues - CPU limitation: "
7468*4882a593Smuzhiyun 				"IRQ %d HDWQ %d\n",
7469*4882a593Smuzhiyun 				phba->cfg_irq_chann,
7470*4882a593Smuzhiyun 				phba->cfg_hdw_queue);
7471*4882a593Smuzhiyun 
7472*4882a593Smuzhiyun 	if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME &&
7473*4882a593Smuzhiyun 	    phba->nvmet_support) {
7474*4882a593Smuzhiyun 		phba->cfg_enable_fc4_type &= ~LPFC_ENABLE_FCP;
7475*4882a593Smuzhiyun 
7476*4882a593Smuzhiyun 		lpfc_printf_log(phba, KERN_INFO, LOG_NVME_DISC,
7477*4882a593Smuzhiyun 				"6013 %s x%x fb_size x%x, fb_max x%x\n",
7478*4882a593Smuzhiyun 				"NVME Target PRLI ACC enable_fb ",
7479*4882a593Smuzhiyun 				phba->cfg_nvme_enable_fb,
7480*4882a593Smuzhiyun 				phba->cfg_nvmet_fb_size,
7481*4882a593Smuzhiyun 				LPFC_NVMET_FB_SZ_MAX);
7482*4882a593Smuzhiyun 
7483*4882a593Smuzhiyun 		if (phba->cfg_nvme_enable_fb == 0)
7484*4882a593Smuzhiyun 			phba->cfg_nvmet_fb_size = 0;
7485*4882a593Smuzhiyun 		else {
7486*4882a593Smuzhiyun 			if (phba->cfg_nvmet_fb_size > LPFC_NVMET_FB_SZ_MAX)
7487*4882a593Smuzhiyun 				phba->cfg_nvmet_fb_size = LPFC_NVMET_FB_SZ_MAX;
7488*4882a593Smuzhiyun 		}
7489*4882a593Smuzhiyun 
7490*4882a593Smuzhiyun 		if (!phba->cfg_nvmet_mrq)
7491*4882a593Smuzhiyun 			phba->cfg_nvmet_mrq = phba->cfg_hdw_queue;
7492*4882a593Smuzhiyun 
7493*4882a593Smuzhiyun 		/* Adjust lpfc_nvmet_mrq to avoid running out of WQE slots */
7494*4882a593Smuzhiyun 		if (phba->cfg_nvmet_mrq > phba->cfg_hdw_queue) {
7495*4882a593Smuzhiyun 			phba->cfg_nvmet_mrq = phba->cfg_hdw_queue;
7496*4882a593Smuzhiyun 			lpfc_printf_log(phba, KERN_ERR, LOG_NVME_DISC,
7497*4882a593Smuzhiyun 					"6018 Adjust lpfc_nvmet_mrq to %d\n",
7498*4882a593Smuzhiyun 					phba->cfg_nvmet_mrq);
7499*4882a593Smuzhiyun 		}
7500*4882a593Smuzhiyun 		if (phba->cfg_nvmet_mrq > LPFC_NVMET_MRQ_MAX)
7501*4882a593Smuzhiyun 			phba->cfg_nvmet_mrq = LPFC_NVMET_MRQ_MAX;
7502*4882a593Smuzhiyun 
7503*4882a593Smuzhiyun 	} else {
7504*4882a593Smuzhiyun 		/* Not NVME Target mode.  Turn off Target parameters. */
7505*4882a593Smuzhiyun 		phba->nvmet_support = 0;
7506*4882a593Smuzhiyun 		phba->cfg_nvmet_mrq = 0;
7507*4882a593Smuzhiyun 		phba->cfg_nvmet_fb_size = 0;
7508*4882a593Smuzhiyun 	}
7509*4882a593Smuzhiyun }
7510*4882a593Smuzhiyun 
7511*4882a593Smuzhiyun /**
7512*4882a593Smuzhiyun  * lpfc_get_vport_cfgparam - Used during port create, init the vport structure
7513*4882a593Smuzhiyun  * @vport: lpfc_vport pointer.
7514*4882a593Smuzhiyun  **/
7515*4882a593Smuzhiyun void
lpfc_get_vport_cfgparam(struct lpfc_vport * vport)7516*4882a593Smuzhiyun lpfc_get_vport_cfgparam(struct lpfc_vport *vport)
7517*4882a593Smuzhiyun {
7518*4882a593Smuzhiyun 	lpfc_log_verbose_init(vport, lpfc_log_verbose);
7519*4882a593Smuzhiyun 	lpfc_lun_queue_depth_init(vport, lpfc_lun_queue_depth);
7520*4882a593Smuzhiyun 	lpfc_tgt_queue_depth_init(vport, lpfc_tgt_queue_depth);
7521*4882a593Smuzhiyun 	lpfc_devloss_tmo_init(vport, lpfc_devloss_tmo);
7522*4882a593Smuzhiyun 	lpfc_nodev_tmo_init(vport, lpfc_nodev_tmo);
7523*4882a593Smuzhiyun 	lpfc_peer_port_login_init(vport, lpfc_peer_port_login);
7524*4882a593Smuzhiyun 	lpfc_restrict_login_init(vport, lpfc_restrict_login);
7525*4882a593Smuzhiyun 	lpfc_fcp_class_init(vport, lpfc_fcp_class);
7526*4882a593Smuzhiyun 	lpfc_use_adisc_init(vport, lpfc_use_adisc);
7527*4882a593Smuzhiyun 	lpfc_first_burst_size_init(vport, lpfc_first_burst_size);
7528*4882a593Smuzhiyun 	lpfc_max_scsicmpl_time_init(vport, lpfc_max_scsicmpl_time);
7529*4882a593Smuzhiyun 	lpfc_discovery_threads_init(vport, lpfc_discovery_threads);
7530*4882a593Smuzhiyun 	lpfc_max_luns_init(vport, lpfc_max_luns);
7531*4882a593Smuzhiyun 	lpfc_scan_down_init(vport, lpfc_scan_down);
7532*4882a593Smuzhiyun 	lpfc_enable_da_id_init(vport, lpfc_enable_da_id);
7533*4882a593Smuzhiyun 	return;
7534*4882a593Smuzhiyun }
7535