// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2021 Broadcom. All Rights Reserved. The term * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
*/
/* Create a directory for sessions in root */ if (!efct->sess_debugfs_dir) {
efct->sess_debugfs_dir = debugfs_create_dir("sessions",
efct_debugfs_root); if (IS_ERR(efct->sess_debugfs_dir)) {
efc_log_err(efct, "failed to create debugfs entry for sessions\n"); goto debugfs_fail;
}
atomic_inc(&efct_debugfs_count);
}
int
efct_xport_status(struct efct_xport *xport, enum efct_xport_status cmd, union efct_xport_stats_u *result)
{ int rc = 0; struct efct *efct = NULL; union efct_xport_stats_u value;
efct = xport->efct;
switch (cmd) { case EFCT_XPORT_CONFIG_PORT_STATUS: if (xport->configured_link_state == 0) { /* * Initial state is offline. configured_link_state is * set to online explicitly when port is brought online
*/
xport->configured_link_state = EFCT_XPORT_PORT_OFFLINE;
}
result->value = xport->configured_link_state; break;
case EFCT_XPORT_PORT_STATUS: /* Determine port status based on link speed. */
value.value = efct_hw_get_link_speed(&efct->hw); if (value.value == 0)
result->value = EFCT_XPORT_PORT_OFFLINE; else
result->value = EFCT_XPORT_PORT_ONLINE; break;
case EFCT_XPORT_LINK_SPEED:
result->value = efct_hw_get_link_speed(&efct->hw); break;
case EFCT_XPORT_LINK_STATISTICS:
memcpy((void *)result, &efct->xport->fc_xport_stats, sizeof(union efct_xport_stats_u)); break; case EFCT_XPORT_LINK_STAT_RESET: { /* Create a completion to synchronize the stat reset process */
init_completion(&result->stats.done);
/* First reset the link stats */
rc = efct_hw_get_link_stats(&efct->hw, 0, 1, 1,
efct_xport_link_stats_cb, result); if (rc) break;
/* Wait for completion to be signaled when the cmd completes */ if (wait_for_completion_interruptible(&result->stats.done)) { /* Undefined failure */
efc_log_debug(efct, "sem wait failed\n");
rc = -EIO; break;
}
/* Next reset the host stats */
rc = efct_hw_get_host_stats(&efct->hw, 1,
efct_xport_host_stats_cb, result);
if (rc) break;
/* Wait for completion to be signaled when the cmd completes */ if (wait_for_completion_interruptible(&result->stats.done)) { /* Undefined failure */
efc_log_debug(efct, "sem wait failed\n");
rc = -EIO; break;
} break;
} default:
rc = -EIO; break;
}
/* populate link supported speeds */ for (i = 0; i < ARRAY_SIZE(supported_speed_list); i++) { if (link_module_type & supported_speed_list[i].lmt_speed)
supported_speeds |= supported_speed_list[i].speed;
}
return supported_speeds;
}
int
efct_scsi_new_device(struct efct *efct)
{ struct Scsi_Host *shost = NULL; int error = 0; struct efct_vport *vport = NULL;
shost = scsi_host_alloc(&efct_template, sizeof(*vport)); if (!shost) {
efc_log_err(efct, "failed to allocate Scsi_Host struct\n"); return -ENOMEM;
}
/* save shost to initiator-client context */
efct->shost = shost;
/* save efct information to shost LLD-specific space */
vport = (struct efct_vport *)shost->hostdata;
vport->efct = efct;
/* * Set initial can_queue value to the max SCSI IOs. This is the maximum * global queue depth (as opposed to the per-LUN queue depth -- * .cmd_per_lun This may need to be adjusted for I+T mode.
*/
shost->can_queue = efct->hw.config.n_io;
shost->max_cmd_len = 16; /* 16-byte CDBs */
shost->max_id = 0xffff;
shost->max_lun = 0xffffffff;
/* * can only accept (from mid-layer) as many SGEs as we've * pre-registered
*/
shost->sg_tablesize = sli_get_max_sgl(&efct->hw.sli);
/* attach FC Transport template to shost */
shost->transportt = efct_xport_fc_tt;
efc_log_debug(efct, "transport template=%p\n", efct_xport_fc_tt);
/* get pci_dev structure and add host to SCSI ML */
error = scsi_add_host_with_dma(shost, &efct->pci->dev,
&efct->pci->dev); if (error) {
efc_log_debug(efct, "failed scsi_add_host_with_dma\n"); return -EIO;
}
/* Set symbolic name for host port */
snprintf(fc_host_symbolic_name(shost), sizeof(fc_host_symbolic_name(shost)), "Emulex %s FV%s DV%s", efct->model,
efct->hw.sli.fw_name[0], EFCT_DRIVER_VERSION);
/* Set host port supported classes */
fc_host_supported_classes(shost) = FC_COS_CLASS3;
switch (cmd) { case EFCT_XPORT_PORT_ONLINE: { /* Bring the port on-line */
rc = efct_hw_port_control(&efct->hw, EFCT_HW_PORT_INIT, 0,
NULL, NULL); if (rc)
efc_log_err(efct, "%s: Can't init port\n", efct->desc); else
xport->configured_link_state = cmd; break;
} case EFCT_XPORT_PORT_OFFLINE: { if (efct_hw_port_control(&efct->hw, EFCT_HW_PORT_SHUTDOWN, 0,
NULL, NULL))
efc_log_err(efct, "port shutdown failed\n"); else
xport->configured_link_state = cmd; break;
}
case EFCT_XPORT_SHUTDOWN: { struct completion done; unsignedlong timeout;
/* if a PHYSDEV reset was performed (e.g. hw dump), will affect * all PCI functions; orderly shutdown won't work, * just force free
*/ if (sli_reset_required(&efct->hw.sli)) { struct efc_domain *domain = efct->efcport->domain;
rc = efct_xport_status(xport, EFCT_XPORT_LINK_STATISTICS, &stats); if (rc) {
pr_err("efct_xport_status returned non 0 - %d\n", rc); return NULL;
}
vport->fc_host_stats.loss_of_sync_count =
stats.stats.link_stats.loss_of_sync_error_count;
vport->fc_host_stats.link_failure_count =
stats.stats.link_stats.link_failure_error_count;
vport->fc_host_stats.prim_seq_protocol_err_count =
stats.stats.link_stats.primitive_sequence_error_count;
vport->fc_host_stats.invalid_tx_word_count =
stats.stats.link_stats.invalid_transmission_word_error_count;
vport->fc_host_stats.invalid_crc_count =
stats.stats.link_stats.crc_error_count; /* mbox returns kbyte count so we need to convert to words */
vport->fc_host_stats.tx_words =
stats.stats.host_stats.transmit_kbyte_count * 256; /* mbox returns kbyte count so we need to convert to words */
vport->fc_host_stats.rx_words =
stats.stats.host_stats.receive_kbyte_count * 256;
vport->fc_host_stats.tx_frames =
stats.stats.host_stats.transmit_frame_count;
vport->fc_host_stats.rx_frames =
stats.stats.host_stats.receive_frame_count;
/* * Bring the link down gracefully then re-init the link. * The firmware will re-initialize the Fibre Channel interface as * required. It does not issue a LIP.
*/
if (efct_xport_control(efct->xport, EFCT_XPORT_PORT_OFFLINE))
efc_log_debug(efct, "EFCT_XPORT_PORT_OFFLINE failed\n");
if (efct_xport_control(efct->xport, EFCT_XPORT_PORT_ONLINE))
efc_log_debug(efct, "EFCT_XPORT_PORT_ONLINE failed\n");
/* can only accept (from mid-layer) as many SGEs as we've pre-regited*/
shost->sg_tablesize = sli_get_max_sgl(&efct->hw.sli);
/* attach FC Transport template to shost */
shost->transportt = efct_vport_fc_tt;
efc_log_debug(efct, "vport transport template=%p\n",
efct_vport_fc_tt);
/* get pci_dev structure and add host to SCSI ML */
error = scsi_add_host_with_dma(shost, dev, &efct->pci->dev); if (error) {
efc_log_debug(efct, "failed scsi_add_host_with_dma\n"); return NULL;
}
/* Set symbolic name for host port */
snprintf(fc_host_symbolic_name(shost), sizeof(fc_host_symbolic_name(shost)), "Emulex %s FV%s DV%s", efct->model, efct->hw.sli.fw_name[0],
EFCT_DRIVER_VERSION);
/* Set host port supported classes */
fc_host_supported_classes(shost) = FC_COS_CLASS3;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.