blob: f37b7642c59d5c7c920a86528caf739974af66a5 [file] [log] [blame]
dea31012005-04-17 16:05:31 -05001/*******************************************************************
2 * This file is part of the Emulex Linux Device Driver for *
James.Smart@Emulex.Comc44ce172005-06-25 10:34:39 -04003 * Fibre Channel Host Bus Adapters. *
4 * Copyright (C) 2004-2005 Emulex. All rights reserved. *
5 * EMULEX and SLI are trademarks of Emulex. *
dea31012005-04-17 16:05:31 -05006 * www.emulex.com *
James.Smart@Emulex.Comc44ce172005-06-25 10:34:39 -04007 * Portions Copyright (C) 2004-2005 Christoph Hellwig *
dea31012005-04-17 16:05:31 -05008 * *
9 * This program is free software; you can redistribute it and/or *
James.Smart@Emulex.Comc44ce172005-06-25 10:34:39 -040010 * modify it under the terms of version 2 of the GNU General *
11 * Public License as published by the Free Software Foundation. *
12 * This program is distributed in the hope that it will be useful. *
13 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
14 * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
15 * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
16 * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
17 * TO BE LEGALLY INVALID. See the GNU General Public License for *
18 * more details, a copy of which can be found in the file COPYING *
19 * included with this package. *
dea31012005-04-17 16:05:31 -050020 *******************************************************************/
21
dea31012005-04-17 16:05:31 -050022#include <linux/ctype.h>
23#include <linux/pci.h>
24#include <linux/interrupt.h>
25
26#include <scsi/scsi_device.h>
27#include <scsi/scsi_host.h>
28#include <scsi/scsi_tcq.h>
29#include <scsi/scsi_transport_fc.h>
30
31#include "lpfc_hw.h"
32#include "lpfc_sli.h"
33#include "lpfc_disc.h"
34#include "lpfc_scsi.h"
35#include "lpfc.h"
36#include "lpfc_logmsg.h"
37#include "lpfc_version.h"
38#include "lpfc_compat.h"
39#include "lpfc_crtn.h"
40
41
42static void
43lpfc_jedec_to_ascii(int incr, char hdw[])
44{
45 int i, j;
46 for (i = 0; i < 8; i++) {
47 j = (incr & 0xf);
48 if (j <= 9)
49 hdw[7 - i] = 0x30 + j;
50 else
51 hdw[7 - i] = 0x61 + j - 10;
52 incr = (incr >> 4);
53 }
54 hdw[8] = 0;
55 return;
56}
57
58static ssize_t
59lpfc_drvr_version_show(struct class_device *cdev, char *buf)
60{
61 return snprintf(buf, PAGE_SIZE, LPFC_MODULE_DESC "\n");
62}
63
64static ssize_t
65management_version_show(struct class_device *cdev, char *buf)
66{
67 return snprintf(buf, PAGE_SIZE, DFC_API_VERSION "\n");
68}
69
70static ssize_t
71lpfc_info_show(struct class_device *cdev, char *buf)
72{
73 struct Scsi_Host *host = class_to_shost(cdev);
74 return snprintf(buf, PAGE_SIZE, "%s\n",lpfc_info(host));
75}
76
77static ssize_t
78lpfc_serialnum_show(struct class_device *cdev, char *buf)
79{
80 struct Scsi_Host *host = class_to_shost(cdev);
81 struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0];
82 return snprintf(buf, PAGE_SIZE, "%s\n",phba->SerialNumber);
83}
84
85static ssize_t
86lpfc_modeldesc_show(struct class_device *cdev, char *buf)
87{
88 struct Scsi_Host *host = class_to_shost(cdev);
89 struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0];
90 return snprintf(buf, PAGE_SIZE, "%s\n",phba->ModelDesc);
91}
92
93static ssize_t
94lpfc_modelname_show(struct class_device *cdev, char *buf)
95{
96 struct Scsi_Host *host = class_to_shost(cdev);
97 struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0];
98 return snprintf(buf, PAGE_SIZE, "%s\n",phba->ModelName);
99}
100
101static ssize_t
102lpfc_programtype_show(struct class_device *cdev, char *buf)
103{
104 struct Scsi_Host *host = class_to_shost(cdev);
105 struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0];
106 return snprintf(buf, PAGE_SIZE, "%s\n",phba->ProgramType);
107}
108
109static ssize_t
110lpfc_portnum_show(struct class_device *cdev, char *buf)
111{
112 struct Scsi_Host *host = class_to_shost(cdev);
113 struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0];
114 return snprintf(buf, PAGE_SIZE, "%s\n",phba->Port);
115}
116
117static ssize_t
118lpfc_fwrev_show(struct class_device *cdev, char *buf)
119{
120 struct Scsi_Host *host = class_to_shost(cdev);
121 struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0];
122 char fwrev[32];
123 lpfc_decode_firmware_rev(phba, fwrev, 1);
124 return snprintf(buf, PAGE_SIZE, "%s\n",fwrev);
125}
126
127static ssize_t
128lpfc_hdw_show(struct class_device *cdev, char *buf)
129{
130 char hdw[9];
131 struct Scsi_Host *host = class_to_shost(cdev);
132 struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0];
133 lpfc_vpd_t *vp = &phba->vpd;
134 lpfc_jedec_to_ascii(vp->rev.biuRev, hdw);
135 return snprintf(buf, PAGE_SIZE, "%s\n", hdw);
136}
137static ssize_t
138lpfc_option_rom_version_show(struct class_device *cdev, char *buf)
139{
140 struct Scsi_Host *host = class_to_shost(cdev);
141 struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0];
142 return snprintf(buf, PAGE_SIZE, "%s\n", phba->OptionROMVersion);
143}
144static ssize_t
145lpfc_state_show(struct class_device *cdev, char *buf)
146{
147 struct Scsi_Host *host = class_to_shost(cdev);
148 struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0];
149 int len = 0;
150 switch (phba->hba_state) {
151 case LPFC_INIT_START:
152 case LPFC_INIT_MBX_CMDS:
153 case LPFC_LINK_DOWN:
154 len += snprintf(buf + len, PAGE_SIZE-len, "Link Down\n");
155 break;
156 case LPFC_LINK_UP:
157 case LPFC_LOCAL_CFG_LINK:
158 len += snprintf(buf + len, PAGE_SIZE-len, "Link Up\n");
159 break;
160 case LPFC_FLOGI:
161 case LPFC_FABRIC_CFG_LINK:
162 case LPFC_NS_REG:
163 case LPFC_NS_QRY:
164 case LPFC_BUILD_DISC_LIST:
165 case LPFC_DISC_AUTH:
166 case LPFC_CLEAR_LA:
167 len += snprintf(buf + len, PAGE_SIZE-len,
168 "Link Up - Discovery\n");
169 break;
170 case LPFC_HBA_READY:
171 len += snprintf(buf + len, PAGE_SIZE-len,
172 "Link Up - Ready:\n");
173 if (phba->fc_topology == TOPOLOGY_LOOP) {
174 if (phba->fc_flag & FC_PUBLIC_LOOP)
175 len += snprintf(buf + len, PAGE_SIZE-len,
176 " Public Loop\n");
177 else
178 len += snprintf(buf + len, PAGE_SIZE-len,
179 " Private Loop\n");
180 } else {
181 if (phba->fc_flag & FC_FABRIC)
182 len += snprintf(buf + len, PAGE_SIZE-len,
183 " Fabric\n");
184 else
185 len += snprintf(buf + len, PAGE_SIZE-len,
186 " Point-2-Point\n");
187 }
188 }
189 return len;
190}
191
192static ssize_t
193lpfc_num_discovered_ports_show(struct class_device *cdev, char *buf)
194{
195 struct Scsi_Host *host = class_to_shost(cdev);
196 struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0];
197 return snprintf(buf, PAGE_SIZE, "%d\n", phba->fc_map_cnt +
198 phba->fc_unmap_cnt);
199}
200
201
202static ssize_t
203lpfc_issue_lip (struct class_device *cdev, const char *buf, size_t count)
204{
205 struct Scsi_Host *host = class_to_shost(cdev);
206 struct lpfc_hba *phba = (struct lpfc_hba *) host->hostdata[0];
207 int val = 0;
208 LPFC_MBOXQ_t *pmboxq;
209 int mbxstatus = MBXERR_ERROR;
210
211 if ((sscanf(buf, "%d", &val) != 1) ||
212 (val != 1))
213 return -EINVAL;
214
215 if ((phba->fc_flag & FC_OFFLINE_MODE) ||
216 (phba->hba_state != LPFC_HBA_READY))
217 return -EPERM;
218
219 pmboxq = mempool_alloc(phba->mbox_mem_pool,GFP_KERNEL);
220
221 if (!pmboxq)
222 return -ENOMEM;
223
224 memset((void *)pmboxq, 0, sizeof (LPFC_MBOXQ_t));
225 lpfc_init_link(phba, pmboxq, phba->cfg_topology, phba->cfg_link_speed);
226 mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
227
228 if (mbxstatus == MBX_TIMEOUT)
229 pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
230 else
231 mempool_free( pmboxq, phba->mbox_mem_pool);
232
233 if (mbxstatus == MBXERR_ERROR)
234 return -EIO;
235
236 return strlen(buf);
237}
238
239static ssize_t
240lpfc_nport_evt_cnt_show(struct class_device *cdev, char *buf)
241{
242 struct Scsi_Host *host = class_to_shost(cdev);
243 struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0];
244 return snprintf(buf, PAGE_SIZE, "%d\n", phba->nport_event_cnt);
245}
246
247static ssize_t
248lpfc_board_online_show(struct class_device *cdev, char *buf)
249{
250 struct Scsi_Host *host = class_to_shost(cdev);
251 struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0];
252
253 if (!phba) return 0;
254
255 if (phba->fc_flag & FC_OFFLINE_MODE)
256 return snprintf(buf, PAGE_SIZE, "0\n");
257 else
258 return snprintf(buf, PAGE_SIZE, "1\n");
259}
260
261static ssize_t
262lpfc_board_online_store(struct class_device *cdev, const char *buf,
263 size_t count)
264{
265 struct Scsi_Host *host = class_to_shost(cdev);
266 struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0];
267 struct completion online_compl;
268 int val=0, status=0;
269
270 if (sscanf(buf, "%d", &val) != 1)
271 return 0;
272
273 init_completion(&online_compl);
274
275 if (val)
276 lpfc_workq_post_event(phba, &status, &online_compl,
277 LPFC_EVT_ONLINE);
278 else
279 lpfc_workq_post_event(phba, &status, &online_compl,
280 LPFC_EVT_OFFLINE);
281 wait_for_completion(&online_compl);
282 if (!status)
283 return strlen(buf);
284 else
285 return 0;
286}
287
288
289#define lpfc_param_show(attr) \
290static ssize_t \
291lpfc_##attr##_show(struct class_device *cdev, char *buf) \
292{ \
293 struct Scsi_Host *host = class_to_shost(cdev);\
294 struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0];\
295 int val = 0;\
296 if (phba){\
297 val = phba->cfg_##attr;\
298 return snprintf(buf, PAGE_SIZE, "%d\n",\
299 phba->cfg_##attr);\
300 }\
301 return 0;\
302}
303
304#define lpfc_param_store(attr, minval, maxval) \
305static ssize_t \
306lpfc_##attr##_store(struct class_device *cdev, const char *buf, size_t count) \
307{ \
308 struct Scsi_Host *host = class_to_shost(cdev);\
309 struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0];\
310 int val = 0;\
311 if (!isdigit(buf[0]))\
312 return -EINVAL;\
313 if (sscanf(buf, "0x%x", &val) != 1)\
314 if (sscanf(buf, "%d", &val) != 1)\
315 return -EINVAL;\
316 if (phba){\
317 if (val >= minval && val <= maxval) {\
318 phba->cfg_##attr = val;\
319 return strlen(buf);\
320 }\
321 }\
322 return 0;\
323}
324
325#define LPFC_ATTR_R_NOINIT(name, desc) \
326extern int lpfc_##name;\
327module_param(lpfc_##name, int, 0);\
328MODULE_PARM_DESC(lpfc_##name, desc);\
329lpfc_param_show(name)\
330static CLASS_DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL)
331
332#define LPFC_ATTR_R(name, defval, minval, maxval, desc) \
333static int lpfc_##name = defval;\
334module_param(lpfc_##name, int, 0);\
335MODULE_PARM_DESC(lpfc_##name, desc);\
336lpfc_param_show(name)\
337static CLASS_DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL)
338
339#define LPFC_ATTR_RW(name, defval, minval, maxval, desc) \
340static int lpfc_##name = defval;\
341module_param(lpfc_##name, int, 0);\
342MODULE_PARM_DESC(lpfc_##name, desc);\
343lpfc_param_show(name)\
344lpfc_param_store(name, minval, maxval)\
345static CLASS_DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\
346 lpfc_##name##_show, lpfc_##name##_store)
347
348static CLASS_DEVICE_ATTR(info, S_IRUGO, lpfc_info_show, NULL);
349static CLASS_DEVICE_ATTR(serialnum, S_IRUGO, lpfc_serialnum_show, NULL);
350static CLASS_DEVICE_ATTR(modeldesc, S_IRUGO, lpfc_modeldesc_show, NULL);
351static CLASS_DEVICE_ATTR(modelname, S_IRUGO, lpfc_modelname_show, NULL);
352static CLASS_DEVICE_ATTR(programtype, S_IRUGO, lpfc_programtype_show, NULL);
353static CLASS_DEVICE_ATTR(portnum, S_IRUGO, lpfc_portnum_show, NULL);
354static CLASS_DEVICE_ATTR(fwrev, S_IRUGO, lpfc_fwrev_show, NULL);
355static CLASS_DEVICE_ATTR(hdw, S_IRUGO, lpfc_hdw_show, NULL);
356static CLASS_DEVICE_ATTR(state, S_IRUGO, lpfc_state_show, NULL);
357static CLASS_DEVICE_ATTR(option_rom_version, S_IRUGO,
358 lpfc_option_rom_version_show, NULL);
359static CLASS_DEVICE_ATTR(num_discovered_ports, S_IRUGO,
360 lpfc_num_discovered_ports_show, NULL);
361static CLASS_DEVICE_ATTR(nport_evt_cnt, S_IRUGO, lpfc_nport_evt_cnt_show, NULL);
362static CLASS_DEVICE_ATTR(lpfc_drvr_version, S_IRUGO, lpfc_drvr_version_show,
363 NULL);
364static CLASS_DEVICE_ATTR(management_version, S_IRUGO, management_version_show,
365 NULL);
366static CLASS_DEVICE_ATTR(issue_lip, S_IWUSR, NULL, lpfc_issue_lip);
367static CLASS_DEVICE_ATTR(board_online, S_IRUGO | S_IWUSR,
368 lpfc_board_online_show, lpfc_board_online_store);
369
370
371/*
372# lpfc_log_verbose: Only turn this flag on if you are willing to risk being
373# deluged with LOTS of information.
374# You can set a bit mask to record specific types of verbose messages:
375#
376# LOG_ELS 0x1 ELS events
377# LOG_DISCOVERY 0x2 Link discovery events
378# LOG_MBOX 0x4 Mailbox events
379# LOG_INIT 0x8 Initialization events
380# LOG_LINK_EVENT 0x10 Link events
381# LOG_IP 0x20 IP traffic history
382# LOG_FCP 0x40 FCP traffic history
383# LOG_NODE 0x80 Node table events
384# LOG_MISC 0x400 Miscellaneous events
385# LOG_SLI 0x800 SLI events
386# LOG_CHK_COND 0x1000 FCP Check condition flag
387# LOG_LIBDFC 0x2000 LIBDFC events
388# LOG_ALL_MSG 0xffff LOG all messages
389*/
390LPFC_ATTR_RW(log_verbose, 0x0, 0x0, 0xffff, "Verbose logging bit-mask");
391
392/*
393# lun_queue_depth: This parameter is used to limit the number of outstanding
394# commands per FCP LUN. Value range is [1,128]. Default value is 30.
395*/
396LPFC_ATTR_R(lun_queue_depth, 30, 1, 128,
397 "Max number of FCP commands we can queue to a specific LUN");
398
399/*
400# Some disk devices have a "select ID" or "select Target" capability.
401# From a protocol standpoint "select ID" usually means select the
402# Fibre channel "ALPA". In the FC-AL Profile there is an "informative
403# annex" which contains a table that maps a "select ID" (a number
404# between 0 and 7F) to an ALPA. By default, for compatibility with
405# older drivers, the lpfc driver scans this table from low ALPA to high
406# ALPA.
407#
408# Turning on the scan-down variable (on = 1, off = 0) will
409# cause the lpfc driver to use an inverted table, effectively
410# scanning ALPAs from high to low. Value range is [0,1]. Default value is 1.
411#
412# (Note: This "select ID" functionality is a LOOP ONLY characteristic
413# and will not work across a fabric. Also this parameter will take
414# effect only in the case when ALPA map is not available.)
415*/
416LPFC_ATTR_R(scan_down, 1, 0, 1,
417 "Start scanning for devices from highest ALPA to lowest");
418
419/*
420# lpfc_nodev_tmo: If set, it will hold all I/O errors on devices that disappear
421# until the timer expires. Value range is [0,255]. Default value is 20.
422# NOTE: this MUST be less then the SCSI Layer command timeout - 1.
423*/
424LPFC_ATTR_RW(nodev_tmo, 30, 0, 255,
425 "Seconds driver will hold I/O waiting for a device to come back");
426
427/*
428# lpfc_topology: link topology for init link
429# 0x0 = attempt loop mode then point-to-point
430# 0x02 = attempt point-to-point mode only
431# 0x04 = attempt loop mode only
432# 0x06 = attempt point-to-point mode then loop
433# Set point-to-point mode if you want to run as an N_Port.
434# Set loop mode if you want to run as an NL_Port. Value range is [0,0x6].
435# Default value is 0.
436*/
437LPFC_ATTR_R(topology, 0, 0, 6, "Select Fibre Channel topology");
438
439/*
440# lpfc_link_speed: Link speed selection for initializing the Fibre Channel
441# connection.
442# 0 = auto select (default)
443# 1 = 1 Gigabaud
444# 2 = 2 Gigabaud
445# 4 = 4 Gigabaud
446# Value range is [0,4]. Default value is 0.
447*/
448LPFC_ATTR_R(link_speed, 0, 0, 4, "Select link speed");
449
450/*
451# lpfc_fcp_class: Determines FC class to use for the FCP protocol.
452# Value range is [2,3]. Default value is 3.
453*/
454LPFC_ATTR_R(fcp_class, 3, 2, 3,
455 "Select Fibre Channel class of service for FCP sequences");
456
457/*
458# lpfc_use_adisc: Use ADISC for FCP rediscovery instead of PLOGI. Value range
459# is [0,1]. Default value is 0.
460*/
461LPFC_ATTR_RW(use_adisc, 0, 0, 1,
462 "Use ADISC on rediscovery to authenticate FCP devices");
463
464/*
465# lpfc_ack0: Use ACK0, instead of ACK1 for class 2 acknowledgement. Value
466# range is [0,1]. Default value is 0.
467*/
468LPFC_ATTR_R(ack0, 0, 0, 1, "Enable ACK0 support");
469
470/*
471# lpfc_cr_delay & lpfc_cr_count: Default values for I/O colaesing
472# cr_delay (msec) or cr_count outstanding commands. cr_delay can take
473# value [0,63]. cr_count can take value [0,255]. Default value of cr_delay
474# is 0. Default value of cr_count is 1. The cr_count feature is disabled if
475# cr_delay is set to 0.
476*/
477static int lpfc_cr_delay = 0;
478module_param(lpfc_cr_delay, int , 0);
479MODULE_PARM_DESC(lpfc_cr_delay, "A count of milliseconds after which an "
480 "interrupt response is generated");
481
482static int lpfc_cr_count = 1;
483module_param(lpfc_cr_count, int, 0);
484MODULE_PARM_DESC(lpfc_cr_count, "A count of I/O completions after which an "
485 "interrupt response is generated");
486
487/*
488# lpfc_fdmi_on: controls FDMI support.
489# 0 = no FDMI support
490# 1 = support FDMI without attribute of hostname
491# 2 = support FDMI with attribute of hostname
492# Value range [0,2]. Default value is 0.
493*/
494LPFC_ATTR_RW(fdmi_on, 0, 0, 2, "Enable FDMI support");
495
496/*
497# Specifies the maximum number of ELS cmds we can have outstanding (for
498# discovery). Value range is [1,64]. Default value = 32.
499*/
500static int lpfc_discovery_threads = 32;
501module_param(lpfc_discovery_threads, int, 0);
502MODULE_PARM_DESC(lpfc_discovery_threads, "Maximum number of ELS commands "
503 "during discovery");
504
505/*
506# lpfc_max_luns: maximum number of LUNs per target driver will support
507# Value range is [1,32768]. Default value is 256.
508# NOTE: The SCSI layer will scan each target for this many luns
509*/
510LPFC_ATTR_R(max_luns, 256, 1, 32768,
511 "Maximum number of LUNs per target driver will support");
512
513struct class_device_attribute *lpfc_host_attrs[] = {
514 &class_device_attr_info,
515 &class_device_attr_serialnum,
516 &class_device_attr_modeldesc,
517 &class_device_attr_modelname,
518 &class_device_attr_programtype,
519 &class_device_attr_portnum,
520 &class_device_attr_fwrev,
521 &class_device_attr_hdw,
522 &class_device_attr_option_rom_version,
523 &class_device_attr_state,
524 &class_device_attr_num_discovered_ports,
525 &class_device_attr_lpfc_drvr_version,
526 &class_device_attr_lpfc_log_verbose,
527 &class_device_attr_lpfc_lun_queue_depth,
528 &class_device_attr_lpfc_nodev_tmo,
529 &class_device_attr_lpfc_fcp_class,
530 &class_device_attr_lpfc_use_adisc,
531 &class_device_attr_lpfc_ack0,
532 &class_device_attr_lpfc_topology,
533 &class_device_attr_lpfc_scan_down,
534 &class_device_attr_lpfc_link_speed,
535 &class_device_attr_lpfc_fdmi_on,
536 &class_device_attr_lpfc_max_luns,
537 &class_device_attr_nport_evt_cnt,
538 &class_device_attr_management_version,
539 &class_device_attr_issue_lip,
540 &class_device_attr_board_online,
541 NULL,
542};
543
544static ssize_t
545sysfs_ctlreg_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
546{
547 size_t buf_off;
548 struct Scsi_Host *host = class_to_shost(container_of(kobj,
549 struct class_device, kobj));
550 struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0];
551
552 if ((off + count) > FF_REG_AREA_SIZE)
553 return -ERANGE;
554
555 if (count == 0) return 0;
556
557 if (off % 4 || count % 4 || (unsigned long)buf % 4)
558 return -EINVAL;
559
560 spin_lock_irq(phba->host->host_lock);
561
562 if (!(phba->fc_flag & FC_OFFLINE_MODE)) {
563 spin_unlock_irq(phba->host->host_lock);
564 return -EPERM;
565 }
566
567 for (buf_off = 0; buf_off < count; buf_off += sizeof(uint32_t))
568 writel(*((uint32_t *)(buf + buf_off)),
569 phba->ctrl_regs_memmap_p + off + buf_off);
570
571 spin_unlock_irq(phba->host->host_lock);
572
573 return count;
574}
575
576static ssize_t
577sysfs_ctlreg_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
578{
579 size_t buf_off;
580 uint32_t * tmp_ptr;
581 struct Scsi_Host *host = class_to_shost(container_of(kobj,
582 struct class_device, kobj));
583 struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0];
584
585 if (off > FF_REG_AREA_SIZE)
586 return -ERANGE;
587
588 if ((off + count) > FF_REG_AREA_SIZE)
589 count = FF_REG_AREA_SIZE - off;
590
591 if (count == 0) return 0;
592
593 if (off % 4 || count % 4 || (unsigned long)buf % 4)
594 return -EINVAL;
595
596 spin_lock_irq(phba->host->host_lock);
597
598 for (buf_off = 0; buf_off < count; buf_off += sizeof(uint32_t)) {
599 tmp_ptr = (uint32_t *)(buf + buf_off);
600 *tmp_ptr = readl(phba->ctrl_regs_memmap_p + off + buf_off);
601 }
602
603 spin_unlock_irq(phba->host->host_lock);
604
605 return count;
606}
607
608static struct bin_attribute sysfs_ctlreg_attr = {
609 .attr = {
610 .name = "ctlreg",
611 .mode = S_IRUSR | S_IWUSR,
612 .owner = THIS_MODULE,
613 },
614 .size = 256,
615 .read = sysfs_ctlreg_read,
616 .write = sysfs_ctlreg_write,
617};
618
619
620static void
621sysfs_mbox_idle (struct lpfc_hba * phba)
622{
623 phba->sysfs_mbox.state = SMBOX_IDLE;
624 phba->sysfs_mbox.offset = 0;
625
626 if (phba->sysfs_mbox.mbox) {
627 mempool_free(phba->sysfs_mbox.mbox,
628 phba->mbox_mem_pool);
629 phba->sysfs_mbox.mbox = NULL;
630 }
631}
632
633static ssize_t
634sysfs_mbox_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
635{
636 struct Scsi_Host * host =
637 class_to_shost(container_of(kobj, struct class_device, kobj));
638 struct lpfc_hba * phba = (struct lpfc_hba*)host->hostdata[0];
639 struct lpfcMboxq * mbox = NULL;
640
641 if ((count + off) > MAILBOX_CMD_SIZE)
642 return -ERANGE;
643
644 if (off % 4 || count % 4 || (unsigned long)buf % 4)
645 return -EINVAL;
646
647 if (count == 0)
648 return 0;
649
650 if (off == 0) {
651 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
652 if (!mbox)
653 return -ENOMEM;
654
655 }
656
657 spin_lock_irq(host->host_lock);
658
659 if (off == 0) {
660 if (phba->sysfs_mbox.mbox)
661 mempool_free(mbox, phba->mbox_mem_pool);
662 else
663 phba->sysfs_mbox.mbox = mbox;
664 phba->sysfs_mbox.state = SMBOX_WRITING;
665 } else {
666 if (phba->sysfs_mbox.state != SMBOX_WRITING ||
667 phba->sysfs_mbox.offset != off ||
668 phba->sysfs_mbox.mbox == NULL ) {
669 sysfs_mbox_idle(phba);
670 spin_unlock_irq(host->host_lock);
671 return -EINVAL;
672 }
673 }
674
675 memcpy((uint8_t *) & phba->sysfs_mbox.mbox->mb + off,
676 buf, count);
677
678 phba->sysfs_mbox.offset = off + count;
679
680 spin_unlock_irq(host->host_lock);
681
682 return count;
683}
684
685static ssize_t
686sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
687{
688 struct Scsi_Host *host =
689 class_to_shost(container_of(kobj, struct class_device,
690 kobj));
691 struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0];
692 int rc;
693
694 if (off > sizeof(MAILBOX_t))
695 return -ERANGE;
696
697 if ((count + off) > sizeof(MAILBOX_t))
698 count = sizeof(MAILBOX_t) - off;
699
700 if (off % 4 || count % 4 || (unsigned long)buf % 4)
701 return -EINVAL;
702
703 if (off && count == 0)
704 return 0;
705
706 spin_lock_irq(phba->host->host_lock);
707
708 if (off == 0 &&
709 phba->sysfs_mbox.state == SMBOX_WRITING &&
710 phba->sysfs_mbox.offset >= 2 * sizeof(uint32_t)) {
711
712 switch (phba->sysfs_mbox.mbox->mb.mbxCommand) {
713 /* Offline only */
714 case MBX_WRITE_NV:
715 case MBX_INIT_LINK:
716 case MBX_DOWN_LINK:
717 case MBX_CONFIG_LINK:
718 case MBX_CONFIG_RING:
719 case MBX_RESET_RING:
720 case MBX_UNREG_LOGIN:
721 case MBX_CLEAR_LA:
722 case MBX_DUMP_CONTEXT:
723 case MBX_RUN_DIAGS:
724 case MBX_RESTART:
725 case MBX_FLASH_WR_ULA:
726 case MBX_SET_MASK:
727 case MBX_SET_SLIM:
728 case MBX_SET_DEBUG:
729 if (!(phba->fc_flag & FC_OFFLINE_MODE)) {
730 printk(KERN_WARNING "mbox_read:Command 0x%x "
731 "is illegal in on-line state\n",
732 phba->sysfs_mbox.mbox->mb.mbxCommand);
733 sysfs_mbox_idle(phba);
734 spin_unlock_irq(phba->host->host_lock);
735 return -EPERM;
736 }
737 case MBX_LOAD_SM:
738 case MBX_READ_NV:
739 case MBX_READ_CONFIG:
740 case MBX_READ_RCONFIG:
741 case MBX_READ_STATUS:
742 case MBX_READ_XRI:
743 case MBX_READ_REV:
744 case MBX_READ_LNK_STAT:
745 case MBX_DUMP_MEMORY:
746 case MBX_DOWN_LOAD:
747 case MBX_UPDATE_CFG:
748 case MBX_LOAD_AREA:
749 case MBX_LOAD_EXP_ROM:
750 break;
751 case MBX_READ_SPARM64:
752 case MBX_READ_LA:
753 case MBX_READ_LA64:
754 case MBX_REG_LOGIN:
755 case MBX_REG_LOGIN64:
756 case MBX_CONFIG_PORT:
757 case MBX_RUN_BIU_DIAG:
758 printk(KERN_WARNING "mbox_read: Illegal Command 0x%x\n",
759 phba->sysfs_mbox.mbox->mb.mbxCommand);
760 sysfs_mbox_idle(phba);
761 spin_unlock_irq(phba->host->host_lock);
762 return -EPERM;
763 default:
764 printk(KERN_WARNING "mbox_read: Unknown Command 0x%x\n",
765 phba->sysfs_mbox.mbox->mb.mbxCommand);
766 sysfs_mbox_idle(phba);
767 spin_unlock_irq(phba->host->host_lock);
768 return -EPERM;
769 }
770
771 if ((phba->fc_flag & FC_OFFLINE_MODE) ||
772 (!(phba->sli.sli_flag & LPFC_SLI2_ACTIVE))){
773
774 spin_unlock_irq(phba->host->host_lock);
775 rc = lpfc_sli_issue_mbox (phba,
776 phba->sysfs_mbox.mbox,
777 MBX_POLL);
778 spin_lock_irq(phba->host->host_lock);
779
780 } else {
781 spin_unlock_irq(phba->host->host_lock);
782 rc = lpfc_sli_issue_mbox_wait (phba,
783 phba->sysfs_mbox.mbox,
784 phba->fc_ratov * 2);
785 spin_lock_irq(phba->host->host_lock);
786 }
787
788 if (rc != MBX_SUCCESS) {
789 sysfs_mbox_idle(phba);
790 spin_unlock_irq(host->host_lock);
791 return -ENODEV;
792 }
793 phba->sysfs_mbox.state = SMBOX_READING;
794 }
795 else if (phba->sysfs_mbox.offset != off ||
796 phba->sysfs_mbox.state != SMBOX_READING) {
797 printk(KERN_WARNING "mbox_read: Bad State\n");
798 sysfs_mbox_idle(phba);
799 spin_unlock_irq(host->host_lock);
800 return -EINVAL;
801 }
802
803 memcpy(buf, (uint8_t *) & phba->sysfs_mbox.mbox->mb + off, count);
804
805 phba->sysfs_mbox.offset = off + count;
806
807 if (phba->sysfs_mbox.offset == sizeof(MAILBOX_t))
808 sysfs_mbox_idle(phba);
809
810 spin_unlock_irq(phba->host->host_lock);
811
812 return count;
813}
814
815static struct bin_attribute sysfs_mbox_attr = {
816 .attr = {
817 .name = "mbox",
818 .mode = S_IRUSR | S_IWUSR,
819 .owner = THIS_MODULE,
820 },
821 .size = sizeof(MAILBOX_t),
822 .read = sysfs_mbox_read,
823 .write = sysfs_mbox_write,
824};
825
826int
827lpfc_alloc_sysfs_attr(struct lpfc_hba *phba)
828{
829 struct Scsi_Host *host = phba->host;
830 int error;
831
832 error = sysfs_create_bin_file(&host->shost_classdev.kobj,
833 &sysfs_ctlreg_attr);
834 if (error)
835 goto out;
836
837 error = sysfs_create_bin_file(&host->shost_classdev.kobj,
838 &sysfs_mbox_attr);
839 if (error)
840 goto out_remove_ctlreg_attr;
841
842 return 0;
843out_remove_ctlreg_attr:
844 sysfs_remove_bin_file(&host->shost_classdev.kobj, &sysfs_ctlreg_attr);
845out:
846 return error;
847}
848
849void
850lpfc_free_sysfs_attr(struct lpfc_hba *phba)
851{
852 struct Scsi_Host *host = phba->host;
853
854 sysfs_remove_bin_file(&host->shost_classdev.kobj, &sysfs_mbox_attr);
855 sysfs_remove_bin_file(&host->shost_classdev.kobj, &sysfs_ctlreg_attr);
856}
857
858
859/*
860 * Dynamic FC Host Attributes Support
861 */
862
863static void
864lpfc_get_host_port_id(struct Scsi_Host *shost)
865{
866 struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata[0];
867 /* note: fc_myDID already in cpu endianness */
868 fc_host_port_id(shost) = phba->fc_myDID;
869}
870
871static void
872lpfc_get_host_port_type(struct Scsi_Host *shost)
873{
874 struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata[0];
875
876 spin_lock_irq(shost->host_lock);
877
878 if (phba->hba_state == LPFC_HBA_READY) {
879 if (phba->fc_topology == TOPOLOGY_LOOP) {
880 if (phba->fc_flag & FC_PUBLIC_LOOP)
881 fc_host_port_type(shost) = FC_PORTTYPE_NLPORT;
882 else
883 fc_host_port_type(shost) = FC_PORTTYPE_LPORT;
884 } else {
885 if (phba->fc_flag & FC_FABRIC)
886 fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
887 else
888 fc_host_port_type(shost) = FC_PORTTYPE_PTP;
889 }
890 } else
891 fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN;
892
893 spin_unlock_irq(shost->host_lock);
894}
895
896static void
897lpfc_get_host_port_state(struct Scsi_Host *shost)
898{
899 struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata[0];
900
901 spin_lock_irq(shost->host_lock);
902
903 if (phba->fc_flag & FC_OFFLINE_MODE)
904 fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE;
905 else {
906 switch (phba->hba_state) {
907 case LPFC_INIT_START:
908 case LPFC_INIT_MBX_CMDS:
909 case LPFC_LINK_DOWN:
910 fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN;
911 break;
912 case LPFC_LINK_UP:
913 case LPFC_LOCAL_CFG_LINK:
914 case LPFC_FLOGI:
915 case LPFC_FABRIC_CFG_LINK:
916 case LPFC_NS_REG:
917 case LPFC_NS_QRY:
918 case LPFC_BUILD_DISC_LIST:
919 case LPFC_DISC_AUTH:
920 case LPFC_CLEAR_LA:
921 case LPFC_HBA_READY:
922 /* Links up, beyond this port_type reports state */
923 fc_host_port_state(shost) = FC_PORTSTATE_ONLINE;
924 break;
925 case LPFC_HBA_ERROR:
926 fc_host_port_state(shost) = FC_PORTSTATE_ERROR;
927 break;
928 default:
929 fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN;
930 break;
931 }
932 }
933
934 spin_unlock_irq(shost->host_lock);
935}
936
937static void
938lpfc_get_host_speed(struct Scsi_Host *shost)
939{
940 struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata[0];
941
942 spin_lock_irq(shost->host_lock);
943
944 if (phba->hba_state == LPFC_HBA_READY) {
945 switch(phba->fc_linkspeed) {
946 case LA_1GHZ_LINK:
947 fc_host_speed(shost) = FC_PORTSPEED_1GBIT;
948 break;
949 case LA_2GHZ_LINK:
950 fc_host_speed(shost) = FC_PORTSPEED_2GBIT;
951 break;
952 case LA_4GHZ_LINK:
953 fc_host_speed(shost) = FC_PORTSPEED_4GBIT;
954 break;
955 default:
956 fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
957 break;
958 }
959 }
960
961 spin_unlock_irq(shost->host_lock);
962}
963
964static void
965lpfc_get_host_fabric_name (struct Scsi_Host *shost)
966{
967 struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata[0];
968 u64 nodename;
969
970 spin_lock_irq(shost->host_lock);
971
972 if ((phba->fc_flag & FC_FABRIC) ||
973 ((phba->fc_topology == TOPOLOGY_LOOP) &&
974 (phba->fc_flag & FC_PUBLIC_LOOP)))
975 memcpy(&nodename, &phba->fc_fabparam.nodeName, sizeof(u64));
976 else
977 /* fabric is local port if there is no F/FL_Port */
978 memcpy(&nodename, &phba->fc_nodename, sizeof(u64));
979
980 spin_unlock_irq(shost->host_lock);
981
982 fc_host_fabric_name(shost) = be64_to_cpu(nodename);
983}
984
985
986static struct fc_host_statistics *
987lpfc_get_stats(struct Scsi_Host *shost)
988{
989 struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata[0];
990 struct lpfc_sli *psli = &phba->sli;
James.Smart@Emulex.Comf888ba32005-08-10 15:03:01 -0400991 struct fc_host_statistics *hs = &phba->link_stats;
dea31012005-04-17 16:05:31 -0500992 LPFC_MBOXQ_t *pmboxq;
993 MAILBOX_t *pmb;
994 int rc=0;
995
996 pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
997 if (!pmboxq)
998 return NULL;
999 memset(pmboxq, 0, sizeof (LPFC_MBOXQ_t));
1000
1001 pmb = &pmboxq->mb;
1002 pmb->mbxCommand = MBX_READ_STATUS;
1003 pmb->mbxOwner = OWN_HOST;
1004 pmboxq->context1 = NULL;
1005
1006 if ((phba->fc_flag & FC_OFFLINE_MODE) ||
1007 (!(psli->sli_flag & LPFC_SLI2_ACTIVE))){
1008 rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL);
1009 } else
1010 rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
1011
1012 if (rc != MBX_SUCCESS) {
1013 if (pmboxq) {
1014 if (rc == MBX_TIMEOUT)
1015 pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
1016 else
1017 mempool_free( pmboxq, phba->mbox_mem_pool);
1018 }
1019 return NULL;
1020 }
1021
James.Smart@Emulex.Comf888ba32005-08-10 15:03:01 -04001022 memset(hs, 0, sizeof (struct fc_host_statistics));
1023
dea31012005-04-17 16:05:31 -05001024 hs->tx_frames = pmb->un.varRdStatus.xmitFrameCnt;
1025 hs->tx_words = (pmb->un.varRdStatus.xmitByteCnt * 256);
1026 hs->rx_frames = pmb->un.varRdStatus.rcvFrameCnt;
1027 hs->rx_words = (pmb->un.varRdStatus.rcvByteCnt * 256);
1028
1029 memset((void *)pmboxq, 0, sizeof (LPFC_MBOXQ_t));
1030 pmb->mbxCommand = MBX_READ_LNK_STAT;
1031 pmb->mbxOwner = OWN_HOST;
1032 pmboxq->context1 = NULL;
1033
1034 if ((phba->fc_flag & FC_OFFLINE_MODE) ||
1035 (!(psli->sli_flag & LPFC_SLI2_ACTIVE))) {
1036 rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL);
1037 } else
1038 rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
1039
1040 if (rc != MBX_SUCCESS) {
1041 if (pmboxq) {
1042 if (rc == MBX_TIMEOUT)
1043 pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
1044 else
1045 mempool_free( pmboxq, phba->mbox_mem_pool);
1046 }
1047 return NULL;
1048 }
1049
1050 hs->link_failure_count = pmb->un.varRdLnk.linkFailureCnt;
1051 hs->loss_of_sync_count = pmb->un.varRdLnk.lossSyncCnt;
1052 hs->loss_of_signal_count = pmb->un.varRdLnk.lossSignalCnt;
1053 hs->prim_seq_protocol_err_count = pmb->un.varRdLnk.primSeqErrCnt;
1054 hs->invalid_tx_word_count = pmb->un.varRdLnk.invalidXmitWord;
1055 hs->invalid_crc_count = pmb->un.varRdLnk.crcCnt;
1056 hs->error_frames = pmb->un.varRdLnk.crcCnt;
1057
1058 if (phba->fc_topology == TOPOLOGY_LOOP) {
1059 hs->lip_count = (phba->fc_eventTag >> 1);
1060 hs->nos_count = -1;
1061 } else {
1062 hs->lip_count = -1;
1063 hs->nos_count = (phba->fc_eventTag >> 1);
1064 }
1065
1066 hs->dumped_frames = -1;
1067
1068/* FIX ME */
1069 /*hs->SecondsSinceLastReset = (jiffies - lpfc_loadtime) / HZ;*/
1070
1071 return hs;
1072}
1073
1074
1075/*
1076 * The LPFC driver treats linkdown handling as target loss events so there
1077 * are no sysfs handlers for link_down_tmo.
1078 */
1079static void
1080lpfc_get_starget_port_id(struct scsi_target *starget)
1081{
1082 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
1083 struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata[0];
1084 uint32_t did = -1;
1085 struct lpfc_nodelist *ndlp = NULL;
1086
1087 spin_lock_irq(shost->host_lock);
1088 /* Search the mapped list for this target ID */
1089 list_for_each_entry(ndlp, &phba->fc_nlpmap_list, nlp_listp) {
1090 if (starget->id == ndlp->nlp_sid) {
1091 did = ndlp->nlp_DID;
1092 break;
1093 }
1094 }
1095 spin_unlock_irq(shost->host_lock);
1096
1097 fc_starget_port_id(starget) = did;
1098}
1099
1100static void
1101lpfc_get_starget_node_name(struct scsi_target *starget)
1102{
1103 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
1104 struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata[0];
1105 uint64_t node_name = 0;
1106 struct lpfc_nodelist *ndlp = NULL;
1107
1108 spin_lock_irq(shost->host_lock);
1109 /* Search the mapped list for this target ID */
1110 list_for_each_entry(ndlp, &phba->fc_nlpmap_list, nlp_listp) {
1111 if (starget->id == ndlp->nlp_sid) {
1112 memcpy(&node_name, &ndlp->nlp_nodename,
1113 sizeof(struct lpfc_name));
1114 break;
1115 }
1116 }
1117 spin_unlock_irq(shost->host_lock);
1118
1119 fc_starget_node_name(starget) = be64_to_cpu(node_name);
1120}
1121
1122static void
1123lpfc_get_starget_port_name(struct scsi_target *starget)
1124{
1125 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
1126 struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata[0];
1127 uint64_t port_name = 0;
1128 struct lpfc_nodelist *ndlp = NULL;
1129
1130 spin_lock_irq(shost->host_lock);
1131 /* Search the mapped list for this target ID */
1132 list_for_each_entry(ndlp, &phba->fc_nlpmap_list, nlp_listp) {
1133 if (starget->id == ndlp->nlp_sid) {
1134 memcpy(&port_name, &ndlp->nlp_portname,
1135 sizeof(struct lpfc_name));
1136 break;
1137 }
1138 }
1139 spin_unlock_irq(shost->host_lock);
1140
1141 fc_starget_port_name(starget) = be64_to_cpu(port_name);
1142}
1143
1144static void
1145lpfc_get_rport_loss_tmo(struct fc_rport *rport)
1146{
1147 /*
1148 * Return the driver's global value for device loss timeout plus
1149 * five seconds to allow the driver's nodev timer to run.
1150 */
1151 rport->dev_loss_tmo = lpfc_nodev_tmo + 5;
1152}
1153
1154static void
1155lpfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
1156{
1157 /*
1158 * The driver doesn't have a per-target timeout setting. Set
1159 * this value globally. lpfc_nodev_tmo should be greater then 0.
1160 */
1161 if (timeout)
1162 lpfc_nodev_tmo = timeout;
1163 else
1164 lpfc_nodev_tmo = 1;
1165 rport->dev_loss_tmo = lpfc_nodev_tmo + 5;
1166}
1167
1168
1169#define lpfc_rport_show_function(field, format_string, sz, cast) \
1170static ssize_t \
1171lpfc_show_rport_##field (struct class_device *cdev, char *buf) \
1172{ \
1173 struct fc_rport *rport = transport_class_to_rport(cdev); \
1174 struct lpfc_rport_data *rdata = rport->hostdata; \
1175 return snprintf(buf, sz, format_string, \
1176 (rdata->target) ? cast rdata->target->field : 0); \
1177}
1178
1179#define lpfc_rport_rd_attr(field, format_string, sz) \
1180 lpfc_rport_show_function(field, format_string, sz, ) \
1181static FC_RPORT_ATTR(field, S_IRUGO, lpfc_show_rport_##field, NULL)
1182
1183
1184struct fc_function_template lpfc_transport_functions = {
1185 /* fixed attributes the driver supports */
1186 .show_host_node_name = 1,
1187 .show_host_port_name = 1,
1188 .show_host_supported_classes = 1,
1189 .show_host_supported_fc4s = 1,
1190 .show_host_symbolic_name = 1,
1191 .show_host_supported_speeds = 1,
1192 .show_host_maxframe_size = 1,
1193
1194 /* dynamic attributes the driver supports */
1195 .get_host_port_id = lpfc_get_host_port_id,
1196 .show_host_port_id = 1,
1197
1198 .get_host_port_type = lpfc_get_host_port_type,
1199 .show_host_port_type = 1,
1200
1201 .get_host_port_state = lpfc_get_host_port_state,
1202 .show_host_port_state = 1,
1203
1204 /* active_fc4s is shown but doesn't change (thus no get function) */
1205 .show_host_active_fc4s = 1,
1206
1207 .get_host_speed = lpfc_get_host_speed,
1208 .show_host_speed = 1,
1209
1210 .get_host_fabric_name = lpfc_get_host_fabric_name,
1211 .show_host_fabric_name = 1,
1212
1213 /*
1214 * The LPFC driver treats linkdown handling as target loss events
1215 * so there are no sysfs handlers for link_down_tmo.
1216 */
1217
1218 .get_fc_host_stats = lpfc_get_stats,
1219
1220 /* the LPFC driver doesn't support resetting stats yet */
1221
1222 .dd_fcrport_size = sizeof(struct lpfc_rport_data),
1223 .show_rport_maxframe_size = 1,
1224 .show_rport_supported_classes = 1,
1225
1226 .get_rport_dev_loss_tmo = lpfc_get_rport_loss_tmo,
1227 .set_rport_dev_loss_tmo = lpfc_set_rport_loss_tmo,
1228 .show_rport_dev_loss_tmo = 1,
1229
1230 .get_starget_port_id = lpfc_get_starget_port_id,
1231 .show_starget_port_id = 1,
1232
1233 .get_starget_node_name = lpfc_get_starget_node_name,
1234 .show_starget_node_name = 1,
1235
1236 .get_starget_port_name = lpfc_get_starget_port_name,
1237 .show_starget_port_name = 1,
1238};
1239
1240void
1241lpfc_get_cfgparam(struct lpfc_hba *phba)
1242{
1243 phba->cfg_log_verbose = lpfc_log_verbose;
1244 phba->cfg_cr_delay = lpfc_cr_delay;
1245 phba->cfg_cr_count = lpfc_cr_count;
1246 phba->cfg_lun_queue_depth = lpfc_lun_queue_depth;
1247 phba->cfg_fcp_class = lpfc_fcp_class;
1248 phba->cfg_use_adisc = lpfc_use_adisc;
1249 phba->cfg_ack0 = lpfc_ack0;
1250 phba->cfg_topology = lpfc_topology;
1251 phba->cfg_scan_down = lpfc_scan_down;
1252 phba->cfg_nodev_tmo = lpfc_nodev_tmo;
1253 phba->cfg_link_speed = lpfc_link_speed;
1254 phba->cfg_fdmi_on = lpfc_fdmi_on;
1255 phba->cfg_discovery_threads = lpfc_discovery_threads;
1256 phba->cfg_max_luns = lpfc_max_luns;
1257
1258 /*
1259 * The total number of segments is the configuration value plus 2
1260 * since the IOCB need a command and response bde.
1261 */
1262 phba->cfg_sg_seg_cnt = LPFC_SG_SEG_CNT + 2;
1263
1264 /*
1265 * Since the sg_tablesize is module parameter, the sg_dma_buf_size
1266 * used to create the sg_dma_buf_pool must be dynamically calculated
1267 */
1268 phba->cfg_sg_dma_buf_size = sizeof(struct fcp_cmnd) +
1269 sizeof(struct fcp_rsp) +
1270 (phba->cfg_sg_seg_cnt * sizeof(struct ulp_bde64));
1271
1272 switch (phba->pcidev->device) {
1273 case PCI_DEVICE_ID_LP101:
1274 case PCI_DEVICE_ID_BSMB:
1275 case PCI_DEVICE_ID_ZSMB:
1276 phba->cfg_hba_queue_depth = LPFC_LP101_HBA_Q_DEPTH;
1277 break;
1278 case PCI_DEVICE_ID_RFLY:
1279 case PCI_DEVICE_ID_PFLY:
1280 case PCI_DEVICE_ID_BMID:
1281 case PCI_DEVICE_ID_ZMID:
1282 case PCI_DEVICE_ID_TFLY:
1283 phba->cfg_hba_queue_depth = LPFC_LC_HBA_Q_DEPTH;
1284 break;
1285 default:
1286 phba->cfg_hba_queue_depth = LPFC_DFT_HBA_Q_DEPTH;
1287 }
1288 return;
1289}