/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 2004-2012 Emulex. All rights reserved.
* Use is subject to license terms.
*/
#include <emlxs.h>
/* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
emlxs_buf_t *sbp);
#ifdef SFCT_SUPPORT
emlxs_buf_t *sbp);
#endif /* SFCT_SUPPORT */
emlxs_buf_t *sbp);
emlxs_buf_t *sbp);
emlxs_buf_t *sbp);
#ifdef MSI_SUPPORT
#endif /* MSI_SUPPORT */
static int emlxs_check_hdw_ready(emlxs_hba_t *);
CQE_ASYNC_t *cqe);
CQE_ASYNC_t *cqe);
/* Define SLI4 API functions */
#ifdef SFCT_SUPPORT
#else
NULL,
#endif /* SFCT_SUPPORT */
};
/* ************************************************************************** */
static void
{
"Default SLI4 parameters set.");
} /* emlxs_sli4_set_default_params() */
/*
* emlxs_sli4_online()
*
* This routine will start initialization of the SLI4 HBA.
*/
static int32_t
{
uint32_t i;
uint32_t j;
/* Set the fw_check flag */
if ((fw_check & 0x04) ||
kern_update = 1;
}
hba->mbox_queue_flag = 0;
/* Networking not supported */
"Networking is not supported in SLI4, turning it off");
}
"Max channels exceeded, dropping num-wq from %d to 1",
}
/* Default channel for everything else is the last channel */
hba->channel_tx_count = 0;
/* Initialize the local dump region buffer */
"Unable to allocate dump region buffer.");
return (ENOMEM);
}
/*
* Get a buffer which will be used repeatedly for mailbox commands
*/
/* Reset & Initialize the adapter */
if (emlxs_sli4_hba_init(hba)) {
"Unable to init hba.");
goto failed1;
}
#ifdef FMA_SUPPORT
/* Access handle validation */
case SLI_INTF_IF_TYPE_2:
if ((emlxs_fm_check_acc_handle(hba,
goto failed1;
}
break;
default :
if ((emlxs_fm_check_acc_handle(hba,
goto failed1;
}
break;
}
#endif /* FMA_SUPPORT */
/*
* Setup and issue mailbox READ REV command
*/
vpd->postKernRev = 0;
vpd->postKernName[0] = 0;
vpd->sli1FwName[0] = 0;
vpd->sli2FwName[0] = 0;
vpd->sli3FwName[0] = 0;
vpd->sli4FwName[0] = 0;
vpd->sli1FwLabel[0] = 0;
vpd->sli2FwLabel[0] = 0;
vpd->sli3FwLabel[0] = 0;
vpd->sli4FwLabel[0] = 0;
"Unable to read parameters. Mailbox cmd=%x status=%x",
/* Set param defaults */
} else {
/* Save parameters */
sizeof (sli_params_t), 0);
}
/* Reuse mbq from previous mbox */
"Unable to get port names. Mailbox cmd=%x status=%x",
} else {
/* Save port names */
}
/* Reuse mbq from previous mbox */
"Unable to read rev. Mailbox cmd=%x status=%x",
goto failed1;
}
"Invalid read rev Version for SLI4: 0x%x",
goto failed1;
}
case EMLXS_DCBX_MODE_CIN: /* Mapped to nonFIP mode */
break;
case EMLXS_DCBX_MODE_CEE: /* Mapped to FIP mode */
break;
default:
"Invalid read rev dcbx mode for SLI4: 0x%x",
goto failed1;
}
} else {
}
/* Save information as VPD data */
/* Decode FW labels */
}
sizeof (vpd->sli4FwName));
sizeof (vpd->postKernName));
sizeof (vpd->sli4FwLabel));
sizeof (vpd->sli4FwLabel));
sizeof (vpd->sli4FwLabel));
} else {
sizeof (vpd->sli4FwLabel));
}
"VPD ULP:%08x %s ARM:%08x %s f:%d %d %d %d : dcbx %d",
/* No key information is needed for SLI4 products */
/* Get adapter VPD information */
/* Reuse mbq from previous mbox */
MBX_SUCCESS) {
} else {
"VPD dumped. rsp_cnt=%d status=%x",
#ifdef FMA_SUPPORT
!= DDI_FM_OK) {
"sli4_online: hdl=%p",
goto failed1;
}
}
#endif /* FMA_SUPPORT */
}
}
if (vpd_data[0]) {
/*
* If there is a VPD part number, and it does not
* match the current default HBA model info,
* replace the default data with an entry that
* does match.
*
* After emlxs_parse_vpd model holds the VPD value
* for V2 and part_num hold the value for PN. These
* 2 values are NOT necessarily the same.
*/
rval = 0;
/* First scan for a V2 match */
for (i = 1; i < emlxs_pci_model_count; i++) {
emlxs_pci_model[i].model) == 0) {
bcopy(&emlxs_pci_model[i],
&hba->model_info,
sizeof (emlxs_model_t));
rval = 1;
break;
}
}
}
/* Next scan for a PN match */
for (i = 1; i < emlxs_pci_model_count; i++) {
emlxs_pci_model[i].model) == 0) {
bcopy(&emlxs_pci_model[i],
&hba->model_info,
sizeof (emlxs_model_t));
break;
}
}
}
/* HP CNA port indices start at 1 instead of 0 */
vpd->port_index--;
}
}
/*
* Now lets update hba->model_info with the real
* VPD data, if any.
*/
/*
* Replace the default model description with vpd data
*/
if (vpd->model_desc[0] != 0) {
}
/* Replace the default model with vpd data */
}
/* Replace the default program types with vpd data */
if (vpd->prog_types[0] != 0) {
}
}
/*
* Since the adapter model may have changed with the vpd data
* lets double check if adapter is not supported
*/
"Unsupported adapter found. "
"Id:%d Device id:0x%x SSDID:0x%x Model:%s",
goto failed1;
}
/* Get fcode version property */
/*
* If firmware checking is enabled and the adapter model indicates
* a firmware image, then perform firmware version check
*/
if (((fw_check & 0x1) &&
/* Find firmware image indicated by adapter model */
for (i = 0; i < emlxs_fw_count; i++) {
fw = &emlxs_fw_table[i];
break;
}
}
/*
* If the image was found, then verify current firmware
* versions of adapter
*/
if (fw) {
/* Obtain current firmware version info */
} else {
}
if (!kern_update &&
"Firmware update needed. "
"Updating. id=%d fw=%d",
#ifdef MODFW_SUPPORT
/*
* Load the firmware image now
* If MODFW_SUPPORT is not defined, the
* firmware image will already be defined
* in the emlxs_fw_table
*/
#endif /* MODFW_SUPPORT */
if ((rc != FC_SUCCESS) &&
(rc != EMLXS_REBOOT_REQUIRED)) {
"Firmware update failed.");
}
#ifdef MODFW_SUPPORT
/*
* Unload the firmware image from
* kernel memory
*/
#endif /* MODFW_SUPPORT */
fw_check = 0;
goto reset;
}
"Firmware image unavailable.");
} else {
"Firmware update not needed.");
}
} else {
/*
* This means either the adapter database is not
* correct or a firmware image is missing from the
* compile
*/
"Firmware image unavailable. id=%d fw=%d",
}
}
/* Reuse mbq from previous mbox */
MBX_SUCCESS) {
} else {
"FCOE info dumped. rsp_cnt=%d status=%x",
(void) emlxs_parse_fcoe(hba,
}
/* Reuse mbq from previous mbox */
status = 0;
}
}
}
}
}
}
"Unable to REQUEST_FEATURES. Mailbox cmd=%x status=%x",
goto failed1;
}
/* Check to see if we get the features we requested */
/* Just report descrepencies, don't abort the attach */
"REQUEST_FEATURES: wanted:%s got:%s",
}
"Initiator mode not supported by adapter.");
#ifdef SFCT_SUPPORT
/* Check if we can fall back to just target mode */
"Disabling dynamic target mode. "
"Enabling target mode only.");
/* This will trigger the driver to reattach */
}
#endif /* SFCT_SUPPORT */
goto failed1;
}
"Target mode not supported by adapter.");
#ifdef SFCT_SUPPORT
/* Check if we can fall back to just initiator mode */
"Disabling dynamic target mode. "
"Enabling initiator mode only.");
/* This will trigger the driver to reattach */
}
#endif /* SFCT_SUPPORT */
goto failed1;
}
}
}
}
/* Reuse mbq from previous mbox */
"Unable to READ_CONFIG. Mailbox cmd=%x status=%x",
goto failed1;
}
/* Set default extents */
"CONFIG: xri:%d rpi:%d vpi:%d vfi:%d fcfi:%d",
"Invalid extent value(s) - xri:%d rpi:%d vpi:%d "
"vfi:%d fcfi:%d",
goto failed1;
}
"Unable to initialize extents.");
goto failed1;
}
}
"CONFIG: port_name:%c %c %c %c",
"CONFIG: ldv:%d link_type:%d link_number:%d",
} else {
}
}
/* Set the max node count */
} else {
}
/* Set the io throttle */
/* Set max_iotag */
/* We add 1 in case all XRI's are non-zero */
}
/* Set out-of-range iotag base */
/* Save the link speed capabilities */
/*
* Allocate some memory for buffers
*/
if (emlxs_mem_alloc_buffer(hba) == 0) {
"Unable to allocate memory buffers.");
goto failed1;
}
if (emlxs_sli4_resource_alloc(hba)) {
"Unable to allocate resources.");
goto failed2;
}
#if (EMLXS_MODREV >= EMLXS_MODREV5)
}
#endif /* >= EMLXS_MODREV5 */
/* Reuse mbq from previous mbox */
"Unable to post sgl pages.");
goto failed3;
}
/* Reuse mbq from previous mbox */
"Unable to post header templates.");
goto failed3;
}
/*
* Add our interrupt routine to kernel's interrupt chain & enable it
* If MSI is enabled this will cause Solaris to program the MSI address
* and data registers in PCI config space
*/
"Unable to add interrupt(s).");
goto failed3;
}
/* Reuse mbq from previous mbox */
/* This MUST be done after EMLXS_INTR_ADD */
"Unable to create queues.");
goto failed3;
}
/* Get and save the current firmware version (based on sli_mode) */
if (SLI4_FC_MODE) {
/* Reuse mbq from previous mbox */
MBX_SUCCESS) {
"Unable to configure link. Mailbox cmd=%x "
"status=%x",
goto failed3;
}
}
/* Reuse mbq from previous mbox */
/*
* We need to get login parameters for NID
*/
"Unable to read parameters. Mailbox cmd=%x status=%x",
goto failed3;
}
/* Free the buffer since we were polling */
/* If no serial number in VPD data, then use the WWPN */
if (vpd->serial_num[0] == 0) {
for (i = 0; i < 12; i++) {
if (j <= 9) {
vpd->serial_num[i] =
} else {
vpd->serial_num[i] =
}
i++;
j = (status & 0xf);
if (j <= 9) {
vpd->serial_num[i] =
} else {
vpd->serial_num[i] =
}
}
/*
* Set port number and port index to zero
* The WWN's are unique to each port and therefore port_num
* must equal zero. This effects the hba_fru_details structure
* in fca_bind_port()
*/
vpd->port_index = 0;
"CONFIG: WWPN: port_index=0");
}
/* Make final attempt to set a port index */
vpd->port_index = 0;
continue;
}
vpd->port_index++;
}
"CONFIG: Device tree: port_index=%d",
vpd->port_index);
}
}
}
"%s %d",
}
if (vpd->manufacturer[0] == 0) {
}
}
if (vpd->model_desc[0] == 0) {
"%s %d",
}
}
if (vpd->prog_types[0] == 0) {
}
/* Create the symbolic names */
"Emulex %s FV%s DV%s %s",
"Emulex PPN-%01x%01x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
/* Check persist-linkdown */
goto done;
}
#ifdef SFCT_SUPPORT
goto done;
}
#endif /* SFCT_SUPPORT */
/* Reuse mbq from previous mbox */
/*
* Setup and issue mailbox INITIALIZE LINK command
* At this point, the interrupt will be generated by the HW
*/
"Unable to initialize link. "
"Mailbox cmd=%x status=%x",
goto failed3;
}
/* Wait for link to come up */
/* Check for hardware error */
goto failed3;
}
BUSYWAIT_MS(1000);
i--;
}
done:
/*
* The leadville driver will now handle the FLOGI at the driver level
*/
if (mbq) {
}
return (0);
if (mp) {
}
(void) EMLXS_INTR_REMOVE(hba);
}
(void) emlxs_mem_free_buffer(hba);
if (mbq) {
}
}
if (rval == 0) {
}
return (rval);
} /* emlxs_sli4_online() */
static void
{
/* Reverse emlxs_sli4_online */
goto killed;
}
if (reset_requested) {
(void) emlxs_sli4_hba_reset(hba, 0, 0, 0);
}
/* Shutdown the adapter interface */
/* Free SLI shared memory */
/* Free driver shared memory */
(void) emlxs_mem_free_buffer(hba);
/* Free the host dump region buffer */
} /* emlxs_sli4_offline() */
/*ARGSUSED*/
static int
{
int status;
case SLI_INTF_IF_TYPE_0:
/* Map in Hardware BAR pages that will be used for */
/* communication with HBA. */
if (status != DDI_SUCCESS) {
"(PCI) ddi_regs_map_setup BAR1 failed. "
"stat=%d mem=%p attr=%p hdl=%p",
goto failed;
}
}
if (status != DDI_SUCCESS) {
"ddi_regs_map_setup BAR2 failed. status=%x",
status);
goto failed;
}
}
/* offset from beginning of register space */
break;
case SLI_INTF_IF_TYPE_2:
/* Map in Hardware BAR pages that will be used for */
/* communication with HBA. */
if (status != DDI_SUCCESS) {
"(PCI) ddi_regs_map_setup BAR0 failed. "
"stat=%d mem=%p attr=%p hdl=%p",
goto failed;
}
}
/* offset from beginning of register space */
break;
case SLI_INTF_IF_TYPE_1:
case SLI_INTF_IF_TYPE_3:
default:
"Map hdw: Unsupported if_type %08x",
goto failed;
}
goto failed;
}
}
return (0);
return (ENOMEM);
} /* emlxs_sli4_map_hdw() */
/*ARGSUSED*/
static void
{
}
}
}
}
}
return;
} /* emlxs_sli4_unmap_hdw() */
static int
{
uint32_t i = 0;
/* Wait for reset completion */
while (i < 30) {
case SLI_INTF_IF_TYPE_0:
/* Check to see if any errors occurred during init */
if (status & ARM_POST_FATAL) {
"SEMA Error: status=%x", status);
return (1);
}
if ((status & ARM_UNRECOVERABLE_ERROR) ==
"Unrecoverable Error: status=%x", status);
return (1);
}
/* ARM Ready !! */
"ARM Ready: status=%x", status);
return (0);
}
break;
case SLI_INTF_IF_TYPE_2:
if (status & SLI_STATUS_READY) {
if (!(status & SLI_STATUS_ERROR)) {
/* ARM Ready !! */
"ARM Ready: status=%x", status);
return (0);
}
if (status & SLI_STATUS_RESET_NEEDED) {
"ARM Ready (Reset Needed): "
"status=%x err1=%x "
"err2=%x",
return (1);
}
"Unrecoverable Error: status=%x err1=%x "
"err2=%x",
return (2);
}
break;
default:
return (3);
}
BUSYWAIT_MS(1000);
i++;
}
/* Timeout occurred */
case SLI_INTF_IF_TYPE_0:
break;
default:
break;
}
if (status & SLI_STATUS_ERROR) {
"Ready Timeout: Port Error: status=%x err1=%x err2=%x",
} else {
"Ready Timeout: status=%x err1=%x err2=%x",
}
return (3);
} /* emlxs_check_hdw_ready() */
static uint32_t
{
#ifdef FMA_SUPPORT
#endif /* FMA_SUPPORT */
case SLI_INTF_IF_TYPE_2:
#ifdef FMA_SUPPORT
/* Access handle validation */
#endif /* FMA_SUPPORT */
break;
default:
status = 0;
break;
}
return (status);
} /* emlxs_sli4_read_status() */
static uint32_t
{
#ifdef FMA_SUPPORT
#endif /* FMA_SUPPORT */
case SLI_INTF_IF_TYPE_0:
#ifdef FMA_SUPPORT
/* Access handle validation */
#endif /* FMA_SUPPORT */
break;
case SLI_INTF_IF_TYPE_2:
#ifdef FMA_SUPPORT
/* Access handle validation */
#endif /* FMA_SUPPORT */
break;
default:
status = 0;
break;
}
return (status);
} /* emlxs_sli4_read_sema() */
static uint32_t
{
#ifdef FMA_SUPPORT
#endif /* FMA_SUPPORT */
case SLI_INTF_IF_TYPE_0:
#ifdef FMA_SUPPORT
/* Access handle validation */
#endif /* FMA_SUPPORT */
break;
case SLI_INTF_IF_TYPE_2:
#ifdef FMA_SUPPORT
/* Access handle validation */
#endif /* FMA_SUPPORT */
break;
default:
status = 0;
break;
}
return (status);
} /* emlxs_sli4_read_mbdb() */
static void
{
case SLI_INTF_IF_TYPE_0:
break;
case SLI_INTF_IF_TYPE_2:
break;
}
} /* emlxs_sli4_write_mbdb() */
static void
{
case SLI_INTF_IF_TYPE_0:
break;
case SLI_INTF_IF_TYPE_2:
break;
}
} /* emlxs_sli4_write_cqdb() */
static void
{
case SLI_INTF_IF_TYPE_0:
break;
case SLI_INTF_IF_TYPE_2:
break;
}
} /* emlxs_sli4_write_rqdb() */
static void
{
case SLI_INTF_IF_TYPE_0:
break;
case SLI_INTF_IF_TYPE_2:
break;
}
} /* emlxs_sli4_write_mqdb() */
static void
{
case SLI_INTF_IF_TYPE_0:
break;
case SLI_INTF_IF_TYPE_2:
break;
}
} /* emlxs_sli4_write_wqdb() */
static uint32_t
{
/* Wait for reset completion, tmo is in 10ms ticks */
while (tmo) {
/* Check to see if any errors occurred during init */
if (status & BMBX_READY) {
"BMBX Ready: status=0x%x", status);
return (tmo);
}
BUSYWAIT_MS(10);
tmo--;
}
case SLI_INTF_IF_TYPE_0:
break;
default:
break;
}
/* Timeout occurred */
"Timeout waiting for BMailbox: status=%x err1=%x err2=%x",
return (0);
} /* emlxs_check_bootstrap_ready() */
static uint32_t
{
/*
* This routine assumes the bootstrap mbox is loaded
* with the mailbox command to be executed.
*
* First, load the high 30 bits of bootstrap mailbox
*/
addr30 |= BMBX_ADDR_HI;
if (tmo == 0) {
return (0);
}
/* Load the low 30 bits of bootstrap mailbox */
if (tmo == 0) {
return (0);
}
"BootstrapMB: %p Completed %08x %08x %08x",
return (tmo);
} /* emlxs_issue_bootstrap_mb() */
static int
{
#ifdef FMA_SUPPORT
#endif /* FMA_SUPPORT */
if (emlxs_check_hdw_ready(hba)) {
return (1);
}
return (0); /* Already initialized */
}
/* NOTE: tmo is in 10ms ticks */
if (tmo == 0) {
return (1);
}
/* Issue FW_INITIALIZE command */
/* Special words to initialize bootstrap mbox MUST be little endian */
return (1);
}
#ifdef FMA_SUPPORT
!= DDI_FM_OK) {
"init_bootstrap_mb: hdl=%p",
return (1);
}
#endif
return (0);
} /* emlxs_init_bootstrap_mb() */
static uint32_t
{
int rc;
uint16_t i;
/* Restart the adapter */
return (1);
}
for (i = 0; i < hba->chan_count; i++) {
}
/* Initialize all the port objects */
for (i = 0; i < MAX_VPORTS; i++) {
}
/* Set the max node count */
} else {
}
}
if (rc) {
return (rc);
}
/* Cache the UE MASK registers value for UE error detection */
}
return (0);
} /* emlxs_sli4_hba_init() */
/*ARGSUSED*/
static uint32_t
{
uint32_t i;
"Adapter reset disabled.");
return (1);
}
case SLI_INTF_IF_TYPE_0:
if (quiesce == 0) {
/*
* Initalize Hardware that will be used to bring
* SLI4 online.
*/
if (rc) {
return (rc);
}
}
if (quiesce == 0) {
MBX_POLL, 0) != MBX_SUCCESS) {
/* Timeout occurred */
"Timeout: RESET");
/* Log a dump event - not supported */
return (1);
}
} else {
MBX_POLL, 0) != MBX_SUCCESS) {
/* Log a dump event - not supported */
return (1);
}
}
break;
case SLI_INTF_IF_TYPE_2:
if (quiesce == 0) {
}
if (rc > 1) {
"Adapter not ready for reset.");
return (1);
}
if (rc == 1) {
/* Don't generate an event if dump was forced */
generate_event = 1;
}
}
/* Reset the port now */
break;
}
/* Reset the hba structure */
}
hba->channel_tx_count = 0;
hba->iodone_count = 0;
hba->heartbeat_active = 0;
hba->discovery_timer = 0;
hba->linkup_timer = 0;
hba->loopback_tics = 0;
/* Reset the port objects */
for (i = 0; i < MAX_VPORTS; i++) {
vport->node_count = 0;
}
}
if (emlxs_check_hdw_ready(hba)) {
return (1);
}
if (generate_event) {
if (status & SLI_STATUS_DUMP_IMAGE_PRESENT) {
}
}
return (0);
} /* emlxs_sli4_hba_reset */
#define SGL_CMD 0
/*ARGSUSED*/
static ULP_SGE64 *
{
#ifdef DEBUG_SGE
#endif /* DEBUG_SGE */
uint_t i;
#if (EMLXS_MODREV >= EMLXS_MODREV3)
switch (sgl_type) {
case SGL_CMD:
break;
case SGL_RESP:
break;
case SGL_DATA:
break;
default:
return (NULL);
}
#else
switch (sgl_type) {
case SGL_CMD:
cookie_cnt = 1;
break;
case SGL_RESP:
cookie_cnt = 1;
break;
case SGL_DATA:
cookie_cnt = 1;
break;
default:
return (NULL);
}
#endif /* >= EMLXS_MODREV3 */
cnt = 0;
if (cnt) {
/* Copy staged SGE before we build next one */
sge++;
}
}
#ifdef DEBUG_SGE
4, 0);
#endif /* DEBUG_SGE */
}
}
if (last) {
}
sizeof (ULP_SGE64));
sge++;
if (pcnt) {
}
return (sge);
} /* emlxs_pkt_to_sgl */
/*ARGSUSED*/
{
#if (EMLXS_MODREV >= EMLXS_MODREV3)
#else
#endif /* >= EMLXS_MODREV3 */
return (1);
}
/* CMD payload */
if (! sge) {
return (1);
}
/* DATA payload */
if (pkt->pkt_datalen != 0) {
/* RSP payload */
if (! sge) {
return (1);
}
/* Data payload */
if (! sge) {
return (1);
}
}
} else {
/* RSP payload */
if (! sge) {
return (1);
}
}
} else {
/* CMD payload */
if (! sge) {
return (1);
}
} else {
/* CMD payload */
if (! sge) {
return (1);
}
/* RSP payload */
if (! sge) {
return (1);
}
}
}
return (0);
} /* emlxs_sli4_bde_setup */
#ifdef SFCT_SUPPORT
/*ARGSUSED*/
static uint32_t
{
return (0);
}
/*
* The hardware will automaticlly round up
* to multiple of 4.
*
* if (size & 3) {
* size = (size + 3) & 0xfffffffc;
* }
*/
"fct_bde_setup: Only 1 sglist entry supported: %d",
return (1);
}
"fct_bde_setup: Cannot allocate XRDY memory");
return (1);
}
/* Save the MATCHMAP info to free this memory later */
/* Point to XRDY payload */
/* Fill in burstsize in payload */
*xrdy_vaddr++ = 0;
*xrdy_vaddr = 0;
/* First 2 SGEs are XRDY and SKIP */
/* Words 0-3 */
} else { /* CMD_FCP_TSEND64_CX */
/* First 2 SGEs are SKIP */
/* Words 0-3 */
/* The BDE should match the contents of the first SGE payload */
/* The PayloadLength should be set to 0 for TSEND64. */
}
/*
* TotalTransferCount equals to Relative Offset field (Word 4)
* in both TSEND64 and TRECEIVE64 WQE.
*/
/* Copy staged SGE into SGL */
sge++;
/* Copy staged SGE into SGL */
sge++;
cnt = 0;
/* Build SGEs */
while (sge_size) {
if (cnt) {
/* Copy staged SGE before we build next one */
sge++;
}
}
}
/* Copy staged SGE into SGL */
return (0);
} /* emlxs_sli4_fct_bde_setup */
#endif /* SFCT_SUPPORT */
static void
{
#ifdef NODE_THROTTLE_SUPPORT
#endif /* NODE_THROTTLE_SUPPORT */
#ifdef DEBUG_FASTPATH
#endif /* DEBUG_FASTPATH */
throttle = 0;
/* Check if FCP ring and adapter is not ready */
/* We may use any ring for FCP_CMD */
return;
}
}
/* Attempt to acquire CMD_RING lock */
/* Queue it for later */
if (iocbq) {
return;
} else {
}
} else {
return;
}
}
/* EMLXS_QUE_LOCK acquired */
/* Throttle check only applies to non special iocb */
/* Check if HBA is full */
if (throttle <= 0) {
/* Hitting adapter throttle limit */
/* Queue it for later */
if (iocbq) {
}
goto busy;
}
}
/* Check to see if we have room for this WQE */
next_wqe = 0;
}
/* Queue it for later */
if (iocbq) {
}
goto busy;
}
/*
* We have a command ring slot available
* Make sure we have an iocb to send
*/
if (iocbq) {
/* Check if the ring already has iocb's waiting */
/* Put the current iocbq on the tx queue */
emlxs_tx_put(iocbq, 0);
/*
* Attempt to replace it with the next iocbq
* in the tx queue
*/
}
} else {
}
/* Process each iocbq */
while (iocbq) {
#ifdef NODE_THROTTLE_SUPPORT
if (node_throttle <= 0) {
/* Node is busy */
/* Queue this iocb and get next iocb from */
/* channel */
if (!marked_node) {
}
emlxs_tx_put(iocbq, 0);
goto busy;
}
continue;
}
}
marked_node = 0;
#endif /* NODE_THROTTLE_SUPPORT */
#ifdef DEBUG_FASTPATH
#endif /* DEBUG_FASTPATH */
if (sbp) {
/* If exchange removed after wqe was prep'ed, drop it */
"Xmit WQE iotag:%x xri:%d aborted",
/* Get next iocb from the tx queue */
continue;
}
/* Perform delay */
drv_usecwait(100000);
} else {
drv_usecwait(20000);
}
}
/* Check for ULP pkt request */
/* Set node to base node by default */
}
#ifdef NODE_THROTTLE_SUPPORT
}
#endif /* NODE_THROTTLE_SUPPORT */
#ifdef SFCT_SUPPORT
#ifdef FCT_IO_TRACE
icmd->ULPCOMMAND);
}
#endif /* FCT_IO_TRACE */
#endif /* SFCT_SUPPORT */
cp->hbaSendCmd_sbp++;
} else {
cp->hbaSendCmd++;
}
/*
* At this point, we have a command ring slot available
* and an iocb to send
*/
wq->release_depth--;
if (wq->release_depth == 0) {
}
/* Send the iocb */
}
sizeof (emlxs_wqe_t));
#ifdef DEBUG_WQE
#endif /* DEBUG_WQE */
(uint64_t)((unsigned long)
4096, DDI_DMA_SYNC_FORDEV);
/* Ring the WQ Doorbell */
/*
* After this, the sbp / iocb / wqe should not be
* accessed in the xmit path.
*/
#ifdef DEBUG_FASTPATH
"WQ RING: %08x", wqdb);
#endif /* DEBUG_FASTPATH */
if (!sbp) {
}
/* Check if HBA is full */
if (throttle <= 0) {
goto busy;
}
}
/* Check to see if we have room for another WQE */
next_wqe++;
next_wqe = 0;
}
/* Queue it for later */
goto busy;
}
/* Get the next iocb from the tx queue if there is one */
}
return;
busy:
if (throttle <= 0) {
} else {
}
return;
} /* emlxs_sli4_issue_iocb_cmd() */
/*ARGSUSED*/
static uint32_t
{
/*
* If this is an embedded mbox, everything should fit
* into the mailbox area.
*/
4096, DDI_DMA_SYNC_FORDEV);
18, 0);
}
} else {
/* SLI_CONFIG and non-embedded */
/*
* If this is not embedded, the MQ area
* MUST contain a SGE pointer to a larger area for the
* non-embedded mailbox command.
* mp will point to the actual mailbox command which
* should be copied into the non-embedded area.
*/
(uint64_t)((unsigned long)
4096, DDI_DMA_SYNC_FORDEV);
}
/* Ring the MQ Doorbell */
"MQ RING: %08x", mqdb);
}
return (MBX_SUCCESS);
} /* emlxs_sli4_issue_mq() */
/*ARGSUSED*/
static uint32_t
{
int nonembed = 0;
/*
* If this is an embedded mbox, everything should fit
* into the bootstrap mailbox area.
*/
} else {
/*
* If this is not embedded, the bootstrap mailbox area
* MUST contain a SGE pointer to a larger area for the
* non-embedded mailbox command.
* mp will point to the actual mailbox command which
* should be copied into the non-embedded area.
*/
nonembed = 1;
}
/* NOTE: tmo is in 10ms ticks */
return (MBX_TIMEOUT);
}
} else {
}
#ifdef FMA_SUPPORT
!= DDI_FM_OK) {
"sli4_issue_bootstrap: mp_hdl=%p",
mp->dma_handle);
return (MBXERR_DMA_ERROR);
}
}
!= DDI_FM_OK) {
"sli4_issue_bootstrap: hdl=%p",
return (MBXERR_DMA_ERROR);
}
#endif
return (MBX_SUCCESS);
} /* emlxs_sli4_issue_bootstrap() */
/*ARGSUSED*/
static uint32_t
{
uint32_t i;
}
rc = MBX_SUCCESS;
/* Check for minimum timeouts */
switch (mb->mbxCommand) {
case MBX_DOWN_LOAD:
case MBX_UPDATE_CFG:
case MBX_LOAD_AREA:
case MBX_LOAD_EXP_ROM:
case MBX_WRITE_NV:
case MBX_FLASH_WR_ULA:
case MBX_DEL_LD_ENTRY:
case MBX_LOAD_SM:
case MBX_DUMP_MEMORY:
case MBX_WRITE_VPARMS:
case MBX_ACCESS_VDATA:
if (tmo < 300) {
tmo = 300;
}
break;
case MBX_SLI_CONFIG: {
hdr_req = (mbox_req_hdr_t *)
case COMMON_OPCODE_WRITE_OBJ:
case COMMON_OPCODE_READ_OBJ:
case COMMON_OPCODE_DELETE_OBJ:
if (tmo < 300) {
tmo = 300;
}
break;
default:
if (tmo < 30) {
tmo = 30;
}
}
if (tmo < 300) {
tmo = 300;
}
break;
default:
if (tmo < 30) {
tmo = 30;
}
}
} else {
if (tmo < 30) {
tmo = 30;
}
}
/*
* Also: VENDOR_MANAGE_FFV (0x13, 0x02) (not currently used)
*/
break;
}
default:
if (tmo < 30) {
tmo = 30;
}
break;
}
/* Convert tmo seconds to 10 millisecond tics */
/* Adjust wait flag */
if (flag != MBX_NOWAIT) {
} else {
}
} else {
/* Must have interrupts enabled to perform MBX_NOWAIT */
"Interrupts disabled. %s failed.",
return (MBX_HARDWARE_ERROR);
}
}
/* Check for hardware error ; special case SLI_CONFIG */
COMMON_OPCODE_RESET))) {
"Hardware error reported. %s failed. status=%x mb=%p",
return (MBX_HARDWARE_ERROR);
}
if (hba->mbox_queue_flag) {
/* If we are not polling, then queue it for later */
if (flag == MBX_NOWAIT) {
"Busy. %s: mb=%p NoWait.",
return (MBX_BUSY);
}
while (hba->mbox_queue_flag) {
if (tmo_local-- == 0) {
"Timeout. %s: mb=%p tmo=%d Waiting.",
tmo);
/* Non-lethalStatus mailbox timeout */
/* Does not indicate a hardware error */
return (MBX_TIMEOUT);
}
BUSYWAIT_MS(10);
/* Check for hardware error ; special case SLI_CONFIG */
COMMON_OPCODE_RESET))) {
"Hardware error reported. %s failed. "
"status=%x mb=%p",
return (MBX_HARDWARE_ERROR);
}
}
}
/* Initialize mailbox area */
}
switch (flag) {
case MBX_NOWAIT:
/* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
"Sending. %s: mb=%p NoWait. embedded %d",
}
}
}
"BDE virt %p phys %p size x%x",
}
break;
case MBX_POLL:
/* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
"Sending. %s: mb=%p Poll. embedded %d",
}
/* Clean up the mailbox area */
if (rc == MBX_TIMEOUT) {
"Timeout. %s: mb=%p tmo=%x Poll. embedded %d",
} else {
/* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
"Completed. %s: mb=%p status=%x Poll. "
"embedded %d",
}
/* Process the result */
}
}
}
if (mp) {
"%s: MBX_NONEMBED_ERROR: 0x%x, 0x%x",
}
}
/* Attempt to send pending mailboxes */
if (mbq) {
/* Attempt to send pending mailboxes */
if ((i != MBX_BUSY) && (i != MBX_SUCCESS)) {
}
}
break;
case MBX_SLEEP:
/* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
"Sending. %s: mb=%p Sleep. embedded %d",
}
}
if (rc != MBX_SUCCESS) {
break;
}
/* Wait for completion */
/* The driver clock is timing the mailbox. */
}
if (mp) {
"%s: MBX_NONEMBED_ERROR: 0x%x, 0x%x",
}
}
if (rc == MBX_TIMEOUT) {
"Timeout. %s: mb=%p tmo=%x Sleep. embedded %d",
} else {
/* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
"Completed. %s: mb=%p status=%x Sleep. "
"embedded %d",
}
}
break;
}
return (rc);
} /* emlxs_sli4_issue_mbox_cmd() */
/*ARGSUSED*/
static uint32_t
{
rc = MBX_SUCCESS;
if (tmo < 30) {
tmo = 30;
}
/* Convert tmo seconds to 10 millisecond tics */
/* Check for hardware error */
return (MBX_HARDWARE_ERROR);
}
/* Initialize mailbox area */
switch (flag) {
case MBX_POLL:
/* Clean up the mailbox area */
if (rc == MBX_TIMEOUT) {
} else {
/* Process the result */
}
}
}
if (mp) {
"%s: MBX_NONEMBED_ERROR: 0x%x, 0x%x",
}
}
break;
}
return (rc);
} /* emlxs_sli4_issue_mbox_cmd4quiesce() */
#ifdef SFCT_SUPPORT
/*ARGSUSED*/
extern uint32_t
{
if (!rpip) {
/* Use the fabric rpi */
}
/* Next allocate an Exchange for this command */
if (!xrip) {
"Adapter Busy. Unable to allocate exchange. "
"did=0x%x", did);
return (FC_TRAN_BUSY);
}
"FCT Abort Request: xri=%d iotag=%d sbp=%p rxid=%x",
cp->ulpSendCmd++;
/* Initalize iocbq */
/*
* Don't give the abort priority, we want the IOCB
* we are aborting to be processed first.
*/
} else {
}
/* Set the pkt timer */
return (IOERR_SUCCESS);
if (!ndlp) {
"Unable to find rpi. did=0x%x", did);
IOERR_INVALID_RPI, 0);
return (0xff);
}
cp->ulpSendCmd++;
/* Initalize iocbq */
if (!xrip) {
"Unable to register xri %x. did=0x%x",
IOERR_NO_XRI, 0);
return (0xff);
}
#if (EMLXS_MODREV >= EMLXS_MODREV3)
#else
#endif /* >= EMLXS_MODREV3 */
/* Make size a multiple of 4 */
if (sge_size & 3) {
}
/* Copy staged SGE into SGL */
/* Words 0-3 */
/* Word 6 */
/* Word 7 */
/* Word 8 */
/* Word 9 */
/* Word 10 */
}
}
/* Word 11 */
/* Set the pkt timer */
if (pkt->pkt_cmdlen) {
}
return (IOERR_SUCCESS);
}
if (!ndlp) {
"Unable to find rpi. did=0x%x", did);
IOERR_INVALID_RPI, 0);
return (0xff);
}
/* Initalize iocbq */
if (!xrip) {
"Unable to find xri. did=0x%x", did);
IOERR_NO_XRI, 0);
return (0xff);
}
"Unable to register xri. did=0x%x", did);
IOERR_NO_XRI, 0);
return (0xff);
}
timeout =
} else {
timeout = 0x80000000;
}
} else { /* TF_READ_DATA */
if ((dbuf->db_data_size >=
/* enable auto-rsp AP feature */
}
}
/* Word 6 */
/* Word 7 */
/* Word 8 */
/* Word 9 */
/* Word 10 */
}
}
/* Word 11 */
/* Word 12 */
return (IOERR_SUCCESS);
} /* emlxs_sli4_prep_fct_iocb() */
#endif /* SFCT_SUPPORT */
/*ARGSUSED*/
extern uint32_t
{
/* Find target node object */
if (!rpip) {
"Unable to find rpi. did=0x%x", did);
IOERR_INVALID_RPI, 0);
return (0xff);
}
/* Next allocate an Exchange for this command */
if (!xrip) {
"Adapter Busy. Unable to allocate exchange. did=0x%x", did);
return (FC_TRAN_BUSY);
}
#ifdef DEBUG_FASTPATH
"FCP: Prep xri=%d iotag=%d oxid=%x rpi=%d",
#endif /* DEBUG_FASTPATH */
/* Indicate this is a FCP cmd */
"Adapter Busy. Unable to setup SGE. did=0x%x", did);
return (FC_TRAN_BUSY);
}
/* DEBUG */
#ifdef DEBUG_FCP
"FCP: CMD virt %p len %d:%d:%d",
#endif /* DEBUG_FCP */
(uint64_t)((unsigned long)
/* if device is FCP-2 device, set the following bit */
/* that says to run the FC-TAPE protocol. */
}
if (pkt->pkt_datalen == 0) {
} else {
}
}
}
case FC_TRAN_CLASS2:
break;
case FC_TRAN_CLASS3:
default:
break;
}
return (FC_SUCCESS);
} /* emlxs_sli4_prep_fcp_iocb() */
/*ARGSUSED*/
static uint32_t
{
return (FC_TRAN_BUSY);
} /* emlxs_sli4_prep_ip_iocb() */
/*ARGSUSED*/
static uint32_t
{
/* Initalize iocbq */
#if (EMLXS_MODREV >= EMLXS_MODREV3)
#else
#endif /* >= EMLXS_MODREV3 */
/* CMD payload */
cmd &= ELS_CMD_MASK;
/* Initalize iocb */
/* ELS Response */
if (!xrip) {
"Unable to find XRI. rxid=%x",
IOERR_NO_XRI, 0);
return (0xff);
}
if (!rpip) {
/* This means that we had a node registered */
/* when the unsol request came in but the node */
/* has since been unregistered. */
"Unable to find RPI. rxid=%x",
IOERR_INVALID_RPI, 0);
return (0xff);
}
"ELS: Prep xri=%d iotag=%d oxid=%x rpi=%d",
}
/* Now sge is fully staged */
sizeof (ULP_SGE64));
} else {
}
}
} else {
/* ELS Request */
if (!rpip) {
/* Use the fabric rpi */
}
/* Next allocate an Exchange for this command */
if (!xrip) {
"Adapter Busy. Unable to allocate exchange. "
"did=0x%x", did);
return (FC_TRAN_BUSY);
}
"ELS: Prep xri=%d iotag=%d rpi=%d",
}
/* setup for rsp */
sizeof (ULP_SGE64));
/* RSP payload */
/* Now sge is fully staged */
sge++;
sizeof (ULP_SGE64));
#ifdef DEBUG_ELS
"ELS: SGLaddr virt %p phys %p",
"ELS: PAYLOAD virt %p phys %p",
12, 0);
#endif /* DEBUG_ELS */
switch (cmd) {
case ELS_CMD_FLOGI:
} else {
}
}
}
break;
case ELS_CMD_FDISC:
}
break;
case ELS_CMD_LOGO:
if ((did == FABRIC_DID) &&
}
break;
case ELS_CMD_PLOGI:
}
} else {
}
break;
default:
} else {
}
break;
}
#ifdef SFCT_SUPPORT
/* This allows fct to abort the request */
}
#endif /* SFCT_SUPPORT */
}
if (!reserved_rpip) {
"Unable to alloc reserved RPI. rxid=%x. Rejecting.",
IOERR_INVALID_RPI, 0);
return (0xff);
}
/* Store the reserved rpi */
} else {
}
}
(uint64_t)((unsigned long)
}
case FC_TRAN_CLASS2:
break;
case FC_TRAN_CLASS3:
default:
break;
}
return (FC_SUCCESS);
} /* emlxs_sli4_prep_els_iocb() */
/*ARGSUSED*/
static uint32_t
{
/* Initalize wqe */
/* CT Response */
if (!xrip) {
"Unable to find XRI. rxid=%x",
IOERR_NO_XRI, 0);
return (0xff);
}
if (!rpip) {
/* This means that we had a node registered */
/* when the unsol request came in but the node */
/* has since been unregistered. */
"Unable to find RPI. rxid=%x",
IOERR_INVALID_RPI, 0);
return (0xff);
}
"CT: Prep xri=%d iotag=%d oxid=%x rpi=%d",
"Adapter Busy. Unable to setup SGE. did=0x%x", did);
return (FC_TRAN_BUSY);
}
}
}
} else {
}
}
}
} else {
/* CT Request */
if (!rpip) {
"Unable to find rpi. did=0x%x rpi=%d",
IOERR_INVALID_RPI, 0);
return (0xff);
}
/* Next allocate an Exchange for this command */
if (!xrip) {
"Adapter Busy. Unable to allocate exchange. "
"did=0x%x", did);
return (FC_TRAN_BUSY);
}
"CT: Prep xri=%d iotag=%d oxid=%x rpi=%d",
"Adapter Busy. Unable to setup SGE. did=0x%x", did);
return (FC_TRAN_BUSY);
}
}
#ifdef DEBUG_CT
12, 0);
"CT: CMD virt %p len %d:%d",
20, 0);
#endif /* DEBUG_CT */
#ifdef SFCT_SUPPORT
/* This allows fct to abort the request */
}
#endif /* SFCT_SUPPORT */
}
/* Setup for rsp */
(uint64_t)((unsigned long)
}
case FC_TRAN_CLASS2:
break;
case FC_TRAN_CLASS3:
default:
break;
}
return (FC_SUCCESS);
} /* emlxs_sli4_prep_ct_iocb() */
/*ARGSUSED*/
static int
{
int rc = 0;
(uint64_t)((unsigned long)
4096, DDI_DMA_SYNC_FORKERNEL);
rc = 1;
}
return (rc);
} /* emlxs_sli4_read_eq */
static void
{
int rc = 0;
int i;
/* Check attention bits once and process if required */
for (i = 0; i < hba->intr_count; i++) {
if (rc == 1) {
break;
}
}
if (rc != 1) {
return;
}
(void) emlxs_sli4_msi_intr((char *)hba,
(char *)(unsigned long)arg[i]);
return;
} /* emlxs_sli4_poll_intr() */
/*ARGSUSED*/
static void
{
/* Save the event tag */
}
switch (cqe->event_code) {
case ASYNC_EVENT_PHYS_LINK_UP:
"Link Async Event: PHYS_LINK_UP. val=%d "
"type=%x event=%x",
break;
"Link Async Event: LOGICAL_LINK_UP. val=%d "
"type=%x event=%x",
break;
"Link Async Event: PHYS_LINK_DOWN. val=%d "
"type=%x event=%x",
break;
"Link Async Event: LOGICAL_LINK_DOWN. val=%d "
"type=%x event=%x",
break;
default:
"Link Async Event: Unknown link status=%d event=%x",
break;
}
break;
case ASYNC_EVENT_NEW_FCF_DISC:
"FIP Async Event: FCF_FOUND %d:%d",
(void) emlxs_fcf_found_notify(port,
break;
"FIP Async Event: FCFTAB_FULL %d:%d",
(void) emlxs_fcf_full_notify(port);
break;
case ASYNC_EVENT_FCF_DEAD:
"FIP Async Event: FCF_LOST %d:%d",
(void) emlxs_fcf_lost_notify(port,
break;
"FIP Async Event: CVL %d",
(void) emlxs_fcf_cvl_notify(port,
break;
case ASYNC_EVENT_FCF_MODIFIED:
"FIP Async Event: FCF_CHANGED %d",
(void) emlxs_fcf_changed_notify(port,
break;
default:
"FIP Async Event: Unknown event type=%d",
break;
}
break;
case ASYNC_EVENT_CODE_DCBX:
"DCBX Async Event: type=%d. Not supported.",
cqe->event_type);
break;
case ASYNC_EVENT_CODE_GRP_5:
}
break;
switch (cqe->event_type) {
case ASYNC_EVENT_FC_LINK_ATT:
"FC Async Event: Link Attention. event=%x",
break;
"FC Async Event: Shared Link Attention. event=%x",
break;
default:
"FC Async Event: Unknown event. type=%d event=%x",
}
break;
case ASYNC_EVENT_CODE_PORT:
status =
switch (status) {
case 0 :
break;
case 1 :
"SLI Port Async Event: Physical media not "
"detected");
"^%s%d: Optics faulted/incorrectly "
"if issue not resolved, replace.",
break;
case 2 :
"SLI Port Async Event: Wrong physical "
"media detected");
"^%s%d: Optics of two types installed - "
"Remove one optic or install matching"
"pair of optics.",
break;
case 3 :
"SLI Port Async Event: Unsupported "
"physical media detected");
"^%s%d: Incompatible optics - Replace "
"with compatible optics for card to "
"function.",
break;
default :
"SLI Port Async Event: Physical media "
"error, status=%x", status);
"^%s%d: Misconfigured port: status=0x%x - "
"Check optics on card.",
break;
}
}
break;
case ASYNC_EVENT_CODE_VF:
"VF Async Event: type=%d",
cqe->event_type);
break;
case ASYNC_EVENT_CODE_MR:
"MR Async Event: type=%d",
cqe->event_type);
break;
default:
"Unknown Async Event: code=%d type=%d.",
break;
}
} /* emlxs_sli4_process_async_event() */
/*ARGSUSED*/
static void
{
int rc;
"CQ ENTRY: Mbox event. Entry consumed but not completed");
return;
}
switch (hba->mbox_queue_flag) {
case 0:
"CQ ENTRY: Mbox event. No mailbox active.");
return;
case MBX_POLL:
/* Mark mailbox complete, this should wake up any polling */
/* threads. This can happen if interrupts are enabled while */
/* a polled mailbox command is outstanding. If we don't set */
/* MBQ_COMPLETED here, the polling thread may wait until */
/* timeout error occurs */
if (mbq) {
"CQ ENTRY: Mbox event. Completing Polled command.");
}
return;
case MBX_SLEEP:
case MBX_NOWAIT:
/* Check mbox_timer, it acts as a service flag too */
/* The first to service the mbox queue will clear the timer */
if (hba->mbox_timer) {
hba->mbox_timer = 0;
}
if (!mbq) {
"Mailbox event. No service required.");
return;
}
break;
default:
"CQ ENTRY: Mbox event. Invalid Mailbox flag (%x).",
return;
}
/* Set port context */
(uint64_t)((unsigned long)
/* Now that we are the owner, DMA Sync entire MQ if needed */
4096, DDI_DMA_SYNC_FORDEV);
"CQ ENTRY: Mbox event. Mbox complete. status=%x cmd=%x",
12, 0);
}
"Mbox sge_cnt: %d length: %d embed: %d",
}
/* Now sync the memory buffer if one was used */
#ifdef FMA_SUPPORT
!= DDI_FM_OK) {
"sli4_process_mbox_event: hdl=%p",
}
#endif
}
/* Now sync the memory buffer if one was used */
#ifdef FMA_SUPPORT
"sli4_process_mbox_event: hdl=%p",
}
#endif
}
/* Mailbox has been completely received at this point */
hba->heartbeat_active = 0;
goto done;
}
/* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
"Received. %s: status=%x Sleep.",
}
} else {
/* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
"Completed. %s: status=%x",
}
}
/* Filter out passthru mailbox */
goto done;
}
}
/* If mbox was retried, return immediately */
if (rc) {
return;
}
}
done:
/* Clean up the mailbox area */
/* Attempt to send pending mailboxes */
if (mbq) {
/* Attempt to send pending mailboxes */
}
}
return;
} /* emlxs_sli4_process_mbox_event() */
/*ARGSUSED*/
static void
{
#ifdef DEBUG_FASTPATH
#endif /* DEBUG_FASTPATH */
#ifdef DEBUG_FASTPATH
#endif /* DEBUG_FASTPATH */
case CMD_FCP_ICMND64_CR:
break;
case CMD_FCP_IREAD64_CR:
}
break;
case CMD_FCP_IWRITE64_CR:
cqe->CmdSpecific) {
} else {
}
}
break;
case CMD_ELS_REQUEST64_CR:
}
/* For LS_RJT, the driver populates the rsp buffer */
*iptr++ = ELS_CMD_LS_RJT;
}
break;
case CMD_GEN_REQUEST64_CR:
break;
case CMD_XMIT_SEQUENCE64_CR:
break;
case CMD_ABORT_XRI_CX:
break;
case CMD_FCP_TRECEIVE64_CX:
/* free memory for XRDY */
}
/*FALLTHROUGH*/
case CMD_FCP_TSEND64_CX:
case CMD_FCP_TRSP64_CX:
default:
}
} /* emlxs_CQE_to_IOCB() */
/*ARGSUSED*/
static void
{
uint16_t i;
continue;
}
cqe.RequestTag = i;
cp->hbaCmplCmd_sbp++;
#ifdef SFCT_SUPPORT
#ifdef FCT_IO_TRACE
}
#endif /* FCT_IO_TRACE */
#endif /* SFCT_SUPPORT */
#ifdef NODE_THROTTLE_SUPPORT
}
#endif /* NODE_THROTTLE_SUPPORT */
}
/* Copy entry to sbp's iocbq */
/* Exchange is no longer busy on-chip, free it */
(PACKET_POLLED | PACKET_ALLOCATED))) {
/* Add the IOCB to the channel list */
} else {
}
trigger = 1;
} else {
}
}
if (trigger) {
for (i = 0; i < hba->chan_count; i++) {
}
}
}
} /* emlxs_sli4_hba_flush_chipq() */
/*ARGSUSED*/
static void
{
/* 1 to 1 mapping between CQ and channel */
cp->hbaCmplCmd++;
"CQ ENTRY: OOR Cmpl: iotag=%d", request_tag);
} /* emlxs_sli4_process_oor_wqe_cmpl() */
/*ARGSUSED*/
static void
{
#ifdef SFCT_SUPPORT
#ifdef FCT_IO_TRACE
#endif /* FCT_IO_TRACE */
#endif /* SFCT_SUPPORT */
/* 1 to 1 mapping between CQ and channel */
if (!sbp) {
cp->hbaCmplCmd++;
"CQ ENTRY: NULL sbp. iotag=%d. Dropping...",
return;
}
if (sbp == STALE_PACKET) {
cp->hbaCmplCmd_sbp++;
"CQ ENTRY: Stale sbp. iotag=%d. Dropping...", request_tag);
return;
}
#ifdef NODE_THROTTLE_SUPPORT
}
#endif /* NODE_THROTTLE_SUPPORT */
}
cp->hbaCmplCmd++;
"CQ ENTRY: NULL sbp xrip %p. iotag=%d. Dropping...",
sbp, request_tag);
return;
}
#ifdef DEBUG_FASTPATH
"CQ ENTRY: process wqe compl");
#endif /* DEBUG_FASTPATH */
cp->hbaCmplCmd_sbp++;
/* Copy entry to sbp's iocbq */
/* Mark exchange as ABORT in progress */
"CQ ENTRY: XRI BUSY: iotag=%d xri=%d", request_tag,
} else {
/* Exchange is no longer busy on-chip, free it */
}
#ifdef SFCT_SUPPORT
#ifdef FCT_IO_TRACE
if (fct_cmd) {
}
#endif /* FCT_IO_TRACE */
#endif /* SFCT_SUPPORT */
/*
* If this is NOT a polled command completion
* or a driver allocated pkt, then defer pkt
* completion.
*/
(PACKET_POLLED | PACKET_ALLOCATED))) {
/* Add the IOCB to the channel list */
} else {
}
/* Delay triggering thread till end of ISR */
} else {
}
} /* emlxs_sli4_process_wqe_cmpl() */
/*ARGSUSED*/
static void
{
uint32_t i;
/* Verify WQ index */
if (wqi == 0xffff) {
"CQ ENTRY: Invalid WQid:%d. Dropping...",
return;
}
#ifdef DEBUG_FASTPATH
#endif /* DEBUG_FASTPATH */
/* Cmd ring may be available. Try sending more iocbs */
for (i = 0; i < hba->chan_count; i++) {
}
}
} /* emlxs_sli4_process_release_wqe() */
/*ARGSUSED*/
{
emlxs_queue_t *q;
case 1: /* ELS */
break;
case 0x20: /* CT */
break;
default:
return (NULL);
}
while (iocbq) {
/* Remove iocbq */
if (prev) {
}
}
}
q->q_cnt--;
break;
}
}
return (iocbq);
} /* emlxs_sli4_rxq_get() */
/*ARGSUSED*/
void
{
emlxs_queue_t *q;
case 1: /* ELS */
break;
case 0x20: /* CT */
break;
default:
return;
}
if (q->q_last) {
q->q_cnt++;
} else {
q->q_cnt = 1;
}
return;
} /* emlxs_sli4_rxq_put() */
static void
{
"RQ POST: rqid=%d count=1", rqid);
/* Ring the RQ doorbell once to repost the RQ buffer */
} /* emlxs_sli4_rq_post() */
/*ARGSUSED*/
static void
{
uint32_t i;
} else {
}
/* Validate the CQE */
/* Check status */
switch (status) {
case RQ_STATUS_SUCCESS: /* 0x10 */
break;
case RQ_STATUS_BUFLEN_EXCEEDED: /* 0x11 */
"CQ ENTRY: Unsol Rcv: Payload truncated.");
break;
case RQ_STATUS_NEED_BUFFER: /* 0x12 */
"CQ ENTRY: Unsol Rcv: Payload buffer needed.");
return;
case RQ_STATUS_FRAME_DISCARDED: /* 0x13 */
"CQ ENTRY: Unsol Rcv: Payload buffer discarded.");
return;
default:
"CQ ENTRY: Unsol Rcv: Unknown status=%x.",
status);
break;
}
/* Make sure there is a frame header */
if (hdr_size < sizeof (fc_frame_hdr_t)) {
"CQ ENTRY: Unsol Rcv: FC header too small. Dropping...");
return;
}
/* Verify RQ index */
if (hdr_rqi == 0xffff) {
"CQ ENTRY: Unsol Rcv: Invalid RQID:%d. Dropping...",
rqid);
return;
}
"CQ ENTRY: Unsol Rcv:%x rqid=%d,%d index=%d status=%x "
"hdr_size=%d data_size=%d",
/* Update host index */
hdr_rq->host_index++;
hdr_rq->host_index = 0;
}
/* Get the next header rqb */
sizeof (fc_frame_hdr_t), DDI_DMA_SYNC_FORKERNEL);
sizeof (fc_frame_hdr_t));
"RQ HDR[%d]: rctl:%x type:%x "
"sid:%x did:%x oxid:%x rxid:%x",
"RQ HDR[%d]: fctl:%x seq_id:%x seq_cnt:%x df_ctl:%x ro:%x",
/* Verify fc header type */
case 0: /* BLS */
"RQ ENTRY: Unexpected FC rctl (0x%x) "
"received. Dropping...",
goto done;
}
/* Make sure there is no payload */
if (data_size != 0) {
"RQ ENTRY: ABTS payload provided. Dropping...");
goto done;
}
buf_type = 0xFFFFFFFF;
break;
case 0x01: /* ELS */
/* Make sure there is a payload */
if (data_size == 0) {
"RQ ENTRY: Unsol Rcv: No ELS payload provided. "
"Dropping...");
goto done;
}
break;
case 0x20: /* CT */
/* Make sure there is a payload */
if (data_size == 0) {
"RQ ENTRY: Unsol Rcv: No CT payload provided. "
"Dropping...");
goto done;
}
break;
case 0x08: /* FCT */
/* Make sure there is a payload */
if (data_size == 0) {
"RQ ENTRY: Unsol Rcv: No FCP payload provided. "
"Dropping...");
goto done;
}
break;
default:
"RQ ENTRY: Unexpected FC type (0x%x) received. Dropping...",
goto done;
}
/* Fc Header is valid */
/* Check if this is an active sequence */
if (!iocbq) {
"RQ ENTRY: %s: First of sequence not"
" set. Dropping...",
label);
goto done;
}
}
"RQ ENTRY: %s: Sequence count not zero (%d). "
"Dropping...",
goto done;
}
/* Find vport */
for (i = 0; i < MAX_VPORTS; i++) {
break;
}
}
if (i == MAX_VPORTS) {
/* Allow unsol FLOGI & PLOGI for P2P */
"RQ ENTRY: %s: Invalid did=%x. Dropping...",
goto done;
}
}
/* Allocate an IOCBQ */
if (!iocbq) {
"RQ ENTRY: %s: Out of IOCB "
"resources. Dropping...",
label);
goto done;
}
/* Allocate a buffer */
if (!seq_mp) {
"RQ ENTRY: %s: Out of buffer "
"resources. Dropping...",
label);
goto done;
}
}
"RQ ENTRY: %s: Node not found. sid=%x",
}
/* Initialize the iocbq */
seq_len = 0;
seq_cnt = 0;
} else {
/* Check sequence order */
"RQ ENTRY: %s: Out of order frame received "
"(%d != %d). Dropping...",
goto done;
}
}
/* We now have an iocbq */
"RQ ENTRY: %s: No fabric connection. "
"Dropping...",
label);
goto done;
}
/* Save the frame data to our seq buffer */
/* Get the next data rqb */
(uint64_t)((unsigned long)
"RQ DAT[%d]: %08x %08x %08x %08x %08x %08x ...",
/* Check sequence length */
"RQ ENTRY: %s: Sequence buffer overflow. "
"(%d > %d). Dropping...",
goto done;
}
/* Copy data to local receive buffer */
}
/* If this is not the last frame of sequence, queue it. */
/* Save sequence header */
if (seq_cnt == 0) {
sizeof (fc_frame_hdr_t));
}
/* Update sequence info in iocb */
/* Queue iocbq for next frame */
/* Don't free resources */
/* No need to abort */
abort = 0;
goto done;
}
posted = 1;
/* End of sequence found. Process request now. */
if (seq_cnt > 0) {
/* Retrieve first frame of sequence */
sizeof (fc_frame_hdr_t));
}
/* Build rcv iocb and process it */
case 0: /* BLS */
"RQ ENTRY: %s: oxid:%x rxid %x sid:%x. Sending BLS ACC...",
/* Try to send abort response */
"RQ ENTRY: %s: Unable to alloc pkt. Dropping...",
label);
goto done;
}
/* Setup sbp / iocb for driver initiated cmd */
/* Free the temporary iocbq */
if (node) {
}
/* BLS ACC Response */
if (rpip) {
} else {
if (!rpip) {
"RQ ENTRY: %s: Unable to alloc "
"reserved RPI. Dropping...",
label);
goto done;
}
/* Store the reserved rpi */
}
}
/* Allocate an exchange for this command */
if (!xrip) {
"RQ ENTRY: %s: Unable to alloc XRI. Dropping...",
label);
goto done;
}
/* The temporary iocbq has been freed already */
break;
case 1: /* ELS */
cmd &= ELS_CMD_MASK;
/* Allow for P2P handshaking */
switch (cmd) {
case ELS_CMD_FLOGI:
dropit = 0;
break;
case ELS_CMD_PLOGI:
case ELS_CMD_PRLI:
dropit = 0;
}
break;
}
if (dropit) {
"RQ ENTRY: %s: Port not yet enabled. "
"Dropping...",
label);
goto done;
}
}
if (cmd != ELS_CMD_LOGO) {
}
if (!rpip) {
/* Use the fabric rpi */
}
if (!xrip) {
"RQ ENTRY: %s: Out of exchange "
"resources. Dropping...",
label);
goto done;
}
/* Build CMD_RCV_ELS64_CX */
}
}
#ifdef SFCT_SUPPORT
}
#endif /* SFCT_SUPPORT */
break;
#ifdef SFCT_SUPPORT
case 8: /* FCT */
"RQ ENTRY: %s: Port not yet enabled. "
"Dropping...",
label);
goto done;
}
if (!rpip) {
"RQ ENTRY: %s: Port not logged in. "
"Dropping...",
label);
goto done;
}
if (!xrip) {
"RQ ENTRY: %s: Out of exchange "
"resources. Dropping...",
label);
goto done;
}
/* Build CMD_RCV_SEQUENCE64_CX */
}
/* pass xrip to FCT in the iocbq */
#define EMLXS_FIX_CISCO_BUG1
#ifdef EMLXS_FIX_CISCO_BUG1
{
"RQ ENTRY: Bad CDB fixed");
*ptr++ = 0;
*ptr = 0;
}
}
#endif
break;
#endif /* SFCT_SUPPORT */
case 0x20: /* CT */
"RQ ENTRY: %s: Port not yet enabled. "
"Dropping...",
label);
goto done;
}
if (!node) {
"RQ ENTRY: %s: Node not found (did=%x). "
"Dropping...",
goto done;
}
if (!rpip) {
"RQ ENTRY: %s: RPI not found (did=%x rpi=%d). "
"Dropping...",
goto done;
}
if (!xrip) {
"RQ ENTRY: %s: Out of exchange "
"resources. Dropping...",
label);
goto done;
}
/* Build CMD_RCV_SEQ64_CX */
}
break;
}
/* Sequence handled, no need to abort */
abort = 0;
done:
if (!posted) {
}
if (abort) {
/* Send ABTS for this exchange */
/* !!! Currently, we have no implementation for this !!! */
abort = 0;
}
/* Return memory resources to pools */
if (iocbq) {
}
}
#ifdef FMA_SUPPORT
!= DDI_FM_OK) {
"sli4_process_unsol_rcv: hdl=%p",
0, 0);
}
#endif
return;
} /* emlxs_sli4_process_unsol_rcv() */
/*ARGSUSED*/
static void
{
/* EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg, */
/* "CQ ENTRY: process xri aborted ignored"); */
return;
}
"CQ ENTRY: XRI Aborted: xri=%d IA=%d EO=%d BR=%d",
"CQ ENTRY: XRI Aborted: xri=%d flag=%x. Bad state.",
return;
}
/* Exchange is no longer busy on-chip, free it */
return;
} /* emlxs_sli4_process_xri_aborted () */
/*ARGSUSED*/
static void
{
int num_entries = 0;
/* EMLXS_PORT_LOCK must be held when entering this routine */
(uint64_t)((unsigned long)
4096, DDI_DMA_SYNC_FORKERNEL);
for (;;) {
break;
}
#ifdef DEBUG_CQE
#endif /* DEBUG_CQE */
num_entries++;
cq->host_index++;
cq->host_index = 0;
} else {
cqe++;
}
/* Now handle specific cq type */
(CQE_ASYNC_t *)&cq_entry);
} else {
(CQE_MBOX_t *)&cq_entry);
}
} else { /* EMLXS_CQ_TYPE_GROUP2 */
case CQE_TYPE_WQ_COMPLETION:
(CQE_CmplWQ_t *)&cq_entry);
} else {
(CQE_CmplWQ_t *)&cq_entry);
}
break;
case CQE_TYPE_RELEASE_WQE:
(CQE_RelWQ_t *)&cq_entry);
break;
case CQE_TYPE_UNSOL_RCV:
case CQE_TYPE_UNSOL_RCV_V1:
(CQE_UnsolRcv_t *)&cq_entry);
break;
case CQE_TYPE_XRI_ABORTED:
(CQE_XRI_Abort_t *)&cq_entry);
break;
default:
"Invalid CQ entry %d: %08x %08x %08x %08x",
break;
}
}
}
/* Number of times this routine gets called for this CQ */
/* num_entries is the number of CQEs we process in this specific CQ */
cqdb |= CQ_DB_REARM;
if (num_entries != 0) {
}
#ifdef DEBUG_FASTPATH
#endif /* DEBUG_FASTPATH */
/* EMLXS_PORT_LOCK must be held when exiting this routine */
} /* emlxs_sli4_process_cq() */
/*ARGSUSED*/
static void
{
uint32_t i;
int num_entries = 0;
/* EMLXS_PORT_LOCK must be held when entering this routine */
hba->intr_busy_cnt ++;
(uint64_t)((unsigned long)
4096, DDI_DMA_SYNC_FORKERNEL);
for (;;) {
break;
}
#ifdef DEBUG_FASTPATH
#endif /* DEBUG_FASTPATH */
*ptr = 0;
num_entries++;
eq->host_index++;
eq->host_index = 0;
} else {
ptr++;
}
/* Verify CQ index */
if (cqi == 0xffff) {
"EQE: Invalid CQid: %d. Dropping...",
continue;
}
#ifdef DEBUG_FASTPATH
#endif /* DEBUG_FASTPATH */
}
/* Number of times the ISR for this EQ gets called */
/* num_entries is the number of EQEs we process in this specific ISR */
}
#ifdef DEBUG_FASTPATH
#endif /* DEBUG_FASTPATH */
if (num_entries != 0) {
for (i = 0; i < hba->chan_count; i++) {
}
}
}
/* EMLXS_PORT_LOCK must be held when exiting this routine */
hba->intr_busy_cnt --;
} /* emlxs_sli4_process_eq() */
#ifdef MSI_SUPPORT
/*ARGSUSED*/
static uint32_t
{
#ifdef DEBUG_FASTPATH
#endif /* DEBUG_FASTPATH */
int rc;
#ifdef DEBUG_FASTPATH
#endif /* DEBUG_FASTPATH */
/* Check for legacy interrupt handling */
return (rc);
}
/* Get MSI message id */
/* Validate the message id */
msgid = 0;
}
return (DDI_INTR_UNCLAIMED);
}
/* The eq[] index == the MSI vector number */
return (DDI_INTR_CLAIMED);
} /* emlxs_sli4_msi_intr() */
#endif /* MSI_SUPPORT */
/*ARGSUSED*/
static int
{
#ifdef DEBUG_FASTPATH
#endif /* DEBUG_FASTPATH */
#ifdef DEBUG_FASTPATH
"intxINTR arg:%p", arg);
#endif /* DEBUG_FASTPATH */
return (DDI_INTR_UNCLAIMED);
}
return (DDI_INTR_CLAIMED);
} /* emlxs_sli4_intx_intr() */
static void
{
uint32_t j;
return;
}
j = 0;
while (j++ < 10000) {
if ((hba->mbox_queue_flag == 0) &&
(hba->intr_busy_cnt == 0)) {
break;
}
BUSYWAIT_US(100);
}
"Board kill failed. Adapter busy, %d, %d.",
return;
}
} /* emlxs_sli4_hba_kill() */
extern void
{
"Reset All failed. Invalid Operation.");
return;
}
/* Issue a Firmware Reset All Request */
if (flag) {
} else {
}
} /* emlxs_sli4_hba_reset_all() */
static void
{
int i;
int num_cq;
/* ARM EQ / CQs */
for (i = 0; i < num_cq; i++) {
data |= CQ_DB_REARM;
}
for (i = 0; i < hba->intr_count; i++) {
}
} /* emlxs_sli4_enable_intr() */
static void
{
if (att) {
return;
}
/* Short of reset, we cannot disable interrupts */
} /* emlxs_sli4_disable_intr() */
static void
{
uint32_t i;
/* Already free */
return;
}
}
"XRIs in use during free!: %p %p != %p\n",
}
}
for (i = 0; i < hba->intr_count; i++) {
}
for (i = 0; i < EMLXS_MAX_CQS; i++) {
}
for (i = 0; i < EMLXS_MAX_WQS; i++) {
}
for (i = 0; i < EMLXS_MAX_RXQS; i++) {
}
for (i = 0; i < EMLXS_MAX_RQS; i++) {
}
/* Free the MQ */
}
} /* emlxs_sli4_resource_free() */
static int
{
int num_eq;
int num_wq;
uint16_t i;
uint32_t j;
uint32_t k;
char *virt;
char *tmp_virt;
void *data_handle;
void *dma_handle;
/* Already allocated */
return (0);
}
case 0:
break;
case 2:
default:
break;
}
/* EQs - 1 per Interrupt vector */
/* Calculate total dmable memory we need */
/* WARNING: make sure each section is aligned on 4K boundary */
/* EQ */
/* CQ */
/* WQ */
/* MQ */
/* RQ */
/* RQB/E */
/* SGL */
/* RPI Header Templates */
/* Bytes per extent */
/* Pages required per extent (page == 4096 bytes) */
k = (j/4096) + ((j%4096)? 1:0);
/* Total size */
}
/* Allocate slim2 for SLI4 */
"Unable to allocate internal memory for SLI4: %d",
count);
goto failed;
}
/* Assign memory to SGL, Head Template, EQ, CQ, WQ, RQ and MQ */
/* Allocate space for queues */
/* EQ */
size = 4096;
for (i = 0; i < num_eq; i++) {
MUTEX_DRIVER, NULL);
}
/* CQ */
for (i = 0; i < (num_wq + EMLXS_CQ_OFFSET_WQ); i++) {
}
/* WQ */
for (i = 0; i < num_wq; i++) {
}
/* MQ */
size = 4096;
/* RXQ */
for (i = 0; i < EMLXS_MAX_RXQS; i++) {
NULL);
}
/* RQ */
size = 4096;
for (i = 0; i < EMLXS_MAX_RQS; i++) {
}
/* RQB/E */
for (i = 0; i < EMLXS_MAX_RQS; i++) {
/* Initialize the RQEs */
for (k = 0; k < RQB_COUNT; k++) {
#ifdef DEBUG_RQE
"RQ_ALLOC: rq[%d] rqb[%d,%d]=%p iotag=%d",
#endif /* DEBUG_RQE */
rqe++;
}
}
(uint64_t)((unsigned long)
/* Sync the RQ buffer list */
}
/* 4K Alignment */
/* SGL */
/* Initialize double linked lists */
iotag = 1;
/* We don't use XRI==0, since it also represents an */
/* uninitialized exchange */
xrip++;
continue;
}
/* Add xrip to end of free list */
/* Allocate SGL for this xrip */
xrip++;
}
/* 4K Alignment */
/* RPI Header Templates */
}
#ifdef FMA_SUPPORT
!= DDI_FM_OK) {
"sli4_resource_alloc: hdl=%p",
goto failed;
}
}
#endif /* FMA_SUPPORT */
return (0);
(void) emlxs_sli4_resource_free(hba);
return (ENOMEM);
} /* emlxs_sli4_resource_alloc */
extern void
{
uint32_t i;
/* EQ */
for (i = 0; i < hba->intr_count; i++) {
}
/* CQ */
for (i = 0; i < (num_wq + EMLXS_CQ_OFFSET_WQ); i++) {
}
/* WQ */
for (i = 0; i < num_wq; i++) {
}
/* RQ */
for (i = 0; i < EMLXS_MAX_RQS; i++) {
}
} /* emlxs_sli4_zero_queue_stat */
extern XRIobj_t *
{
"Unable to reserve XRI. type=%d",
type);
return (NULL);
}
if ((!iotag) ||
/*
* No more command slots available, retry later
*/
"Adapter Busy. Unable to reserve iotag. type=%d",
type);
return (NULL);
}
/* Take it off free list */
/* Add it to end of inuse list */
return (xrip);
} /* emlxs_sli4_reserve_xri() */
extern uint32_t
{
if (lock) {
}
if (lock) {
}
"sli4_unreserve_xri:%d already freed.", xri);
return (0);
}
/* Flush this unsolicited ct command */
}
if (lock) {
}
"sli4_unreserve_xri:%d in use. type=%d",
return (1);
}
"sli4_unreserve_xri:%d sbp dropped:%p type=%d",
}
"sli4_unreserve_xri:%d unreserved. type=%d",
}
if (xrip->reserved_rpip) {
}
/* Take it off inuse list */
/* Add it to end of free list */
if (lock) {
}
return (0);
} /* emlxs_sli4_unreserve_xri() */
XRIobj_t *
{
if (!xrip) {
if (!xrip) {
"sli4_register_xri:%d XRI not found.", xri);
return (NULL);
}
}
"sli4_register_xri:%d Invalid XRI. xrip=%p "
"state=%x flag=%x",
return (NULL);
}
if ((!iotag) ||
"sli4_register_xri:%d Invalid fc_table entry. "
"iotag=%d entry=%p",
return (NULL);
}
/* If we did not have a registered RPI when we reserved */
/* this exchange, check again now. */
/* Move the XRI to the new RPI */
}
}
return (xrip);
} /* emlxs_sli4_register_xri() */
/* Performs both reserve and register functions for XRI */
static XRIobj_t *
{
return (NULL);
}
/* Get the iotag by registering the packet */
if ((!iotag) ||
/*
* No more command slots available, retry later
*/
"Adapter Busy. Unable to alloc iotag:(0x%x)(%p) type=%d",
return (NULL);
}
/* Take it off free list */
/* Add it to end of inuse list */
return (xrip);
} /* emlxs_sli4_alloc_xri() */
/* EMLXS_FCTAB_LOCK must be held to enter */
extern XRIobj_t *
{
return (xrip);
}
}
"Unable to find XRI x%x", xri);
return (NULL);
} /* emlxs_sli4_find_xri() */
extern void
{
if (lock) {
}
if (xrip) {
if (lock) {
}
"Free XRI:%x, Already freed. type=%d",
return;
}
}
}
}
if (xrip->reserved_rpip) {
}
/* Take it off inuse list */
/* Add it to end of free list */
}
if (sbp) {
if (lock) {
}
"Free XRI: sbp invalid. sbp=%p flags=%x xri=%d",
return;
}
}
/* Exchange is still reserved */
}
}
}
if (xrip) {
}
if (lock) {
}
/* Clean up the sbp */
hba->channel_tx_count--;
}
}
} else {
if (lock) {
}
}
} /* emlxs_sli4_free_xri() */
static int
{
uint32_t i;
uint32_t j;
"Unable to POST_SGL. Mailbox cmd=%x ",
mb->mbxCommand);
return (EIO);
}
/*
* Signifies a non embedded command
*/
post_sgl =
/* For each extent */
while (cnt) {
cnt--;
xrip++;
continue;
}
sizeof (IOCTL_FCOE_CFG_POST_SGL_PAGES)) /
sizeof (FCOE_SGL_PAGES);
cnt--;
xrip++;
}
MBX_SUCCESS) {
"Unable to POST_SGL. Mailbox cmd=%x "
"status=%x XRI cnt:%d start:%d",
return (EIO);
}
}
}
return (0);
} /* emlxs_sli4_post_sgl_pages() */
static int
{
uint32_t j;
uint32_t k;
return (0);
}
/* Bytes per extent */
/* Pages required per extent (page == 4096 bytes) */
/* For each extent */
/*
* Signifies an embedded command
*/
sizeof (IOCTL_FCOE_POST_HDR_TEMPLATES) + IOCTL_HEADER_SZ;
sizeof (IOCTL_FCOE_POST_HDR_TEMPLATES);
post_hdr =
for (k = 0; k < num_pages; k++) {
addr += 4096;
}
MBX_SUCCESS) {
"Unable to POST_HDR_TEMPLATES. Mailbox cmd=%x "
"status=%x ",
return (EIO);
}
}
return (0);
} /* emlxs_sli4_post_hdr_tmplates() */
static int
{
uint16_t i, j;
/*
* The first CQ is reserved for ASYNC events,
* the second is reserved for unsol rcv, the rest
* correspond to WQs. (WQ0 -> CQ2, WQ1 -> CQ3, ...)
*/
total_cq = 0;
total_wq = 0;
/* Create EQ's */
for (i = 0; i < hba->intr_count; i++) {
MBX_SUCCESS) {
"Unable to Create EQ %d: Mailbox cmd=%x status=%x ",
return (EIO);
}
if (i == 0) {
}
/* Create CQ's */
for (j = 0; j < num_cq; j++) {
/* Reuse mbq from previous mbox */
MBX_SUCCESS) {
&emlxs_init_failed_msg, "Unable to Create "
"CQ %d: Mailbox cmd=%x status=%x ",
return (EIO);
}
cq = (IOCTL_COMMON_CQ_CREATE *)
switch (total_cq) {
case EMLXS_CQ_MBOX:
/* First CQ is for async event handling */
break;
case EMLXS_CQ_RCV:
/* Second CQ is for unsol receive handling */
break;
default:
/* Setup CQ to channel mapping */
break;
}
18, 0);
total_cq++;
}
/* Create WQ's */
for (j = 0; j < num_wq; j++) {
/* Reuse mbq from previous mbox */
MBX_SUCCESS) {
&emlxs_init_failed_msg, "Unable to Create "
"WQ %d: Mailbox cmd=%x status=%x ",
return (EIO);
}
wq = (IOCTL_FCOE_WQ_CREATE *)
18, 0);
total_wq++;
}
hba->last_msiid = i;
}
/* We assume 1 RQ pair will handle ALL incoming data */
/* Create RQs */
for (i = 0; i < EMLXS_MAX_RQS; i++) {
/* Personalize the RQ */
switch (i) {
case 0:
break;
case 1:
break;
default:
}
/* Reuse mbq from previous mbox */
MBX_SUCCESS) {
"Unable to Create RQ %d: Mailbox cmd=%x status=%x ",
return (EIO);
}
"RQ CREATE: rq[%d].qid=%d cqid=%d",
/* Initialize the host_index */
/* If Data queue was just created, */
/* then post buffers using the header qid */
if ((i & 0x1)) {
/* Ring the RQ doorbell to post buffers */
"RQ CREATE: Doorbell rang: qid=%d count=%d",
}
}
/* Create MQ */
/* Personalize the MQ */
/* Reuse mbq from previous mbox */
MBX_SUCCESS) {
"Unable to Create MQ_EXT %d: Mailbox cmd=%x status=%x ",
/* Reuse mbq from previous mbox */
MBX_SUCCESS) {
"Unable to Create MQ %d: Mailbox cmd=%x status=%x ",
return (EIO);
}
return (0);
}
return (0);
} /* emlxs_sli4_create_queues() */
extern void
{
/* Perform SLI4 level timer checks */
return;
} /* emlxs_sli4_timer() */
static void
{
return;
}
/* Return if timer hasn't expired */
return;
}
/* The first to service the mbox queue will clear the timer */
hba->mbox_timer = 0;
if (hba->mbox_queue_flag) {
}
}
if (mb) {
switch (hba->mbox_queue_flag) {
case MBX_NOWAIT:
"%s: Nowait.",
break;
case MBX_SLEEP:
"%s: mb=%p Sleep.",
mb);
break;
case MBX_POLL:
"%s: mb=%p Polled.",
mb);
break;
default:
"%s: mb=%p (%d).",
break;
}
} else {
}
/* Perform mailbox cleanup */
/* This will wake any sleeping or polling threads */
/* Trigger adapter shutdown */
return;
} /* emlxs_sli4_timer_check_mbox() */
extern void
{
void *msg;
return;
}
if (err) {
msg = &emlxs_sli_err_msg;
} else {
}
if (cnt) {
}
if (cnt > 6) {
}
if (cnt > 12) {
}
if (cnt > 18) {
}
if (cnt > 24) {
}
if (cnt > 30) {
}
if (cnt > 36) {
}
} /* emlxs_data_dump() */
extern void
{
case SLI_INTF_IF_TYPE_0:
"%s: ueLow:%08x ueHigh:%08x on1:%08x on2:%08x", str,
break;
case SLI_INTF_IF_TYPE_2:
"%s: status:%08x err1:%08x err2:%08x", str,
break;
}
#ifdef FMA_SUPPORT
/* Access handle validation */
#endif /* FMA_SUPPORT */
} /* emlxs_ue_dump() */
static void
{
return;
}
case SLI_INTF_IF_TYPE_0:
"Host Error: ueLow:%08x ueHigh:%08x maskLow:%08x "
"maskHigh:%08x flag:%08x",
error = 2;
}
break;
case SLI_INTF_IF_TYPE_2:
if ((status & SLI_STATUS_ERROR) ||
if (error == 1) {
"Host Error: status:%08x err1:%08x "
"err2:%08x flag:%08x",
} else {
"Host Error: status:%08x err1:%08x "
"err2:%08x flag:%08x",
}
}
break;
}
if (error == 2) {
} else if (error == 1) {
}
#ifdef FMA_SUPPORT
/* Access handle validation */
#endif /* FMA_SUPPORT */
} /* emlxs_sli4_poll_erratt() */
static uint32_t
{
/* Check for invalid node ids to register */
return (1);
}
if (did & 0xff000000) {
return (1);
}
/* We don't register our own did */
return (1);
}
if (did != FABRIC_DID) {
"Invalid service parameters. did=%06x rval=%d", did,
rval);
return (1);
}
}
/* Check if the node limit has been reached */
"Limit reached. did=%06x count=%d", did,
port->node_count);
return (1);
}
return (rval);
} /* emlxs_sli4_reg_did() */
static uint32_t
{
if (!node) {
/* Unreg all nodes */
(void) emlxs_sli4_unreg_all_nodes(port);
return (1);
}
/* Check for base node */
/* Just flush base node */
0, 0, 0);
(void) emlxs_chipq_node_flush(port, 0,
/* Return now */
return (1);
}
"unreg_node:%p did=%x rpi=%d",
if (!rpip) {
"unreg_node:%p did=%x rpi=%d. RPI not found.",
return (1);
}
(void *)iocbq);
return (rval);
} /* emlxs_sli4_unreg_node() */
extern uint32_t
{
int i;
/* Set the node tags */
/* We will process all nodes with this tag */
found = 0;
for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
found = 1;
}
}
if (!found) {
return (0);
}
for (;;) {
found = 0;
for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
continue;
}
found = 1;
break;
}
if (found) {
break;
}
}
if (!found) {
break;
}
}
return (0);
} /* emlxs_sli4_unreg_all_nodes() */
static void
{
/* Handle link down */
(void) emlxs_fcf_linkdown_notify(port);
return;
}
/* Link is up */
/* Set linkspeed */
case PHY_1GHZ_LINK:
break;
case PHY_10GHZ_LINK:
break;
default:
"sli4_handle_fcoe_link_event: Unknown link speed=%x.",
break;
}
/* Set qos_linkspeed */
/* Set topology */
(void) emlxs_fcf_linkup_notify(port);
return;
} /* emlxs_sli4_handle_fcoe_link_event() */
static void
{
/* Handle link down */
(void) emlxs_fcf_linkdown_notify(port);
return;
}
/* Link is up */
/* Set linkspeed */
case 1:
break;
case 2:
break;
case 4:
break;
case 8:
break;
case 10:
break;
case 16:
break;
default:
"sli4_handle_fc_link_att: Unknown link speed=%x.",
break;
}
/* Set qos_linkspeed */
/* Set topology */
(void) emlxs_fcf_linkup_notify(port);
return;
} /* emlxs_sli4_handle_fc_link_att() */
static int
{
uint32_t i;
return (0);
}
/* Discover XRI Extents */
"Unable to discover XRI extents. Mailbox cmd=%x status=%x",
return (EIO);
}
/* Allocate XRI Extents */
"Unable to allocate XRI extents. Mailbox cmd=%x status=%x",
return (EIO);
}
"XRI Ext: size=%d cnt=%d/%d",
"XRI Ext%d: %d, %d, %d, %d", i,
}
/* Discover RPI Extents */
"Unable to discover RPI extents. Mailbox cmd=%x status=%x",
return (EIO);
}
/* Allocate RPI Extents */
"Unable to allocate RPI extents. Mailbox cmd=%x status=%x",
return (EIO);
}
"RPI Ext: size=%d cnt=%d/%d",
"RPI Ext%d: %d, %d, %d, %d", i,
}
/* Discover VPI Extents */
"Unable to discover VPI extents. Mailbox cmd=%x status=%x",
return (EIO);
}
/* Allocate VPI Extents */
"Unable to allocate VPI extents. Mailbox cmd=%x status=%x",
return (EIO);
}
"VPI Ext: size=%d cnt=%d/%d",
"VPI Ext%d: %d, %d, %d, %d", i,
}
/* Discover VFI Extents */
"Unable to discover VFI extents. Mailbox cmd=%x status=%x",
return (EIO);
}
/* Allocate VFI Extents */
"Unable to allocate VFI extents. Mailbox cmd=%x status=%x",
return (EIO);
}
"VFI Ext: size=%d cnt=%d/%d",
"VFI Ext%d: %d, %d, %d, %d", i,
}
return (0);
} /* emlxs_sli4_init_extents() */
extern uint32_t
{
uint32_t i;
uint32_t j;
return (rpi);
} /* emlxs_sli4_index_to_rpi */
extern uint32_t
{
uint32_t i;
break;
}
}
return (index);
} /* emlxs_sli4_rpi_to_index */
extern uint32_t
{
uint32_t i;
uint32_t j;
return (xri);
} /* emlxs_sli4_index_to_xri */
extern uint32_t
{
uint32_t i;
uint32_t j;
return (vpi);
} /* emlxs_sli4_index_to_vpi */
extern uint32_t
{
uint32_t i;
break;
}
}
return (index);
} /* emlxs_sli4_vpi_to_index */
extern uint32_t
{
uint32_t i;
uint32_t j;
return (vfi);
} /* emlxs_sli4_index_to_vfi */
static uint16_t
{
uint16_t i;
if (rqid < 0xffff) {
for (i = 0; i < EMLXS_MAX_RQS; i++) {
return (i);
}
}
}
return (0xffff);
} /* emlxs_sli4_rqid_to_index */
static uint16_t
{
uint16_t i;
if (wqid < 0xffff) {
for (i = 0; i < EMLXS_MAX_WQS; i++) {
return (i);
}
}
}
return (0xffff);
} /* emlxs_sli4_wqid_to_index */
static uint16_t
{
uint16_t i;
if (cqid < 0xffff) {
for (i = 0; i < EMLXS_MAX_CQS; i++) {
return (i);
}
}
}
return (0xffff);
} /* emlxs_sli4_cqid_to_index */