162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2021 Broadcom. All Rights Reserved. The term
462306a36Sopenharmony_ci * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include "efct_driver.h"
862306a36Sopenharmony_ci#include "efct_unsol.h"
962306a36Sopenharmony_ci
1062306a36Sopenharmony_cistatic struct dentry *efct_debugfs_root;
1162306a36Sopenharmony_cistatic atomic_t efct_debugfs_count;
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_cistatic const struct scsi_host_template efct_template = {
1462306a36Sopenharmony_ci	.module			= THIS_MODULE,
1562306a36Sopenharmony_ci	.name			= EFCT_DRIVER_NAME,
1662306a36Sopenharmony_ci	.supported_mode		= MODE_TARGET,
1762306a36Sopenharmony_ci};
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci/* globals */
2062306a36Sopenharmony_cistatic struct fc_function_template efct_xport_functions;
2162306a36Sopenharmony_cistatic struct fc_function_template efct_vport_functions;
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_cistatic struct scsi_transport_template *efct_xport_fc_tt;
2462306a36Sopenharmony_cistatic struct scsi_transport_template *efct_vport_fc_tt;
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_cistruct efct_xport *
2762306a36Sopenharmony_ciefct_xport_alloc(struct efct *efct)
2862306a36Sopenharmony_ci{
2962306a36Sopenharmony_ci	struct efct_xport *xport;
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci	xport = kzalloc(sizeof(*xport), GFP_KERNEL);
3262306a36Sopenharmony_ci	if (!xport)
3362306a36Sopenharmony_ci		return xport;
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	xport->efct = efct;
3662306a36Sopenharmony_ci	return xport;
3762306a36Sopenharmony_ci}
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_cistatic int
4062306a36Sopenharmony_ciefct_xport_init_debugfs(struct efct *efct)
4162306a36Sopenharmony_ci{
4262306a36Sopenharmony_ci	/* Setup efct debugfs root directory */
4362306a36Sopenharmony_ci	if (!efct_debugfs_root) {
4462306a36Sopenharmony_ci		efct_debugfs_root = debugfs_create_dir("efct", NULL);
4562306a36Sopenharmony_ci		atomic_set(&efct_debugfs_count, 0);
4662306a36Sopenharmony_ci	}
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci	/* Create a directory for sessions in root */
4962306a36Sopenharmony_ci	if (!efct->sess_debugfs_dir) {
5062306a36Sopenharmony_ci		efct->sess_debugfs_dir = debugfs_create_dir("sessions",
5162306a36Sopenharmony_ci							efct_debugfs_root);
5262306a36Sopenharmony_ci		if (IS_ERR(efct->sess_debugfs_dir)) {
5362306a36Sopenharmony_ci			efc_log_err(efct,
5462306a36Sopenharmony_ci				    "failed to create debugfs entry for sessions\n");
5562306a36Sopenharmony_ci			goto debugfs_fail;
5662306a36Sopenharmony_ci		}
5762306a36Sopenharmony_ci		atomic_inc(&efct_debugfs_count);
5862306a36Sopenharmony_ci	}
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	return 0;
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_cidebugfs_fail:
6362306a36Sopenharmony_ci	return -EIO;
6462306a36Sopenharmony_ci}
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_cistatic void efct_xport_delete_debugfs(struct efct *efct)
6762306a36Sopenharmony_ci{
6862306a36Sopenharmony_ci	/* Remove session debugfs directory */
6962306a36Sopenharmony_ci	debugfs_remove(efct->sess_debugfs_dir);
7062306a36Sopenharmony_ci	efct->sess_debugfs_dir = NULL;
7162306a36Sopenharmony_ci	atomic_dec(&efct_debugfs_count);
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci	if (atomic_read(&efct_debugfs_count) == 0) {
7462306a36Sopenharmony_ci		/* remove root debugfs directory */
7562306a36Sopenharmony_ci		debugfs_remove(efct_debugfs_root);
7662306a36Sopenharmony_ci		efct_debugfs_root = NULL;
7762306a36Sopenharmony_ci	}
7862306a36Sopenharmony_ci}
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ciint
8162306a36Sopenharmony_ciefct_xport_attach(struct efct_xport *xport)
8262306a36Sopenharmony_ci{
8362306a36Sopenharmony_ci	struct efct *efct = xport->efct;
8462306a36Sopenharmony_ci	int rc;
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci	rc = efct_hw_setup(&efct->hw, efct, efct->pci);
8762306a36Sopenharmony_ci	if (rc) {
8862306a36Sopenharmony_ci		efc_log_err(efct, "%s: Can't setup hardware\n", efct->desc);
8962306a36Sopenharmony_ci		return rc;
9062306a36Sopenharmony_ci	}
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci	efct_hw_parse_filter(&efct->hw, (void *)efct->filter_def);
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci	xport->io_pool = efct_io_pool_create(efct, efct->hw.config.n_sgl);
9562306a36Sopenharmony_ci	if (!xport->io_pool) {
9662306a36Sopenharmony_ci		efc_log_err(efct, "Can't allocate IO pool\n");
9762306a36Sopenharmony_ci		return -ENOMEM;
9862306a36Sopenharmony_ci	}
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci	return 0;
10162306a36Sopenharmony_ci}
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_cistatic void
10462306a36Sopenharmony_ciefct_xport_link_stats_cb(int status, u32 num_counters,
10562306a36Sopenharmony_ci			 struct efct_hw_link_stat_counts *counters, void *arg)
10662306a36Sopenharmony_ci{
10762306a36Sopenharmony_ci	union efct_xport_stats_u *result = arg;
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	result->stats.link_stats.link_failure_error_count =
11062306a36Sopenharmony_ci		counters[EFCT_HW_LINK_STAT_LINK_FAILURE_COUNT].counter;
11162306a36Sopenharmony_ci	result->stats.link_stats.loss_of_sync_error_count =
11262306a36Sopenharmony_ci		counters[EFCT_HW_LINK_STAT_LOSS_OF_SYNC_COUNT].counter;
11362306a36Sopenharmony_ci	result->stats.link_stats.primitive_sequence_error_count =
11462306a36Sopenharmony_ci		counters[EFCT_HW_LINK_STAT_PRIMITIVE_SEQ_COUNT].counter;
11562306a36Sopenharmony_ci	result->stats.link_stats.invalid_transmission_word_error_count =
11662306a36Sopenharmony_ci		counters[EFCT_HW_LINK_STAT_INVALID_XMIT_WORD_COUNT].counter;
11762306a36Sopenharmony_ci	result->stats.link_stats.crc_error_count =
11862306a36Sopenharmony_ci		counters[EFCT_HW_LINK_STAT_CRC_COUNT].counter;
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci	complete(&result->stats.done);
12162306a36Sopenharmony_ci}
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_cistatic void
12462306a36Sopenharmony_ciefct_xport_host_stats_cb(int status, u32 num_counters,
12562306a36Sopenharmony_ci			 struct efct_hw_host_stat_counts *counters, void *arg)
12662306a36Sopenharmony_ci{
12762306a36Sopenharmony_ci	union efct_xport_stats_u *result = arg;
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci	result->stats.host_stats.transmit_kbyte_count =
13062306a36Sopenharmony_ci		counters[EFCT_HW_HOST_STAT_TX_KBYTE_COUNT].counter;
13162306a36Sopenharmony_ci	result->stats.host_stats.receive_kbyte_count =
13262306a36Sopenharmony_ci		counters[EFCT_HW_HOST_STAT_RX_KBYTE_COUNT].counter;
13362306a36Sopenharmony_ci	result->stats.host_stats.transmit_frame_count =
13462306a36Sopenharmony_ci		counters[EFCT_HW_HOST_STAT_TX_FRAME_COUNT].counter;
13562306a36Sopenharmony_ci	result->stats.host_stats.receive_frame_count =
13662306a36Sopenharmony_ci		counters[EFCT_HW_HOST_STAT_RX_FRAME_COUNT].counter;
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci	complete(&result->stats.done);
13962306a36Sopenharmony_ci}
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_cistatic void
14262306a36Sopenharmony_ciefct_xport_async_link_stats_cb(int status, u32 num_counters,
14362306a36Sopenharmony_ci			       struct efct_hw_link_stat_counts *counters,
14462306a36Sopenharmony_ci			       void *arg)
14562306a36Sopenharmony_ci{
14662306a36Sopenharmony_ci	union efct_xport_stats_u *result = arg;
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci	result->stats.link_stats.link_failure_error_count =
14962306a36Sopenharmony_ci		counters[EFCT_HW_LINK_STAT_LINK_FAILURE_COUNT].counter;
15062306a36Sopenharmony_ci	result->stats.link_stats.loss_of_sync_error_count =
15162306a36Sopenharmony_ci		counters[EFCT_HW_LINK_STAT_LOSS_OF_SYNC_COUNT].counter;
15262306a36Sopenharmony_ci	result->stats.link_stats.primitive_sequence_error_count =
15362306a36Sopenharmony_ci		counters[EFCT_HW_LINK_STAT_PRIMITIVE_SEQ_COUNT].counter;
15462306a36Sopenharmony_ci	result->stats.link_stats.invalid_transmission_word_error_count =
15562306a36Sopenharmony_ci		counters[EFCT_HW_LINK_STAT_INVALID_XMIT_WORD_COUNT].counter;
15662306a36Sopenharmony_ci	result->stats.link_stats.crc_error_count =
15762306a36Sopenharmony_ci		counters[EFCT_HW_LINK_STAT_CRC_COUNT].counter;
15862306a36Sopenharmony_ci}
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_cistatic void
16162306a36Sopenharmony_ciefct_xport_async_host_stats_cb(int status, u32 num_counters,
16262306a36Sopenharmony_ci			       struct efct_hw_host_stat_counts *counters,
16362306a36Sopenharmony_ci			       void *arg)
16462306a36Sopenharmony_ci{
16562306a36Sopenharmony_ci	union efct_xport_stats_u *result = arg;
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci	result->stats.host_stats.transmit_kbyte_count =
16862306a36Sopenharmony_ci		counters[EFCT_HW_HOST_STAT_TX_KBYTE_COUNT].counter;
16962306a36Sopenharmony_ci	result->stats.host_stats.receive_kbyte_count =
17062306a36Sopenharmony_ci		counters[EFCT_HW_HOST_STAT_RX_KBYTE_COUNT].counter;
17162306a36Sopenharmony_ci	result->stats.host_stats.transmit_frame_count =
17262306a36Sopenharmony_ci		counters[EFCT_HW_HOST_STAT_TX_FRAME_COUNT].counter;
17362306a36Sopenharmony_ci	result->stats.host_stats.receive_frame_count =
17462306a36Sopenharmony_ci		counters[EFCT_HW_HOST_STAT_RX_FRAME_COUNT].counter;
17562306a36Sopenharmony_ci}
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_cistatic void
17862306a36Sopenharmony_ciefct_xport_config_stats_timer(struct efct *efct);
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_cistatic void
18162306a36Sopenharmony_ciefct_xport_stats_timer_cb(struct timer_list *t)
18262306a36Sopenharmony_ci{
18362306a36Sopenharmony_ci	struct efct_xport *xport = from_timer(xport, t, stats_timer);
18462306a36Sopenharmony_ci	struct efct *efct = xport->efct;
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ci	efct_xport_config_stats_timer(efct);
18762306a36Sopenharmony_ci}
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_cistatic void
19062306a36Sopenharmony_ciefct_xport_config_stats_timer(struct efct *efct)
19162306a36Sopenharmony_ci{
19262306a36Sopenharmony_ci	u32 timeout = 3 * 1000;
19362306a36Sopenharmony_ci	struct efct_xport *xport = NULL;
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci	if (!efct) {
19662306a36Sopenharmony_ci		pr_err("%s: failed to locate EFCT device\n", __func__);
19762306a36Sopenharmony_ci		return;
19862306a36Sopenharmony_ci	}
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci	xport = efct->xport;
20162306a36Sopenharmony_ci	efct_hw_get_link_stats(&efct->hw, 0, 0, 0,
20262306a36Sopenharmony_ci			       efct_xport_async_link_stats_cb,
20362306a36Sopenharmony_ci			       &xport->fc_xport_stats);
20462306a36Sopenharmony_ci	efct_hw_get_host_stats(&efct->hw, 0, efct_xport_async_host_stats_cb,
20562306a36Sopenharmony_ci			       &xport->fc_xport_stats);
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ci	timer_setup(&xport->stats_timer,
20862306a36Sopenharmony_ci		    &efct_xport_stats_timer_cb, 0);
20962306a36Sopenharmony_ci	mod_timer(&xport->stats_timer,
21062306a36Sopenharmony_ci		  jiffies + msecs_to_jiffies(timeout));
21162306a36Sopenharmony_ci}
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ciint
21462306a36Sopenharmony_ciefct_xport_initialize(struct efct_xport *xport)
21562306a36Sopenharmony_ci{
21662306a36Sopenharmony_ci	struct efct *efct = xport->efct;
21762306a36Sopenharmony_ci	int rc = 0;
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ci	/* Initialize io lists */
22062306a36Sopenharmony_ci	spin_lock_init(&xport->io_pending_lock);
22162306a36Sopenharmony_ci	INIT_LIST_HEAD(&xport->io_pending_list);
22262306a36Sopenharmony_ci	atomic_set(&xport->io_active_count, 0);
22362306a36Sopenharmony_ci	atomic_set(&xport->io_pending_count, 0);
22462306a36Sopenharmony_ci	atomic_set(&xport->io_total_free, 0);
22562306a36Sopenharmony_ci	atomic_set(&xport->io_total_pending, 0);
22662306a36Sopenharmony_ci	atomic_set(&xport->io_alloc_failed_count, 0);
22762306a36Sopenharmony_ci	atomic_set(&xport->io_pending_recursing, 0);
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci	rc = efct_hw_init(&efct->hw);
23062306a36Sopenharmony_ci	if (rc) {
23162306a36Sopenharmony_ci		efc_log_err(efct, "efct_hw_init failure\n");
23262306a36Sopenharmony_ci		goto out;
23362306a36Sopenharmony_ci	}
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci	rc = efct_scsi_tgt_new_device(efct);
23662306a36Sopenharmony_ci	if (rc) {
23762306a36Sopenharmony_ci		efc_log_err(efct, "failed to initialize target\n");
23862306a36Sopenharmony_ci		goto hw_init_out;
23962306a36Sopenharmony_ci	}
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci	rc = efct_scsi_new_device(efct);
24262306a36Sopenharmony_ci	if (rc) {
24362306a36Sopenharmony_ci		efc_log_err(efct, "failed to initialize initiator\n");
24462306a36Sopenharmony_ci		goto tgt_dev_out;
24562306a36Sopenharmony_ci	}
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci	/* Get FC link and host statistics perodically*/
24862306a36Sopenharmony_ci	efct_xport_config_stats_timer(efct);
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci	efct_xport_init_debugfs(efct);
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci	return rc;
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_citgt_dev_out:
25562306a36Sopenharmony_ci	efct_scsi_tgt_del_device(efct);
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_cihw_init_out:
25862306a36Sopenharmony_ci	efct_hw_teardown(&efct->hw);
25962306a36Sopenharmony_ciout:
26062306a36Sopenharmony_ci	return rc;
26162306a36Sopenharmony_ci}
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ciint
26462306a36Sopenharmony_ciefct_xport_status(struct efct_xport *xport, enum efct_xport_status cmd,
26562306a36Sopenharmony_ci		  union efct_xport_stats_u *result)
26662306a36Sopenharmony_ci{
26762306a36Sopenharmony_ci	int rc = 0;
26862306a36Sopenharmony_ci	struct efct *efct = NULL;
26962306a36Sopenharmony_ci	union efct_xport_stats_u value;
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci	efct = xport->efct;
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci	switch (cmd) {
27462306a36Sopenharmony_ci	case EFCT_XPORT_CONFIG_PORT_STATUS:
27562306a36Sopenharmony_ci		if (xport->configured_link_state == 0) {
27662306a36Sopenharmony_ci			/*
27762306a36Sopenharmony_ci			 * Initial state is offline. configured_link_state is
27862306a36Sopenharmony_ci			 * set to online explicitly when port is brought online
27962306a36Sopenharmony_ci			 */
28062306a36Sopenharmony_ci			xport->configured_link_state = EFCT_XPORT_PORT_OFFLINE;
28162306a36Sopenharmony_ci		}
28262306a36Sopenharmony_ci		result->value = xport->configured_link_state;
28362306a36Sopenharmony_ci		break;
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci	case EFCT_XPORT_PORT_STATUS:
28662306a36Sopenharmony_ci		/* Determine port status based on link speed. */
28762306a36Sopenharmony_ci		value.value = efct_hw_get_link_speed(&efct->hw);
28862306a36Sopenharmony_ci		if (value.value == 0)
28962306a36Sopenharmony_ci			result->value = EFCT_XPORT_PORT_OFFLINE;
29062306a36Sopenharmony_ci		else
29162306a36Sopenharmony_ci			result->value = EFCT_XPORT_PORT_ONLINE;
29262306a36Sopenharmony_ci		break;
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci	case EFCT_XPORT_LINK_SPEED:
29562306a36Sopenharmony_ci		result->value = efct_hw_get_link_speed(&efct->hw);
29662306a36Sopenharmony_ci		break;
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_ci	case EFCT_XPORT_LINK_STATISTICS:
29962306a36Sopenharmony_ci		memcpy((void *)result, &efct->xport->fc_xport_stats,
30062306a36Sopenharmony_ci		       sizeof(union efct_xport_stats_u));
30162306a36Sopenharmony_ci		break;
30262306a36Sopenharmony_ci	case EFCT_XPORT_LINK_STAT_RESET: {
30362306a36Sopenharmony_ci		/* Create a completion to synchronize the stat reset process */
30462306a36Sopenharmony_ci		init_completion(&result->stats.done);
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci		/* First reset the link stats */
30762306a36Sopenharmony_ci		rc = efct_hw_get_link_stats(&efct->hw, 0, 1, 1,
30862306a36Sopenharmony_ci					    efct_xport_link_stats_cb, result);
30962306a36Sopenharmony_ci		if (rc)
31062306a36Sopenharmony_ci			break;
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci		/* Wait for completion to be signaled when the cmd completes */
31362306a36Sopenharmony_ci		if (wait_for_completion_interruptible(&result->stats.done)) {
31462306a36Sopenharmony_ci			/* Undefined failure */
31562306a36Sopenharmony_ci			efc_log_debug(efct, "sem wait failed\n");
31662306a36Sopenharmony_ci			rc = -EIO;
31762306a36Sopenharmony_ci			break;
31862306a36Sopenharmony_ci		}
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci		/* Next reset the host stats */
32162306a36Sopenharmony_ci		rc = efct_hw_get_host_stats(&efct->hw, 1,
32262306a36Sopenharmony_ci					    efct_xport_host_stats_cb, result);
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci		if (rc)
32562306a36Sopenharmony_ci			break;
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci		/* Wait for completion to be signaled when the cmd completes */
32862306a36Sopenharmony_ci		if (wait_for_completion_interruptible(&result->stats.done)) {
32962306a36Sopenharmony_ci			/* Undefined failure */
33062306a36Sopenharmony_ci			efc_log_debug(efct, "sem wait failed\n");
33162306a36Sopenharmony_ci			rc = -EIO;
33262306a36Sopenharmony_ci			break;
33362306a36Sopenharmony_ci		}
33462306a36Sopenharmony_ci		break;
33562306a36Sopenharmony_ci	}
33662306a36Sopenharmony_ci	default:
33762306a36Sopenharmony_ci		rc = -EIO;
33862306a36Sopenharmony_ci		break;
33962306a36Sopenharmony_ci	}
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci	return rc;
34262306a36Sopenharmony_ci}
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_cistatic int
34562306a36Sopenharmony_ciefct_get_link_supported_speeds(struct efct *efct)
34662306a36Sopenharmony_ci{
34762306a36Sopenharmony_ci	u32 supported_speeds = 0;
34862306a36Sopenharmony_ci	u32 link_module_type, i;
34962306a36Sopenharmony_ci	struct {
35062306a36Sopenharmony_ci		u32 lmt_speed;
35162306a36Sopenharmony_ci		u32 speed;
35262306a36Sopenharmony_ci	} supported_speed_list[] = {
35362306a36Sopenharmony_ci		{SLI4_LINK_MODULE_TYPE_1GB, FC_PORTSPEED_1GBIT},
35462306a36Sopenharmony_ci		{SLI4_LINK_MODULE_TYPE_2GB, FC_PORTSPEED_2GBIT},
35562306a36Sopenharmony_ci		{SLI4_LINK_MODULE_TYPE_4GB, FC_PORTSPEED_4GBIT},
35662306a36Sopenharmony_ci		{SLI4_LINK_MODULE_TYPE_8GB, FC_PORTSPEED_8GBIT},
35762306a36Sopenharmony_ci		{SLI4_LINK_MODULE_TYPE_16GB, FC_PORTSPEED_16GBIT},
35862306a36Sopenharmony_ci		{SLI4_LINK_MODULE_TYPE_32GB, FC_PORTSPEED_32GBIT},
35962306a36Sopenharmony_ci		{SLI4_LINK_MODULE_TYPE_64GB, FC_PORTSPEED_64GBIT},
36062306a36Sopenharmony_ci		{SLI4_LINK_MODULE_TYPE_128GB, FC_PORTSPEED_128GBIT},
36162306a36Sopenharmony_ci	};
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci	link_module_type = sli_get_lmt(&efct->hw.sli);
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_ci	/* populate link supported speeds */
36662306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(supported_speed_list); i++) {
36762306a36Sopenharmony_ci		if (link_module_type & supported_speed_list[i].lmt_speed)
36862306a36Sopenharmony_ci			supported_speeds |= supported_speed_list[i].speed;
36962306a36Sopenharmony_ci	}
37062306a36Sopenharmony_ci
37162306a36Sopenharmony_ci	return supported_speeds;
37262306a36Sopenharmony_ci}
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ciint
37562306a36Sopenharmony_ciefct_scsi_new_device(struct efct *efct)
37662306a36Sopenharmony_ci{
37762306a36Sopenharmony_ci	struct Scsi_Host *shost = NULL;
37862306a36Sopenharmony_ci	int error = 0;
37962306a36Sopenharmony_ci	struct efct_vport *vport = NULL;
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_ci	shost = scsi_host_alloc(&efct_template, sizeof(*vport));
38262306a36Sopenharmony_ci	if (!shost) {
38362306a36Sopenharmony_ci		efc_log_err(efct, "failed to allocate Scsi_Host struct\n");
38462306a36Sopenharmony_ci		return -ENOMEM;
38562306a36Sopenharmony_ci	}
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_ci	/* save shost to initiator-client context */
38862306a36Sopenharmony_ci	efct->shost = shost;
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ci	/* save efct information to shost LLD-specific space */
39162306a36Sopenharmony_ci	vport = (struct efct_vport *)shost->hostdata;
39262306a36Sopenharmony_ci	vport->efct = efct;
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci	/*
39562306a36Sopenharmony_ci	 * Set initial can_queue value to the max SCSI IOs. This is the maximum
39662306a36Sopenharmony_ci	 * global queue depth (as opposed to the per-LUN queue depth --
39762306a36Sopenharmony_ci	 * .cmd_per_lun This may need to be adjusted for I+T mode.
39862306a36Sopenharmony_ci	 */
39962306a36Sopenharmony_ci	shost->can_queue = efct->hw.config.n_io;
40062306a36Sopenharmony_ci	shost->max_cmd_len = 16; /* 16-byte CDBs */
40162306a36Sopenharmony_ci	shost->max_id = 0xffff;
40262306a36Sopenharmony_ci	shost->max_lun = 0xffffffff;
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci	/*
40562306a36Sopenharmony_ci	 * can only accept (from mid-layer) as many SGEs as we've
40662306a36Sopenharmony_ci	 * pre-registered
40762306a36Sopenharmony_ci	 */
40862306a36Sopenharmony_ci	shost->sg_tablesize = sli_get_max_sgl(&efct->hw.sli);
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_ci	/* attach FC Transport template to shost */
41162306a36Sopenharmony_ci	shost->transportt = efct_xport_fc_tt;
41262306a36Sopenharmony_ci	efc_log_debug(efct, "transport template=%p\n", efct_xport_fc_tt);
41362306a36Sopenharmony_ci
41462306a36Sopenharmony_ci	/* get pci_dev structure and add host to SCSI ML */
41562306a36Sopenharmony_ci	error = scsi_add_host_with_dma(shost, &efct->pci->dev,
41662306a36Sopenharmony_ci				       &efct->pci->dev);
41762306a36Sopenharmony_ci	if (error) {
41862306a36Sopenharmony_ci		efc_log_debug(efct, "failed scsi_add_host_with_dma\n");
41962306a36Sopenharmony_ci		return -EIO;
42062306a36Sopenharmony_ci	}
42162306a36Sopenharmony_ci
42262306a36Sopenharmony_ci	/* Set symbolic name for host port */
42362306a36Sopenharmony_ci	snprintf(fc_host_symbolic_name(shost),
42462306a36Sopenharmony_ci		 sizeof(fc_host_symbolic_name(shost)),
42562306a36Sopenharmony_ci		     "Emulex %s FV%s DV%s", efct->model,
42662306a36Sopenharmony_ci		     efct->hw.sli.fw_name[0], EFCT_DRIVER_VERSION);
42762306a36Sopenharmony_ci
42862306a36Sopenharmony_ci	/* Set host port supported classes */
42962306a36Sopenharmony_ci	fc_host_supported_classes(shost) = FC_COS_CLASS3;
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci	fc_host_supported_speeds(shost) = efct_get_link_supported_speeds(efct);
43262306a36Sopenharmony_ci
43362306a36Sopenharmony_ci	fc_host_node_name(shost) = efct_get_wwnn(&efct->hw);
43462306a36Sopenharmony_ci	fc_host_port_name(shost) = efct_get_wwpn(&efct->hw);
43562306a36Sopenharmony_ci	fc_host_max_npiv_vports(shost) = 128;
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_ci	return 0;
43862306a36Sopenharmony_ci}
43962306a36Sopenharmony_ci
44062306a36Sopenharmony_cistruct scsi_transport_template *
44162306a36Sopenharmony_ciefct_attach_fc_transport(void)
44262306a36Sopenharmony_ci{
44362306a36Sopenharmony_ci	struct scsi_transport_template *efct_fc_template = NULL;
44462306a36Sopenharmony_ci
44562306a36Sopenharmony_ci	efct_fc_template = fc_attach_transport(&efct_xport_functions);
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_ci	if (!efct_fc_template)
44862306a36Sopenharmony_ci		pr_err("failed to attach EFCT with fc transport\n");
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_ci	return efct_fc_template;
45162306a36Sopenharmony_ci}
45262306a36Sopenharmony_ci
45362306a36Sopenharmony_cistruct scsi_transport_template *
45462306a36Sopenharmony_ciefct_attach_vport_fc_transport(void)
45562306a36Sopenharmony_ci{
45662306a36Sopenharmony_ci	struct scsi_transport_template *efct_fc_template = NULL;
45762306a36Sopenharmony_ci
45862306a36Sopenharmony_ci	efct_fc_template = fc_attach_transport(&efct_vport_functions);
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci	if (!efct_fc_template)
46162306a36Sopenharmony_ci		pr_err("failed to attach EFCT with fc transport\n");
46262306a36Sopenharmony_ci
46362306a36Sopenharmony_ci	return efct_fc_template;
46462306a36Sopenharmony_ci}
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ciint
46762306a36Sopenharmony_ciefct_scsi_reg_fc_transport(void)
46862306a36Sopenharmony_ci{
46962306a36Sopenharmony_ci	/* attach to appropriate scsi_tranport_* module */
47062306a36Sopenharmony_ci	efct_xport_fc_tt = efct_attach_fc_transport();
47162306a36Sopenharmony_ci	if (!efct_xport_fc_tt) {
47262306a36Sopenharmony_ci		pr_err("%s: failed to attach to scsi_transport_*", __func__);
47362306a36Sopenharmony_ci		return -EIO;
47462306a36Sopenharmony_ci	}
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_ci	efct_vport_fc_tt = efct_attach_vport_fc_transport();
47762306a36Sopenharmony_ci	if (!efct_vport_fc_tt) {
47862306a36Sopenharmony_ci		pr_err("%s: failed to attach to scsi_transport_*", __func__);
47962306a36Sopenharmony_ci		efct_release_fc_transport(efct_xport_fc_tt);
48062306a36Sopenharmony_ci		efct_xport_fc_tt = NULL;
48162306a36Sopenharmony_ci		return -EIO;
48262306a36Sopenharmony_ci	}
48362306a36Sopenharmony_ci
48462306a36Sopenharmony_ci	return 0;
48562306a36Sopenharmony_ci}
48662306a36Sopenharmony_ci
48762306a36Sopenharmony_civoid
48862306a36Sopenharmony_ciefct_scsi_release_fc_transport(void)
48962306a36Sopenharmony_ci{
49062306a36Sopenharmony_ci	/* detach from scsi_transport_* */
49162306a36Sopenharmony_ci	efct_release_fc_transport(efct_xport_fc_tt);
49262306a36Sopenharmony_ci	efct_xport_fc_tt = NULL;
49362306a36Sopenharmony_ci	if (efct_vport_fc_tt)
49462306a36Sopenharmony_ci		efct_release_fc_transport(efct_vport_fc_tt);
49562306a36Sopenharmony_ci
49662306a36Sopenharmony_ci	efct_vport_fc_tt = NULL;
49762306a36Sopenharmony_ci}
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_civoid
50062306a36Sopenharmony_ciefct_xport_detach(struct efct_xport *xport)
50162306a36Sopenharmony_ci{
50262306a36Sopenharmony_ci	struct efct *efct = xport->efct;
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_ci	/* free resources associated with target-server and initiator-client */
50562306a36Sopenharmony_ci	efct_scsi_tgt_del_device(efct);
50662306a36Sopenharmony_ci
50762306a36Sopenharmony_ci	efct_scsi_del_device(efct);
50862306a36Sopenharmony_ci
50962306a36Sopenharmony_ci	/*Shutdown FC Statistics timer*/
51062306a36Sopenharmony_ci	if (timer_pending(&xport->stats_timer))
51162306a36Sopenharmony_ci		del_timer(&xport->stats_timer);
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_ci	efct_hw_teardown(&efct->hw);
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_ci	efct_xport_delete_debugfs(efct);
51662306a36Sopenharmony_ci}
51762306a36Sopenharmony_ci
51862306a36Sopenharmony_cistatic void
51962306a36Sopenharmony_ciefct_xport_domain_free_cb(struct efc *efc, void *arg)
52062306a36Sopenharmony_ci{
52162306a36Sopenharmony_ci	struct completion *done = arg;
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_ci	complete(done);
52462306a36Sopenharmony_ci}
52562306a36Sopenharmony_ci
52662306a36Sopenharmony_ciint
52762306a36Sopenharmony_ciefct_xport_control(struct efct_xport *xport, enum efct_xport_ctrl cmd, ...)
52862306a36Sopenharmony_ci{
52962306a36Sopenharmony_ci	u32 rc = 0;
53062306a36Sopenharmony_ci	struct efct *efct = NULL;
53162306a36Sopenharmony_ci	va_list argp;
53262306a36Sopenharmony_ci
53362306a36Sopenharmony_ci	efct = xport->efct;
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_ci	switch (cmd) {
53662306a36Sopenharmony_ci	case EFCT_XPORT_PORT_ONLINE: {
53762306a36Sopenharmony_ci		/* Bring the port on-line */
53862306a36Sopenharmony_ci		rc = efct_hw_port_control(&efct->hw, EFCT_HW_PORT_INIT, 0,
53962306a36Sopenharmony_ci					  NULL, NULL);
54062306a36Sopenharmony_ci		if (rc)
54162306a36Sopenharmony_ci			efc_log_err(efct,
54262306a36Sopenharmony_ci				    "%s: Can't init port\n", efct->desc);
54362306a36Sopenharmony_ci		else
54462306a36Sopenharmony_ci			xport->configured_link_state = cmd;
54562306a36Sopenharmony_ci		break;
54662306a36Sopenharmony_ci	}
54762306a36Sopenharmony_ci	case EFCT_XPORT_PORT_OFFLINE: {
54862306a36Sopenharmony_ci		if (efct_hw_port_control(&efct->hw, EFCT_HW_PORT_SHUTDOWN, 0,
54962306a36Sopenharmony_ci					 NULL, NULL))
55062306a36Sopenharmony_ci			efc_log_err(efct, "port shutdown failed\n");
55162306a36Sopenharmony_ci		else
55262306a36Sopenharmony_ci			xport->configured_link_state = cmd;
55362306a36Sopenharmony_ci		break;
55462306a36Sopenharmony_ci	}
55562306a36Sopenharmony_ci
55662306a36Sopenharmony_ci	case EFCT_XPORT_SHUTDOWN: {
55762306a36Sopenharmony_ci		struct completion done;
55862306a36Sopenharmony_ci		unsigned long timeout;
55962306a36Sopenharmony_ci
56062306a36Sopenharmony_ci		/* if a PHYSDEV reset was performed (e.g. hw dump), will affect
56162306a36Sopenharmony_ci		 * all PCI functions; orderly shutdown won't work,
56262306a36Sopenharmony_ci		 * just force free
56362306a36Sopenharmony_ci		 */
56462306a36Sopenharmony_ci		if (sli_reset_required(&efct->hw.sli)) {
56562306a36Sopenharmony_ci			struct efc_domain *domain = efct->efcport->domain;
56662306a36Sopenharmony_ci
56762306a36Sopenharmony_ci			if (domain)
56862306a36Sopenharmony_ci				efc_domain_cb(efct->efcport, EFC_HW_DOMAIN_LOST,
56962306a36Sopenharmony_ci					      domain);
57062306a36Sopenharmony_ci		} else {
57162306a36Sopenharmony_ci			efct_hw_port_control(&efct->hw, EFCT_HW_PORT_SHUTDOWN,
57262306a36Sopenharmony_ci					     0, NULL, NULL);
57362306a36Sopenharmony_ci		}
57462306a36Sopenharmony_ci
57562306a36Sopenharmony_ci		init_completion(&done);
57662306a36Sopenharmony_ci
57762306a36Sopenharmony_ci		efc_register_domain_free_cb(efct->efcport,
57862306a36Sopenharmony_ci					    efct_xport_domain_free_cb, &done);
57962306a36Sopenharmony_ci
58062306a36Sopenharmony_ci		efc_log_debug(efct, "Waiting %d seconds for domain shutdown\n",
58162306a36Sopenharmony_ci			      (EFC_SHUTDOWN_TIMEOUT_USEC / 1000000));
58262306a36Sopenharmony_ci
58362306a36Sopenharmony_ci		timeout = usecs_to_jiffies(EFC_SHUTDOWN_TIMEOUT_USEC);
58462306a36Sopenharmony_ci		if (!wait_for_completion_timeout(&done, timeout)) {
58562306a36Sopenharmony_ci			efc_log_err(efct, "Domain shutdown timed out!!\n");
58662306a36Sopenharmony_ci			WARN_ON(1);
58762306a36Sopenharmony_ci		}
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_ci		efc_register_domain_free_cb(efct->efcport, NULL, NULL);
59062306a36Sopenharmony_ci
59162306a36Sopenharmony_ci		/* Free up any saved virtual ports */
59262306a36Sopenharmony_ci		efc_vport_del_all(efct->efcport);
59362306a36Sopenharmony_ci		break;
59462306a36Sopenharmony_ci	}
59562306a36Sopenharmony_ci
59662306a36Sopenharmony_ci	/*
59762306a36Sopenharmony_ci	 * Set wwnn for the port. This will be used instead of the default
59862306a36Sopenharmony_ci	 * provided by FW.
59962306a36Sopenharmony_ci	 */
60062306a36Sopenharmony_ci	case EFCT_XPORT_WWNN_SET: {
60162306a36Sopenharmony_ci		u64 wwnn;
60262306a36Sopenharmony_ci
60362306a36Sopenharmony_ci		/* Retrieve arguments */
60462306a36Sopenharmony_ci		va_start(argp, cmd);
60562306a36Sopenharmony_ci		wwnn = va_arg(argp, uint64_t);
60662306a36Sopenharmony_ci		va_end(argp);
60762306a36Sopenharmony_ci
60862306a36Sopenharmony_ci		efc_log_debug(efct, " WWNN %016llx\n", wwnn);
60962306a36Sopenharmony_ci		xport->req_wwnn = wwnn;
61062306a36Sopenharmony_ci
61162306a36Sopenharmony_ci		break;
61262306a36Sopenharmony_ci	}
61362306a36Sopenharmony_ci	/*
61462306a36Sopenharmony_ci	 * Set wwpn for the port. This will be used instead of the default
61562306a36Sopenharmony_ci	 * provided by FW.
61662306a36Sopenharmony_ci	 */
61762306a36Sopenharmony_ci	case EFCT_XPORT_WWPN_SET: {
61862306a36Sopenharmony_ci		u64 wwpn;
61962306a36Sopenharmony_ci
62062306a36Sopenharmony_ci		/* Retrieve arguments */
62162306a36Sopenharmony_ci		va_start(argp, cmd);
62262306a36Sopenharmony_ci		wwpn = va_arg(argp, uint64_t);
62362306a36Sopenharmony_ci		va_end(argp);
62462306a36Sopenharmony_ci
62562306a36Sopenharmony_ci		efc_log_debug(efct, " WWPN %016llx\n", wwpn);
62662306a36Sopenharmony_ci		xport->req_wwpn = wwpn;
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_ci		break;
62962306a36Sopenharmony_ci	}
63062306a36Sopenharmony_ci
63162306a36Sopenharmony_ci	default:
63262306a36Sopenharmony_ci		break;
63362306a36Sopenharmony_ci	}
63462306a36Sopenharmony_ci	return rc;
63562306a36Sopenharmony_ci}
63662306a36Sopenharmony_ci
63762306a36Sopenharmony_civoid
63862306a36Sopenharmony_ciefct_xport_free(struct efct_xport *xport)
63962306a36Sopenharmony_ci{
64062306a36Sopenharmony_ci	if (xport) {
64162306a36Sopenharmony_ci		efct_io_pool_free(xport->io_pool);
64262306a36Sopenharmony_ci
64362306a36Sopenharmony_ci		kfree(xport);
64462306a36Sopenharmony_ci	}
64562306a36Sopenharmony_ci}
64662306a36Sopenharmony_ci
64762306a36Sopenharmony_civoid
64862306a36Sopenharmony_ciefct_release_fc_transport(struct scsi_transport_template *transport_template)
64962306a36Sopenharmony_ci{
65062306a36Sopenharmony_ci	if (transport_template)
65162306a36Sopenharmony_ci		pr_err("releasing transport layer\n");
65262306a36Sopenharmony_ci
65362306a36Sopenharmony_ci	/* Releasing FC transport */
65462306a36Sopenharmony_ci	fc_release_transport(transport_template);
65562306a36Sopenharmony_ci}
65662306a36Sopenharmony_ci
65762306a36Sopenharmony_cistatic void
65862306a36Sopenharmony_ciefct_xport_remove_host(struct Scsi_Host *shost)
65962306a36Sopenharmony_ci{
66062306a36Sopenharmony_ci	fc_remove_host(shost);
66162306a36Sopenharmony_ci}
66262306a36Sopenharmony_ci
66362306a36Sopenharmony_civoid
66462306a36Sopenharmony_ciefct_scsi_del_device(struct efct *efct)
66562306a36Sopenharmony_ci{
66662306a36Sopenharmony_ci	if (!efct->shost)
66762306a36Sopenharmony_ci		return;
66862306a36Sopenharmony_ci
66962306a36Sopenharmony_ci	efc_log_debug(efct, "Unregistering with Transport Layer\n");
67062306a36Sopenharmony_ci	efct_xport_remove_host(efct->shost);
67162306a36Sopenharmony_ci	efc_log_debug(efct, "Unregistering with SCSI Midlayer\n");
67262306a36Sopenharmony_ci	scsi_remove_host(efct->shost);
67362306a36Sopenharmony_ci	scsi_host_put(efct->shost);
67462306a36Sopenharmony_ci	efct->shost = NULL;
67562306a36Sopenharmony_ci}
67662306a36Sopenharmony_ci
67762306a36Sopenharmony_cistatic void
67862306a36Sopenharmony_ciefct_get_host_port_id(struct Scsi_Host *shost)
67962306a36Sopenharmony_ci{
68062306a36Sopenharmony_ci	struct efct_vport *vport = (struct efct_vport *)shost->hostdata;
68162306a36Sopenharmony_ci	struct efct *efct = vport->efct;
68262306a36Sopenharmony_ci	struct efc *efc = efct->efcport;
68362306a36Sopenharmony_ci	struct efc_nport *nport;
68462306a36Sopenharmony_ci
68562306a36Sopenharmony_ci	if (efc->domain && efc->domain->nport) {
68662306a36Sopenharmony_ci		nport = efc->domain->nport;
68762306a36Sopenharmony_ci		fc_host_port_id(shost) = nport->fc_id;
68862306a36Sopenharmony_ci	}
68962306a36Sopenharmony_ci}
69062306a36Sopenharmony_ci
69162306a36Sopenharmony_cistatic void
69262306a36Sopenharmony_ciefct_get_host_port_type(struct Scsi_Host *shost)
69362306a36Sopenharmony_ci{
69462306a36Sopenharmony_ci	struct efct_vport *vport = (struct efct_vport *)shost->hostdata;
69562306a36Sopenharmony_ci	struct efct *efct = vport->efct;
69662306a36Sopenharmony_ci	struct efc *efc = efct->efcport;
69762306a36Sopenharmony_ci	int type = FC_PORTTYPE_UNKNOWN;
69862306a36Sopenharmony_ci
69962306a36Sopenharmony_ci	if (efc->domain && efc->domain->nport) {
70062306a36Sopenharmony_ci		if (efc->domain->is_loop) {
70162306a36Sopenharmony_ci			type = FC_PORTTYPE_LPORT;
70262306a36Sopenharmony_ci		} else {
70362306a36Sopenharmony_ci			struct efc_nport *nport = efc->domain->nport;
70462306a36Sopenharmony_ci
70562306a36Sopenharmony_ci			if (nport->is_vport)
70662306a36Sopenharmony_ci				type = FC_PORTTYPE_NPIV;
70762306a36Sopenharmony_ci			else if (nport->topology == EFC_NPORT_TOPO_P2P)
70862306a36Sopenharmony_ci				type = FC_PORTTYPE_PTP;
70962306a36Sopenharmony_ci			else if (nport->topology == EFC_NPORT_TOPO_UNKNOWN)
71062306a36Sopenharmony_ci				type = FC_PORTTYPE_UNKNOWN;
71162306a36Sopenharmony_ci			else
71262306a36Sopenharmony_ci				type = FC_PORTTYPE_NPORT;
71362306a36Sopenharmony_ci		}
71462306a36Sopenharmony_ci	}
71562306a36Sopenharmony_ci	fc_host_port_type(shost) = type;
71662306a36Sopenharmony_ci}
71762306a36Sopenharmony_ci
71862306a36Sopenharmony_cistatic void
71962306a36Sopenharmony_ciefct_get_host_vport_type(struct Scsi_Host *shost)
72062306a36Sopenharmony_ci{
72162306a36Sopenharmony_ci	fc_host_port_type(shost) = FC_PORTTYPE_NPIV;
72262306a36Sopenharmony_ci}
72362306a36Sopenharmony_ci
72462306a36Sopenharmony_cistatic void
72562306a36Sopenharmony_ciefct_get_host_port_state(struct Scsi_Host *shost)
72662306a36Sopenharmony_ci{
72762306a36Sopenharmony_ci	struct efct_vport *vport = (struct efct_vport *)shost->hostdata;
72862306a36Sopenharmony_ci	struct efct *efct = vport->efct;
72962306a36Sopenharmony_ci	union efct_xport_stats_u status;
73062306a36Sopenharmony_ci	int rc;
73162306a36Sopenharmony_ci
73262306a36Sopenharmony_ci	rc = efct_xport_status(efct->xport, EFCT_XPORT_PORT_STATUS, &status);
73362306a36Sopenharmony_ci	if ((!rc) && (status.value == EFCT_XPORT_PORT_ONLINE))
73462306a36Sopenharmony_ci		fc_host_port_state(shost) = FC_PORTSTATE_ONLINE;
73562306a36Sopenharmony_ci	else
73662306a36Sopenharmony_ci		fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE;
73762306a36Sopenharmony_ci}
73862306a36Sopenharmony_ci
73962306a36Sopenharmony_cistatic void
74062306a36Sopenharmony_ciefct_get_host_speed(struct Scsi_Host *shost)
74162306a36Sopenharmony_ci{
74262306a36Sopenharmony_ci	struct efct_vport *vport = (struct efct_vport *)shost->hostdata;
74362306a36Sopenharmony_ci	struct efct *efct = vport->efct;
74462306a36Sopenharmony_ci	struct efc *efc = efct->efcport;
74562306a36Sopenharmony_ci	union efct_xport_stats_u speed;
74662306a36Sopenharmony_ci	u32 fc_speed = FC_PORTSPEED_UNKNOWN;
74762306a36Sopenharmony_ci	int rc;
74862306a36Sopenharmony_ci
74962306a36Sopenharmony_ci	if (!efc->domain || !efc->domain->nport) {
75062306a36Sopenharmony_ci		fc_host_speed(shost) = fc_speed;
75162306a36Sopenharmony_ci		return;
75262306a36Sopenharmony_ci	}
75362306a36Sopenharmony_ci
75462306a36Sopenharmony_ci	rc = efct_xport_status(efct->xport, EFCT_XPORT_LINK_SPEED, &speed);
75562306a36Sopenharmony_ci	if (!rc) {
75662306a36Sopenharmony_ci		switch (speed.value) {
75762306a36Sopenharmony_ci		case 1000:
75862306a36Sopenharmony_ci			fc_speed = FC_PORTSPEED_1GBIT;
75962306a36Sopenharmony_ci			break;
76062306a36Sopenharmony_ci		case 2000:
76162306a36Sopenharmony_ci			fc_speed = FC_PORTSPEED_2GBIT;
76262306a36Sopenharmony_ci			break;
76362306a36Sopenharmony_ci		case 4000:
76462306a36Sopenharmony_ci			fc_speed = FC_PORTSPEED_4GBIT;
76562306a36Sopenharmony_ci			break;
76662306a36Sopenharmony_ci		case 8000:
76762306a36Sopenharmony_ci			fc_speed = FC_PORTSPEED_8GBIT;
76862306a36Sopenharmony_ci			break;
76962306a36Sopenharmony_ci		case 10000:
77062306a36Sopenharmony_ci			fc_speed = FC_PORTSPEED_10GBIT;
77162306a36Sopenharmony_ci			break;
77262306a36Sopenharmony_ci		case 16000:
77362306a36Sopenharmony_ci			fc_speed = FC_PORTSPEED_16GBIT;
77462306a36Sopenharmony_ci			break;
77562306a36Sopenharmony_ci		case 32000:
77662306a36Sopenharmony_ci			fc_speed = FC_PORTSPEED_32GBIT;
77762306a36Sopenharmony_ci			break;
77862306a36Sopenharmony_ci		case 64000:
77962306a36Sopenharmony_ci			fc_speed = FC_PORTSPEED_64GBIT;
78062306a36Sopenharmony_ci			break;
78162306a36Sopenharmony_ci		case 128000:
78262306a36Sopenharmony_ci			fc_speed = FC_PORTSPEED_128GBIT;
78362306a36Sopenharmony_ci			break;
78462306a36Sopenharmony_ci		}
78562306a36Sopenharmony_ci	}
78662306a36Sopenharmony_ci
78762306a36Sopenharmony_ci	fc_host_speed(shost) = fc_speed;
78862306a36Sopenharmony_ci}
78962306a36Sopenharmony_ci
79062306a36Sopenharmony_cistatic void
79162306a36Sopenharmony_ciefct_get_host_fabric_name(struct Scsi_Host *shost)
79262306a36Sopenharmony_ci{
79362306a36Sopenharmony_ci	struct efct_vport *vport = (struct efct_vport *)shost->hostdata;
79462306a36Sopenharmony_ci	struct efct *efct = vport->efct;
79562306a36Sopenharmony_ci	struct efc *efc = efct->efcport;
79662306a36Sopenharmony_ci
79762306a36Sopenharmony_ci	if (efc->domain) {
79862306a36Sopenharmony_ci		struct fc_els_flogi  *sp =
79962306a36Sopenharmony_ci			(struct fc_els_flogi  *)
80062306a36Sopenharmony_ci				efc->domain->flogi_service_params;
80162306a36Sopenharmony_ci
80262306a36Sopenharmony_ci		fc_host_fabric_name(shost) = be64_to_cpu(sp->fl_wwnn);
80362306a36Sopenharmony_ci	}
80462306a36Sopenharmony_ci}
80562306a36Sopenharmony_ci
80662306a36Sopenharmony_cistatic struct fc_host_statistics *
80762306a36Sopenharmony_ciefct_get_stats(struct Scsi_Host *shost)
80862306a36Sopenharmony_ci{
80962306a36Sopenharmony_ci	struct efct_vport *vport = (struct efct_vport *)shost->hostdata;
81062306a36Sopenharmony_ci	struct efct *efct = vport->efct;
81162306a36Sopenharmony_ci	union efct_xport_stats_u stats;
81262306a36Sopenharmony_ci	struct efct_xport *xport = efct->xport;
81362306a36Sopenharmony_ci	int rc = 0;
81462306a36Sopenharmony_ci
81562306a36Sopenharmony_ci	rc = efct_xport_status(xport, EFCT_XPORT_LINK_STATISTICS, &stats);
81662306a36Sopenharmony_ci	if (rc) {
81762306a36Sopenharmony_ci		pr_err("efct_xport_status returned non 0 - %d\n", rc);
81862306a36Sopenharmony_ci		return NULL;
81962306a36Sopenharmony_ci	}
82062306a36Sopenharmony_ci
82162306a36Sopenharmony_ci	vport->fc_host_stats.loss_of_sync_count =
82262306a36Sopenharmony_ci		stats.stats.link_stats.loss_of_sync_error_count;
82362306a36Sopenharmony_ci	vport->fc_host_stats.link_failure_count =
82462306a36Sopenharmony_ci		stats.stats.link_stats.link_failure_error_count;
82562306a36Sopenharmony_ci	vport->fc_host_stats.prim_seq_protocol_err_count =
82662306a36Sopenharmony_ci		stats.stats.link_stats.primitive_sequence_error_count;
82762306a36Sopenharmony_ci	vport->fc_host_stats.invalid_tx_word_count =
82862306a36Sopenharmony_ci		stats.stats.link_stats.invalid_transmission_word_error_count;
82962306a36Sopenharmony_ci	vport->fc_host_stats.invalid_crc_count =
83062306a36Sopenharmony_ci		stats.stats.link_stats.crc_error_count;
83162306a36Sopenharmony_ci	/* mbox returns kbyte count so we need to convert to words */
83262306a36Sopenharmony_ci	vport->fc_host_stats.tx_words =
83362306a36Sopenharmony_ci		stats.stats.host_stats.transmit_kbyte_count * 256;
83462306a36Sopenharmony_ci	/* mbox returns kbyte count so we need to convert to words */
83562306a36Sopenharmony_ci	vport->fc_host_stats.rx_words =
83662306a36Sopenharmony_ci		stats.stats.host_stats.receive_kbyte_count * 256;
83762306a36Sopenharmony_ci	vport->fc_host_stats.tx_frames =
83862306a36Sopenharmony_ci		stats.stats.host_stats.transmit_frame_count;
83962306a36Sopenharmony_ci	vport->fc_host_stats.rx_frames =
84062306a36Sopenharmony_ci		stats.stats.host_stats.receive_frame_count;
84162306a36Sopenharmony_ci
84262306a36Sopenharmony_ci	vport->fc_host_stats.fcp_input_requests =
84362306a36Sopenharmony_ci			xport->fcp_stats.input_requests;
84462306a36Sopenharmony_ci	vport->fc_host_stats.fcp_output_requests =
84562306a36Sopenharmony_ci			xport->fcp_stats.output_requests;
84662306a36Sopenharmony_ci	vport->fc_host_stats.fcp_output_megabytes =
84762306a36Sopenharmony_ci			xport->fcp_stats.output_bytes >> 20;
84862306a36Sopenharmony_ci	vport->fc_host_stats.fcp_input_megabytes =
84962306a36Sopenharmony_ci			xport->fcp_stats.input_bytes >> 20;
85062306a36Sopenharmony_ci	vport->fc_host_stats.fcp_control_requests =
85162306a36Sopenharmony_ci			xport->fcp_stats.control_requests;
85262306a36Sopenharmony_ci
85362306a36Sopenharmony_ci	return &vport->fc_host_stats;
85462306a36Sopenharmony_ci}
85562306a36Sopenharmony_ci
85662306a36Sopenharmony_cistatic void
85762306a36Sopenharmony_ciefct_reset_stats(struct Scsi_Host *shost)
85862306a36Sopenharmony_ci{
85962306a36Sopenharmony_ci	struct efct_vport *vport = (struct efct_vport *)shost->hostdata;
86062306a36Sopenharmony_ci	struct efct *efct = vport->efct;
86162306a36Sopenharmony_ci	/* argument has no purpose for this action */
86262306a36Sopenharmony_ci	union efct_xport_stats_u dummy;
86362306a36Sopenharmony_ci	int rc;
86462306a36Sopenharmony_ci
86562306a36Sopenharmony_ci	rc = efct_xport_status(efct->xport, EFCT_XPORT_LINK_STAT_RESET, &dummy);
86662306a36Sopenharmony_ci	if (rc)
86762306a36Sopenharmony_ci		pr_err("efct_xport_status returned non 0 - %d\n", rc);
86862306a36Sopenharmony_ci}
86962306a36Sopenharmony_ci
87062306a36Sopenharmony_cistatic int
87162306a36Sopenharmony_ciefct_issue_lip(struct Scsi_Host *shost)
87262306a36Sopenharmony_ci{
87362306a36Sopenharmony_ci	struct efct_vport *vport =
87462306a36Sopenharmony_ci			shost ? (struct efct_vport *)shost->hostdata : NULL;
87562306a36Sopenharmony_ci	struct efct *efct = vport ? vport->efct : NULL;
87662306a36Sopenharmony_ci
87762306a36Sopenharmony_ci	if (!shost || !vport || !efct) {
87862306a36Sopenharmony_ci		pr_err("%s: shost=%p vport=%p efct=%p\n", __func__,
87962306a36Sopenharmony_ci		       shost, vport, efct);
88062306a36Sopenharmony_ci		return -EPERM;
88162306a36Sopenharmony_ci	}
88262306a36Sopenharmony_ci
88362306a36Sopenharmony_ci	/*
88462306a36Sopenharmony_ci	 * Bring the link down gracefully then re-init the link.
88562306a36Sopenharmony_ci	 * The firmware will re-initialize the Fibre Channel interface as
88662306a36Sopenharmony_ci	 * required. It does not issue a LIP.
88762306a36Sopenharmony_ci	 */
88862306a36Sopenharmony_ci
88962306a36Sopenharmony_ci	if (efct_xport_control(efct->xport, EFCT_XPORT_PORT_OFFLINE))
89062306a36Sopenharmony_ci		efc_log_debug(efct, "EFCT_XPORT_PORT_OFFLINE failed\n");
89162306a36Sopenharmony_ci
89262306a36Sopenharmony_ci	if (efct_xport_control(efct->xport, EFCT_XPORT_PORT_ONLINE))
89362306a36Sopenharmony_ci		efc_log_debug(efct, "EFCT_XPORT_PORT_ONLINE failed\n");
89462306a36Sopenharmony_ci
89562306a36Sopenharmony_ci	return 0;
89662306a36Sopenharmony_ci}
89762306a36Sopenharmony_ci
89862306a36Sopenharmony_cistruct efct_vport *
89962306a36Sopenharmony_ciefct_scsi_new_vport(struct efct *efct, struct device *dev)
90062306a36Sopenharmony_ci{
90162306a36Sopenharmony_ci	struct Scsi_Host *shost = NULL;
90262306a36Sopenharmony_ci	int error = 0;
90362306a36Sopenharmony_ci	struct efct_vport *vport = NULL;
90462306a36Sopenharmony_ci
90562306a36Sopenharmony_ci	shost = scsi_host_alloc(&efct_template, sizeof(*vport));
90662306a36Sopenharmony_ci	if (!shost) {
90762306a36Sopenharmony_ci		efc_log_err(efct, "failed to allocate Scsi_Host struct\n");
90862306a36Sopenharmony_ci		return NULL;
90962306a36Sopenharmony_ci	}
91062306a36Sopenharmony_ci
91162306a36Sopenharmony_ci	/* save efct information to shost LLD-specific space */
91262306a36Sopenharmony_ci	vport = (struct efct_vport *)shost->hostdata;
91362306a36Sopenharmony_ci	vport->efct = efct;
91462306a36Sopenharmony_ci	vport->is_vport = true;
91562306a36Sopenharmony_ci
91662306a36Sopenharmony_ci	shost->can_queue = efct->hw.config.n_io;
91762306a36Sopenharmony_ci	shost->max_cmd_len = 16; /* 16-byte CDBs */
91862306a36Sopenharmony_ci	shost->max_id = 0xffff;
91962306a36Sopenharmony_ci	shost->max_lun = 0xffffffff;
92062306a36Sopenharmony_ci
92162306a36Sopenharmony_ci	/* can only accept (from mid-layer) as many SGEs as we've pre-regited*/
92262306a36Sopenharmony_ci	shost->sg_tablesize = sli_get_max_sgl(&efct->hw.sli);
92362306a36Sopenharmony_ci
92462306a36Sopenharmony_ci	/* attach FC Transport template to shost */
92562306a36Sopenharmony_ci	shost->transportt = efct_vport_fc_tt;
92662306a36Sopenharmony_ci	efc_log_debug(efct, "vport transport template=%p\n",
92762306a36Sopenharmony_ci		      efct_vport_fc_tt);
92862306a36Sopenharmony_ci
92962306a36Sopenharmony_ci	/* get pci_dev structure and add host to SCSI ML */
93062306a36Sopenharmony_ci	error = scsi_add_host_with_dma(shost, dev, &efct->pci->dev);
93162306a36Sopenharmony_ci	if (error) {
93262306a36Sopenharmony_ci		efc_log_debug(efct, "failed scsi_add_host_with_dma\n");
93362306a36Sopenharmony_ci		return NULL;
93462306a36Sopenharmony_ci	}
93562306a36Sopenharmony_ci
93662306a36Sopenharmony_ci	/* Set symbolic name for host port */
93762306a36Sopenharmony_ci	snprintf(fc_host_symbolic_name(shost),
93862306a36Sopenharmony_ci		 sizeof(fc_host_symbolic_name(shost)),
93962306a36Sopenharmony_ci		 "Emulex %s FV%s DV%s", efct->model, efct->hw.sli.fw_name[0],
94062306a36Sopenharmony_ci		 EFCT_DRIVER_VERSION);
94162306a36Sopenharmony_ci
94262306a36Sopenharmony_ci	/* Set host port supported classes */
94362306a36Sopenharmony_ci	fc_host_supported_classes(shost) = FC_COS_CLASS3;
94462306a36Sopenharmony_ci
94562306a36Sopenharmony_ci	fc_host_supported_speeds(shost) = efct_get_link_supported_speeds(efct);
94662306a36Sopenharmony_ci	vport->shost = shost;
94762306a36Sopenharmony_ci
94862306a36Sopenharmony_ci	return vport;
94962306a36Sopenharmony_ci}
95062306a36Sopenharmony_ci
95162306a36Sopenharmony_ciint efct_scsi_del_vport(struct efct *efct, struct Scsi_Host *shost)
95262306a36Sopenharmony_ci{
95362306a36Sopenharmony_ci	if (shost) {
95462306a36Sopenharmony_ci		efc_log_debug(efct,
95562306a36Sopenharmony_ci			      "Unregistering vport with Transport Layer\n");
95662306a36Sopenharmony_ci		efct_xport_remove_host(shost);
95762306a36Sopenharmony_ci		efc_log_debug(efct, "Unregistering vport with SCSI Midlayer\n");
95862306a36Sopenharmony_ci		scsi_remove_host(shost);
95962306a36Sopenharmony_ci		scsi_host_put(shost);
96062306a36Sopenharmony_ci		return 0;
96162306a36Sopenharmony_ci	}
96262306a36Sopenharmony_ci	return -EIO;
96362306a36Sopenharmony_ci}
96462306a36Sopenharmony_ci
96562306a36Sopenharmony_cistatic int
96662306a36Sopenharmony_ciefct_vport_create(struct fc_vport *fc_vport, bool disable)
96762306a36Sopenharmony_ci{
96862306a36Sopenharmony_ci	struct Scsi_Host *shost = fc_vport ? fc_vport->shost : NULL;
96962306a36Sopenharmony_ci	struct efct_vport *pport = shost ?
97062306a36Sopenharmony_ci					(struct efct_vport *)shost->hostdata :
97162306a36Sopenharmony_ci					NULL;
97262306a36Sopenharmony_ci	struct efct *efct = pport ? pport->efct : NULL;
97362306a36Sopenharmony_ci	struct efct_vport *vport = NULL;
97462306a36Sopenharmony_ci
97562306a36Sopenharmony_ci	if (!fc_vport || !shost || !efct)
97662306a36Sopenharmony_ci		goto fail;
97762306a36Sopenharmony_ci
97862306a36Sopenharmony_ci	vport = efct_scsi_new_vport(efct, &fc_vport->dev);
97962306a36Sopenharmony_ci	if (!vport) {
98062306a36Sopenharmony_ci		efc_log_err(efct, "failed to create vport\n");
98162306a36Sopenharmony_ci		goto fail;
98262306a36Sopenharmony_ci	}
98362306a36Sopenharmony_ci
98462306a36Sopenharmony_ci	vport->fc_vport = fc_vport;
98562306a36Sopenharmony_ci	vport->npiv_wwpn = fc_vport->port_name;
98662306a36Sopenharmony_ci	vport->npiv_wwnn = fc_vport->node_name;
98762306a36Sopenharmony_ci	fc_host_node_name(vport->shost) = vport->npiv_wwnn;
98862306a36Sopenharmony_ci	fc_host_port_name(vport->shost) = vport->npiv_wwpn;
98962306a36Sopenharmony_ci	*(struct efct_vport **)fc_vport->dd_data = vport;
99062306a36Sopenharmony_ci
99162306a36Sopenharmony_ci	return 0;
99262306a36Sopenharmony_ci
99362306a36Sopenharmony_cifail:
99462306a36Sopenharmony_ci	return -EIO;
99562306a36Sopenharmony_ci}
99662306a36Sopenharmony_ci
99762306a36Sopenharmony_cistatic int
99862306a36Sopenharmony_ciefct_vport_delete(struct fc_vport *fc_vport)
99962306a36Sopenharmony_ci{
100062306a36Sopenharmony_ci	struct efct_vport *vport = *(struct efct_vport **)fc_vport->dd_data;
100162306a36Sopenharmony_ci	struct Scsi_Host *shost = vport ? vport->shost : NULL;
100262306a36Sopenharmony_ci	struct efct *efct = vport ? vport->efct : NULL;
100362306a36Sopenharmony_ci	int rc;
100462306a36Sopenharmony_ci
100562306a36Sopenharmony_ci	rc = efct_scsi_del_vport(efct, shost);
100662306a36Sopenharmony_ci
100762306a36Sopenharmony_ci	if (rc)
100862306a36Sopenharmony_ci		pr_err("%s: vport delete failed\n", __func__);
100962306a36Sopenharmony_ci
101062306a36Sopenharmony_ci	return rc;
101162306a36Sopenharmony_ci}
101262306a36Sopenharmony_ci
101362306a36Sopenharmony_cistatic int
101462306a36Sopenharmony_ciefct_vport_disable(struct fc_vport *fc_vport, bool disable)
101562306a36Sopenharmony_ci{
101662306a36Sopenharmony_ci	return 0;
101762306a36Sopenharmony_ci}
101862306a36Sopenharmony_ci
101962306a36Sopenharmony_cistatic struct fc_function_template efct_xport_functions = {
102062306a36Sopenharmony_ci	.get_host_port_id = efct_get_host_port_id,
102162306a36Sopenharmony_ci	.get_host_port_type = efct_get_host_port_type,
102262306a36Sopenharmony_ci	.get_host_port_state = efct_get_host_port_state,
102362306a36Sopenharmony_ci	.get_host_speed = efct_get_host_speed,
102462306a36Sopenharmony_ci	.get_host_fabric_name = efct_get_host_fabric_name,
102562306a36Sopenharmony_ci
102662306a36Sopenharmony_ci	.get_fc_host_stats = efct_get_stats,
102762306a36Sopenharmony_ci	.reset_fc_host_stats = efct_reset_stats,
102862306a36Sopenharmony_ci
102962306a36Sopenharmony_ci	.issue_fc_host_lip = efct_issue_lip,
103062306a36Sopenharmony_ci
103162306a36Sopenharmony_ci	.vport_disable = efct_vport_disable,
103262306a36Sopenharmony_ci
103362306a36Sopenharmony_ci	/* allocation lengths for host-specific data */
103462306a36Sopenharmony_ci	.dd_fcrport_size = sizeof(struct efct_rport_data),
103562306a36Sopenharmony_ci	.dd_fcvport_size = 128, /* should be sizeof(...) */
103662306a36Sopenharmony_ci
103762306a36Sopenharmony_ci	/* remote port fixed attributes */
103862306a36Sopenharmony_ci	.show_rport_maxframe_size = 1,
103962306a36Sopenharmony_ci	.show_rport_supported_classes = 1,
104062306a36Sopenharmony_ci	.show_rport_dev_loss_tmo = 1,
104162306a36Sopenharmony_ci
104262306a36Sopenharmony_ci	/* target dynamic attributes */
104362306a36Sopenharmony_ci	.show_starget_node_name = 1,
104462306a36Sopenharmony_ci	.show_starget_port_name = 1,
104562306a36Sopenharmony_ci	.show_starget_port_id = 1,
104662306a36Sopenharmony_ci
104762306a36Sopenharmony_ci	/* host fixed attributes */
104862306a36Sopenharmony_ci	.show_host_node_name = 1,
104962306a36Sopenharmony_ci	.show_host_port_name = 1,
105062306a36Sopenharmony_ci	.show_host_supported_classes = 1,
105162306a36Sopenharmony_ci	.show_host_supported_fc4s = 1,
105262306a36Sopenharmony_ci	.show_host_supported_speeds = 1,
105362306a36Sopenharmony_ci	.show_host_maxframe_size = 1,
105462306a36Sopenharmony_ci
105562306a36Sopenharmony_ci	/* host dynamic attributes */
105662306a36Sopenharmony_ci	.show_host_port_id = 1,
105762306a36Sopenharmony_ci	.show_host_port_type = 1,
105862306a36Sopenharmony_ci	.show_host_port_state = 1,
105962306a36Sopenharmony_ci	/* active_fc4s is shown but doesn't change (thus no get function) */
106062306a36Sopenharmony_ci	.show_host_active_fc4s = 1,
106162306a36Sopenharmony_ci	.show_host_speed = 1,
106262306a36Sopenharmony_ci	.show_host_fabric_name = 1,
106362306a36Sopenharmony_ci	.show_host_symbolic_name = 1,
106462306a36Sopenharmony_ci	.vport_create = efct_vport_create,
106562306a36Sopenharmony_ci	.vport_delete = efct_vport_delete,
106662306a36Sopenharmony_ci};
106762306a36Sopenharmony_ci
106862306a36Sopenharmony_cistatic struct fc_function_template efct_vport_functions = {
106962306a36Sopenharmony_ci	.get_host_port_id = efct_get_host_port_id,
107062306a36Sopenharmony_ci	.get_host_port_type = efct_get_host_vport_type,
107162306a36Sopenharmony_ci	.get_host_port_state = efct_get_host_port_state,
107262306a36Sopenharmony_ci	.get_host_speed = efct_get_host_speed,
107362306a36Sopenharmony_ci	.get_host_fabric_name = efct_get_host_fabric_name,
107462306a36Sopenharmony_ci
107562306a36Sopenharmony_ci	.get_fc_host_stats = efct_get_stats,
107662306a36Sopenharmony_ci	.reset_fc_host_stats = efct_reset_stats,
107762306a36Sopenharmony_ci
107862306a36Sopenharmony_ci	.issue_fc_host_lip = efct_issue_lip,
107962306a36Sopenharmony_ci
108062306a36Sopenharmony_ci	/* allocation lengths for host-specific data */
108162306a36Sopenharmony_ci	.dd_fcrport_size = sizeof(struct efct_rport_data),
108262306a36Sopenharmony_ci	.dd_fcvport_size = 128, /* should be sizeof(...) */
108362306a36Sopenharmony_ci
108462306a36Sopenharmony_ci	/* remote port fixed attributes */
108562306a36Sopenharmony_ci	.show_rport_maxframe_size = 1,
108662306a36Sopenharmony_ci	.show_rport_supported_classes = 1,
108762306a36Sopenharmony_ci	.show_rport_dev_loss_tmo = 1,
108862306a36Sopenharmony_ci
108962306a36Sopenharmony_ci	/* target dynamic attributes */
109062306a36Sopenharmony_ci	.show_starget_node_name = 1,
109162306a36Sopenharmony_ci	.show_starget_port_name = 1,
109262306a36Sopenharmony_ci	.show_starget_port_id = 1,
109362306a36Sopenharmony_ci
109462306a36Sopenharmony_ci	/* host fixed attributes */
109562306a36Sopenharmony_ci	.show_host_node_name = 1,
109662306a36Sopenharmony_ci	.show_host_port_name = 1,
109762306a36Sopenharmony_ci	.show_host_supported_classes = 1,
109862306a36Sopenharmony_ci	.show_host_supported_fc4s = 1,
109962306a36Sopenharmony_ci	.show_host_supported_speeds = 1,
110062306a36Sopenharmony_ci	.show_host_maxframe_size = 1,
110162306a36Sopenharmony_ci
110262306a36Sopenharmony_ci	/* host dynamic attributes */
110362306a36Sopenharmony_ci	.show_host_port_id = 1,
110462306a36Sopenharmony_ci	.show_host_port_type = 1,
110562306a36Sopenharmony_ci	.show_host_port_state = 1,
110662306a36Sopenharmony_ci	/* active_fc4s is shown but doesn't change (thus no get function) */
110762306a36Sopenharmony_ci	.show_host_active_fc4s = 1,
110862306a36Sopenharmony_ci	.show_host_speed = 1,
110962306a36Sopenharmony_ci	.show_host_fabric_name = 1,
111062306a36Sopenharmony_ci	.show_host_symbolic_name = 1,
111162306a36Sopenharmony_ci};
1112