Print this page
MFV: illumos-omnios@aea0472ecb9ee91fa70556d6f6a941c10c989f1d
Add support for Emulex Corporation Lancer Gen6: LPe32000 FC Host Adapter
Author: Andy Fiddaman <omnios@citrus-it.co.uk>
NEX-8705 Drivers for ATTO Celerity FC-162E Gen 5 and Celerity FC-162P Gen 6 16GB FC cards support
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
NEX-1878 update emlxs from source provided by Emulex
*** 20,29 ****
--- 20,30 ----
*/
/*
* Copyright (c) 2004-2012 Emulex. All rights reserved.
* Use is subject to license terms.
+ * Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
*/
#include <emlxs.h>
*** 119,128 ****
--- 120,142 ----
static void emlxs_sli4_timer(emlxs_hba_t *hba);
static void emlxs_sli4_timer_check_mbox(emlxs_hba_t *hba);
+ static void emlxs_sli4_gpio_timer_start(emlxs_hba_t *hba);
+
+ static void emlxs_sli4_gpio_timer_stop(emlxs_hba_t *hba);
+
+ static void emlxs_sli4_gpio_timer(void *arg);
+
+ static void emlxs_sli4_check_gpio(emlxs_hba_t *hba);
+
+ static uint32_t emlxs_sli4_fix_gpio(emlxs_hba_t *hba,
+ uint8_t *pin, uint8_t *pinval);
+
+ static uint32_t emlxs_sli4_fix_gpio_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq);
+
static void emlxs_sli4_poll_erratt(emlxs_hba_t *hba);
extern XRIobj_t *emlxs_sli4_reserve_xri(emlxs_port_t *port,
RPIobj_t *rpip, uint32_t type, uint16_t rx_id);
static int emlxs_check_hdw_ready(emlxs_hba_t *);
*** 330,348 ****
--- 344,387 ----
cfg[CFG_NUM_WQ].current = 1;
hba->chan_count = hba->intr_count * cfg[CFG_NUM_WQ].current;
}
hba->channel_fcp = 0; /* First channel */
+ /* Gen6 chips only support P2P topologies */
+ if ((hba->model_info.flags & EMLXS_FC_GEN6) &&
+ cfg[CFG_TOPOLOGY].current != 2) {
+ EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
+ "Loop topologies are not supported by this HBA. "
+ "Forcing topology to P2P.");
+ cfg[CFG_TOPOLOGY].current = 2;
+ }
+
/* Default channel for everything else is the last channel */
hba->channel_ip = hba->chan_count - 1;
hba->channel_els = hba->chan_count - 1;
hba->channel_ct = hba->chan_count - 1;
hba->fc_iotag = 1;
hba->io_count = 0;
hba->channel_tx_count = 0;
+ /* Specific to ATTO G5 boards */
+ if (hba->model_info.flags & EMLXS_GPIO_LEDS) {
+ /* Set hard-coded GPIO pins */
+ if (hba->pci_function_number) {
+ hba->gpio_pin[EMLXS_GPIO_PIN_LO] = 27;
+ hba->gpio_pin[EMLXS_GPIO_PIN_HI] = 28;
+ hba->gpio_pin[EMLXS_GPIO_PIN_ACT] = 29;
+ hba->gpio_pin[EMLXS_GPIO_PIN_LASER] = 8;
+ } else {
+ hba->gpio_pin[EMLXS_GPIO_PIN_LO] = 13;
+ hba->gpio_pin[EMLXS_GPIO_PIN_HI] = 25;
+ hba->gpio_pin[EMLXS_GPIO_PIN_ACT] = 26;
+ hba->gpio_pin[EMLXS_GPIO_PIN_LASER] = 12;
+ }
+ }
+
/* Initialize the local dump region buffer */
bzero(&hba->sli.sli4.dump_region, sizeof (MBUF_INFO));
hba->sli.sli4.dump_region.size = EMLXS_DUMP_REGION_SIZE;
hba->sli.sli4.dump_region.flags = FC_MBUF_DMA | FC_MBUF_SNGLSG
| FC_MBUF_DMA32;
*** 1327,1342 ****
emlxs_build_prog_types(hba, vpd);
}
/* Create the symbolic names */
(void) snprintf(hba->snn, (sizeof (hba->snn)-1),
! "Emulex %s FV%s DV%s %s",
! hba->model_info.model, hba->vpd.fw_version, emlxs_version,
(char *)utsname.nodename);
(void) snprintf(hba->spn, (sizeof (hba->spn)-1),
! "Emulex PPN-%01x%01x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
hba->wwpn.nameType, hba->wwpn.IEEEextMsn, hba->wwpn.IEEEextLsb,
hba->wwpn.IEEE[0], hba->wwpn.IEEE[1], hba->wwpn.IEEE[2],
hba->wwpn.IEEE[3], hba->wwpn.IEEE[4], hba->wwpn.IEEE[5]);
--- 1366,1383 ----
emlxs_build_prog_types(hba, vpd);
}
/* Create the symbolic names */
(void) snprintf(hba->snn, (sizeof (hba->snn)-1),
! "%s %s FV%s DV%s %s",
! hba->model_info.manufacturer, hba->model_info.model,
! hba->vpd.fw_version, emlxs_version,
(char *)utsname.nodename);
(void) snprintf(hba->spn, (sizeof (hba->spn)-1),
! "%s PPN-%01x%01x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
! hba->model_info.manufacturer,
hba->wwpn.nameType, hba->wwpn.IEEEextMsn, hba->wwpn.IEEEextLsb,
hba->wwpn.IEEE[0], hba->wwpn.IEEE[1], hba->wwpn.IEEE[2],
hba->wwpn.IEEE[3], hba->wwpn.IEEE[4], hba->wwpn.IEEE[5]);
*** 1403,1412 ****
--- 1444,1457 ----
if (mbq) {
(void) kmem_free((uint8_t *)mbq, sizeof (MAILBOXQ));
mbq = NULL;
mb = NULL;
}
+
+ if (hba->model_info.flags & EMLXS_GPIO_LEDS)
+ emlxs_sli4_gpio_timer_start(hba);
+
return (0);
failed3:
EMLXS_STATE_CHANGE(hba, FC_ERROR);
*** 1448,1457 ****
--- 1493,1505 ----
static void
emlxs_sli4_offline(emlxs_hba_t *hba, uint32_t reset_requested)
{
/* Reverse emlxs_sli4_online */
+ if (hba->model_info.flags & EMLXS_GPIO_LEDS)
+ emlxs_sli4_gpio_timer_stop(hba);
+
mutex_enter(&EMLXS_PORT_LOCK);
if (hba->flag & FC_INTERLOCKED) {
mutex_exit(&EMLXS_PORT_LOCK);
goto killed;
}
*** 2361,2370 ****
--- 2409,2427 ----
hba->heartbeat_active = 0;
hba->discovery_timer = 0;
hba->linkup_timer = 0;
hba->loopback_tics = 0;
+ /* Specific to ATTO G5 boards */
+ if (hba->model_info.flags & EMLXS_GPIO_LEDS) {
+ /* Assume the boot driver enabled all LEDs */
+ hba->gpio_current =
+ EMLXS_GPIO_LO | EMLXS_GPIO_HI | EMLXS_GPIO_ACT;
+ hba->gpio_desired = 0;
+ hba->gpio_bit = 0;
+ }
+
/* Reset the port objects */
for (i = 0; i < MAX_VPORTS; i++) {
vport = &VPORT(i);
vport->flag &= EMLXS_PORT_RESET_MASK;
*** 2553,2563 ****
iocbq = (IOCBQ *) &sbp->iocbq;
wqe = &iocbq->wqe;
pkt = PRIV2PKT(sbp);
xrip = sbp->xrip;
! sge = xrip->SGList.virt;
#if (EMLXS_MODREV >= EMLXS_MODREV3)
cp_cmd = pkt->pkt_cmd_cookie;
cp_data = pkt->pkt_data_cookie;
#else
--- 2610,2620 ----
iocbq = (IOCBQ *) &sbp->iocbq;
wqe = &iocbq->wqe;
pkt = PRIV2PKT(sbp);
xrip = sbp->xrip;
! sge = xrip->SGList->virt;
#if (EMLXS_MODREV >= EMLXS_MODREV3)
cp_cmd = pkt->pkt_cmd_cookie;
cp_data = pkt->pkt_data_cookie;
#else
*** 2703,2713 ****
"fct_bde_setup: Only 1 sglist entry supported: %d",
sbp->fct_buf->db_sglist_length);
return (1);
}
! sge = xrip->SGList.virt;
if (iocb->ULPCOMMAND == CMD_FCP_TRECEIVE64_CX) {
mp = emlxs_mem_buf_alloc(hba, EMLXS_XFER_RDY_SIZE);
if (!mp || !mp->virt || !mp->phys) {
--- 2760,2770 ----
"fct_bde_setup: Only 1 sglist entry supported: %d",
sbp->fct_buf->db_sglist_length);
return (1);
}
! sge = xrip->SGList->virt;
if (iocb->ULPCOMMAND == CMD_FCP_TRECEIVE64_CX) {
mp = emlxs_mem_buf_alloc(hba, EMLXS_XFER_RDY_SIZE);
if (!mp || !mp->virt || !mp->phys) {
*** 3986,3996 ****
/* Make size a multiple of 4 */
if (sge_size & 3) {
sge_size = (sge_size + 3) & 0xfffffffc;
}
sge_addr = cp_cmd->dmac_laddress;
! sge = xrip->SGList.virt;
stage_sge.addrHigh = PADDR_HI(sge_addr);
stage_sge.addrLow = PADDR_LO(sge_addr);
stage_sge.length = sge_size;
stage_sge.offset = 0;
--- 4043,4053 ----
/* Make size a multiple of 4 */
if (sge_size & 3) {
sge_size = (sge_size + 3) & 0xfffffffc;
}
sge_addr = cp_cmd->dmac_laddress;
! sge = xrip->SGList->virt;
stage_sge.addrHigh = PADDR_HI(sge_addr);
stage_sge.addrLow = PADDR_LO(sge_addr);
stage_sge.length = sge_size;
stage_sge.offset = 0;
*** 4178,4188 ****
IOCBQ *iocbq;
IOCB *iocb;
NODELIST *node;
uint16_t iotag;
uint32_t did;
- off_t offset;
pkt = PRIV2PKT(sbp);
did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
cp = &hba->chan[channel];
--- 4235,4244 ----
*** 4240,4266 ****
}
/* DEBUG */
#ifdef DEBUG_FCP
EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
! "FCP: SGLaddr virt %p phys %p size %d", xrip->SGList.virt,
! xrip->SGList.phys, pkt->pkt_datalen);
! emlxs_data_dump(port, "FCP: SGL", (uint32_t *)xrip->SGList.virt, 20, 0);
EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
"FCP: CMD virt %p len %d:%d:%d",
pkt->pkt_cmd, pkt->pkt_cmdlen, pkt->pkt_rsplen, pkt->pkt_datalen);
emlxs_data_dump(port, "FCP: CMD", (uint32_t *)pkt->pkt_cmd, 10, 0);
#endif /* DEBUG_FCP */
! offset = (off_t)((uint64_t)((unsigned long)
! xrip->SGList.virt) -
! (uint64_t)((unsigned long)
! hba->sli.sli4.slim2.virt));
- EMLXS_MPDATA_SYNC(xrip->SGList.dma_handle, offset,
- xrip->SGList.size, DDI_DMA_SYNC_FORDEV);
-
/* if device is FCP-2 device, set the following bit */
/* that says to run the FC-TAPE protocol. */
if (node->nlp_fcp_info & NLP_FCP_2_DEVICE) {
wqe->ERP = 1;
}
--- 4296,4318 ----
}
/* DEBUG */
#ifdef DEBUG_FCP
EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
! "FCP: SGLaddr virt %p phys %p size %d", xrip->SGList->virt,
! xrip->SGList->phys, pkt->pkt_datalen);
! emlxs_data_dump(port, "FCP: SGL",
! (uint32_t *)xrip->SGList->virt, 20, 0);
EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
"FCP: CMD virt %p len %d:%d:%d",
pkt->pkt_cmd, pkt->pkt_cmdlen, pkt->pkt_rsplen, pkt->pkt_datalen);
emlxs_data_dump(port, "FCP: CMD", (uint32_t *)pkt->pkt_cmd, 10, 0);
#endif /* DEBUG_FCP */
! EMLXS_MPDATA_SYNC(xrip->SGList->dma_handle, 0,
! xrip->SGList->size, DDI_DMA_SYNC_FORDEV);
/* if device is FCP-2 device, set the following bit */
/* that says to run the FC-TAPE protocol. */
if (node->nlp_fcp_info & NLP_FCP_2_DEVICE) {
wqe->ERP = 1;
}
*** 4340,4350 ****
ULP_SGE64 stage_sge;
ULP_SGE64 *sge;
ddi_dma_cookie_t *cp_cmd;
ddi_dma_cookie_t *cp_resp;
emlxs_node_t *node;
- off_t offset;
pkt = PRIV2PKT(sbp);
did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
iocbq = &sbp->iocbq;
--- 4392,4401 ----
*** 4434,4444 ****
wqe->OXId = xrip->rx_id;
sge->last = 1;
/* Now sge is fully staged */
! sge = xrip->SGList.virt;
BE_SWAP32_BCOPY((uint8_t *)&stage_sge, (uint8_t *)sge,
sizeof (ULP_SGE64));
if (rpip->RPI == FABRIC_RPI) {
wqe->ContextTag = port->vpip->VPI;
--- 4485,4495 ----
wqe->OXId = xrip->rx_id;
sge->last = 1;
/* Now sge is fully staged */
! sge = xrip->SGList->virt;
BE_SWAP32_BCOPY((uint8_t *)&stage_sge, (uint8_t *)sge,
sizeof (ULP_SGE64));
if (rpip->RPI == FABRIC_RPI) {
wqe->ContextTag = port->vpip->VPI;
*** 4499,4509 ****
iocb->un.elsreq64.remoteID = (did == BCAST_DID) ? 0 : did;
iocb->ULPPU = 1; /* Wd4 is relative offset */
sge->last = 0;
! sge = xrip->SGList.virt;
BE_SWAP32_BCOPY((uint8_t *)&stage_sge, (uint8_t *)sge,
sizeof (ULP_SGE64));
wqe->un.ElsCmd.PayloadLength =
pkt->pkt_cmdlen; /* Byte offset of rsp data */
--- 4550,4560 ----
iocb->un.elsreq64.remoteID = (did == BCAST_DID) ? 0 : did;
iocb->ULPPU = 1; /* Wd4 is relative offset */
sge->last = 0;
! sge = xrip->SGList->virt;
BE_SWAP32_BCOPY((uint8_t *)&stage_sge, (uint8_t *)sge,
sizeof (ULP_SGE64));
wqe->un.ElsCmd.PayloadLength =
pkt->pkt_cmdlen; /* Byte offset of rsp data */
*** 4515,4537 ****
sge->length = pkt->pkt_rsplen;
sge->offset = 0;
sge->last = 1;
/* Now sge is fully staged */
! sge = xrip->SGList.virt;
sge++;
BE_SWAP32_BCOPY((uint8_t *)&stage_sge, (uint8_t *)sge,
sizeof (ULP_SGE64));
#ifdef DEBUG_ELS
EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
"ELS: SGLaddr virt %p phys %p",
! xrip->SGList.virt, xrip->SGList.phys);
EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
"ELS: PAYLOAD virt %p phys %p",
pkt->pkt_cmd, cp_cmd->dmac_laddress);
! emlxs_data_dump(port, "ELS: SGL", (uint32_t *)xrip->SGList.virt,
! 12, 0);
#endif /* DEBUG_ELS */
switch (cmd) {
case ELS_CMD_FLOGI:
wqe->un.ElsCmd.SP = 1;
--- 4566,4588 ----
sge->length = pkt->pkt_rsplen;
sge->offset = 0;
sge->last = 1;
/* Now sge is fully staged */
! sge = xrip->SGList->virt;
sge++;
BE_SWAP32_BCOPY((uint8_t *)&stage_sge, (uint8_t *)sge,
sizeof (ULP_SGE64));
#ifdef DEBUG_ELS
EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
"ELS: SGLaddr virt %p phys %p",
! xrip->SGList->virt, xrip->SGList->phys);
EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
"ELS: PAYLOAD virt %p phys %p",
pkt->pkt_cmd, cp_cmd->dmac_laddress);
! emlxs_data_dump(port, "ELS: SGL",
! (uint32_t *)xrip->SGList->virt, 12, 0);
#endif /* DEBUG_ELS */
switch (cmd) {
case ELS_CMD_FLOGI:
wqe->un.ElsCmd.SP = 1;
*** 4633,4650 ****
} else {
wqe->CmdSpecific = reserved_rpip->RPI;
}
}
! offset = (off_t)((uint64_t)((unsigned long)
! xrip->SGList.virt) -
! (uint64_t)((unsigned long)
! hba->sli.sli4.slim2.virt));
- EMLXS_MPDATA_SYNC(xrip->SGList.dma_handle, offset,
- xrip->SGList.size, DDI_DMA_SYNC_FORDEV);
-
if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_CHAINED_SEQ) {
wqe->CCPE = 1;
wqe->CCP = pkt->pkt_cmd_fhdr.rsvd;
}
--- 4684,4696 ----
} else {
wqe->CmdSpecific = reserved_rpip->RPI;
}
}
! EMLXS_MPDATA_SYNC(xrip->SGList->dma_handle, 0,
! xrip->SGList->size, DDI_DMA_SYNC_FORDEV);
if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_CHAINED_SEQ) {
wqe->CCPE = 1;
wqe->CCP = pkt->pkt_cmd_fhdr.rsvd;
}
*** 4678,4688 ****
NODELIST *node = NULL;
CHANNEL *cp;
RPIobj_t *rpip;
XRIobj_t *xrip;
uint32_t did;
- off_t offset;
pkt = PRIV2PKT(sbp);
did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
iocbq = &sbp->iocbq;
--- 4724,4733 ----
*** 4830,4842 ****
wqe->un.GenReq.Rctl = pkt->pkt_cmd_fhdr.r_ctl;
wqe->un.GenReq.Type = pkt->pkt_cmd_fhdr.type;
#ifdef DEBUG_CT
EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
! "CT: SGLaddr virt %p phys %p", xrip->SGList.virt,
! xrip->SGList.phys);
! emlxs_data_dump(port, "CT: SGL", (uint32_t *)xrip->SGList.virt,
12, 0);
EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
"CT: CMD virt %p len %d:%d",
pkt->pkt_cmd, pkt->pkt_cmdlen, pkt->pkt_rsplen);
emlxs_data_dump(port, "CT: DATA", (uint32_t *)pkt->pkt_cmd,
--- 4875,4887 ----
wqe->un.GenReq.Rctl = pkt->pkt_cmd_fhdr.r_ctl;
wqe->un.GenReq.Type = pkt->pkt_cmd_fhdr.type;
#ifdef DEBUG_CT
EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
! "CT: SGLaddr virt %p phys %p", xrip->SGList->virt,
! xrip->SGList->phys);
! emlxs_data_dump(port, "CT: SGL", (uint32_t *)xrip->SGList->virt,
12, 0);
EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
"CT: CMD virt %p len %d:%d",
pkt->pkt_cmd, pkt->pkt_cmdlen, pkt->pkt_rsplen);
emlxs_data_dump(port, "CT: DATA", (uint32_t *)pkt->pkt_cmd,
*** 4856,4873 ****
iocb->un.genreq64.w5.hcsw.Rctl = pkt->pkt_cmd_fhdr.r_ctl;
iocb->un.genreq64.w5.hcsw.Type = pkt->pkt_cmd_fhdr.type;
iocb->un.genreq64.w5.hcsw.Dfctl = pkt->pkt_cmd_fhdr.df_ctl;
iocb->ULPPU = 1; /* Wd4 is relative offset */
! offset = (off_t)((uint64_t)((unsigned long)
! xrip->SGList.virt) -
! (uint64_t)((unsigned long)
! hba->sli.sli4.slim2.virt));
- EMLXS_MPDATA_SYNC(xrip->SGList.dma_handle, offset,
- xrip->SGList.size, DDI_DMA_SYNC_FORDEV);
-
wqe->ContextTag = rpip->RPI;
wqe->ContextType = WQE_RPI_CONTEXT;
wqe->XRITag = xrip->XRI;
wqe->Timer = ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout);
--- 4901,4913 ----
iocb->un.genreq64.w5.hcsw.Rctl = pkt->pkt_cmd_fhdr.r_ctl;
iocb->un.genreq64.w5.hcsw.Type = pkt->pkt_cmd_fhdr.type;
iocb->un.genreq64.w5.hcsw.Dfctl = pkt->pkt_cmd_fhdr.df_ctl;
iocb->ULPPU = 1; /* Wd4 is relative offset */
! EMLXS_MPDATA_SYNC(xrip->SGList->dma_handle, 0,
! xrip->SGList->size, DDI_DMA_SYNC_FORDEV);
wqe->ContextTag = rpip->RPI;
wqe->ContextType = WQE_RPI_CONTEXT;
wqe->XRITag = xrip->XRI;
wqe->Timer = ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout);
*** 5106,5116 ****
}
break;
case ASYNC_EVENT_CODE_PORT:
EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
"SLI Port Async Event: type=%d", cqe->event_type);
! if (cqe->event_type == ASYNC_EVENT_MISCONFIG_PORT) {
*((uint32_t *)cqe->un.port.link_status) =
BE_SWAP32(*((uint32_t *)cqe->un.port.link_status));
status =
cqe->un.port.link_status[hba->sli.sli4.link_number];
--- 5146,5177 ----
}
break;
case ASYNC_EVENT_CODE_PORT:
EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
"SLI Port Async Event: type=%d", cqe->event_type);
!
! switch (cqe->event_type) {
! case ASYNC_EVENT_PORT_OTEMP:
! EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
! "SLI Port Async Event: Temperature limit exceeded");
! cmn_err(CE_WARN,
! "^%s%d: Temperature limit exceeded. Fibre channel "
! "controller temperature %u degrees C",
! DRIVER_NAME, hba->ddiinst,
! BE_SWAP32(*(uint32_t *)cqe->un.port.link_status));
! break;
!
! case ASYNC_EVENT_PORT_NTEMP:
! EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
! "SLI Port Async Event: Temperature returned to "
! "normal");
! cmn_err(CE_WARN,
! "^%s%d: Temperature returned to normal",
! DRIVER_NAME, hba->ddiinst);
! break;
!
! case ASYNC_EVENT_MISCONFIG_PORT:
*((uint32_t *)cqe->un.port.link_status) =
BE_SWAP32(*((uint32_t *)cqe->un.port.link_status));
status =
cqe->un.port.link_status[hba->sli.sli4.link_number];
*** 5159,5169 ****
--- 5220,5232 ----
"^%s%d: Misconfigured port: status=0x%x - "
"Check optics on card.",
DRIVER_NAME, hba->ddiinst, status);
break;
}
+ break;
}
+
break;
case ASYNC_EVENT_CODE_VF:
EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
"VF Async Event: type=%d",
cqe->event_type);
*** 6597,6619 ****
}
/* pass xrip to FCT in the iocbq */
iocbq->sbp = xrip;
- #define EMLXS_FIX_CISCO_BUG1
- #ifdef EMLXS_FIX_CISCO_BUG1
- {
- uint8_t *ptr;
- ptr = ((uint8_t *)seq_mp->virt);
- if (((*ptr+12) != 0xa0) && (*(ptr+20) == 0x8) && (*(ptr+21) == 0x8)) {
- EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
- "RQ ENTRY: Bad CDB fixed");
- *ptr++ = 0;
- *ptr = 0;
- }
- }
- #endif
(void) emlxs_fct_handle_unsol_req(port, cp, iocbq,
seq_mp, seq_len);
break;
#endif /* SFCT_SUPPORT */
--- 6660,6669 ----
*** 7194,7204 ****
hba->sli.sli4.flag &= ~EMLXS_SLI4_INTR_ENABLED;
/* Short of reset, we cannot disable interrupts */
} /* emlxs_sli4_disable_intr() */
-
static void
emlxs_sli4_resource_free(emlxs_hba_t *hba)
{
emlxs_port_t *port = &PPORT;
MBUF_INFO *buf_info;
--- 7244,7253 ----
*** 7216,7225 ****
--- 7265,7276 ----
if (buf_info->virt) {
bzero(buf_info, sizeof (MBUF_INFO));
}
if (hba->sli.sli4.XRIp) {
+ XRIobj_t *xrip;
+
if ((hba->sli.sli4.XRIinuse_f !=
(XRIobj_t *)&hba->sli.sli4.XRIinuse_f) ||
(hba->sli.sli4.XRIinuse_b !=
(XRIobj_t *)&hba->sli.sli4.XRIinuse_f)) {
EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_debug_msg,
*** 7226,7235 ****
--- 7277,7297 ----
"XRIs in use during free!: %p %p != %p\n",
hba->sli.sli4.XRIinuse_f,
hba->sli.sli4.XRIinuse_b,
&hba->sli.sli4.XRIinuse_f);
}
+
+ xrip = hba->sli.sli4.XRIp;
+ for (i = 0; i < hba->sli.sli4.XRICount; i++) {
+ xrip->XRI = emlxs_sli4_index_to_xri(hba, i);
+
+ if (xrip->XRI != 0)
+ emlxs_mem_put(hba, xrip->SGSeg, xrip->SGList);
+
+ xrip++;
+ }
+
kmem_free(hba->sli.sli4.XRIp,
(sizeof (XRIobj_t) * hba->sli.sli4.XRICount));
hba->sli.sli4.XRIp = NULL;
hba->sli.sli4.XRIfree_f =
*** 7270,7282 ****
buf_info->flags = FC_MBUF_DMA;
emlxs_mem_free(hba, buf_info);
bzero(buf_info, sizeof (MBUF_INFO));
}
} /* emlxs_sli4_resource_free() */
-
static int
emlxs_sli4_resource_alloc(emlxs_hba_t *hba)
{
emlxs_port_t *port = &PPORT;
emlxs_config_t *cfg = &CFG;
--- 7332,7347 ----
buf_info->flags = FC_MBUF_DMA;
emlxs_mem_free(hba, buf_info);
bzero(buf_info, sizeof (MBUF_INFO));
}
+ /* GPIO lock */
+ if (hba->model_info.flags & EMLXS_GPIO_LEDS)
+ mutex_destroy(&hba->gpio_lock);
+
} /* emlxs_sli4_resource_free() */
static int
emlxs_sli4_resource_alloc(emlxs_hba_t *hba)
{
emlxs_port_t *port = &PPORT;
emlxs_config_t *cfg = &CFG;
*** 7350,7363 ****
/* RQB/E */
count += RQB_COUNT * (RQB_DATA_SIZE + RQB_HEADER_SIZE);
count += (4096 - (count%4096)); /* Ensure 4K alignment */
- /* SGL */
- count += hba->sli.sli4.XRIExtSize * hba->sli.sli4.mem_sgl_size;
- count += (4096 - (count%4096)); /* Ensure 4K alignment */
-
/* RPI Header Templates */
if (hba->sli.sli4.param.HDRR) {
/* Bytes per extent */
j = hba->sli.sli4.RPIExtSize * sizeof (RPIHdrTmplate_t);
--- 7415,7424 ----
*** 7374,7383 ****
--- 7435,7447 ----
buf_info = &hba->sli.sli4.slim2;
buf_info->size = count;
buf_info->flags = FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
buf_info->align = ddi_ptob(hba->dip, 1L);
+ EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
+ "Allocating memory for slim2: %d", count);
+
(void) emlxs_mem_alloc(hba, buf_info);
if (buf_info->virt == NULL) {
EMLXS_MSGF(EMLXS_CONTEXT,
&emlxs_init_failed_msg,
*** 7387,7397 ****
}
bzero(buf_info->virt, buf_info->size);
EMLXS_MPDATA_SYNC(buf_info->dma_handle, 0,
buf_info->size, DDI_DMA_SYNC_FORDEV);
! /* Assign memory to SGL, Head Template, EQ, CQ, WQ, RQ and MQ */
data_handle = buf_info->data_handle;
dma_handle = buf_info->dma_handle;
phys = buf_info->phys;
virt = (char *)buf_info->virt;
--- 7451,7461 ----
}
bzero(buf_info->virt, buf_info->size);
EMLXS_MPDATA_SYNC(buf_info->dma_handle, 0,
buf_info->size, DDI_DMA_SYNC_FORDEV);
! /* Assign memory to Head Template, EQ, CQ, WQ, RQ and MQ */
data_handle = buf_info->data_handle;
dma_handle = buf_info->dma_handle;
phys = buf_info->phys;
virt = (char *)buf_info->virt;
*** 7577,7587 ****
--- 7641,7669 ----
/* 4K Alignment */
align = (4096 - (phys%4096));
phys += align;
virt += align;
+ /* RPI Header Templates */
+ if (hba->sli.sli4.param.HDRR) {
+ buf_info = &hba->sli.sli4.HeaderTmplate;
+ bzero(buf_info, sizeof (MBUF_INFO));
+ buf_info->size = hddr_size;
+ buf_info->flags = FC_MBUF_DMA | FC_MBUF_DMA32;
+ buf_info->align = ddi_ptob(hba->dip, 1L);
+ buf_info->phys = phys;
+ buf_info->virt = (void *)virt;
+ buf_info->data_handle = data_handle;
+ buf_info->dma_handle = dma_handle;
+ }
+
/* SGL */
+
+ EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
+ "Allocating memory for %d SGLs: %d/%d",
+ hba->sli.sli4.XRICount, sizeof (XRIobj_t), size);
+
/* Initialize double linked lists */
hba->sli.sli4.XRIinuse_f =
(XRIobj_t *)&hba->sli.sli4.XRIinuse_f;
hba->sli.sli4.XRIinuse_b =
(XRIobj_t *)&hba->sli.sli4.XRIinuse_f;
*** 7589,7606 ****
hba->sli.sli4.XRIfree_f =
(XRIobj_t *)&hba->sli.sli4.XRIfree_f;
hba->sli.sli4.XRIfree_b =
(XRIobj_t *)&hba->sli.sli4.XRIfree_f;
! hba->sli.sli4.xria_count = 0;
hba->sli.sli4.XRIp = (XRIobj_t *)kmem_zalloc(
(sizeof (XRIobj_t) * hba->sli.sli4.XRICount), KM_SLEEP);
xrip = hba->sli.sli4.XRIp;
- size = hba->sli.sli4.mem_sgl_size;
iotag = 1;
for (i = 0; i < hba->sli.sli4.XRICount; i++) {
xrip->XRI = emlxs_sli4_index_to_xri(hba, i);
/* We don't use XRI==0, since it also represents an */
/* uninitialized exchange */
--- 7671,7707 ----
hba->sli.sli4.XRIfree_f =
(XRIobj_t *)&hba->sli.sli4.XRIfree_f;
hba->sli.sli4.XRIfree_b =
(XRIobj_t *)&hba->sli.sli4.XRIfree_f;
! hba->sli.sli4.xrif_count = 0;
+ uint32_t mseg;
+
+ switch (hba->sli.sli4.mem_sgl_size) {
+ case 1024:
+ mseg = MEM_SGL1K;
+ break;
+ case 2048:
+ mseg = MEM_SGL2K;
+ break;
+ case 4096:
+ mseg = MEM_SGL4K;
+ break;
+ default:
+ EMLXS_MSGF(EMLXS_CONTEXT,
+ &emlxs_init_failed_msg,
+ "Unsupported SGL Size: %d", hba->sli.sli4.mem_sgl_size);
+ goto failed;
+ }
+
hba->sli.sli4.XRIp = (XRIobj_t *)kmem_zalloc(
(sizeof (XRIobj_t) * hba->sli.sli4.XRICount), KM_SLEEP);
xrip = hba->sli.sli4.XRIp;
iotag = 1;
+
for (i = 0; i < hba->sli.sli4.XRICount; i++) {
xrip->XRI = emlxs_sli4_index_to_xri(hba, i);
/* We don't use XRI==0, since it also represents an */
/* uninitialized exchange */
*** 7619,7662 ****
xrip->_f = (XRIobj_t *)&hba->sli.sli4.XRIfree_f;
hba->sli.sli4.XRIfree_b = xrip;
hba->sli.sli4.xrif_count++;
/* Allocate SGL for this xrip */
! buf_info = &xrip->SGList;
! buf_info->size = size;
! buf_info->flags =
! FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
! buf_info->align = size;
! buf_info->phys = phys;
! buf_info->virt = (void *)virt;
! buf_info->data_handle = data_handle;
! buf_info->dma_handle = dma_handle;
! phys += size;
! virt += size;
!
! xrip++;
}
! /* 4K Alignment */
! align = (4096 - (phys%4096));
! phys += align;
! virt += align;
! /* RPI Header Templates */
! if (hba->sli.sli4.param.HDRR) {
! buf_info = &hba->sli.sli4.HeaderTmplate;
! bzero(buf_info, sizeof (MBUF_INFO));
! buf_info->size = hddr_size;
! buf_info->flags = FC_MBUF_DMA | FC_MBUF_DMA32;
! buf_info->align = ddi_ptob(hba->dip, 1L);
! buf_info->phys = phys;
! buf_info->virt = (void *)virt;
! buf_info->data_handle = data_handle;
! buf_info->dma_handle = dma_handle;
}
#ifdef FMA_SUPPORT
if (hba->sli.sli4.slim2.dma_handle) {
if (emlxs_fm_check_dma_handle(hba,
hba->sli.sli4.slim2.dma_handle)
!= DDI_FM_OK) {
--- 7720,7748 ----
xrip->_f = (XRIobj_t *)&hba->sli.sli4.XRIfree_f;
hba->sli.sli4.XRIfree_b = xrip;
hba->sli.sli4.xrif_count++;
/* Allocate SGL for this xrip */
! xrip->SGSeg = mseg;
! xrip->SGList = emlxs_mem_get(hba, xrip->SGSeg);
! if (xrip->SGList == NULL) {
! EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
! "Unable to allocate memory for SGL %d", i);
! goto failed;
}
! EMLXS_MPDATA_SYNC(xrip->SGList->dma_handle, 0,
! xrip->SGList->size, DDI_DMA_SYNC_FORDEV);
! xrip++;
}
+ /* GPIO lock */
+ if (hba->model_info.flags & EMLXS_GPIO_LEDS)
+ mutex_init(&hba->gpio_lock, NULL, MUTEX_DRIVER, NULL);
+
#ifdef FMA_SUPPORT
if (hba->sli.sli4.slim2.dma_handle) {
if (emlxs_fm_check_dma_handle(hba,
hba->sli.sli4.slim2.dma_handle)
!= DDI_FM_OK) {
*** 8249,8262 ****
for (i = 0; (i < xri_cnt) && cnt; i++) {
post_sgl->params.request.xri_count++;
post_sgl->params.request.pages[i].\
sgl_page0.addrLow =
! PADDR_LO(xrip->SGList.phys);
post_sgl->params.request.pages[i].\
sgl_page0.addrHigh =
! PADDR_HI(xrip->SGList.phys);
cnt--;
xrip++;
}
--- 8335,8348 ----
for (i = 0; (i < xri_cnt) && cnt; i++) {
post_sgl->params.request.xri_count++;
post_sgl->params.request.pages[i].\
sgl_page0.addrLow =
! PADDR_LO(xrip->SGList->phys);
post_sgl->params.request.pages[i].\
sgl_page0.addrHigh =
! PADDR_HI(xrip->SGList->phys);
cnt--;
xrip++;
}
*** 8670,8680 ****
--- 8756,8959 ----
return;
} /* emlxs_sli4_timer_check_mbox() */
+ static void
+ emlxs_sli4_gpio_timer_start(emlxs_hba_t *hba)
+ {
+ mutex_enter(&hba->gpio_lock);
+ if (!hba->gpio_timer) {
+ hba->gpio_timer = timeout(emlxs_sli4_gpio_timer, (void *)hba,
+ drv_usectohz(100000));
+ }
+
+ mutex_exit(&hba->gpio_lock);
+
+ } /* emlxs_sli4_gpio_timer_start() */
+
+ static void
+ emlxs_sli4_gpio_timer_stop(emlxs_hba_t *hba)
+ {
+ mutex_enter(&hba->gpio_lock);
+
+ if (hba->gpio_timer) {
+ (void) untimeout(hba->gpio_timer);
+ hba->gpio_timer = 0;
+ }
+
+ mutex_exit(&hba->gpio_lock);
+
+ delay(drv_usectohz(300000));
+ } /* emlxs_sli4_gpio_timer_stop() */
+
+ static void
+ emlxs_sli4_gpio_timer(void *arg)
+ {
+ emlxs_hba_t *hba = (emlxs_hba_t *)arg;
+
+ mutex_enter(&hba->gpio_lock);
+
+ if (hba->gpio_timer) {
+ emlxs_sli4_check_gpio(hba);
+ hba->gpio_timer = timeout(emlxs_sli4_gpio_timer, (void *)hba,
+ drv_usectohz(100000));
+ }
+
+ mutex_exit(&hba->gpio_lock);
+ } /* emlxs_sli4_gpio_timer() */
+
+ static void
+ emlxs_sli4_check_gpio(emlxs_hba_t *hba)
+ {
+ hba->gpio_desired = 0;
+
+ if (hba->flag & FC_GPIO_LINK_UP) {
+ if (hba->io_active)
+ hba->gpio_desired |= EMLXS_GPIO_ACT;
+
+ /* This is model specific to ATTO gen5 lancer cards */
+
+ switch (hba->linkspeed) {
+ case LA_4GHZ_LINK:
+ hba->gpio_desired |= EMLXS_GPIO_LO;
+ break;
+
+ case LA_8GHZ_LINK:
+ hba->gpio_desired |= EMLXS_GPIO_HI;
+ break;
+
+ case LA_16GHZ_LINK:
+ hba->gpio_desired |=
+ EMLXS_GPIO_LO | EMLXS_GPIO_HI;
+ break;
+ }
+ }
+
+ if (hba->gpio_current != hba->gpio_desired) {
+ emlxs_port_t *port = &PPORT;
+ uint8_t pin;
+ uint8_t pinval;
+ MAILBOXQ *mbq;
+ uint32_t rval;
+
+ if (!emlxs_sli4_fix_gpio(hba, &pin, &pinval))
+ return;
+
+ if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX)) == NULL) {
+ EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
+ "Unable to allocate GPIO mailbox.");
+
+ hba->gpio_bit = 0;
+ return;
+ }
+
+ emlxs_mb_gpio_write(hba, mbq, pin, pinval);
+ mbq->mbox_cmpl = emlxs_sli4_fix_gpio_mbcmpl;
+
+ rval = emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_NOWAIT, 0);
+
+ if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
+ EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
+ "Unable to start GPIO mailbox.");
+
+ hba->gpio_bit = 0;
+ emlxs_mem_put(hba, MEM_MBOX, mbq);
+ return;
+ }
+ }
+ } /* emlxs_sli4_check_gpio */
+
+ static uint32_t
+ emlxs_sli4_fix_gpio(emlxs_hba_t *hba, uint8_t *pin, uint8_t *pinval)
+ {
+ uint8_t dif = hba->gpio_desired ^ hba->gpio_current;
+ uint8_t bit;
+ uint8_t i;
+
+ /* Get out if no pins to set a GPIO request is pending */
+
+ if (dif == 0 || hba->gpio_bit)
+ return (0);
+
+ /* Fix one pin at a time */
+
+ bit = dif & -dif;
+ hba->gpio_bit = bit;
+ dif = hba->gpio_current ^ bit;
+
+ for (i = EMLXS_GPIO_PIN_LO; bit > 1; ++i) {
+ dif >>= 1;
+ bit >>= 1;
+ }
+
+ /* Pins are active low so invert the bit value */
+
+ *pin = hba->gpio_pin[i];
+ *pinval = ~dif & bit;
+
+ return (1);
+ } /* emlxs_sli4_fix_gpio */
+
+ static uint32_t
+ emlxs_sli4_fix_gpio_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
+ {
+ MAILBOX *mb;
+ uint8_t pin;
+ uint8_t pinval;
+
+ mb = (MAILBOX *)mbq;
+
+ mutex_enter(&hba->gpio_lock);
+
+ if (mb->mbxStatus == 0)
+ hba->gpio_current ^= hba->gpio_bit;
+
+ hba->gpio_bit = 0;
+
+ if (emlxs_sli4_fix_gpio(hba, &pin, &pinval)) {
+ emlxs_port_t *port = &PPORT;
+ MAILBOXQ *mbq;
+ uint32_t rval;
+
+ /*
+ * We're not using the mb_retry routine here because for some
+ * reason it doesn't preserve the completion routine. Just let
+ * this mbox cmd fail to start here and run when the mailbox
+ * is no longer busy.
+ */
+
+ if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX)) == NULL) {
+ EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
+ "Unable to allocate GPIO mailbox.");
+
+ hba->gpio_bit = 0;
+ goto done;
+ }
+
+ emlxs_mb_gpio_write(hba, mbq, pin, pinval);
+ mbq->mbox_cmpl = emlxs_sli4_fix_gpio_mbcmpl;
+
+ rval = emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_NOWAIT, 0);
+
+ if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
+ EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
+ "Unable to start GPIO mailbox.");
+
+ hba->gpio_bit = 0;
+ emlxs_mem_put(hba, MEM_MBOX, mbq);
+ goto done;
+ }
+ }
+
+ done:
+ mutex_exit(&hba->gpio_lock);
+
+ return (0);
+ }
+
extern void
emlxs_data_dump(emlxs_port_t *port, char *str, uint32_t *iptr, int cnt, int err)
{
void *msg;
*** 9111,9120 ****
--- 9390,9402 ----
hba->linkspeed = LA_10GHZ_LINK;
break;
case 16:
hba->linkspeed = LA_16GHZ_LINK;
break;
+ case 32:
+ hba->linkspeed = LA_32GHZ_LINK;
+ break;
default:
EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
"sli4_handle_fc_link_att: Unknown link speed=%x.",
cqe->un.fc.port_speed);
hba->linkspeed = 0;