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