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