1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2021 Broadcom. All Rights Reserved. The term
4 * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
7 #include "efct_driver.h"
8 #include "efct_unsol.h"
10 static struct dentry
*efct_debugfs_root
;
11 static atomic_t efct_debugfs_count
;
13 static const struct scsi_host_template efct_template
= {
14 .module
= THIS_MODULE
,
15 .name
= EFCT_DRIVER_NAME
,
16 .supported_mode
= MODE_TARGET
,
20 static struct fc_function_template efct_xport_functions
;
21 static struct fc_function_template efct_vport_functions
;
23 static struct scsi_transport_template
*efct_xport_fc_tt
;
24 static struct scsi_transport_template
*efct_vport_fc_tt
;
27 efct_xport_alloc(struct efct
*efct
)
29 struct efct_xport
*xport
;
31 xport
= kzalloc(sizeof(*xport
), GFP_KERNEL
);
40 efct_xport_init_debugfs(struct efct
*efct
)
42 /* Setup efct debugfs root directory */
43 if (!efct_debugfs_root
) {
44 efct_debugfs_root
= debugfs_create_dir("efct", NULL
);
45 atomic_set(&efct_debugfs_count
, 0);
48 /* Create a directory for sessions in root */
49 if (!efct
->sess_debugfs_dir
) {
50 efct
->sess_debugfs_dir
= debugfs_create_dir("sessions",
52 if (IS_ERR(efct
->sess_debugfs_dir
)) {
54 "failed to create debugfs entry for sessions\n");
57 atomic_inc(&efct_debugfs_count
);
66 static void efct_xport_delete_debugfs(struct efct
*efct
)
68 /* Remove session debugfs directory */
69 debugfs_remove(efct
->sess_debugfs_dir
);
70 efct
->sess_debugfs_dir
= NULL
;
71 atomic_dec(&efct_debugfs_count
);
73 if (atomic_read(&efct_debugfs_count
) == 0) {
74 /* remove root debugfs directory */
75 debugfs_remove(efct_debugfs_root
);
76 efct_debugfs_root
= NULL
;
81 efct_xport_attach(struct efct_xport
*xport
)
83 struct efct
*efct
= xport
->efct
;
86 rc
= efct_hw_setup(&efct
->hw
, efct
, efct
->pci
);
88 efc_log_err(efct
, "%s: Can't setup hardware\n", efct
->desc
);
92 efct_hw_parse_filter(&efct
->hw
, (void *)efct
->filter_def
);
94 xport
->io_pool
= efct_io_pool_create(efct
, efct
->hw
.config
.n_sgl
);
95 if (!xport
->io_pool
) {
96 efc_log_err(efct
, "Can't allocate IO pool\n");
104 efct_xport_link_stats_cb(int status
, u32 num_counters
,
105 struct efct_hw_link_stat_counts
*counters
, void *arg
)
107 union efct_xport_stats_u
*result
= arg
;
109 result
->stats
.link_stats
.link_failure_error_count
=
110 counters
[EFCT_HW_LINK_STAT_LINK_FAILURE_COUNT
].counter
;
111 result
->stats
.link_stats
.loss_of_sync_error_count
=
112 counters
[EFCT_HW_LINK_STAT_LOSS_OF_SYNC_COUNT
].counter
;
113 result
->stats
.link_stats
.primitive_sequence_error_count
=
114 counters
[EFCT_HW_LINK_STAT_PRIMITIVE_SEQ_COUNT
].counter
;
115 result
->stats
.link_stats
.invalid_transmission_word_error_count
=
116 counters
[EFCT_HW_LINK_STAT_INVALID_XMIT_WORD_COUNT
].counter
;
117 result
->stats
.link_stats
.crc_error_count
=
118 counters
[EFCT_HW_LINK_STAT_CRC_COUNT
].counter
;
120 complete(&result
->stats
.done
);
124 efct_xport_host_stats_cb(int status
, u32 num_counters
,
125 struct efct_hw_host_stat_counts
*counters
, void *arg
)
127 union efct_xport_stats_u
*result
= arg
;
129 result
->stats
.host_stats
.transmit_kbyte_count
=
130 counters
[EFCT_HW_HOST_STAT_TX_KBYTE_COUNT
].counter
;
131 result
->stats
.host_stats
.receive_kbyte_count
=
132 counters
[EFCT_HW_HOST_STAT_RX_KBYTE_COUNT
].counter
;
133 result
->stats
.host_stats
.transmit_frame_count
=
134 counters
[EFCT_HW_HOST_STAT_TX_FRAME_COUNT
].counter
;
135 result
->stats
.host_stats
.receive_frame_count
=
136 counters
[EFCT_HW_HOST_STAT_RX_FRAME_COUNT
].counter
;
138 complete(&result
->stats
.done
);
142 efct_xport_async_link_stats_cb(int status
, u32 num_counters
,
143 struct efct_hw_link_stat_counts
*counters
,
146 union efct_xport_stats_u
*result
= arg
;
148 result
->stats
.link_stats
.link_failure_error_count
=
149 counters
[EFCT_HW_LINK_STAT_LINK_FAILURE_COUNT
].counter
;
150 result
->stats
.link_stats
.loss_of_sync_error_count
=
151 counters
[EFCT_HW_LINK_STAT_LOSS_OF_SYNC_COUNT
].counter
;
152 result
->stats
.link_stats
.primitive_sequence_error_count
=
153 counters
[EFCT_HW_LINK_STAT_PRIMITIVE_SEQ_COUNT
].counter
;
154 result
->stats
.link_stats
.invalid_transmission_word_error_count
=
155 counters
[EFCT_HW_LINK_STAT_INVALID_XMIT_WORD_COUNT
].counter
;
156 result
->stats
.link_stats
.crc_error_count
=
157 counters
[EFCT_HW_LINK_STAT_CRC_COUNT
].counter
;
161 efct_xport_async_host_stats_cb(int status
, u32 num_counters
,
162 struct efct_hw_host_stat_counts
*counters
,
165 union efct_xport_stats_u
*result
= arg
;
167 result
->stats
.host_stats
.transmit_kbyte_count
=
168 counters
[EFCT_HW_HOST_STAT_TX_KBYTE_COUNT
].counter
;
169 result
->stats
.host_stats
.receive_kbyte_count
=
170 counters
[EFCT_HW_HOST_STAT_RX_KBYTE_COUNT
].counter
;
171 result
->stats
.host_stats
.transmit_frame_count
=
172 counters
[EFCT_HW_HOST_STAT_TX_FRAME_COUNT
].counter
;
173 result
->stats
.host_stats
.receive_frame_count
=
174 counters
[EFCT_HW_HOST_STAT_RX_FRAME_COUNT
].counter
;
178 efct_xport_config_stats_timer(struct efct
*efct
);
181 efct_xport_stats_timer_cb(struct timer_list
*t
)
183 struct efct_xport
*xport
= from_timer(xport
, t
, stats_timer
);
184 struct efct
*efct
= xport
->efct
;
186 efct_xport_config_stats_timer(efct
);
190 efct_xport_config_stats_timer(struct efct
*efct
)
192 u32 timeout
= 3 * 1000;
193 struct efct_xport
*xport
= NULL
;
196 pr_err("%s: failed to locate EFCT device\n", __func__
);
201 efct_hw_get_link_stats(&efct
->hw
, 0, 0, 0,
202 efct_xport_async_link_stats_cb
,
203 &xport
->fc_xport_stats
);
204 efct_hw_get_host_stats(&efct
->hw
, 0, efct_xport_async_host_stats_cb
,
205 &xport
->fc_xport_stats
);
207 timer_setup(&xport
->stats_timer
,
208 &efct_xport_stats_timer_cb
, 0);
209 mod_timer(&xport
->stats_timer
,
210 jiffies
+ msecs_to_jiffies(timeout
));
214 efct_xport_initialize(struct efct_xport
*xport
)
216 struct efct
*efct
= xport
->efct
;
219 /* Initialize io lists */
220 spin_lock_init(&xport
->io_pending_lock
);
221 INIT_LIST_HEAD(&xport
->io_pending_list
);
222 atomic_set(&xport
->io_active_count
, 0);
223 atomic_set(&xport
->io_pending_count
, 0);
224 atomic_set(&xport
->io_total_free
, 0);
225 atomic_set(&xport
->io_total_pending
, 0);
226 atomic_set(&xport
->io_alloc_failed_count
, 0);
227 atomic_set(&xport
->io_pending_recursing
, 0);
229 rc
= efct_hw_init(&efct
->hw
);
231 efc_log_err(efct
, "efct_hw_init failure\n");
235 rc
= efct_scsi_tgt_new_device(efct
);
237 efc_log_err(efct
, "failed to initialize target\n");
241 rc
= efct_scsi_new_device(efct
);
243 efc_log_err(efct
, "failed to initialize initiator\n");
247 /* Get FC link and host statistics perodically*/
248 efct_xport_config_stats_timer(efct
);
250 efct_xport_init_debugfs(efct
);
255 efct_scsi_tgt_del_device(efct
);
258 efct_hw_teardown(&efct
->hw
);
264 efct_xport_status(struct efct_xport
*xport
, enum efct_xport_status cmd
,
265 union efct_xport_stats_u
*result
)
268 struct efct
*efct
= NULL
;
269 union efct_xport_stats_u value
;
274 case EFCT_XPORT_CONFIG_PORT_STATUS
:
275 if (xport
->configured_link_state
== 0) {
277 * Initial state is offline. configured_link_state is
278 * set to online explicitly when port is brought online
280 xport
->configured_link_state
= EFCT_XPORT_PORT_OFFLINE
;
282 result
->value
= xport
->configured_link_state
;
285 case EFCT_XPORT_PORT_STATUS
:
286 /* Determine port status based on link speed. */
287 value
.value
= efct_hw_get_link_speed(&efct
->hw
);
288 if (value
.value
== 0)
289 result
->value
= EFCT_XPORT_PORT_OFFLINE
;
291 result
->value
= EFCT_XPORT_PORT_ONLINE
;
294 case EFCT_XPORT_LINK_SPEED
:
295 result
->value
= efct_hw_get_link_speed(&efct
->hw
);
298 case EFCT_XPORT_LINK_STATISTICS
:
299 memcpy((void *)result
, &efct
->xport
->fc_xport_stats
,
300 sizeof(union efct_xport_stats_u
));
302 case EFCT_XPORT_LINK_STAT_RESET
: {
303 /* Create a completion to synchronize the stat reset process */
304 init_completion(&result
->stats
.done
);
306 /* First reset the link stats */
307 rc
= efct_hw_get_link_stats(&efct
->hw
, 0, 1, 1,
308 efct_xport_link_stats_cb
, result
);
312 /* Wait for completion to be signaled when the cmd completes */
313 if (wait_for_completion_interruptible(&result
->stats
.done
)) {
314 /* Undefined failure */
315 efc_log_debug(efct
, "sem wait failed\n");
320 /* Next reset the host stats */
321 rc
= efct_hw_get_host_stats(&efct
->hw
, 1,
322 efct_xport_host_stats_cb
, result
);
327 /* Wait for completion to be signaled when the cmd completes */
328 if (wait_for_completion_interruptible(&result
->stats
.done
)) {
329 /* Undefined failure */
330 efc_log_debug(efct
, "sem wait failed\n");
345 efct_get_link_supported_speeds(struct efct
*efct
)
347 u32 supported_speeds
= 0;
348 u32 link_module_type
, i
;
352 } supported_speed_list
[] = {
353 {SLI4_LINK_MODULE_TYPE_1GB
, FC_PORTSPEED_1GBIT
},
354 {SLI4_LINK_MODULE_TYPE_2GB
, FC_PORTSPEED_2GBIT
},
355 {SLI4_LINK_MODULE_TYPE_4GB
, FC_PORTSPEED_4GBIT
},
356 {SLI4_LINK_MODULE_TYPE_8GB
, FC_PORTSPEED_8GBIT
},
357 {SLI4_LINK_MODULE_TYPE_16GB
, FC_PORTSPEED_16GBIT
},
358 {SLI4_LINK_MODULE_TYPE_32GB
, FC_PORTSPEED_32GBIT
},
359 {SLI4_LINK_MODULE_TYPE_64GB
, FC_PORTSPEED_64GBIT
},
360 {SLI4_LINK_MODULE_TYPE_128GB
, FC_PORTSPEED_128GBIT
},
363 link_module_type
= sli_get_lmt(&efct
->hw
.sli
);
365 /* populate link supported speeds */
366 for (i
= 0; i
< ARRAY_SIZE(supported_speed_list
); i
++) {
367 if (link_module_type
& supported_speed_list
[i
].lmt_speed
)
368 supported_speeds
|= supported_speed_list
[i
].speed
;
371 return supported_speeds
;
375 efct_scsi_new_device(struct efct
*efct
)
377 struct Scsi_Host
*shost
= NULL
;
379 struct efct_vport
*vport
= NULL
;
381 shost
= scsi_host_alloc(&efct_template
, sizeof(*vport
));
383 efc_log_err(efct
, "failed to allocate Scsi_Host struct\n");
387 /* save shost to initiator-client context */
390 /* save efct information to shost LLD-specific space */
391 vport
= (struct efct_vport
*)shost
->hostdata
;
395 * Set initial can_queue value to the max SCSI IOs. This is the maximum
396 * global queue depth (as opposed to the per-LUN queue depth --
397 * .cmd_per_lun This may need to be adjusted for I+T mode.
399 shost
->can_queue
= efct
->hw
.config
.n_io
;
400 shost
->max_cmd_len
= 16; /* 16-byte CDBs */
401 shost
->max_id
= 0xffff;
402 shost
->max_lun
= 0xffffffff;
405 * can only accept (from mid-layer) as many SGEs as we've
408 shost
->sg_tablesize
= sli_get_max_sgl(&efct
->hw
.sli
);
410 /* attach FC Transport template to shost */
411 shost
->transportt
= efct_xport_fc_tt
;
412 efc_log_debug(efct
, "transport template=%p\n", efct_xport_fc_tt
);
414 /* get pci_dev structure and add host to SCSI ML */
415 error
= scsi_add_host_with_dma(shost
, &efct
->pci
->dev
,
418 efc_log_debug(efct
, "failed scsi_add_host_with_dma\n");
422 /* Set symbolic name for host port */
423 snprintf(fc_host_symbolic_name(shost
),
424 sizeof(fc_host_symbolic_name(shost
)),
425 "Emulex %s FV%s DV%s", efct
->model
,
426 efct
->hw
.sli
.fw_name
[0], EFCT_DRIVER_VERSION
);
428 /* Set host port supported classes */
429 fc_host_supported_classes(shost
) = FC_COS_CLASS3
;
431 fc_host_supported_speeds(shost
) = efct_get_link_supported_speeds(efct
);
433 fc_host_node_name(shost
) = efct_get_wwnn(&efct
->hw
);
434 fc_host_port_name(shost
) = efct_get_wwpn(&efct
->hw
);
435 fc_host_max_npiv_vports(shost
) = 128;
440 struct scsi_transport_template
*
441 efct_attach_fc_transport(void)
443 struct scsi_transport_template
*efct_fc_template
= NULL
;
445 efct_fc_template
= fc_attach_transport(&efct_xport_functions
);
447 if (!efct_fc_template
)
448 pr_err("failed to attach EFCT with fc transport\n");
450 return efct_fc_template
;
453 struct scsi_transport_template
*
454 efct_attach_vport_fc_transport(void)
456 struct scsi_transport_template
*efct_fc_template
= NULL
;
458 efct_fc_template
= fc_attach_transport(&efct_vport_functions
);
460 if (!efct_fc_template
)
461 pr_err("failed to attach EFCT with fc transport\n");
463 return efct_fc_template
;
467 efct_scsi_reg_fc_transport(void)
469 /* attach to appropriate scsi_tranport_* module */
470 efct_xport_fc_tt
= efct_attach_fc_transport();
471 if (!efct_xport_fc_tt
) {
472 pr_err("%s: failed to attach to scsi_transport_*", __func__
);
476 efct_vport_fc_tt
= efct_attach_vport_fc_transport();
477 if (!efct_vport_fc_tt
) {
478 pr_err("%s: failed to attach to scsi_transport_*", __func__
);
479 efct_release_fc_transport(efct_xport_fc_tt
);
480 efct_xport_fc_tt
= NULL
;
488 efct_scsi_release_fc_transport(void)
490 /* detach from scsi_transport_* */
491 efct_release_fc_transport(efct_xport_fc_tt
);
492 efct_xport_fc_tt
= NULL
;
493 if (efct_vport_fc_tt
)
494 efct_release_fc_transport(efct_vport_fc_tt
);
496 efct_vport_fc_tt
= NULL
;
500 efct_xport_detach(struct efct_xport
*xport
)
502 struct efct
*efct
= xport
->efct
;
504 /* free resources associated with target-server and initiator-client */
505 efct_scsi_tgt_del_device(efct
);
507 efct_scsi_del_device(efct
);
509 /*Shutdown FC Statistics timer*/
510 if (timer_pending(&xport
->stats_timer
))
511 del_timer(&xport
->stats_timer
);
513 efct_hw_teardown(&efct
->hw
);
515 efct_xport_delete_debugfs(efct
);
519 efct_xport_domain_free_cb(struct efc
*efc
, void *arg
)
521 struct completion
*done
= arg
;
527 efct_xport_control(struct efct_xport
*xport
, enum efct_xport_ctrl cmd
, ...)
530 struct efct
*efct
= NULL
;
536 case EFCT_XPORT_PORT_ONLINE
: {
537 /* Bring the port on-line */
538 rc
= efct_hw_port_control(&efct
->hw
, EFCT_HW_PORT_INIT
, 0,
542 "%s: Can't init port\n", efct
->desc
);
544 xport
->configured_link_state
= cmd
;
547 case EFCT_XPORT_PORT_OFFLINE
: {
548 if (efct_hw_port_control(&efct
->hw
, EFCT_HW_PORT_SHUTDOWN
, 0,
550 efc_log_err(efct
, "port shutdown failed\n");
552 xport
->configured_link_state
= cmd
;
556 case EFCT_XPORT_SHUTDOWN
: {
557 struct completion done
;
558 unsigned long timeout
;
560 /* if a PHYSDEV reset was performed (e.g. hw dump), will affect
561 * all PCI functions; orderly shutdown won't work,
564 if (sli_reset_required(&efct
->hw
.sli
)) {
565 struct efc_domain
*domain
= efct
->efcport
->domain
;
568 efc_domain_cb(efct
->efcport
, EFC_HW_DOMAIN_LOST
,
571 efct_hw_port_control(&efct
->hw
, EFCT_HW_PORT_SHUTDOWN
,
575 init_completion(&done
);
577 efc_register_domain_free_cb(efct
->efcport
,
578 efct_xport_domain_free_cb
, &done
);
580 efc_log_debug(efct
, "Waiting %d seconds for domain shutdown\n",
581 (EFC_SHUTDOWN_TIMEOUT_USEC
/ 1000000));
583 timeout
= usecs_to_jiffies(EFC_SHUTDOWN_TIMEOUT_USEC
);
584 if (!wait_for_completion_timeout(&done
, timeout
)) {
585 efc_log_err(efct
, "Domain shutdown timed out!!\n");
589 efc_register_domain_free_cb(efct
->efcport
, NULL
, NULL
);
591 /* Free up any saved virtual ports */
592 efc_vport_del_all(efct
->efcport
);
597 * Set wwnn for the port. This will be used instead of the default
600 case EFCT_XPORT_WWNN_SET
: {
603 /* Retrieve arguments */
605 wwnn
= va_arg(argp
, uint64_t);
608 efc_log_debug(efct
, " WWNN %016llx\n", wwnn
);
609 xport
->req_wwnn
= wwnn
;
614 * Set wwpn for the port. This will be used instead of the default
617 case EFCT_XPORT_WWPN_SET
: {
620 /* Retrieve arguments */
622 wwpn
= va_arg(argp
, uint64_t);
625 efc_log_debug(efct
, " WWPN %016llx\n", wwpn
);
626 xport
->req_wwpn
= wwpn
;
638 efct_xport_free(struct efct_xport
*xport
)
641 efct_io_pool_free(xport
->io_pool
);
648 efct_release_fc_transport(struct scsi_transport_template
*transport_template
)
650 if (transport_template
)
651 pr_err("releasing transport layer\n");
653 /* Releasing FC transport */
654 fc_release_transport(transport_template
);
658 efct_xport_remove_host(struct Scsi_Host
*shost
)
660 fc_remove_host(shost
);
664 efct_scsi_del_device(struct efct
*efct
)
669 efc_log_debug(efct
, "Unregistering with Transport Layer\n");
670 efct_xport_remove_host(efct
->shost
);
671 efc_log_debug(efct
, "Unregistering with SCSI Midlayer\n");
672 scsi_remove_host(efct
->shost
);
673 scsi_host_put(efct
->shost
);
678 efct_get_host_port_id(struct Scsi_Host
*shost
)
680 struct efct_vport
*vport
= (struct efct_vport
*)shost
->hostdata
;
681 struct efct
*efct
= vport
->efct
;
682 struct efc
*efc
= efct
->efcport
;
683 struct efc_nport
*nport
;
685 if (efc
->domain
&& efc
->domain
->nport
) {
686 nport
= efc
->domain
->nport
;
687 fc_host_port_id(shost
) = nport
->fc_id
;
692 efct_get_host_port_type(struct Scsi_Host
*shost
)
694 struct efct_vport
*vport
= (struct efct_vport
*)shost
->hostdata
;
695 struct efct
*efct
= vport
->efct
;
696 struct efc
*efc
= efct
->efcport
;
697 int type
= FC_PORTTYPE_UNKNOWN
;
699 if (efc
->domain
&& efc
->domain
->nport
) {
700 if (efc
->domain
->is_loop
) {
701 type
= FC_PORTTYPE_LPORT
;
703 struct efc_nport
*nport
= efc
->domain
->nport
;
706 type
= FC_PORTTYPE_NPIV
;
707 else if (nport
->topology
== EFC_NPORT_TOPO_P2P
)
708 type
= FC_PORTTYPE_PTP
;
709 else if (nport
->topology
== EFC_NPORT_TOPO_UNKNOWN
)
710 type
= FC_PORTTYPE_UNKNOWN
;
712 type
= FC_PORTTYPE_NPORT
;
715 fc_host_port_type(shost
) = type
;
719 efct_get_host_vport_type(struct Scsi_Host
*shost
)
721 fc_host_port_type(shost
) = FC_PORTTYPE_NPIV
;
725 efct_get_host_port_state(struct Scsi_Host
*shost
)
727 struct efct_vport
*vport
= (struct efct_vport
*)shost
->hostdata
;
728 struct efct
*efct
= vport
->efct
;
729 union efct_xport_stats_u status
;
732 rc
= efct_xport_status(efct
->xport
, EFCT_XPORT_PORT_STATUS
, &status
);
733 if ((!rc
) && (status
.value
== EFCT_XPORT_PORT_ONLINE
))
734 fc_host_port_state(shost
) = FC_PORTSTATE_ONLINE
;
736 fc_host_port_state(shost
) = FC_PORTSTATE_OFFLINE
;
740 efct_get_host_speed(struct Scsi_Host
*shost
)
742 struct efct_vport
*vport
= (struct efct_vport
*)shost
->hostdata
;
743 struct efct
*efct
= vport
->efct
;
744 struct efc
*efc
= efct
->efcport
;
745 union efct_xport_stats_u speed
;
746 u32 fc_speed
= FC_PORTSPEED_UNKNOWN
;
749 if (!efc
->domain
|| !efc
->domain
->nport
) {
750 fc_host_speed(shost
) = fc_speed
;
754 rc
= efct_xport_status(efct
->xport
, EFCT_XPORT_LINK_SPEED
, &speed
);
756 switch (speed
.value
) {
758 fc_speed
= FC_PORTSPEED_1GBIT
;
761 fc_speed
= FC_PORTSPEED_2GBIT
;
764 fc_speed
= FC_PORTSPEED_4GBIT
;
767 fc_speed
= FC_PORTSPEED_8GBIT
;
770 fc_speed
= FC_PORTSPEED_10GBIT
;
773 fc_speed
= FC_PORTSPEED_16GBIT
;
776 fc_speed
= FC_PORTSPEED_32GBIT
;
779 fc_speed
= FC_PORTSPEED_64GBIT
;
782 fc_speed
= FC_PORTSPEED_128GBIT
;
787 fc_host_speed(shost
) = fc_speed
;
791 efct_get_host_fabric_name(struct Scsi_Host
*shost
)
793 struct efct_vport
*vport
= (struct efct_vport
*)shost
->hostdata
;
794 struct efct
*efct
= vport
->efct
;
795 struct efc
*efc
= efct
->efcport
;
798 struct fc_els_flogi
*sp
=
799 (struct fc_els_flogi
*)
800 efc
->domain
->flogi_service_params
;
802 fc_host_fabric_name(shost
) = be64_to_cpu(sp
->fl_wwnn
);
806 static struct fc_host_statistics
*
807 efct_get_stats(struct Scsi_Host
*shost
)
809 struct efct_vport
*vport
= (struct efct_vport
*)shost
->hostdata
;
810 struct efct
*efct
= vport
->efct
;
811 union efct_xport_stats_u stats
;
812 struct efct_xport
*xport
= efct
->xport
;
815 rc
= efct_xport_status(xport
, EFCT_XPORT_LINK_STATISTICS
, &stats
);
817 pr_err("efct_xport_status returned non 0 - %d\n", rc
);
821 vport
->fc_host_stats
.loss_of_sync_count
=
822 stats
.stats
.link_stats
.loss_of_sync_error_count
;
823 vport
->fc_host_stats
.link_failure_count
=
824 stats
.stats
.link_stats
.link_failure_error_count
;
825 vport
->fc_host_stats
.prim_seq_protocol_err_count
=
826 stats
.stats
.link_stats
.primitive_sequence_error_count
;
827 vport
->fc_host_stats
.invalid_tx_word_count
=
828 stats
.stats
.link_stats
.invalid_transmission_word_error_count
;
829 vport
->fc_host_stats
.invalid_crc_count
=
830 stats
.stats
.link_stats
.crc_error_count
;
831 /* mbox returns kbyte count so we need to convert to words */
832 vport
->fc_host_stats
.tx_words
=
833 stats
.stats
.host_stats
.transmit_kbyte_count
* 256;
834 /* mbox returns kbyte count so we need to convert to words */
835 vport
->fc_host_stats
.rx_words
=
836 stats
.stats
.host_stats
.receive_kbyte_count
* 256;
837 vport
->fc_host_stats
.tx_frames
=
838 stats
.stats
.host_stats
.transmit_frame_count
;
839 vport
->fc_host_stats
.rx_frames
=
840 stats
.stats
.host_stats
.receive_frame_count
;
842 vport
->fc_host_stats
.fcp_input_requests
=
843 xport
->fcp_stats
.input_requests
;
844 vport
->fc_host_stats
.fcp_output_requests
=
845 xport
->fcp_stats
.output_requests
;
846 vport
->fc_host_stats
.fcp_output_megabytes
=
847 xport
->fcp_stats
.output_bytes
>> 20;
848 vport
->fc_host_stats
.fcp_input_megabytes
=
849 xport
->fcp_stats
.input_bytes
>> 20;
850 vport
->fc_host_stats
.fcp_control_requests
=
851 xport
->fcp_stats
.control_requests
;
853 return &vport
->fc_host_stats
;
857 efct_reset_stats(struct Scsi_Host
*shost
)
859 struct efct_vport
*vport
= (struct efct_vport
*)shost
->hostdata
;
860 struct efct
*efct
= vport
->efct
;
861 /* argument has no purpose for this action */
862 union efct_xport_stats_u dummy
;
865 rc
= efct_xport_status(efct
->xport
, EFCT_XPORT_LINK_STAT_RESET
, &dummy
);
867 pr_err("efct_xport_status returned non 0 - %d\n", rc
);
871 efct_issue_lip(struct Scsi_Host
*shost
)
873 struct efct_vport
*vport
=
874 shost
? (struct efct_vport
*)shost
->hostdata
: NULL
;
875 struct efct
*efct
= vport
? vport
->efct
: NULL
;
877 if (!shost
|| !vport
|| !efct
) {
878 pr_err("%s: shost=%p vport=%p efct=%p\n", __func__
,
884 * Bring the link down gracefully then re-init the link.
885 * The firmware will re-initialize the Fibre Channel interface as
886 * required. It does not issue a LIP.
889 if (efct_xport_control(efct
->xport
, EFCT_XPORT_PORT_OFFLINE
))
890 efc_log_debug(efct
, "EFCT_XPORT_PORT_OFFLINE failed\n");
892 if (efct_xport_control(efct
->xport
, EFCT_XPORT_PORT_ONLINE
))
893 efc_log_debug(efct
, "EFCT_XPORT_PORT_ONLINE failed\n");
899 efct_scsi_new_vport(struct efct
*efct
, struct device
*dev
)
901 struct Scsi_Host
*shost
= NULL
;
903 struct efct_vport
*vport
= NULL
;
905 shost
= scsi_host_alloc(&efct_template
, sizeof(*vport
));
907 efc_log_err(efct
, "failed to allocate Scsi_Host struct\n");
911 /* save efct information to shost LLD-specific space */
912 vport
= (struct efct_vport
*)shost
->hostdata
;
914 vport
->is_vport
= true;
916 shost
->can_queue
= efct
->hw
.config
.n_io
;
917 shost
->max_cmd_len
= 16; /* 16-byte CDBs */
918 shost
->max_id
= 0xffff;
919 shost
->max_lun
= 0xffffffff;
921 /* can only accept (from mid-layer) as many SGEs as we've pre-regited*/
922 shost
->sg_tablesize
= sli_get_max_sgl(&efct
->hw
.sli
);
924 /* attach FC Transport template to shost */
925 shost
->transportt
= efct_vport_fc_tt
;
926 efc_log_debug(efct
, "vport transport template=%p\n",
929 /* get pci_dev structure and add host to SCSI ML */
930 error
= scsi_add_host_with_dma(shost
, dev
, &efct
->pci
->dev
);
932 efc_log_debug(efct
, "failed scsi_add_host_with_dma\n");
936 /* Set symbolic name for host port */
937 snprintf(fc_host_symbolic_name(shost
),
938 sizeof(fc_host_symbolic_name(shost
)),
939 "Emulex %s FV%s DV%s", efct
->model
, efct
->hw
.sli
.fw_name
[0],
940 EFCT_DRIVER_VERSION
);
942 /* Set host port supported classes */
943 fc_host_supported_classes(shost
) = FC_COS_CLASS3
;
945 fc_host_supported_speeds(shost
) = efct_get_link_supported_speeds(efct
);
946 vport
->shost
= shost
;
951 int efct_scsi_del_vport(struct efct
*efct
, struct Scsi_Host
*shost
)
955 "Unregistering vport with Transport Layer\n");
956 efct_xport_remove_host(shost
);
957 efc_log_debug(efct
, "Unregistering vport with SCSI Midlayer\n");
958 scsi_remove_host(shost
);
959 scsi_host_put(shost
);
966 efct_vport_create(struct fc_vport
*fc_vport
, bool disable
)
968 struct Scsi_Host
*shost
= fc_vport
? fc_vport
->shost
: NULL
;
969 struct efct_vport
*pport
= shost
?
970 (struct efct_vport
*)shost
->hostdata
:
972 struct efct
*efct
= pport
? pport
->efct
: NULL
;
973 struct efct_vport
*vport
= NULL
;
975 if (!fc_vport
|| !shost
|| !efct
)
978 vport
= efct_scsi_new_vport(efct
, &fc_vport
->dev
);
980 efc_log_err(efct
, "failed to create vport\n");
984 vport
->fc_vport
= fc_vport
;
985 vport
->npiv_wwpn
= fc_vport
->port_name
;
986 vport
->npiv_wwnn
= fc_vport
->node_name
;
987 fc_host_node_name(vport
->shost
) = vport
->npiv_wwnn
;
988 fc_host_port_name(vport
->shost
) = vport
->npiv_wwpn
;
989 *(struct efct_vport
**)fc_vport
->dd_data
= vport
;
998 efct_vport_delete(struct fc_vport
*fc_vport
)
1000 struct efct_vport
*vport
= *(struct efct_vport
**)fc_vport
->dd_data
;
1001 struct Scsi_Host
*shost
= vport
? vport
->shost
: NULL
;
1002 struct efct
*efct
= vport
? vport
->efct
: NULL
;
1005 rc
= efct_scsi_del_vport(efct
, shost
);
1008 pr_err("%s: vport delete failed\n", __func__
);
1014 efct_vport_disable(struct fc_vport
*fc_vport
, bool disable
)
1019 static struct fc_function_template efct_xport_functions
= {
1020 .get_host_port_id
= efct_get_host_port_id
,
1021 .get_host_port_type
= efct_get_host_port_type
,
1022 .get_host_port_state
= efct_get_host_port_state
,
1023 .get_host_speed
= efct_get_host_speed
,
1024 .get_host_fabric_name
= efct_get_host_fabric_name
,
1026 .get_fc_host_stats
= efct_get_stats
,
1027 .reset_fc_host_stats
= efct_reset_stats
,
1029 .issue_fc_host_lip
= efct_issue_lip
,
1031 .vport_disable
= efct_vport_disable
,
1033 /* allocation lengths for host-specific data */
1034 .dd_fcrport_size
= sizeof(struct efct_rport_data
),
1035 .dd_fcvport_size
= 128, /* should be sizeof(...) */
1037 /* remote port fixed attributes */
1038 .show_rport_maxframe_size
= 1,
1039 .show_rport_supported_classes
= 1,
1040 .show_rport_dev_loss_tmo
= 1,
1042 /* target dynamic attributes */
1043 .show_starget_node_name
= 1,
1044 .show_starget_port_name
= 1,
1045 .show_starget_port_id
= 1,
1047 /* host fixed attributes */
1048 .show_host_node_name
= 1,
1049 .show_host_port_name
= 1,
1050 .show_host_supported_classes
= 1,
1051 .show_host_supported_fc4s
= 1,
1052 .show_host_supported_speeds
= 1,
1053 .show_host_maxframe_size
= 1,
1055 /* host dynamic attributes */
1056 .show_host_port_id
= 1,
1057 .show_host_port_type
= 1,
1058 .show_host_port_state
= 1,
1059 /* active_fc4s is shown but doesn't change (thus no get function) */
1060 .show_host_active_fc4s
= 1,
1061 .show_host_speed
= 1,
1062 .show_host_fabric_name
= 1,
1063 .show_host_symbolic_name
= 1,
1064 .vport_create
= efct_vport_create
,
1065 .vport_delete
= efct_vport_delete
,
1068 static struct fc_function_template efct_vport_functions
= {
1069 .get_host_port_id
= efct_get_host_port_id
,
1070 .get_host_port_type
= efct_get_host_vport_type
,
1071 .get_host_port_state
= efct_get_host_port_state
,
1072 .get_host_speed
= efct_get_host_speed
,
1073 .get_host_fabric_name
= efct_get_host_fabric_name
,
1075 .get_fc_host_stats
= efct_get_stats
,
1076 .reset_fc_host_stats
= efct_reset_stats
,
1078 .issue_fc_host_lip
= efct_issue_lip
,
1080 /* allocation lengths for host-specific data */
1081 .dd_fcrport_size
= sizeof(struct efct_rport_data
),
1082 .dd_fcvport_size
= 128, /* should be sizeof(...) */
1084 /* remote port fixed attributes */
1085 .show_rport_maxframe_size
= 1,
1086 .show_rport_supported_classes
= 1,
1087 .show_rport_dev_loss_tmo
= 1,
1089 /* target dynamic attributes */
1090 .show_starget_node_name
= 1,
1091 .show_starget_port_name
= 1,
1092 .show_starget_port_id
= 1,
1094 /* host fixed attributes */
1095 .show_host_node_name
= 1,
1096 .show_host_port_name
= 1,
1097 .show_host_supported_classes
= 1,
1098 .show_host_supported_fc4s
= 1,
1099 .show_host_supported_speeds
= 1,
1100 .show_host_maxframe_size
= 1,
1102 /* host dynamic attributes */
1103 .show_host_port_id
= 1,
1104 .show_host_port_type
= 1,
1105 .show_host_port_state
= 1,
1106 /* active_fc4s is shown but doesn't change (thus no get function) */
1107 .show_host_active_fc4s
= 1,
1108 .show_host_speed
= 1,
1109 .show_host_fabric_name
= 1,
1110 .show_host_symbolic_name
= 1,