1fcf3ce44SJohn Forte /* 2fcf3ce44SJohn Forte * CDDL HEADER START 3fcf3ce44SJohn Forte * 4fcf3ce44SJohn Forte * The contents of this file are subject to the terms of the 5fcf3ce44SJohn Forte * Common Development and Distribution License (the "License"). 6fcf3ce44SJohn Forte * You may not use this file except in compliance with the License. 7fcf3ce44SJohn Forte * 8fcf3ce44SJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9fcf3ce44SJohn Forte * or http://www.opensolaris.org/os/licensing. 10fcf3ce44SJohn Forte * See the License for the specific language governing permissions 11fcf3ce44SJohn Forte * and limitations under the License. 12fcf3ce44SJohn Forte * 13fcf3ce44SJohn Forte * When distributing Covered Code, include this CDDL HEADER in each 14fcf3ce44SJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15fcf3ce44SJohn Forte * If applicable, add the following below this CDDL HEADER, with the 16fcf3ce44SJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying 17fcf3ce44SJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner] 18fcf3ce44SJohn Forte * 19fcf3ce44SJohn Forte * CDDL HEADER END 20fcf3ce44SJohn Forte */ 21fcf3ce44SJohn Forte 22fcf3ce44SJohn Forte /* 23*a9800bebSGarrett D'Amore * Copyright 2011 Emulex. All rights reserved. 2482527734SSukumar Swaminathan * Use is subject to license terms. 25fcf3ce44SJohn Forte */ 26fcf3ce44SJohn Forte 2782527734SSukumar Swaminathan 28291a2b48SSukumar Swaminathan #include <emlxs.h> 29fcf3ce44SJohn Forte 30fcf3ce44SJohn Forte /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */ 31fcf3ce44SJohn Forte EMLXS_MSG_DEF(EMLXS_FCP_C); 32fcf3ce44SJohn Forte 33fcf3ce44SJohn Forte #define EMLXS_GET_VADDR(hba, rp, icmd) emlxs_mem_get_vaddr(hba, rp, \ 3482527734SSukumar Swaminathan PADDR(icmd->un.cont64[i].addrHigh, icmd->un.cont64[i].addrLow)); 35fcf3ce44SJohn Forte 36291a2b48SSukumar Swaminathan static void emlxs_sbp_abort_add(emlxs_port_t *port, emlxs_buf_t *sbp, 37291a2b48SSukumar Swaminathan Q *abort, uint8_t *flag, emlxs_buf_t *fpkt); 38fcf3ce44SJohn Forte 39fcf3ce44SJohn Forte #define SCSI3_PERSISTENT_RESERVE_IN 0x5e 40291a2b48SSukumar Swaminathan #define SCSI_INQUIRY 0x12 41291a2b48SSukumar Swaminathan #define SCSI_RX_DIAG 0x1C 42fcf3ce44SJohn Forte 43fcf3ce44SJohn Forte 44fcf3ce44SJohn Forte /* 45fcf3ce44SJohn Forte * emlxs_handle_fcp_event 46fcf3ce44SJohn Forte * 47fcf3ce44SJohn Forte * Description: Process an FCP Rsp Ring completion 48fcf3ce44SJohn Forte * 49fcf3ce44SJohn Forte */ 50fcf3ce44SJohn Forte /* ARGSUSED */ 51fcf3ce44SJohn Forte extern void 5282527734SSukumar Swaminathan emlxs_handle_fcp_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq) 53fcf3ce44SJohn Forte { 54fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 5582527734SSukumar Swaminathan emlxs_config_t *cfg = &CFG; 56fcf3ce44SJohn Forte IOCB *cmd; 57fcf3ce44SJohn Forte emlxs_buf_t *sbp; 58fcf3ce44SJohn Forte fc_packet_t *pkt = NULL; 59291a2b48SSukumar Swaminathan #ifdef SAN_DIAG_SUPPORT 60291a2b48SSukumar Swaminathan NODELIST *ndlp; 61291a2b48SSukumar Swaminathan #endif 62fcf3ce44SJohn Forte uint32_t iostat; 63fcf3ce44SJohn Forte uint8_t localstat; 64fcf3ce44SJohn Forte fcp_rsp_t *rsp; 65fcf3ce44SJohn Forte uint32_t rsp_data_resid; 66fcf3ce44SJohn Forte uint32_t check_underrun; 67fcf3ce44SJohn Forte uint8_t asc; 68fcf3ce44SJohn Forte uint8_t ascq; 69fcf3ce44SJohn Forte uint8_t scsi_status; 70fcf3ce44SJohn Forte uint8_t sense; 71fcf3ce44SJohn Forte uint32_t did; 72fcf3ce44SJohn Forte uint32_t fix_it; 73fcf3ce44SJohn Forte uint8_t *scsi_cmd; 74fcf3ce44SJohn Forte uint8_t scsi_opcode; 75fcf3ce44SJohn Forte uint16_t scsi_dl; 76fcf3ce44SJohn Forte uint32_t data_rx; 77fcf3ce44SJohn Forte 78fcf3ce44SJohn Forte cmd = &iocbq->iocb; 79fcf3ce44SJohn Forte 80fcf3ce44SJohn Forte /* Initialize the status */ 8182527734SSukumar Swaminathan iostat = cmd->ULPSTATUS; 82fcf3ce44SJohn Forte localstat = 0; 83fcf3ce44SJohn Forte scsi_status = 0; 84fcf3ce44SJohn Forte asc = 0; 85fcf3ce44SJohn Forte ascq = 0; 86fcf3ce44SJohn Forte sense = 0; 87fcf3ce44SJohn Forte check_underrun = 0; 88fcf3ce44SJohn Forte fix_it = 0; 89fcf3ce44SJohn Forte 90fcf3ce44SJohn Forte HBASTATS.FcpEvent++; 91fcf3ce44SJohn Forte 92fcf3ce44SJohn Forte sbp = (emlxs_buf_t *)iocbq->sbp; 93fcf3ce44SJohn Forte 94fcf3ce44SJohn Forte if (!sbp) { 95fcf3ce44SJohn Forte /* completion with missing xmit command */ 96fcf3ce44SJohn Forte HBASTATS.FcpStray++; 97fcf3ce44SJohn Forte 98fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_fcp_completion_msg, 9982527734SSukumar Swaminathan "cmd=%x iotag=%x", cmd->ULPCOMMAND, cmd->ULPIOTAG); 100fcf3ce44SJohn Forte 101fcf3ce44SJohn Forte return; 102fcf3ce44SJohn Forte } 103291a2b48SSukumar Swaminathan 104fcf3ce44SJohn Forte HBASTATS.FcpCompleted++; 105fcf3ce44SJohn Forte 106291a2b48SSukumar Swaminathan #ifdef SAN_DIAG_SUPPORT 107291a2b48SSukumar Swaminathan emlxs_update_sd_bucket(sbp); 108291a2b48SSukumar Swaminathan #endif /* SAN_DIAG_SUPPORT */ 109291a2b48SSukumar Swaminathan 110fcf3ce44SJohn Forte pkt = PRIV2PKT(sbp); 111fcf3ce44SJohn Forte 11282527734SSukumar Swaminathan did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id); 113fcf3ce44SJohn Forte scsi_cmd = (uint8_t *)pkt->pkt_cmd; 114fcf3ce44SJohn Forte scsi_opcode = scsi_cmd[12]; 115fcf3ce44SJohn Forte data_rx = 0; 116fcf3ce44SJohn Forte 117fcf3ce44SJohn Forte /* Sync data in data buffer only on FC_PKT_FCP_READ */ 118fcf3ce44SJohn Forte if (pkt->pkt_datalen && (pkt->pkt_tran_type == FC_PKT_FCP_READ)) { 11982527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(pkt->pkt_data_dma, 0, pkt->pkt_datalen, 120fcf3ce44SJohn Forte DDI_DMA_SYNC_FORKERNEL); 121fcf3ce44SJohn Forte 122fcf3ce44SJohn Forte #ifdef TEST_SUPPORT 123fcf3ce44SJohn Forte if (hba->underrun_counter && (iostat == IOSTAT_SUCCESS) && 124fcf3ce44SJohn Forte (pkt->pkt_datalen >= 512)) { 125fcf3ce44SJohn Forte hba->underrun_counter--; 126fcf3ce44SJohn Forte iostat = IOSTAT_FCP_RSP_ERROR; 127fcf3ce44SJohn Forte 128fcf3ce44SJohn Forte /* Report 512 bytes missing by adapter */ 129fcf3ce44SJohn Forte cmd->un.fcpi.fcpi_parm = pkt->pkt_datalen - 512; 130fcf3ce44SJohn Forte 131fcf3ce44SJohn Forte /* Corrupt 512 bytes of Data buffer */ 132fcf3ce44SJohn Forte bzero((uint8_t *)pkt->pkt_data, 512); 133fcf3ce44SJohn Forte 134fcf3ce44SJohn Forte /* Set FCP response to STATUS_GOOD */ 135fcf3ce44SJohn Forte bzero((uint8_t *)pkt->pkt_resp, pkt->pkt_rsplen); 136fcf3ce44SJohn Forte } 137291a2b48SSukumar Swaminathan #endif /* TEST_SUPPORT */ 138fcf3ce44SJohn Forte } 139291a2b48SSukumar Swaminathan 140fcf3ce44SJohn Forte /* Process the pkt */ 141fcf3ce44SJohn Forte mutex_enter(&sbp->mtx); 142fcf3ce44SJohn Forte 143fcf3ce44SJohn Forte /* Check for immediate return */ 144fcf3ce44SJohn Forte if ((iostat == IOSTAT_SUCCESS) && 145fcf3ce44SJohn Forte (pkt->pkt_comp) && 146291a2b48SSukumar Swaminathan !(sbp->pkt_flags & 14782527734SSukumar Swaminathan (PACKET_ULP_OWNED | PACKET_COMPLETED | 148fcf3ce44SJohn Forte PACKET_IN_COMPLETION | PACKET_IN_TXQ | PACKET_IN_CHIPQ | 149fcf3ce44SJohn Forte PACKET_IN_DONEQ | PACKET_IN_TIMEOUT | PACKET_IN_FLUSH | 150fcf3ce44SJohn Forte PACKET_IN_ABORT | PACKET_POLLED))) { 151fcf3ce44SJohn Forte HBASTATS.FcpGood++; 152fcf3ce44SJohn Forte 153291a2b48SSukumar Swaminathan sbp->pkt_flags |= 154291a2b48SSukumar Swaminathan (PACKET_STATE_VALID | PACKET_IN_COMPLETION | 15582527734SSukumar Swaminathan PACKET_COMPLETED | PACKET_ULP_OWNED); 156fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 157fcf3ce44SJohn Forte 158fcf3ce44SJohn Forte #if (EMLXS_MODREVX == EMLXS_MODREV2X) 159fcf3ce44SJohn Forte emlxs_unswap_pkt(sbp); 160291a2b48SSukumar Swaminathan #endif /* EMLXS_MODREV2X */ 161b3660a96SSukumar Swaminathan 162b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT 163b3660a96SSukumar Swaminathan emlxs_check_dma(hba, sbp); 164b3660a96SSukumar Swaminathan #endif /* FMA_SUPPORT */ 165b3660a96SSukumar Swaminathan 16682527734SSukumar Swaminathan cp->ulpCmplCmd++; 167fcf3ce44SJohn Forte (*pkt->pkt_comp) (pkt); 168fcf3ce44SJohn Forte 169b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT 170b3660a96SSukumar Swaminathan if (hba->flag & FC_DMA_CHECK_ERROR) { 171b3660a96SSukumar Swaminathan emlxs_thread_spawn(hba, emlxs_restart_thread, 172b3660a96SSukumar Swaminathan NULL, NULL); 173b3660a96SSukumar Swaminathan } 174b3660a96SSukumar Swaminathan #endif /* FMA_SUPPORT */ 175b3660a96SSukumar Swaminathan 176fcf3ce44SJohn Forte return; 177fcf3ce44SJohn Forte } 178291a2b48SSukumar Swaminathan 179fcf3ce44SJohn Forte /* 180291a2b48SSukumar Swaminathan * A response is only placed in the resp buffer if IOSTAT_FCP_RSP_ERROR 181291a2b48SSukumar Swaminathan * is reported. 182fcf3ce44SJohn Forte */ 183fcf3ce44SJohn Forte 184fcf3ce44SJohn Forte /* Check if a response buffer was provided */ 185fcf3ce44SJohn Forte if ((iostat == IOSTAT_FCP_RSP_ERROR) && pkt->pkt_rsplen) { 18682527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(pkt->pkt_resp_dma, 0, pkt->pkt_rsplen, 187fcf3ce44SJohn Forte DDI_DMA_SYNC_FORKERNEL); 188fcf3ce44SJohn Forte 189fcf3ce44SJohn Forte /* Get the response buffer pointer */ 190fcf3ce44SJohn Forte rsp = (fcp_rsp_t *)pkt->pkt_resp; 191fcf3ce44SJohn Forte 192fcf3ce44SJohn Forte /* Set the valid response flag */ 193fcf3ce44SJohn Forte sbp->pkt_flags |= PACKET_FCP_RSP_VALID; 194fcf3ce44SJohn Forte 195fcf3ce44SJohn Forte scsi_status = rsp->fcp_u.fcp_status.scsi_status; 196fcf3ce44SJohn Forte 197291a2b48SSukumar Swaminathan #ifdef SAN_DIAG_SUPPORT 198291a2b48SSukumar Swaminathan ndlp = (NODELIST *)iocbq->node; 199291a2b48SSukumar Swaminathan if (scsi_status == SCSI_STAT_QUE_FULL) { 200291a2b48SSukumar Swaminathan emlxs_log_sd_scsi_event(port, SD_SCSI_SUBCATEGORY_QFULL, 201291a2b48SSukumar Swaminathan (HBA_WWN *)&ndlp->nlp_portname, sbp->lun); 202291a2b48SSukumar Swaminathan } else if (scsi_status == SCSI_STAT_BUSY) { 203291a2b48SSukumar Swaminathan emlxs_log_sd_scsi_event(port, 204291a2b48SSukumar Swaminathan SD_SCSI_SUBCATEGORY_DEVBSY, 205291a2b48SSukumar Swaminathan (HBA_WWN *)&ndlp->nlp_portname, sbp->lun); 206291a2b48SSukumar Swaminathan } 207291a2b48SSukumar Swaminathan #endif 208291a2b48SSukumar Swaminathan 209fcf3ce44SJohn Forte /* 210fcf3ce44SJohn Forte * Convert a task abort to a check condition with no data 211291a2b48SSukumar Swaminathan * transferred. We saw a data corruption when Solaris received 212291a2b48SSukumar Swaminathan * a Task Abort from a tape. 213fcf3ce44SJohn Forte */ 214*a9800bebSGarrett D'Amore 215fcf3ce44SJohn Forte if (scsi_status == SCSI_STAT_TASK_ABORT) { 216fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 217fcf3ce44SJohn Forte &emlxs_fcp_completion_error_msg, 218291a2b48SSukumar Swaminathan "Task Abort. " 219291a2b48SSukumar Swaminathan "Fixed.did=0x%06x sbp=%p cmd=%02x dl=%d", 220fcf3ce44SJohn Forte did, sbp, scsi_opcode, pkt->pkt_datalen); 221fcf3ce44SJohn Forte 222fcf3ce44SJohn Forte rsp->fcp_u.fcp_status.scsi_status = 223fcf3ce44SJohn Forte SCSI_STAT_CHECK_COND; 224fcf3ce44SJohn Forte rsp->fcp_u.fcp_status.rsp_len_set = 0; 225fcf3ce44SJohn Forte rsp->fcp_u.fcp_status.sense_len_set = 0; 226fcf3ce44SJohn Forte rsp->fcp_u.fcp_status.resid_over = 0; 227fcf3ce44SJohn Forte 228fcf3ce44SJohn Forte if (pkt->pkt_datalen) { 229fcf3ce44SJohn Forte rsp->fcp_u.fcp_status.resid_under = 1; 230291a2b48SSukumar Swaminathan rsp->fcp_resid = 23182527734SSukumar Swaminathan LE_SWAP32(pkt->pkt_datalen); 232fcf3ce44SJohn Forte } else { 233fcf3ce44SJohn Forte rsp->fcp_u.fcp_status.resid_under = 0; 234fcf3ce44SJohn Forte rsp->fcp_resid = 0; 235fcf3ce44SJohn Forte } 236fcf3ce44SJohn Forte 237fcf3ce44SJohn Forte scsi_status = SCSI_STAT_CHECK_COND; 238fcf3ce44SJohn Forte } 239291a2b48SSukumar Swaminathan 240fcf3ce44SJohn Forte /* 241291a2b48SSukumar Swaminathan * We only need to check underrun if data could 242291a2b48SSukumar Swaminathan * have been sent 243fcf3ce44SJohn Forte */ 244fcf3ce44SJohn Forte 245fcf3ce44SJohn Forte /* Always check underrun if status is good */ 246fcf3ce44SJohn Forte if (scsi_status == SCSI_STAT_GOOD) { 247fcf3ce44SJohn Forte check_underrun = 1; 248fcf3ce44SJohn Forte } 249fcf3ce44SJohn Forte /* Check the sense codes if this is a check condition */ 250fcf3ce44SJohn Forte else if (scsi_status == SCSI_STAT_CHECK_COND) { 251fcf3ce44SJohn Forte check_underrun = 1; 252fcf3ce44SJohn Forte 253fcf3ce44SJohn Forte /* Check if sense data was provided */ 25482527734SSukumar Swaminathan if (LE_SWAP32(rsp->fcp_sense_len) >= 14) { 255fcf3ce44SJohn Forte sense = *((uint8_t *)rsp + 32 + 2); 256fcf3ce44SJohn Forte asc = *((uint8_t *)rsp + 32 + 12); 257fcf3ce44SJohn Forte ascq = *((uint8_t *)rsp + 32 + 13); 258fcf3ce44SJohn Forte } 259291a2b48SSukumar Swaminathan 260291a2b48SSukumar Swaminathan #ifdef SAN_DIAG_SUPPORT 261291a2b48SSukumar Swaminathan emlxs_log_sd_scsi_check_event(port, 262291a2b48SSukumar Swaminathan (HBA_WWN *)&ndlp->nlp_portname, sbp->lun, 263291a2b48SSukumar Swaminathan scsi_opcode, sense, asc, ascq); 264291a2b48SSukumar Swaminathan #endif 265fcf3ce44SJohn Forte } 266fcf3ce44SJohn Forte /* Status is not good and this is not a check condition */ 267fcf3ce44SJohn Forte /* No data should have been sent */ 268fcf3ce44SJohn Forte else { 269fcf3ce44SJohn Forte check_underrun = 0; 270fcf3ce44SJohn Forte } 271fcf3ce44SJohn Forte 272fcf3ce44SJohn Forte /* Get the residual underrun count reported by the SCSI reply */ 273fcf3ce44SJohn Forte rsp_data_resid = (pkt->pkt_datalen && 27482527734SSukumar Swaminathan rsp->fcp_u.fcp_status.resid_under) ? LE_SWAP32(rsp-> 275291a2b48SSukumar Swaminathan fcp_resid) : 0; 276fcf3ce44SJohn Forte 277fcf3ce44SJohn Forte /* Set the pkt resp_resid field */ 278fcf3ce44SJohn Forte pkt->pkt_resp_resid = 0; 279fcf3ce44SJohn Forte 280fcf3ce44SJohn Forte /* Set the pkt data_resid field */ 281fcf3ce44SJohn Forte if (pkt->pkt_datalen && 282fcf3ce44SJohn Forte (pkt->pkt_tran_type == FC_PKT_FCP_READ)) { 283fcf3ce44SJohn Forte /* 284291a2b48SSukumar Swaminathan * Get the residual underrun count reported by 285291a2b48SSukumar Swaminathan * our adapter 286fcf3ce44SJohn Forte */ 287fcf3ce44SJohn Forte pkt->pkt_data_resid = cmd->un.fcpi.fcpi_parm; 288fcf3ce44SJohn Forte 289291a2b48SSukumar Swaminathan #ifdef SAN_DIAG_SUPPORT 290291a2b48SSukumar Swaminathan if ((rsp_data_resid == 0) && (pkt->pkt_data_resid)) { 291291a2b48SSukumar Swaminathan emlxs_log_sd_fc_rdchk_event(port, 292291a2b48SSukumar Swaminathan (HBA_WWN *)&ndlp->nlp_portname, sbp->lun, 293291a2b48SSukumar Swaminathan scsi_opcode, pkt->pkt_data_resid); 294291a2b48SSukumar Swaminathan } 295291a2b48SSukumar Swaminathan #endif 296291a2b48SSukumar Swaminathan 297fcf3ce44SJohn Forte /* Get the actual amount of data transferred */ 298fcf3ce44SJohn Forte data_rx = pkt->pkt_datalen - pkt->pkt_data_resid; 299fcf3ce44SJohn Forte 300fcf3ce44SJohn Forte /* 301fcf3ce44SJohn Forte * If the residual being reported by the adapter is 302fcf3ce44SJohn Forte * greater than the residual being reported in the 303fcf3ce44SJohn Forte * reply, then we have a true underrun. 304fcf3ce44SJohn Forte */ 305fcf3ce44SJohn Forte if (check_underrun && 306fcf3ce44SJohn Forte (pkt->pkt_data_resid > rsp_data_resid)) { 307fcf3ce44SJohn Forte switch (scsi_opcode) { 308fcf3ce44SJohn Forte case SCSI_INQUIRY: 309fcf3ce44SJohn Forte scsi_dl = scsi_cmd[16]; 310fcf3ce44SJohn Forte break; 311fcf3ce44SJohn Forte 312fcf3ce44SJohn Forte case SCSI_RX_DIAG: 313291a2b48SSukumar Swaminathan scsi_dl = 314291a2b48SSukumar Swaminathan (scsi_cmd[15] * 0x100) + 315fcf3ce44SJohn Forte scsi_cmd[16]; 316fcf3ce44SJohn Forte break; 317fcf3ce44SJohn Forte 318fcf3ce44SJohn Forte default: 319fcf3ce44SJohn Forte scsi_dl = pkt->pkt_datalen; 320fcf3ce44SJohn Forte } 321fcf3ce44SJohn Forte 322fcf3ce44SJohn Forte #ifdef FCP_UNDERRUN_PATCH1 32382527734SSukumar Swaminathan if (cfg[CFG_ENABLE_PATCH].current & FCP_UNDERRUN_PATCH1) { 324fcf3ce44SJohn Forte /* 325fcf3ce44SJohn Forte * If status is not good and no data was 326291a2b48SSukumar Swaminathan * actually transferred, then we must fix 327291a2b48SSukumar Swaminathan * the issue 328fcf3ce44SJohn Forte */ 329fcf3ce44SJohn Forte if ((scsi_status != SCSI_STAT_GOOD) && 330fcf3ce44SJohn Forte (data_rx == 0)) { 331fcf3ce44SJohn Forte fix_it = 1; 332fcf3ce44SJohn Forte 333fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 334fcf3ce44SJohn Forte &emlxs_fcp_completion_error_msg, 335291a2b48SSukumar Swaminathan "Underrun(1). Fixed. " 336291a2b48SSukumar Swaminathan "did=0x%06x sbp=%p cmd=%02x " 337291a2b48SSukumar Swaminathan "dl=%d,%d rx=%d rsp=%d", 338fcf3ce44SJohn Forte did, sbp, scsi_opcode, 339fcf3ce44SJohn Forte pkt->pkt_datalen, scsi_dl, 340fcf3ce44SJohn Forte (pkt->pkt_datalen - 341fcf3ce44SJohn Forte cmd->un.fcpi.fcpi_parm), 342fcf3ce44SJohn Forte rsp_data_resid); 343fcf3ce44SJohn Forte 344fcf3ce44SJohn Forte } 34582527734SSukumar Swaminathan } 346291a2b48SSukumar Swaminathan #endif /* FCP_UNDERRUN_PATCH1 */ 347fcf3ce44SJohn Forte 348fcf3ce44SJohn Forte 349fcf3ce44SJohn Forte #ifdef FCP_UNDERRUN_PATCH2 35082527734SSukumar Swaminathan if (cfg[CFG_ENABLE_PATCH].current & FCP_UNDERRUN_PATCH2) { 351fcf3ce44SJohn Forte if ((scsi_status == SCSI_STAT_GOOD)) { 352291a2b48SSukumar Swaminathan emlxs_msg_t *msg; 353fcf3ce44SJohn Forte 354fcf3ce44SJohn Forte msg = &emlxs_fcp_completion_error_msg; 355fcf3ce44SJohn Forte /* 356fcf3ce44SJohn Forte * If status is good and this is an 357fcf3ce44SJohn Forte * inquiry request and the amount of 358fcf3ce44SJohn Forte * data 359fcf3ce44SJohn Forte */ 360fcf3ce44SJohn Forte /* 361291a2b48SSukumar Swaminathan * requested <= data received, then we 362291a2b48SSukumar Swaminathan * must fix the issue. 363fcf3ce44SJohn Forte */ 364fcf3ce44SJohn Forte 365fcf3ce44SJohn Forte if ((scsi_opcode == SCSI_INQUIRY) && 366fcf3ce44SJohn Forte (pkt->pkt_datalen >= data_rx) && 367fcf3ce44SJohn Forte (scsi_dl <= data_rx)) { 368fcf3ce44SJohn Forte fix_it = 1; 369fcf3ce44SJohn Forte 370291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, msg, 371fcf3ce44SJohn Forte "Underrun(2). Fixed. " 372fcf3ce44SJohn Forte "did=0x%06x sbp=%p " 373fcf3ce44SJohn Forte "cmd=%02x dl=%d,%d " 374fcf3ce44SJohn Forte "rx=%d rsp=%d", 375fcf3ce44SJohn Forte did, sbp, scsi_opcode, 376fcf3ce44SJohn Forte pkt->pkt_datalen, scsi_dl, 377fcf3ce44SJohn Forte data_rx, rsp_data_resid); 378fcf3ce44SJohn Forte 379fcf3ce44SJohn Forte } 380291a2b48SSukumar Swaminathan 381fcf3ce44SJohn Forte /* 382fcf3ce44SJohn Forte * If status is good and this is an 383fcf3ce44SJohn Forte * inquiry request and the amount of 384291a2b48SSukumar Swaminathan * data requested >= 128 bytes, but 385291a2b48SSukumar Swaminathan * only 128 bytes were received, 386291a2b48SSukumar Swaminathan * then we must fix the issue. 387fcf3ce44SJohn Forte */ 388291a2b48SSukumar Swaminathan else if ((scsi_opcode == 389291a2b48SSukumar Swaminathan SCSI_INQUIRY) && 390fcf3ce44SJohn Forte (pkt->pkt_datalen >= 128) && 391fcf3ce44SJohn Forte (scsi_dl >= 128) && 392fcf3ce44SJohn Forte (data_rx == 128)) { 393fcf3ce44SJohn Forte fix_it = 1; 394fcf3ce44SJohn Forte 395291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, msg, 396fcf3ce44SJohn Forte "Underrun(3). Fixed. " 397fcf3ce44SJohn Forte "did=0x%06x sbp=%p " 398291a2b48SSukumar Swaminathan "cmd=%02x dl=%d,%d " 399291a2b48SSukumar Swaminathan "rx=%d rsp=%d", 400fcf3ce44SJohn Forte did, sbp, scsi_opcode, 401fcf3ce44SJohn Forte pkt->pkt_datalen, scsi_dl, 402fcf3ce44SJohn Forte data_rx, rsp_data_resid); 403fcf3ce44SJohn Forte 404fcf3ce44SJohn Forte } 405291a2b48SSukumar Swaminathan 406fcf3ce44SJohn Forte } 40782527734SSukumar Swaminathan } 408291a2b48SSukumar Swaminathan #endif /* FCP_UNDERRUN_PATCH2 */ 409fcf3ce44SJohn Forte 410fcf3ce44SJohn Forte /* 411fcf3ce44SJohn Forte * Check if SCSI response payload should be 412291a2b48SSukumar Swaminathan * fixed or if a DATA_UNDERRUN should be 413291a2b48SSukumar Swaminathan * reported 414fcf3ce44SJohn Forte */ 415fcf3ce44SJohn Forte if (fix_it) { 416fcf3ce44SJohn Forte /* 417291a2b48SSukumar Swaminathan * Fix the SCSI response payload itself 418fcf3ce44SJohn Forte */ 419fcf3ce44SJohn Forte rsp->fcp_u.fcp_status.resid_under = 1; 420fcf3ce44SJohn Forte rsp->fcp_resid = 42182527734SSukumar Swaminathan LE_SWAP32(pkt->pkt_data_resid); 422fcf3ce44SJohn Forte } else { 423fcf3ce44SJohn Forte /* 424fcf3ce44SJohn Forte * Change the status from 425fcf3ce44SJohn Forte * IOSTAT_FCP_RSP_ERROR to 426fcf3ce44SJohn Forte * IOSTAT_DATA_UNDERRUN 427fcf3ce44SJohn Forte */ 428fcf3ce44SJohn Forte iostat = IOSTAT_DATA_UNDERRUN; 429291a2b48SSukumar Swaminathan pkt->pkt_data_resid = 430291a2b48SSukumar Swaminathan pkt->pkt_datalen; 431fcf3ce44SJohn Forte } 432fcf3ce44SJohn Forte } 433291a2b48SSukumar Swaminathan 434fcf3ce44SJohn Forte /* 435fcf3ce44SJohn Forte * If the residual being reported by the adapter is 436291a2b48SSukumar Swaminathan * less than the residual being reported in the reply, 437291a2b48SSukumar Swaminathan * then we have a true overrun. Since we don't know 438291a2b48SSukumar Swaminathan * where the extra data came from or went to then we 439291a2b48SSukumar Swaminathan * cannot trust anything we received 440fcf3ce44SJohn Forte */ 441fcf3ce44SJohn Forte else if (rsp_data_resid > pkt->pkt_data_resid) { 442fcf3ce44SJohn Forte /* 443fcf3ce44SJohn Forte * Change the status from 444fcf3ce44SJohn Forte * IOSTAT_FCP_RSP_ERROR to 445fcf3ce44SJohn Forte * IOSTAT_DATA_OVERRUN 446fcf3ce44SJohn Forte */ 447fcf3ce44SJohn Forte iostat = IOSTAT_DATA_OVERRUN; 448fcf3ce44SJohn Forte pkt->pkt_data_resid = pkt->pkt_datalen; 449fcf3ce44SJohn Forte } 450fcf3ce44SJohn Forte } else { /* pkt->pkt_datalen==0 or FC_PKT_FCP_WRITE */ 451291a2b48SSukumar Swaminathan 452fcf3ce44SJohn Forte /* Report whatever the target reported */ 453fcf3ce44SJohn Forte pkt->pkt_data_resid = rsp_data_resid; 454fcf3ce44SJohn Forte } 455fcf3ce44SJohn Forte } 456291a2b48SSukumar Swaminathan 457fcf3ce44SJohn Forte /* Print completion message */ 458fcf3ce44SJohn Forte switch (iostat) { 459fcf3ce44SJohn Forte case IOSTAT_SUCCESS: 460fcf3ce44SJohn Forte /* Build SCSI GOOD status */ 461fcf3ce44SJohn Forte if (pkt->pkt_rsplen) { 462fcf3ce44SJohn Forte bzero((uint8_t *)pkt->pkt_resp, pkt->pkt_rsplen); 463fcf3ce44SJohn Forte } 464fcf3ce44SJohn Forte break; 465fcf3ce44SJohn Forte 466fcf3ce44SJohn Forte case IOSTAT_FCP_RSP_ERROR: 467fcf3ce44SJohn Forte break; 468fcf3ce44SJohn Forte 469fcf3ce44SJohn Forte case IOSTAT_REMOTE_STOP: 470fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, 471291a2b48SSukumar Swaminathan "Remote Stop. did=0x%06x sbp=%p cmd=%02x", did, sbp, 472291a2b48SSukumar Swaminathan scsi_opcode); 473fcf3ce44SJohn Forte break; 474fcf3ce44SJohn Forte 475fcf3ce44SJohn Forte case IOSTAT_LOCAL_REJECT: 476fcf3ce44SJohn Forte localstat = cmd->un.grsp.perr.statLocalError; 477fcf3ce44SJohn Forte 478fcf3ce44SJohn Forte switch (localstat) { 479fcf3ce44SJohn Forte case IOERR_SEQUENCE_TIMEOUT: 480fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 481fcf3ce44SJohn Forte &emlxs_fcp_completion_error_msg, 482291a2b48SSukumar Swaminathan "Local reject. " 483291a2b48SSukumar Swaminathan "%s did=0x%06x sbp=%p cmd=%02x tmo=%d ", 484fcf3ce44SJohn Forte emlxs_error_xlate(localstat), did, sbp, 485fcf3ce44SJohn Forte scsi_opcode, pkt->pkt_timeout); 486fcf3ce44SJohn Forte break; 487fcf3ce44SJohn Forte 488fcf3ce44SJohn Forte default: 489fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 490fcf3ce44SJohn Forte &emlxs_fcp_completion_error_msg, 491*a9800bebSGarrett D'Amore "Local reject. %s 0x%06x %p %02x (%x)(%x)", 492291a2b48SSukumar Swaminathan emlxs_error_xlate(localstat), did, sbp, 493*a9800bebSGarrett D'Amore scsi_opcode, (uint16_t)cmd->ULPIOTAG, 494*a9800bebSGarrett D'Amore (uint16_t)cmd->ULPCONTEXT); 495fcf3ce44SJohn Forte } 496fcf3ce44SJohn Forte 497fcf3ce44SJohn Forte break; 498fcf3ce44SJohn Forte 499fcf3ce44SJohn Forte case IOSTAT_NPORT_RJT: 500fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, 501291a2b48SSukumar Swaminathan "Nport reject. did=0x%06x sbp=%p cmd=%02x", did, sbp, 502291a2b48SSukumar Swaminathan scsi_opcode); 503fcf3ce44SJohn Forte break; 504fcf3ce44SJohn Forte 505fcf3ce44SJohn Forte case IOSTAT_FABRIC_RJT: 506fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, 507291a2b48SSukumar Swaminathan "Fabric reject. did=0x%06x sbp=%p cmd=%02x", did, sbp, 508291a2b48SSukumar Swaminathan scsi_opcode); 509fcf3ce44SJohn Forte break; 510fcf3ce44SJohn Forte 511fcf3ce44SJohn Forte case IOSTAT_NPORT_BSY: 512291a2b48SSukumar Swaminathan #ifdef SAN_DIAG_SUPPORT 513291a2b48SSukumar Swaminathan ndlp = (NODELIST *)iocbq->node; 514291a2b48SSukumar Swaminathan emlxs_log_sd_fc_bsy_event(port, (HBA_WWN *)&ndlp->nlp_portname); 515291a2b48SSukumar Swaminathan #endif 516291a2b48SSukumar Swaminathan 517fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, 518291a2b48SSukumar Swaminathan "Nport busy. did=0x%06x sbp=%p cmd=%02x", did, sbp, 519291a2b48SSukumar Swaminathan scsi_opcode); 520fcf3ce44SJohn Forte break; 521fcf3ce44SJohn Forte 522fcf3ce44SJohn Forte case IOSTAT_FABRIC_BSY: 523291a2b48SSukumar Swaminathan #ifdef SAN_DIAG_SUPPORT 524291a2b48SSukumar Swaminathan ndlp = (NODELIST *)iocbq->node; 525291a2b48SSukumar Swaminathan emlxs_log_sd_fc_bsy_event(port, NULL); 526291a2b48SSukumar Swaminathan #endif 527291a2b48SSukumar Swaminathan 528fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, 529291a2b48SSukumar Swaminathan "Fabric busy. did=0x%06x sbp=%p cmd=%02x", did, sbp, 530291a2b48SSukumar Swaminathan scsi_opcode); 531fcf3ce44SJohn Forte break; 532fcf3ce44SJohn Forte 533fcf3ce44SJohn Forte case IOSTAT_INTERMED_RSP: 534fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, 535291a2b48SSukumar Swaminathan "Intermediate response. did=0x%06x sbp=%p cmd=%02x", did, 536291a2b48SSukumar Swaminathan sbp, scsi_opcode); 537fcf3ce44SJohn Forte break; 538fcf3ce44SJohn Forte 539fcf3ce44SJohn Forte case IOSTAT_LS_RJT: 540fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, 541291a2b48SSukumar Swaminathan "LS Reject. did=0x%06x sbp=%p cmd=%02x", did, sbp, 542291a2b48SSukumar Swaminathan scsi_opcode); 543fcf3ce44SJohn Forte break; 544fcf3ce44SJohn Forte 545fcf3ce44SJohn Forte case IOSTAT_DATA_UNDERRUN: 546fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, 547291a2b48SSukumar Swaminathan "Underrun. did=0x%06x sbp=%p cmd=%02x " 548291a2b48SSukumar Swaminathan "dl=%d,%d rx=%d rsp=%d (%02x,%02x,%02x,%02x)", 549291a2b48SSukumar Swaminathan did, sbp, scsi_opcode, pkt->pkt_datalen, scsi_dl, data_rx, 550291a2b48SSukumar Swaminathan rsp_data_resid, scsi_status, sense, asc, ascq); 551fcf3ce44SJohn Forte break; 552fcf3ce44SJohn Forte 553fcf3ce44SJohn Forte case IOSTAT_DATA_OVERRUN: 554fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, 555291a2b48SSukumar Swaminathan "Overrun. did=0x%06x sbp=%p cmd=%02x " 556291a2b48SSukumar Swaminathan "dl=%d,%d rx=%d rsp=%d (%02x,%02x,%02x,%02x)", 557291a2b48SSukumar Swaminathan did, sbp, scsi_opcode, pkt->pkt_datalen, scsi_dl, data_rx, 558291a2b48SSukumar Swaminathan rsp_data_resid, scsi_status, sense, asc, ascq); 559fcf3ce44SJohn Forte break; 560fcf3ce44SJohn Forte 561fcf3ce44SJohn Forte default: 562fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, 563fcf3ce44SJohn Forte "Unknown status=%x reason=%x did=0x%06x sbp=%p cmd=%02x", 564291a2b48SSukumar Swaminathan iostat, cmd->un.grsp.perr.statLocalError, did, sbp, 565291a2b48SSukumar Swaminathan scsi_opcode); 566fcf3ce44SJohn Forte break; 567fcf3ce44SJohn Forte } 568fcf3ce44SJohn Forte 569fcf3ce44SJohn Forte done: 570fcf3ce44SJohn Forte 571fcf3ce44SJohn Forte if (iostat == IOSTAT_SUCCESS) { 572fcf3ce44SJohn Forte HBASTATS.FcpGood++; 573fcf3ce44SJohn Forte } else { 574fcf3ce44SJohn Forte HBASTATS.FcpError++; 575fcf3ce44SJohn Forte } 576fcf3ce44SJohn Forte 577fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 578fcf3ce44SJohn Forte 579fcf3ce44SJohn Forte emlxs_pkt_complete(sbp, iostat, localstat, 0); 580fcf3ce44SJohn Forte 581fcf3ce44SJohn Forte return; 582fcf3ce44SJohn Forte 58382527734SSukumar Swaminathan } /* emlxs_handle_fcp_event() */ 584fcf3ce44SJohn Forte 585fcf3ce44SJohn Forte 586fcf3ce44SJohn Forte 587fcf3ce44SJohn Forte /* 588fcf3ce44SJohn Forte * emlxs_post_buffer 589fcf3ce44SJohn Forte * 590fcf3ce44SJohn Forte * This routine will post count buffers to the 591fcf3ce44SJohn Forte * ring with the QUE_RING_BUF_CN command. This 592fcf3ce44SJohn Forte * allows 2 buffers / command to be posted. 593fcf3ce44SJohn Forte * Returns the number of buffers NOT posted. 594fcf3ce44SJohn Forte */ 59582527734SSukumar Swaminathan /* SLI3 */ 596fcf3ce44SJohn Forte extern int 597fcf3ce44SJohn Forte emlxs_post_buffer(emlxs_hba_t *hba, RING *rp, int16_t cnt) 598fcf3ce44SJohn Forte { 599fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 600fcf3ce44SJohn Forte IOCB *icmd; 601fcf3ce44SJohn Forte IOCBQ *iocbq; 602fcf3ce44SJohn Forte MATCHMAP *mp; 603fcf3ce44SJohn Forte uint16_t tag; 604fcf3ce44SJohn Forte uint32_t maxqbuf; 605fcf3ce44SJohn Forte int32_t i; 606fcf3ce44SJohn Forte int32_t j; 607fcf3ce44SJohn Forte uint32_t seg; 608fcf3ce44SJohn Forte uint32_t size; 609fcf3ce44SJohn Forte 610fcf3ce44SJohn Forte mp = 0; 611fcf3ce44SJohn Forte maxqbuf = 2; 612fcf3ce44SJohn Forte tag = (uint16_t)cnt; 613fcf3ce44SJohn Forte cnt += rp->fc_missbufcnt; 614fcf3ce44SJohn Forte 61582527734SSukumar Swaminathan if (rp->ringno == hba->channel_els) { 616fcf3ce44SJohn Forte seg = MEM_BUF; 617fcf3ce44SJohn Forte size = MEM_ELSBUF_SIZE; 61882527734SSukumar Swaminathan } else if (rp->ringno == hba->channel_ip) { 619fcf3ce44SJohn Forte seg = MEM_IPBUF; 620fcf3ce44SJohn Forte size = MEM_IPBUF_SIZE; 62182527734SSukumar Swaminathan } else if (rp->ringno == hba->channel_ct) { 622fcf3ce44SJohn Forte seg = MEM_CTBUF; 623fcf3ce44SJohn Forte size = MEM_CTBUF_SIZE; 624fcf3ce44SJohn Forte } 625fcf3ce44SJohn Forte #ifdef SFCT_SUPPORT 62682527734SSukumar Swaminathan else if (rp->ringno == hba->CHANNEL_FCT) { 627fcf3ce44SJohn Forte seg = MEM_FCTBUF; 628fcf3ce44SJohn Forte size = MEM_FCTBUF_SIZE; 629fcf3ce44SJohn Forte } 630291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 631fcf3ce44SJohn Forte else { 632fcf3ce44SJohn Forte return (0); 633fcf3ce44SJohn Forte } 634fcf3ce44SJohn Forte 635fcf3ce44SJohn Forte /* 636fcf3ce44SJohn Forte * While there are buffers to post 637fcf3ce44SJohn Forte */ 638fcf3ce44SJohn Forte while (cnt) { 63982527734SSukumar Swaminathan if ((iocbq = (IOCBQ *)emlxs_mem_get(hba, MEM_IOCB, 0)) == 0) { 640fcf3ce44SJohn Forte rp->fc_missbufcnt = cnt; 641fcf3ce44SJohn Forte return (cnt); 642fcf3ce44SJohn Forte } 643291a2b48SSukumar Swaminathan 64482527734SSukumar Swaminathan iocbq->channel = (void *)&hba->chan[rp->ringno]; 645fcf3ce44SJohn Forte iocbq->port = (void *)port; 646fcf3ce44SJohn Forte iocbq->flag |= (IOCB_PRIORITY | IOCB_SPECIAL); 647fcf3ce44SJohn Forte 648fcf3ce44SJohn Forte icmd = &iocbq->iocb; 649fcf3ce44SJohn Forte 650fcf3ce44SJohn Forte /* 651fcf3ce44SJohn Forte * Max buffers can be posted per command 652fcf3ce44SJohn Forte */ 653fcf3ce44SJohn Forte for (i = 0; i < maxqbuf; i++) { 654fcf3ce44SJohn Forte if (cnt <= 0) 655fcf3ce44SJohn Forte break; 656fcf3ce44SJohn Forte 657fcf3ce44SJohn Forte /* fill in BDEs for command */ 65882527734SSukumar Swaminathan if ((mp = (MATCHMAP *)emlxs_mem_get(hba, seg, 1)) 65982527734SSukumar Swaminathan == 0) { 66082527734SSukumar Swaminathan icmd->ULPBDECOUNT = i; 661fcf3ce44SJohn Forte for (j = 0; j < i; j++) { 662291a2b48SSukumar Swaminathan mp = EMLXS_GET_VADDR(hba, rp, icmd); 663fcf3ce44SJohn Forte if (mp) { 664*a9800bebSGarrett D'Amore emlxs_mem_put(hba, seg, 665*a9800bebSGarrett D'Amore (void *)mp); 666fcf3ce44SJohn Forte } 667fcf3ce44SJohn Forte } 668fcf3ce44SJohn Forte 669fcf3ce44SJohn Forte rp->fc_missbufcnt = cnt + i; 670fcf3ce44SJohn Forte 671*a9800bebSGarrett D'Amore emlxs_mem_put(hba, MEM_IOCB, (void *)iocbq); 672fcf3ce44SJohn Forte 673fcf3ce44SJohn Forte return (cnt + i); 674fcf3ce44SJohn Forte } 675291a2b48SSukumar Swaminathan 676fcf3ce44SJohn Forte /* 677fcf3ce44SJohn Forte * map that page and save the address pair for lookup 678fcf3ce44SJohn Forte * later 679fcf3ce44SJohn Forte */ 680291a2b48SSukumar Swaminathan emlxs_mem_map_vaddr(hba, 681291a2b48SSukumar Swaminathan rp, 682291a2b48SSukumar Swaminathan mp, 683fcf3ce44SJohn Forte (uint32_t *)&icmd->un.cont64[i].addrHigh, 684fcf3ce44SJohn Forte (uint32_t *)&icmd->un.cont64[i].addrLow); 685fcf3ce44SJohn Forte 686fcf3ce44SJohn Forte icmd->un.cont64[i].tus.f.bdeSize = size; 68782527734SSukumar Swaminathan icmd->ULPCOMMAND = CMD_QUE_RING_BUF64_CN; 688fcf3ce44SJohn Forte 689291a2b48SSukumar Swaminathan /* 690291a2b48SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 691291a2b48SSukumar Swaminathan * "UB Post: ring=%d addr=%08x%08x size=%d", 692291a2b48SSukumar Swaminathan * rp->ringno, icmd->un.cont64[i].addrHigh, 693291a2b48SSukumar Swaminathan * icmd->un.cont64[i].addrLow, size); 694291a2b48SSukumar Swaminathan */ 695fcf3ce44SJohn Forte 696fcf3ce44SJohn Forte cnt--; 697fcf3ce44SJohn Forte } 698fcf3ce44SJohn Forte 69982527734SSukumar Swaminathan icmd->ULPIOTAG = tag; 70082527734SSukumar Swaminathan icmd->ULPBDECOUNT = i; 70182527734SSukumar Swaminathan icmd->ULPLE = 1; 70282527734SSukumar Swaminathan icmd->ULPOWNER = OWN_CHIP; 703291a2b48SSukumar Swaminathan /* used for delimiter between commands */ 704*a9800bebSGarrett D'Amore iocbq->bp = (void *)mp; 705fcf3ce44SJohn Forte 70682527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, &hba->chan[rp->ringno], iocbq); 707fcf3ce44SJohn Forte } 708fcf3ce44SJohn Forte 709fcf3ce44SJohn Forte rp->fc_missbufcnt = 0; 710fcf3ce44SJohn Forte 711fcf3ce44SJohn Forte return (0); 712fcf3ce44SJohn Forte 71382527734SSukumar Swaminathan } /* emlxs_post_buffer() */ 714fcf3ce44SJohn Forte 715fcf3ce44SJohn Forte 716fcf3ce44SJohn Forte extern int 717fcf3ce44SJohn Forte emlxs_port_offline(emlxs_port_t *port, uint32_t scope) 718fcf3ce44SJohn Forte { 719fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 720fcf3ce44SJohn Forte emlxs_config_t *cfg; 721fcf3ce44SJohn Forte NODELIST *nlp; 722fcf3ce44SJohn Forte fc_affected_id_t *aid; 723fcf3ce44SJohn Forte uint32_t mask; 724fcf3ce44SJohn Forte uint32_t aff_d_id; 725fcf3ce44SJohn Forte uint32_t linkdown; 726fcf3ce44SJohn Forte uint32_t vlinkdown; 727fcf3ce44SJohn Forte uint32_t action; 728fcf3ce44SJohn Forte int i; 729fcf3ce44SJohn Forte uint32_t unreg_vpi; 730fcf3ce44SJohn Forte uint32_t update; 731fcf3ce44SJohn Forte uint32_t adisc_support; 732*a9800bebSGarrett D'Amore uint32_t clear_all; 7333be114edSSukumar Swaminathan uint8_t format; 734fcf3ce44SJohn Forte 735fcf3ce44SJohn Forte /* Target mode only uses this routine for linkdowns */ 736fcf3ce44SJohn Forte if (port->tgt_mode && (scope != 0xffffffff) && (scope != 0xfeffffff)) { 737fcf3ce44SJohn Forte return (0); 738fcf3ce44SJohn Forte } 739291a2b48SSukumar Swaminathan 740fcf3ce44SJohn Forte cfg = &CFG; 741fcf3ce44SJohn Forte aid = (fc_affected_id_t *)&scope; 742fcf3ce44SJohn Forte linkdown = 0; 743fcf3ce44SJohn Forte vlinkdown = 0; 744fcf3ce44SJohn Forte unreg_vpi = 0; 745fcf3ce44SJohn Forte update = 0; 746*a9800bebSGarrett D'Amore clear_all = 0; 747fcf3ce44SJohn Forte 748fcf3ce44SJohn Forte if (!(port->flag & EMLXS_PORT_BOUND)) { 749fcf3ce44SJohn Forte return (0); 750fcf3ce44SJohn Forte } 751291a2b48SSukumar Swaminathan 7523be114edSSukumar Swaminathan format = aid->aff_format; 7533be114edSSukumar Swaminathan 7543be114edSSukumar Swaminathan switch (format) { 755fcf3ce44SJohn Forte case 0: /* Port */ 756fcf3ce44SJohn Forte mask = 0x00ffffff; 757fcf3ce44SJohn Forte break; 758fcf3ce44SJohn Forte 759fcf3ce44SJohn Forte case 1: /* Area */ 760fcf3ce44SJohn Forte mask = 0x00ffff00; 761fcf3ce44SJohn Forte break; 762fcf3ce44SJohn Forte 763fcf3ce44SJohn Forte case 2: /* Domain */ 764fcf3ce44SJohn Forte mask = 0x00ff0000; 765fcf3ce44SJohn Forte break; 766fcf3ce44SJohn Forte 767fcf3ce44SJohn Forte case 3: /* Network */ 768fcf3ce44SJohn Forte mask = 0x00000000; 769fcf3ce44SJohn Forte break; 770fcf3ce44SJohn Forte 771*a9800bebSGarrett D'Amore case 0xfd: /* New fabric */ 772*a9800bebSGarrett D'Amore mask = 0x00000000; 773*a9800bebSGarrett D'Amore linkdown = 1; 774*a9800bebSGarrett D'Amore clear_all = 1; 775*a9800bebSGarrett D'Amore break; 776*a9800bebSGarrett D'Amore 777fcf3ce44SJohn Forte #ifdef DHCHAP_SUPPORT 778fcf3ce44SJohn Forte case 0xfe: /* Virtual link down */ 779fcf3ce44SJohn Forte mask = 0x00000000; 780fcf3ce44SJohn Forte vlinkdown = 1; 781fcf3ce44SJohn Forte break; 782291a2b48SSukumar Swaminathan #endif /* DHCHAP_SUPPORT */ 783fcf3ce44SJohn Forte 784fcf3ce44SJohn Forte case 0xff: /* link is down */ 785fcf3ce44SJohn Forte mask = 0x00000000; 786fcf3ce44SJohn Forte linkdown = 1; 787fcf3ce44SJohn Forte break; 788fcf3ce44SJohn Forte 789fcf3ce44SJohn Forte } 790fcf3ce44SJohn Forte 791fcf3ce44SJohn Forte aff_d_id = aid->aff_d_id & mask; 792fcf3ce44SJohn Forte 793fcf3ce44SJohn Forte 794fcf3ce44SJohn Forte /* 795291a2b48SSukumar Swaminathan * If link is down then this is a hard shutdown and flush 796291a2b48SSukumar Swaminathan * If link not down then this is a soft shutdown and flush 797291a2b48SSukumar Swaminathan * (e.g. RSCN) 798fcf3ce44SJohn Forte */ 799fcf3ce44SJohn Forte if (linkdown) { 800fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 801fcf3ce44SJohn Forte 802fcf3ce44SJohn Forte port->flag &= EMLXS_PORT_LINKDOWN_MASK; 803fcf3ce44SJohn Forte 804fcf3ce44SJohn Forte if (port->ulp_statec != FC_STATE_OFFLINE) { 805fcf3ce44SJohn Forte port->ulp_statec = FC_STATE_OFFLINE; 806*a9800bebSGarrett D'Amore port->prev_did = port->did; 807*a9800bebSGarrett D'Amore bcopy(&port->fabric_sparam, &port->prev_fabric_sparam, 808*a9800bebSGarrett D'Amore sizeof (SERV_PARM)); 809*a9800bebSGarrett D'Amore port->did = 0; 810fcf3ce44SJohn Forte update = 1; 811fcf3ce44SJohn Forte } 812291a2b48SSukumar Swaminathan 813fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 814fcf3ce44SJohn Forte 815fcf3ce44SJohn Forte /* Tell ULP about it */ 816fcf3ce44SJohn Forte if (update) { 817fcf3ce44SJohn Forte if (port->flag & EMLXS_PORT_BOUND) { 818fcf3ce44SJohn Forte if (port->vpi == 0) { 819fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 820291a2b48SSukumar Swaminathan &emlxs_link_down_msg, NULL); 821fcf3ce44SJohn Forte } 822291a2b48SSukumar Swaminathan 8233be114edSSukumar Swaminathan if (port->ini_mode) { 8243be114edSSukumar Swaminathan port->ulp_statec_cb(port->ulp_handle, 8253be114edSSukumar Swaminathan FC_STATE_OFFLINE); 8263be114edSSukumar Swaminathan } 827291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT 8283be114edSSukumar Swaminathan else if (port->tgt_mode) { 829fcf3ce44SJohn Forte emlxs_fct_link_down(port); 8303be114edSSukumar Swaminathan } 831291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 832fcf3ce44SJohn Forte 833fcf3ce44SJohn Forte } else { 834fcf3ce44SJohn Forte if (port->vpi == 0) { 835fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 836291a2b48SSukumar Swaminathan &emlxs_link_down_msg, "*"); 837fcf3ce44SJohn Forte } 838fcf3ce44SJohn Forte } 839fcf3ce44SJohn Forte 840fcf3ce44SJohn Forte 841fcf3ce44SJohn Forte } 842291a2b48SSukumar Swaminathan 843fcf3ce44SJohn Forte unreg_vpi = 1; 844fcf3ce44SJohn Forte 845fcf3ce44SJohn Forte #ifdef DHCHAP_SUPPORT 846fcf3ce44SJohn Forte /* Stop authentication with all nodes */ 847fcf3ce44SJohn Forte emlxs_dhc_auth_stop(port, NULL); 848291a2b48SSukumar Swaminathan #endif /* DHCHAP_SUPPORT */ 849fcf3ce44SJohn Forte 850fcf3ce44SJohn Forte /* Flush the base node */ 851fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, &port->node_base, 0, 0, 0); 852fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 0, &port->node_base, 0); 853fcf3ce44SJohn Forte 854fcf3ce44SJohn Forte /* Flush any pending ub buffers */ 855fcf3ce44SJohn Forte emlxs_ub_flush(port); 856fcf3ce44SJohn Forte } 857fcf3ce44SJohn Forte #ifdef DHCHAP_SUPPORT 858fcf3ce44SJohn Forte /* virtual link down */ 859fcf3ce44SJohn Forte else if (vlinkdown) { 860fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 861fcf3ce44SJohn Forte 862fcf3ce44SJohn Forte if (port->ulp_statec != FC_STATE_OFFLINE) { 863fcf3ce44SJohn Forte port->ulp_statec = FC_STATE_OFFLINE; 864fcf3ce44SJohn Forte update = 1; 865fcf3ce44SJohn Forte } 866291a2b48SSukumar Swaminathan 867fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 868fcf3ce44SJohn Forte 869fcf3ce44SJohn Forte /* Tell ULP about it */ 870fcf3ce44SJohn Forte if (update) { 871fcf3ce44SJohn Forte if (port->flag & EMLXS_PORT_BOUND) { 872fcf3ce44SJohn Forte if (port->vpi == 0) { 873fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 874fcf3ce44SJohn Forte &emlxs_link_down_msg, 875fcf3ce44SJohn Forte "Switch authentication failed."); 876fcf3ce44SJohn Forte } 877291a2b48SSukumar Swaminathan 878fcf3ce44SJohn Forte #ifdef SFCT_SUPPORT 879fcf3ce44SJohn Forte if (port->tgt_mode) { 880fcf3ce44SJohn Forte emlxs_fct_link_down(port); 881291a2b48SSukumar Swaminathan 882fcf3ce44SJohn Forte } else if (port->ini_mode) { 883fcf3ce44SJohn Forte port->ulp_statec_cb(port->ulp_handle, 884fcf3ce44SJohn Forte FC_STATE_OFFLINE); 885fcf3ce44SJohn Forte } 886fcf3ce44SJohn Forte #else 887fcf3ce44SJohn Forte port->ulp_statec_cb(port->ulp_handle, 888fcf3ce44SJohn Forte FC_STATE_OFFLINE); 889fcf3ce44SJohn Forte #endif /* SFCT_SUPPORT */ 890fcf3ce44SJohn Forte } else { 891fcf3ce44SJohn Forte if (port->vpi == 0) { 892fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 893fcf3ce44SJohn Forte &emlxs_link_down_msg, 894fcf3ce44SJohn Forte "Switch authentication failed. *"); 895fcf3ce44SJohn Forte } 896fcf3ce44SJohn Forte } 897fcf3ce44SJohn Forte 898fcf3ce44SJohn Forte 899fcf3ce44SJohn Forte } 900291a2b48SSukumar Swaminathan 901fcf3ce44SJohn Forte /* Flush the base node */ 902fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, &port->node_base, 0, 0, 0); 903fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 0, &port->node_base, 0); 904fcf3ce44SJohn Forte } 905291a2b48SSukumar Swaminathan #endif /* DHCHAP_SUPPORT */ 906fcf3ce44SJohn Forte 907fcf3ce44SJohn Forte if (port->tgt_mode) { 908fcf3ce44SJohn Forte goto done; 909fcf3ce44SJohn Forte } 910291a2b48SSukumar Swaminathan 911fcf3ce44SJohn Forte /* Set the node tags */ 912fcf3ce44SJohn Forte /* We will process all nodes with this tag */ 913fcf3ce44SJohn Forte rw_enter(&port->node_rwlock, RW_READER); 914fcf3ce44SJohn Forte for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 915fcf3ce44SJohn Forte nlp = port->node_table[i]; 916fcf3ce44SJohn Forte while (nlp != NULL) { 917fcf3ce44SJohn Forte nlp->nlp_tag = 1; 918fcf3ce44SJohn Forte nlp = nlp->nlp_list_next; 919fcf3ce44SJohn Forte } 920fcf3ce44SJohn Forte } 921fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 922fcf3ce44SJohn Forte 923*a9800bebSGarrett D'Amore if (!clear_all && (hba->flag & FC_ONLINE_MODE)) { 924fcf3ce44SJohn Forte adisc_support = cfg[CFG_ADISC_SUPPORT].current; 925fcf3ce44SJohn Forte } else { 926fcf3ce44SJohn Forte adisc_support = 0; 927fcf3ce44SJohn Forte } 928fcf3ce44SJohn Forte 929fcf3ce44SJohn Forte /* Check ADISC support level */ 930fcf3ce44SJohn Forte switch (adisc_support) { 931fcf3ce44SJohn Forte case 0: /* No support - Flush all IO to all matching nodes */ 932fcf3ce44SJohn Forte 933291a2b48SSukumar Swaminathan for (;;) { 934fcf3ce44SJohn Forte /* 935fcf3ce44SJohn Forte * We need to hold the locks this way because 936*a9800bebSGarrett D'Amore * emlxs_mb_unreg_node and the flush routines enter the 937291a2b48SSukumar Swaminathan * same locks. Also, when we release the lock the list 938291a2b48SSukumar Swaminathan * can change out from under us. 939fcf3ce44SJohn Forte */ 940fcf3ce44SJohn Forte 941fcf3ce44SJohn Forte /* Find first node */ 942fcf3ce44SJohn Forte rw_enter(&port->node_rwlock, RW_READER); 943fcf3ce44SJohn Forte action = 0; 944fcf3ce44SJohn Forte for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 945fcf3ce44SJohn Forte nlp = port->node_table[i]; 946fcf3ce44SJohn Forte while (nlp != NULL) { 947fcf3ce44SJohn Forte if (!nlp->nlp_tag) { 948fcf3ce44SJohn Forte nlp = nlp->nlp_list_next; 949fcf3ce44SJohn Forte continue; 950fcf3ce44SJohn Forte } 951fcf3ce44SJohn Forte nlp->nlp_tag = 0; 952fcf3ce44SJohn Forte 953fcf3ce44SJohn Forte /* 954fcf3ce44SJohn Forte * Check for any device that matches 955fcf3ce44SJohn Forte * our mask 956fcf3ce44SJohn Forte */ 957fcf3ce44SJohn Forte if ((nlp->nlp_DID & mask) == aff_d_id) { 958fcf3ce44SJohn Forte if (linkdown) { 959fcf3ce44SJohn Forte action = 1; 960fcf3ce44SJohn Forte break; 961291a2b48SSukumar Swaminathan } else { /* Must be an RCSN */ 962291a2b48SSukumar Swaminathan 963fcf3ce44SJohn Forte action = 2; 964fcf3ce44SJohn Forte break; 965fcf3ce44SJohn Forte } 966fcf3ce44SJohn Forte } 967fcf3ce44SJohn Forte nlp = nlp->nlp_list_next; 968fcf3ce44SJohn Forte } 969fcf3ce44SJohn Forte 970fcf3ce44SJohn Forte if (action) { 971fcf3ce44SJohn Forte break; 972fcf3ce44SJohn Forte } 973fcf3ce44SJohn Forte } 974fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 975fcf3ce44SJohn Forte 976fcf3ce44SJohn Forte 977fcf3ce44SJohn Forte /* Check if nothing was found */ 978fcf3ce44SJohn Forte if (action == 0) { 979fcf3ce44SJohn Forte break; 980fcf3ce44SJohn Forte } else if (action == 1) { 981*a9800bebSGarrett D'Amore (void) emlxs_mb_unreg_node(port, nlp, 982fcf3ce44SJohn Forte NULL, NULL, NULL); 983fcf3ce44SJohn Forte } else if (action == 2) { 984fcf3ce44SJohn Forte #ifdef DHCHAP_SUPPORT 985fcf3ce44SJohn Forte emlxs_dhc_auth_stop(port, nlp); 986291a2b48SSukumar Swaminathan #endif /* DHCHAP_SUPPORT */ 987fcf3ce44SJohn Forte 988291a2b48SSukumar Swaminathan /* 989291a2b48SSukumar Swaminathan * Close the node for any further normal IO 990291a2b48SSukumar Swaminathan * A PLOGI with reopen the node 991291a2b48SSukumar Swaminathan */ 99282527734SSukumar Swaminathan emlxs_node_close(port, nlp, 99382527734SSukumar Swaminathan hba->channel_fcp, 60); 99482527734SSukumar Swaminathan emlxs_node_close(port, nlp, 99582527734SSukumar Swaminathan hba->channel_ip, 60); 996fcf3ce44SJohn Forte 997fcf3ce44SJohn Forte /* Flush tx queue */ 998fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, nlp, 0, 0, 0); 999fcf3ce44SJohn Forte 1000fcf3ce44SJohn Forte /* Flush chip queue */ 1001fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 0, nlp, 0); 1002fcf3ce44SJohn Forte } 1003291a2b48SSukumar Swaminathan 1004fcf3ce44SJohn Forte } 1005fcf3ce44SJohn Forte 1006fcf3ce44SJohn Forte break; 1007fcf3ce44SJohn Forte 1008291a2b48SSukumar Swaminathan case 1: /* Partial support - Flush IO for non-FCP2 matching nodes */ 1009fcf3ce44SJohn Forte 1010fcf3ce44SJohn Forte for (;;) { 1011fcf3ce44SJohn Forte 1012fcf3ce44SJohn Forte /* 1013fcf3ce44SJohn Forte * We need to hold the locks this way because 1014*a9800bebSGarrett D'Amore * emlxs_mb_unreg_node and the flush routines enter the 1015291a2b48SSukumar Swaminathan * same locks. Also, when we release the lock the list 1016291a2b48SSukumar Swaminathan * can change out from under us. 1017fcf3ce44SJohn Forte */ 1018fcf3ce44SJohn Forte rw_enter(&port->node_rwlock, RW_READER); 1019fcf3ce44SJohn Forte action = 0; 1020fcf3ce44SJohn Forte for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 1021fcf3ce44SJohn Forte nlp = port->node_table[i]; 1022fcf3ce44SJohn Forte while (nlp != NULL) { 1023fcf3ce44SJohn Forte if (!nlp->nlp_tag) { 1024fcf3ce44SJohn Forte nlp = nlp->nlp_list_next; 1025fcf3ce44SJohn Forte continue; 1026fcf3ce44SJohn Forte } 1027fcf3ce44SJohn Forte nlp->nlp_tag = 0; 1028fcf3ce44SJohn Forte 1029fcf3ce44SJohn Forte /* 1030291a2b48SSukumar Swaminathan * Check for special FCP2 target device 1031291a2b48SSukumar Swaminathan * that matches our mask 1032fcf3ce44SJohn Forte */ 1033fcf3ce44SJohn Forte if ((nlp->nlp_fcp_info & 1034fcf3ce44SJohn Forte NLP_FCP_TGT_DEVICE) && 1035291a2b48SSukumar Swaminathan (nlp-> nlp_fcp_info & 1036fcf3ce44SJohn Forte NLP_FCP_2_DEVICE) && 1037291a2b48SSukumar Swaminathan (nlp->nlp_DID & mask) == 1038291a2b48SSukumar Swaminathan aff_d_id) { 1039fcf3ce44SJohn Forte action = 3; 1040fcf3ce44SJohn Forte break; 1041fcf3ce44SJohn Forte } 1042291a2b48SSukumar Swaminathan 1043fcf3ce44SJohn Forte /* 1044fcf3ce44SJohn Forte * Check for any other device that 1045fcf3ce44SJohn Forte * matches our mask 1046fcf3ce44SJohn Forte */ 1047fcf3ce44SJohn Forte else if ((nlp->nlp_DID & mask) == 1048fcf3ce44SJohn Forte aff_d_id) { 1049fcf3ce44SJohn Forte if (linkdown) { 1050fcf3ce44SJohn Forte action = 1; 1051fcf3ce44SJohn Forte break; 1052291a2b48SSukumar Swaminathan } else { /* Must be an RSCN */ 1053291a2b48SSukumar Swaminathan 1054fcf3ce44SJohn Forte action = 2; 1055fcf3ce44SJohn Forte break; 1056fcf3ce44SJohn Forte } 1057fcf3ce44SJohn Forte } 1058291a2b48SSukumar Swaminathan 1059fcf3ce44SJohn Forte nlp = nlp->nlp_list_next; 1060fcf3ce44SJohn Forte } 1061fcf3ce44SJohn Forte 1062fcf3ce44SJohn Forte if (action) { 1063fcf3ce44SJohn Forte break; 1064fcf3ce44SJohn Forte } 1065fcf3ce44SJohn Forte } 1066fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 1067fcf3ce44SJohn Forte 1068fcf3ce44SJohn Forte /* Check if nothing was found */ 1069fcf3ce44SJohn Forte if (action == 0) { 1070fcf3ce44SJohn Forte break; 1071fcf3ce44SJohn Forte } else if (action == 1) { 1072*a9800bebSGarrett D'Amore (void) emlxs_mb_unreg_node(port, nlp, 1073fcf3ce44SJohn Forte NULL, NULL, NULL); 1074fcf3ce44SJohn Forte } else if (action == 2) { 1075fcf3ce44SJohn Forte #ifdef DHCHAP_SUPPORT 1076fcf3ce44SJohn Forte emlxs_dhc_auth_stop(port, nlp); 1077291a2b48SSukumar Swaminathan #endif /* DHCHAP_SUPPORT */ 1078fcf3ce44SJohn Forte 1079291a2b48SSukumar Swaminathan /* 1080291a2b48SSukumar Swaminathan * Close the node for any further normal IO 1081291a2b48SSukumar Swaminathan * A PLOGI with reopen the node 1082291a2b48SSukumar Swaminathan */ 108382527734SSukumar Swaminathan emlxs_node_close(port, nlp, 108482527734SSukumar Swaminathan hba->channel_fcp, 60); 108582527734SSukumar Swaminathan emlxs_node_close(port, nlp, 108682527734SSukumar Swaminathan hba->channel_ip, 60); 1087fcf3ce44SJohn Forte 1088fcf3ce44SJohn Forte /* Flush tx queue */ 1089fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, nlp, 0, 0, 0); 1090fcf3ce44SJohn Forte 1091fcf3ce44SJohn Forte /* Flush chip queue */ 1092fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 0, nlp, 0); 1093291a2b48SSukumar Swaminathan 1094fcf3ce44SJohn Forte } else if (action == 3) { /* FCP2 devices */ 1095fcf3ce44SJohn Forte unreg_vpi = 0; 1096fcf3ce44SJohn Forte 1097*a9800bebSGarrett D'Amore if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 1098*a9800bebSGarrett D'Amore (void) emlxs_rpi_pause_notify(port, 1099*a9800bebSGarrett D'Amore nlp->rpip); 1100*a9800bebSGarrett D'Amore } 1101*a9800bebSGarrett D'Amore 1102fcf3ce44SJohn Forte #ifdef DHCHAP_SUPPORT 1103fcf3ce44SJohn Forte emlxs_dhc_auth_stop(port, nlp); 1104291a2b48SSukumar Swaminathan #endif /* DHCHAP_SUPPORT */ 1105fcf3ce44SJohn Forte 1106291a2b48SSukumar Swaminathan /* 1107291a2b48SSukumar Swaminathan * Close the node for any further normal IO 1108291a2b48SSukumar Swaminathan * An ADISC or a PLOGI with reopen the node 1109291a2b48SSukumar Swaminathan */ 111082527734SSukumar Swaminathan emlxs_node_close(port, nlp, 111182527734SSukumar Swaminathan hba->channel_fcp, -1); 111282527734SSukumar Swaminathan emlxs_node_close(port, nlp, hba->channel_ip, 1113fcf3ce44SJohn Forte ((linkdown) ? 0 : 60)); 1114fcf3ce44SJohn Forte 1115fcf3ce44SJohn Forte /* Flush tx queues except for FCP ring */ 1116fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, nlp, 111782527734SSukumar Swaminathan &hba->chan[hba->channel_ct], 0, 0); 1118fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, nlp, 111982527734SSukumar Swaminathan &hba->chan[hba->channel_els], 0, 0); 1120fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, nlp, 112182527734SSukumar Swaminathan &hba->chan[hba->channel_ip], 0, 0); 1122fcf3ce44SJohn Forte 1123fcf3ce44SJohn Forte /* Flush chip queues except for FCP ring */ 1124fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 112582527734SSukumar Swaminathan &hba->chan[hba->channel_ct], nlp, 0); 1126fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 112782527734SSukumar Swaminathan &hba->chan[hba->channel_els], nlp, 0); 1128fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 112982527734SSukumar Swaminathan &hba->chan[hba->channel_ip], nlp, 0); 1130fcf3ce44SJohn Forte } 1131fcf3ce44SJohn Forte } 1132fcf3ce44SJohn Forte break; 1133fcf3ce44SJohn Forte 1134fcf3ce44SJohn Forte case 2: /* Full support - Hold FCP IO to FCP target matching nodes */ 1135fcf3ce44SJohn Forte 1136fcf3ce44SJohn Forte if (!linkdown && !vlinkdown) { 1137fcf3ce44SJohn Forte break; 1138fcf3ce44SJohn Forte } 1139291a2b48SSukumar Swaminathan 1140fcf3ce44SJohn Forte for (;;) { 1141fcf3ce44SJohn Forte /* 1142fcf3ce44SJohn Forte * We need to hold the locks this way because 1143*a9800bebSGarrett D'Amore * emlxs_mb_unreg_node and the flush routines enter the 1144291a2b48SSukumar Swaminathan * same locks. Also, when we release the lock the list 1145291a2b48SSukumar Swaminathan * can change out from under us. 1146fcf3ce44SJohn Forte */ 1147fcf3ce44SJohn Forte rw_enter(&port->node_rwlock, RW_READER); 1148fcf3ce44SJohn Forte action = 0; 1149fcf3ce44SJohn Forte for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 1150fcf3ce44SJohn Forte nlp = port->node_table[i]; 1151fcf3ce44SJohn Forte while (nlp != NULL) { 1152fcf3ce44SJohn Forte if (!nlp->nlp_tag) { 1153fcf3ce44SJohn Forte nlp = nlp->nlp_list_next; 1154fcf3ce44SJohn Forte continue; 1155fcf3ce44SJohn Forte } 1156fcf3ce44SJohn Forte nlp->nlp_tag = 0; 1157fcf3ce44SJohn Forte 1158fcf3ce44SJohn Forte /* 1159fcf3ce44SJohn Forte * Check for FCP target device that 1160fcf3ce44SJohn Forte * matches our mask 1161fcf3ce44SJohn Forte */ 1162291a2b48SSukumar Swaminathan if ((nlp-> nlp_fcp_info & 1163fcf3ce44SJohn Forte NLP_FCP_TGT_DEVICE) && 1164291a2b48SSukumar Swaminathan (nlp->nlp_DID & mask) == 1165291a2b48SSukumar Swaminathan aff_d_id) { 1166fcf3ce44SJohn Forte action = 3; 1167fcf3ce44SJohn Forte break; 1168fcf3ce44SJohn Forte } 1169291a2b48SSukumar Swaminathan 1170fcf3ce44SJohn Forte /* 1171fcf3ce44SJohn Forte * Check for any other device that 1172fcf3ce44SJohn Forte * matches our mask 1173fcf3ce44SJohn Forte */ 1174fcf3ce44SJohn Forte else if ((nlp->nlp_DID & mask) == 1175fcf3ce44SJohn Forte aff_d_id) { 1176fcf3ce44SJohn Forte if (linkdown) { 1177fcf3ce44SJohn Forte action = 1; 1178fcf3ce44SJohn Forte break; 1179fcf3ce44SJohn Forte } else { /* Must be an RSCN */ 1180291a2b48SSukumar Swaminathan 1181fcf3ce44SJohn Forte action = 2; 1182fcf3ce44SJohn Forte break; 1183fcf3ce44SJohn Forte } 1184fcf3ce44SJohn Forte } 1185291a2b48SSukumar Swaminathan 1186fcf3ce44SJohn Forte nlp = nlp->nlp_list_next; 1187fcf3ce44SJohn Forte } 1188fcf3ce44SJohn Forte if (action) { 1189fcf3ce44SJohn Forte break; 1190fcf3ce44SJohn Forte } 1191fcf3ce44SJohn Forte } 1192fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 1193fcf3ce44SJohn Forte 1194fcf3ce44SJohn Forte /* Check if nothing was found */ 1195fcf3ce44SJohn Forte if (action == 0) { 1196fcf3ce44SJohn Forte break; 1197fcf3ce44SJohn Forte } else if (action == 1) { 1198*a9800bebSGarrett D'Amore (void) emlxs_mb_unreg_node(port, nlp, 1199fcf3ce44SJohn Forte NULL, NULL, NULL); 1200fcf3ce44SJohn Forte } else if (action == 2) { 1201291a2b48SSukumar Swaminathan /* 1202291a2b48SSukumar Swaminathan * Close the node for any further normal IO 1203291a2b48SSukumar Swaminathan * A PLOGI with reopen the node 1204291a2b48SSukumar Swaminathan */ 120582527734SSukumar Swaminathan emlxs_node_close(port, nlp, 120682527734SSukumar Swaminathan hba->channel_fcp, 60); 120782527734SSukumar Swaminathan emlxs_node_close(port, nlp, 120882527734SSukumar Swaminathan hba->channel_ip, 60); 1209fcf3ce44SJohn Forte 1210fcf3ce44SJohn Forte /* Flush tx queue */ 1211fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, nlp, 0, 0, 0); 1212fcf3ce44SJohn Forte 1213fcf3ce44SJohn Forte /* Flush chip queue */ 1214fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 0, nlp, 0); 1215fcf3ce44SJohn Forte 1216fcf3ce44SJohn Forte } else if (action == 3) { /* FCP2 devices */ 1217fcf3ce44SJohn Forte unreg_vpi = 0; 1218fcf3ce44SJohn Forte 1219*a9800bebSGarrett D'Amore if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 1220*a9800bebSGarrett D'Amore (void) emlxs_rpi_pause_notify(port, 1221*a9800bebSGarrett D'Amore nlp->rpip); 1222*a9800bebSGarrett D'Amore } 1223*a9800bebSGarrett D'Amore 1224291a2b48SSukumar Swaminathan /* 1225291a2b48SSukumar Swaminathan * Close the node for any further normal IO 1226291a2b48SSukumar Swaminathan * An ADISC or a PLOGI with reopen the node 1227291a2b48SSukumar Swaminathan */ 122882527734SSukumar Swaminathan emlxs_node_close(port, nlp, 122982527734SSukumar Swaminathan hba->channel_fcp, -1); 123082527734SSukumar Swaminathan emlxs_node_close(port, nlp, hba->channel_ip, 1231fcf3ce44SJohn Forte ((linkdown) ? 0 : 60)); 1232fcf3ce44SJohn Forte 1233fcf3ce44SJohn Forte /* Flush tx queues except for FCP ring */ 1234fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, nlp, 123582527734SSukumar Swaminathan &hba->chan[hba->channel_ct], 0, 0); 1236fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, nlp, 123782527734SSukumar Swaminathan &hba->chan[hba->channel_els], 0, 0); 1238fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, nlp, 123982527734SSukumar Swaminathan &hba->chan[hba->channel_ip], 0, 0); 1240fcf3ce44SJohn Forte 1241fcf3ce44SJohn Forte /* Flush chip queues except for FCP ring */ 1242fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 124382527734SSukumar Swaminathan &hba->chan[hba->channel_ct], nlp, 0); 1244fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 124582527734SSukumar Swaminathan &hba->chan[hba->channel_els], nlp, 0); 1246fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 124782527734SSukumar Swaminathan &hba->chan[hba->channel_ip], nlp, 0); 1248fcf3ce44SJohn Forte } 1249fcf3ce44SJohn Forte } 1250fcf3ce44SJohn Forte 1251fcf3ce44SJohn Forte break; 1252fcf3ce44SJohn Forte 1253fcf3ce44SJohn Forte } /* switch() */ 1254fcf3ce44SJohn Forte 1255fcf3ce44SJohn Forte done: 1256fcf3ce44SJohn Forte 1257*a9800bebSGarrett D'Amore if (unreg_vpi) { 1258*a9800bebSGarrett D'Amore (void) emlxs_mb_unreg_vpi(port); 1259fcf3ce44SJohn Forte } 1260fcf3ce44SJohn Forte 1261291a2b48SSukumar Swaminathan return (0); 1262fcf3ce44SJohn Forte 126382527734SSukumar Swaminathan } /* emlxs_port_offline() */ 1264fcf3ce44SJohn Forte 1265fcf3ce44SJohn Forte 1266fcf3ce44SJohn Forte extern void 1267fcf3ce44SJohn Forte emlxs_port_online(emlxs_port_t *vport) 1268fcf3ce44SJohn Forte { 1269fcf3ce44SJohn Forte emlxs_hba_t *hba = vport->hba; 1270fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 1271fcf3ce44SJohn Forte uint32_t state; 1272fcf3ce44SJohn Forte uint32_t update; 1273fcf3ce44SJohn Forte uint32_t npiv_linkup; 1274fcf3ce44SJohn Forte char topology[32]; 1275fcf3ce44SJohn Forte char linkspeed[32]; 1276fcf3ce44SJohn Forte char mode[32]; 1277fcf3ce44SJohn Forte 1278fcf3ce44SJohn Forte /* 1279291a2b48SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_up_msg, 1280291a2b48SSukumar Swaminathan * "linkup_callback. vpi=%d fc_flag=%x", vport->vpi, hba->flag); 1281fcf3ce44SJohn Forte */ 1282fcf3ce44SJohn Forte 1283fcf3ce44SJohn Forte if ((vport->vpi > 0) && 1284fcf3ce44SJohn Forte (!(hba->flag & FC_NPIV_ENABLED) || 1285fcf3ce44SJohn Forte !(hba->flag & FC_NPIV_SUPPORTED))) { 1286fcf3ce44SJohn Forte return; 1287fcf3ce44SJohn Forte } 1288291a2b48SSukumar Swaminathan 1289fcf3ce44SJohn Forte if (!(vport->flag & EMLXS_PORT_BOUND) || 1290fcf3ce44SJohn Forte !(vport->flag & EMLXS_PORT_ENABLE)) { 1291fcf3ce44SJohn Forte return; 1292fcf3ce44SJohn Forte } 1293291a2b48SSukumar Swaminathan 1294fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 1295fcf3ce44SJohn Forte 1296fcf3ce44SJohn Forte /* Check for mode */ 1297fcf3ce44SJohn Forte if (port->tgt_mode) { 1298fcf3ce44SJohn Forte (void) strcpy(mode, ", target"); 1299fcf3ce44SJohn Forte } else if (port->ini_mode) { 1300fcf3ce44SJohn Forte (void) strcpy(mode, ", initiator"); 1301fcf3ce44SJohn Forte } else { 1302fcf3ce44SJohn Forte (void) strcpy(mode, ""); 1303fcf3ce44SJohn Forte } 1304fcf3ce44SJohn Forte 1305fcf3ce44SJohn Forte /* Check for loop topology */ 1306fcf3ce44SJohn Forte if (hba->topology == TOPOLOGY_LOOP) { 1307fcf3ce44SJohn Forte state = FC_STATE_LOOP; 1308fcf3ce44SJohn Forte (void) strcpy(topology, ", loop"); 1309fcf3ce44SJohn Forte } else { 1310fcf3ce44SJohn Forte state = FC_STATE_ONLINE; 1311fcf3ce44SJohn Forte (void) strcpy(topology, ", fabric"); 1312fcf3ce44SJohn Forte } 1313fcf3ce44SJohn Forte 1314fcf3ce44SJohn Forte /* Set the link speed */ 1315fcf3ce44SJohn Forte switch (hba->linkspeed) { 1316fcf3ce44SJohn Forte case 0: 1317fcf3ce44SJohn Forte (void) strcpy(linkspeed, "Gb"); 1318fcf3ce44SJohn Forte state |= FC_STATE_1GBIT_SPEED; 1319fcf3ce44SJohn Forte break; 1320fcf3ce44SJohn Forte 1321fcf3ce44SJohn Forte case LA_1GHZ_LINK: 1322fcf3ce44SJohn Forte (void) strcpy(linkspeed, "1Gb"); 1323fcf3ce44SJohn Forte state |= FC_STATE_1GBIT_SPEED; 1324fcf3ce44SJohn Forte break; 1325fcf3ce44SJohn Forte case LA_2GHZ_LINK: 1326fcf3ce44SJohn Forte (void) strcpy(linkspeed, "2Gb"); 1327fcf3ce44SJohn Forte state |= FC_STATE_2GBIT_SPEED; 1328fcf3ce44SJohn Forte break; 1329fcf3ce44SJohn Forte case LA_4GHZ_LINK: 1330fcf3ce44SJohn Forte (void) strcpy(linkspeed, "4Gb"); 1331fcf3ce44SJohn Forte state |= FC_STATE_4GBIT_SPEED; 1332fcf3ce44SJohn Forte break; 1333fcf3ce44SJohn Forte case LA_8GHZ_LINK: 1334fcf3ce44SJohn Forte (void) strcpy(linkspeed, "8Gb"); 1335fcf3ce44SJohn Forte state |= FC_STATE_8GBIT_SPEED; 1336fcf3ce44SJohn Forte break; 1337fcf3ce44SJohn Forte case LA_10GHZ_LINK: 1338fcf3ce44SJohn Forte (void) strcpy(linkspeed, "10Gb"); 1339fcf3ce44SJohn Forte state |= FC_STATE_10GBIT_SPEED; 1340fcf3ce44SJohn Forte break; 1341fcf3ce44SJohn Forte default: 1342fcf3ce44SJohn Forte (void) sprintf(linkspeed, "unknown(0x%x)", hba->linkspeed); 1343fcf3ce44SJohn Forte break; 1344fcf3ce44SJohn Forte } 1345fcf3ce44SJohn Forte 1346fcf3ce44SJohn Forte npiv_linkup = 0; 1347fcf3ce44SJohn Forte update = 0; 1348fcf3ce44SJohn Forte 1349fcf3ce44SJohn Forte if ((hba->state >= FC_LINK_UP) && 1350291a2b48SSukumar Swaminathan !(hba->flag & FC_LOOPBACK_MODE) && (vport->ulp_statec != state)) { 1351fcf3ce44SJohn Forte update = 1; 1352fcf3ce44SJohn Forte vport->ulp_statec = state; 1353fcf3ce44SJohn Forte 1354fcf3ce44SJohn Forte if ((vport->vpi > 0) && !(hba->flag & FC_NPIV_LINKUP)) { 1355fcf3ce44SJohn Forte hba->flag |= FC_NPIV_LINKUP; 1356fcf3ce44SJohn Forte npiv_linkup = 1; 1357fcf3ce44SJohn Forte } 1358fcf3ce44SJohn Forte } 1359291a2b48SSukumar Swaminathan 1360fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1361fcf3ce44SJohn Forte 136282527734SSukumar Swaminathan 1363fcf3ce44SJohn Forte /* 1364291a2b48SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_up_msg, 136582527734SSukumar Swaminathan * "linkup_callback: update=%d vpi=%d flag=%d fc_flag=%x state=%x" 136682527734SSukumar Swaminathan * "statec=%x", update, vport->vpi, npiv_linkup, hba->flag, 1367291a2b48SSukumar Swaminathan * hba->state, vport->ulp_statec); 1368fcf3ce44SJohn Forte */ 136982527734SSukumar Swaminathan 1370fcf3ce44SJohn Forte if (update) { 1371fcf3ce44SJohn Forte if (vport->flag & EMLXS_PORT_BOUND) { 1372fcf3ce44SJohn Forte if (vport->vpi == 0) { 1373fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_up_msg, 1374291a2b48SSukumar Swaminathan "%s%s%s", linkspeed, topology, mode); 13756a573d82SSukumar Swaminathan 1376fcf3ce44SJohn Forte } else if (npiv_linkup) { 1377fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 1378291a2b48SSukumar Swaminathan &emlxs_npiv_link_up_msg, "%s%s%s", 1379fcf3ce44SJohn Forte linkspeed, topology, mode); 1380fcf3ce44SJohn Forte } 1381291a2b48SSukumar Swaminathan 13823be114edSSukumar Swaminathan if (vport->ini_mode) { 1383291a2b48SSukumar Swaminathan vport->ulp_statec_cb(vport->ulp_handle, 1384291a2b48SSukumar Swaminathan state); 1385fcf3ce44SJohn Forte } 13863be114edSSukumar Swaminathan #ifdef SFCT_SUPPORT 13873be114edSSukumar Swaminathan else if (vport->tgt_mode) { 13883be114edSSukumar Swaminathan emlxs_fct_link_up(vport); 13893be114edSSukumar Swaminathan } 13903be114edSSukumar Swaminathan #endif /* SFCT_SUPPORT */ 1391fcf3ce44SJohn Forte } else { 1392fcf3ce44SJohn Forte if (vport->vpi == 0) { 1393fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_up_msg, 1394291a2b48SSukumar Swaminathan "%s%s%s *", linkspeed, topology, mode); 13956a573d82SSukumar Swaminathan 1396fcf3ce44SJohn Forte } else if (npiv_linkup) { 1397fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 1398291a2b48SSukumar Swaminathan &emlxs_npiv_link_up_msg, "%s%s%s *", 1399fcf3ce44SJohn Forte linkspeed, topology, mode); 1400fcf3ce44SJohn Forte } 1401fcf3ce44SJohn Forte } 1402fcf3ce44SJohn Forte 1403fcf3ce44SJohn Forte /* Check for waiting threads */ 1404fcf3ce44SJohn Forte if (vport->vpi == 0) { 1405fcf3ce44SJohn Forte mutex_enter(&EMLXS_LINKUP_LOCK); 1406fcf3ce44SJohn Forte if (hba->linkup_wait_flag == TRUE) { 1407fcf3ce44SJohn Forte hba->linkup_wait_flag = FALSE; 1408fcf3ce44SJohn Forte cv_broadcast(&EMLXS_LINKUP_CV); 1409fcf3ce44SJohn Forte } 1410fcf3ce44SJohn Forte mutex_exit(&EMLXS_LINKUP_LOCK); 1411fcf3ce44SJohn Forte } 1412291a2b48SSukumar Swaminathan 1413fcf3ce44SJohn Forte /* Flush any pending ub buffers */ 1414fcf3ce44SJohn Forte emlxs_ub_flush(vport); 1415fcf3ce44SJohn Forte } 1416291a2b48SSukumar Swaminathan 1417fcf3ce44SJohn Forte return; 1418fcf3ce44SJohn Forte 141982527734SSukumar Swaminathan } /* emlxs_port_online() */ 1420fcf3ce44SJohn Forte 1421fcf3ce44SJohn Forte 1422*a9800bebSGarrett D'Amore /* SLI3 */ 1423fcf3ce44SJohn Forte extern void 1424fcf3ce44SJohn Forte emlxs_linkdown(emlxs_hba_t *hba) 1425fcf3ce44SJohn Forte { 1426fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 1427fcf3ce44SJohn Forte int i; 1428*a9800bebSGarrett D'Amore uint32_t scope; 1429fcf3ce44SJohn Forte 1430fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 1431fcf3ce44SJohn Forte 143282527734SSukumar Swaminathan if (hba->state > FC_LINK_DOWN) { 143382527734SSukumar Swaminathan HBASTATS.LinkDown++; 143482527734SSukumar Swaminathan EMLXS_STATE_CHANGE_LOCKED(hba, FC_LINK_DOWN); 143582527734SSukumar Swaminathan } 1436fcf3ce44SJohn Forte 1437*a9800bebSGarrett D'Amore /* Set scope */ 1438*a9800bebSGarrett D'Amore scope = (hba->flag & FC_NEW_FABRIC)? 0xFDFFFFFF:0xFFFFFFFF; 1439*a9800bebSGarrett D'Amore 1440fcf3ce44SJohn Forte /* Filter hba flags */ 1441fcf3ce44SJohn Forte hba->flag &= FC_LINKDOWN_MASK; 1442fcf3ce44SJohn Forte hba->discovery_timer = 0; 1443fcf3ce44SJohn Forte hba->linkup_timer = 0; 1444fcf3ce44SJohn Forte 1445fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1446fcf3ce44SJohn Forte 1447fcf3ce44SJohn Forte for (i = 0; i < MAX_VPORTS; i++) { 1448fcf3ce44SJohn Forte port = &VPORT(i); 1449fcf3ce44SJohn Forte 1450fcf3ce44SJohn Forte if (!(port->flag & EMLXS_PORT_BOUND)) { 1451fcf3ce44SJohn Forte continue; 1452fcf3ce44SJohn Forte } 1453291a2b48SSukumar Swaminathan 1454*a9800bebSGarrett D'Amore (void) emlxs_port_offline(port, scope); 1455fcf3ce44SJohn Forte 1456fcf3ce44SJohn Forte } 1457fcf3ce44SJohn Forte 1458*a9800bebSGarrett D'Amore emlxs_log_link_event(port); 1459*a9800bebSGarrett D'Amore 1460fcf3ce44SJohn Forte return; 1461fcf3ce44SJohn Forte 146282527734SSukumar Swaminathan } /* emlxs_linkdown() */ 1463fcf3ce44SJohn Forte 1464fcf3ce44SJohn Forte 1465*a9800bebSGarrett D'Amore /* SLI3 */ 1466fcf3ce44SJohn Forte extern void 1467fcf3ce44SJohn Forte emlxs_linkup(emlxs_hba_t *hba) 1468fcf3ce44SJohn Forte { 1469fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 1470fcf3ce44SJohn Forte emlxs_config_t *cfg = &CFG; 1471fcf3ce44SJohn Forte 1472fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 1473fcf3ce44SJohn Forte 1474fcf3ce44SJohn Forte HBASTATS.LinkUp++; 147582527734SSukumar Swaminathan EMLXS_STATE_CHANGE_LOCKED(hba, FC_LINK_UP); 1476fcf3ce44SJohn Forte 1477fcf3ce44SJohn Forte #ifdef MENLO_SUPPORT 1478fcf3ce44SJohn Forte if (hba->flag & FC_MENLO_MODE) { 1479fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1480fcf3ce44SJohn Forte 1481fcf3ce44SJohn Forte /* 1482fcf3ce44SJohn Forte * Trigger linkup CV and don't start linkup & discovery 1483fcf3ce44SJohn Forte * timers 1484fcf3ce44SJohn Forte */ 1485fcf3ce44SJohn Forte mutex_enter(&EMLXS_LINKUP_LOCK); 1486fcf3ce44SJohn Forte cv_broadcast(&EMLXS_LINKUP_CV); 1487fcf3ce44SJohn Forte mutex_exit(&EMLXS_LINKUP_LOCK); 1488fcf3ce44SJohn Forte 1489*a9800bebSGarrett D'Amore emlxs_log_link_event(port); 1490*a9800bebSGarrett D'Amore 1491fcf3ce44SJohn Forte return; 1492fcf3ce44SJohn Forte } 1493291a2b48SSukumar Swaminathan #endif /* MENLO_SUPPORT */ 1494fcf3ce44SJohn Forte 1495fcf3ce44SJohn Forte /* Set the linkup & discovery timers */ 1496fcf3ce44SJohn Forte hba->linkup_timer = hba->timer_tics + cfg[CFG_LINKUP_TIMEOUT].current; 1497291a2b48SSukumar Swaminathan hba->discovery_timer = 1498291a2b48SSukumar Swaminathan hba->timer_tics + cfg[CFG_LINKUP_TIMEOUT].current + 1499291a2b48SSukumar Swaminathan cfg[CFG_DISC_TIMEOUT].current; 1500fcf3ce44SJohn Forte 1501fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1502fcf3ce44SJohn Forte 1503*a9800bebSGarrett D'Amore emlxs_log_link_event(port); 1504*a9800bebSGarrett D'Amore 1505fcf3ce44SJohn Forte return; 1506fcf3ce44SJohn Forte 150782527734SSukumar Swaminathan } /* emlxs_linkup() */ 1508fcf3ce44SJohn Forte 1509fcf3ce44SJohn Forte 1510fcf3ce44SJohn Forte /* 1511fcf3ce44SJohn Forte * emlxs_reset_link 1512fcf3ce44SJohn Forte * 1513fcf3ce44SJohn Forte * Description: 1514fcf3ce44SJohn Forte * Called to reset the link with an init_link 1515fcf3ce44SJohn Forte * 1516fcf3ce44SJohn Forte * Returns: 1517fcf3ce44SJohn Forte * 1518fcf3ce44SJohn Forte */ 1519fcf3ce44SJohn Forte extern int 152082527734SSukumar Swaminathan emlxs_reset_link(emlxs_hba_t *hba, uint32_t linkup, uint32_t wait) 1521fcf3ce44SJohn Forte { 1522fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 1523fcf3ce44SJohn Forte emlxs_config_t *cfg; 152482527734SSukumar Swaminathan MAILBOXQ *mbq = NULL; 152582527734SSukumar Swaminathan MAILBOX *mb = NULL; 152682527734SSukumar Swaminathan int rval = 0; 152782527734SSukumar Swaminathan int rc; 1528fcf3ce44SJohn Forte 1529fcf3ce44SJohn Forte /* 1530fcf3ce44SJohn Forte * Get a buffer to use for the mailbox command 1531fcf3ce44SJohn Forte */ 153282527734SSukumar Swaminathan if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1)) 153382527734SSukumar Swaminathan == NULL) { 1534fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_reset_failed_msg, 1535fcf3ce44SJohn Forte "Unable to allocate mailbox buffer."); 153682527734SSukumar Swaminathan rval = 1; 153782527734SSukumar Swaminathan goto reset_link_fail; 153882527734SSukumar Swaminathan } 1539fcf3ce44SJohn Forte 1540*a9800bebSGarrett D'Amore if (linkup) { 1541*a9800bebSGarrett D'Amore EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_reset_msg, 1542*a9800bebSGarrett D'Amore "Resetting link..."); 1543*a9800bebSGarrett D'Amore } else { 1544*a9800bebSGarrett D'Amore EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_reset_msg, 1545*a9800bebSGarrett D'Amore "Disabling link..."); 1546*a9800bebSGarrett D'Amore } 1547*a9800bebSGarrett D'Amore 154882527734SSukumar Swaminathan mb = (MAILBOX *)mbq; 154982527734SSukumar Swaminathan 155082527734SSukumar Swaminathan /* Bring link down first */ 155182527734SSukumar Swaminathan emlxs_mb_down_link(hba, mbq); 155282527734SSukumar Swaminathan 155382527734SSukumar Swaminathan #define MBXERR_LINK_DOWN 0x33 155482527734SSukumar Swaminathan 155582527734SSukumar Swaminathan if (wait) { 155682527734SSukumar Swaminathan wait = MBX_WAIT; 155782527734SSukumar Swaminathan } else { 155882527734SSukumar Swaminathan wait = MBX_NOWAIT; 155982527734SSukumar Swaminathan } 156082527734SSukumar Swaminathan rc = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, wait, 0); 156182527734SSukumar Swaminathan if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS) && 156282527734SSukumar Swaminathan (rc != MBXERR_LINK_DOWN)) { 156382527734SSukumar Swaminathan rval = 1; 156482527734SSukumar Swaminathan goto reset_link_fail; 1565fcf3ce44SJohn Forte } 1566291a2b48SSukumar Swaminathan 1567fcf3ce44SJohn Forte if (linkup) { 1568fcf3ce44SJohn Forte /* 1569fcf3ce44SJohn Forte * Setup and issue mailbox INITIALIZE LINK command 1570fcf3ce44SJohn Forte */ 1571fcf3ce44SJohn Forte 157282527734SSukumar Swaminathan if (wait == MBX_NOWAIT) { 157382527734SSukumar Swaminathan if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1)) 157482527734SSukumar Swaminathan == NULL) { 157582527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 157682527734SSukumar Swaminathan &emlxs_link_reset_failed_msg, 157782527734SSukumar Swaminathan "Unable to allocate mailbox buffer."); 157882527734SSukumar Swaminathan rval = 1; 157982527734SSukumar Swaminathan goto reset_link_fail; 158082527734SSukumar Swaminathan } 158182527734SSukumar Swaminathan mb = (MAILBOX *)mbq; 158282527734SSukumar Swaminathan } else { 158382527734SSukumar Swaminathan /* Reuse mbq from previous mbox */ 158482527734SSukumar Swaminathan mb = (MAILBOX *)mbq; 158582527734SSukumar Swaminathan } 158682527734SSukumar Swaminathan cfg = &CFG; 158782527734SSukumar Swaminathan 158882527734SSukumar Swaminathan emlxs_mb_init_link(hba, mbq, 1589fcf3ce44SJohn Forte cfg[CFG_TOPOLOGY].current, cfg[CFG_LINK_SPEED].current); 1590fcf3ce44SJohn Forte 1591fcf3ce44SJohn Forte mb->un.varInitLnk.lipsr_AL_PA = 0; 1592fcf3ce44SJohn Forte 1593fcf3ce44SJohn Forte /* Clear the loopback mode */ 1594fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 1595fcf3ce44SJohn Forte hba->flag &= ~FC_LOOPBACK_MODE; 1596291a2b48SSukumar Swaminathan hba->loopback_tics = 0; 1597fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1598fcf3ce44SJohn Forte 159982527734SSukumar Swaminathan rc = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, wait, 0); 160082527734SSukumar Swaminathan if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { 160182527734SSukumar Swaminathan rval = 1; 160282527734SSukumar Swaminathan goto reset_link_fail; 1603fcf3ce44SJohn Forte } 1604291a2b48SSukumar Swaminathan 1605fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_reset_msg, NULL); 160682527734SSukumar Swaminathan } 1607fcf3ce44SJohn Forte 160882527734SSukumar Swaminathan reset_link_fail: 1609291a2b48SSukumar Swaminathan 161082527734SSukumar Swaminathan if ((wait == MBX_WAIT) && mbq) { 1611*a9800bebSGarrett D'Amore emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 1612fcf3ce44SJohn Forte } 1613fcf3ce44SJohn Forte 161482527734SSukumar Swaminathan return (rval); 161582527734SSukumar Swaminathan } /* emlxs_reset_link() */ 1616fcf3ce44SJohn Forte 1617fcf3ce44SJohn Forte 1618fcf3ce44SJohn Forte extern int 1619fcf3ce44SJohn Forte emlxs_online(emlxs_hba_t *hba) 1620fcf3ce44SJohn Forte { 1621fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 1622fcf3ce44SJohn Forte int32_t rval = 0; 1623fcf3ce44SJohn Forte uint32_t i = 0; 1624fcf3ce44SJohn Forte 1625fcf3ce44SJohn Forte /* Make sure adapter is offline or exit trying (30 seconds) */ 1626291a2b48SSukumar Swaminathan while (i++ < 30) { 1627fcf3ce44SJohn Forte /* Check if adapter is already going online */ 1628fcf3ce44SJohn Forte if (hba->flag & (FC_ONLINE_MODE | FC_ONLINING_MODE)) { 1629fcf3ce44SJohn Forte return (0); 1630fcf3ce44SJohn Forte } 1631291a2b48SSukumar Swaminathan 1632fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 1633fcf3ce44SJohn Forte 1634fcf3ce44SJohn Forte /* Check again */ 1635fcf3ce44SJohn Forte if (hba->flag & (FC_ONLINE_MODE | FC_ONLINING_MODE)) { 1636fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1637fcf3ce44SJohn Forte return (0); 1638fcf3ce44SJohn Forte } 1639291a2b48SSukumar Swaminathan 1640fcf3ce44SJohn Forte /* Check if adapter is offline */ 1641fcf3ce44SJohn Forte if (hba->flag & FC_OFFLINE_MODE) { 1642fcf3ce44SJohn Forte /* Mark it going online */ 1643fcf3ce44SJohn Forte hba->flag &= ~FC_OFFLINE_MODE; 1644fcf3ce44SJohn Forte hba->flag |= FC_ONLINING_MODE; 1645fcf3ce44SJohn Forte 1646fcf3ce44SJohn Forte /* Currently !FC_ONLINE_MODE and !FC_OFFLINE_MODE */ 1647fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1648fcf3ce44SJohn Forte break; 1649fcf3ce44SJohn Forte } 1650291a2b48SSukumar Swaminathan 1651fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1652fcf3ce44SJohn Forte 1653fcf3ce44SJohn Forte DELAYMS(1000); 1654fcf3ce44SJohn Forte } 1655fcf3ce44SJohn Forte 1656fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg, 1657fcf3ce44SJohn Forte "Going online..."); 1658fcf3ce44SJohn Forte 165982527734SSukumar Swaminathan if (rval = EMLXS_SLI_ONLINE(hba)) { 1660291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, "status=%x", 1661fcf3ce44SJohn Forte rval); 1662fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_offline_msg, NULL); 1663fcf3ce44SJohn Forte 1664fcf3ce44SJohn Forte /* Set FC_OFFLINE_MODE */ 1665fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 1666fcf3ce44SJohn Forte emlxs_diag_state = DDI_OFFDI; 1667fcf3ce44SJohn Forte hba->flag |= FC_OFFLINE_MODE; 1668fcf3ce44SJohn Forte hba->flag &= ~FC_ONLINING_MODE; 1669fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1670fcf3ce44SJohn Forte 1671fcf3ce44SJohn Forte return (rval); 1672fcf3ce44SJohn Forte } 1673291a2b48SSukumar Swaminathan 1674fcf3ce44SJohn Forte /* Start the timer */ 1675fcf3ce44SJohn Forte emlxs_timer_start(hba); 1676fcf3ce44SJohn Forte 1677fcf3ce44SJohn Forte /* Set FC_ONLINE_MODE */ 1678fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 1679fcf3ce44SJohn Forte emlxs_diag_state = DDI_ONDI; 1680fcf3ce44SJohn Forte hba->flag |= FC_ONLINE_MODE; 1681fcf3ce44SJohn Forte hba->flag &= ~FC_ONLINING_MODE; 1682fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1683fcf3ce44SJohn Forte 1684fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_online_msg, NULL); 1685fcf3ce44SJohn Forte 1686fcf3ce44SJohn Forte #ifdef SFCT_SUPPORT 1687fcf3ce44SJohn Forte (void) emlxs_fct_port_initialize(port); 1688291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 1689fcf3ce44SJohn Forte 1690fcf3ce44SJohn Forte return (rval); 1691fcf3ce44SJohn Forte 169282527734SSukumar Swaminathan } /* emlxs_online() */ 1693fcf3ce44SJohn Forte 1694fcf3ce44SJohn Forte 1695fcf3ce44SJohn Forte extern int 1696fcf3ce44SJohn Forte emlxs_offline(emlxs_hba_t *hba) 1697fcf3ce44SJohn Forte { 1698fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 1699fcf3ce44SJohn Forte uint32_t i = 0; 1700fcf3ce44SJohn Forte int rval = 1; 1701fcf3ce44SJohn Forte 1702fcf3ce44SJohn Forte /* Make sure adapter is online or exit trying (30 seconds) */ 1703291a2b48SSukumar Swaminathan while (i++ < 30) { 1704fcf3ce44SJohn Forte /* Check if adapter is already going offline */ 1705fcf3ce44SJohn Forte if (hba->flag & (FC_OFFLINE_MODE | FC_OFFLINING_MODE)) { 1706fcf3ce44SJohn Forte return (0); 1707fcf3ce44SJohn Forte } 1708291a2b48SSukumar Swaminathan 1709fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 1710fcf3ce44SJohn Forte 1711fcf3ce44SJohn Forte /* Check again */ 1712fcf3ce44SJohn Forte if (hba->flag & (FC_OFFLINE_MODE | FC_OFFLINING_MODE)) { 1713fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1714fcf3ce44SJohn Forte return (0); 1715fcf3ce44SJohn Forte } 1716291a2b48SSukumar Swaminathan 1717fcf3ce44SJohn Forte /* Check if adapter is online */ 1718fcf3ce44SJohn Forte if (hba->flag & FC_ONLINE_MODE) { 1719fcf3ce44SJohn Forte /* Mark it going offline */ 1720fcf3ce44SJohn Forte hba->flag &= ~FC_ONLINE_MODE; 1721fcf3ce44SJohn Forte hba->flag |= FC_OFFLINING_MODE; 1722fcf3ce44SJohn Forte 1723fcf3ce44SJohn Forte /* Currently !FC_ONLINE_MODE and !FC_OFFLINE_MODE */ 1724fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1725fcf3ce44SJohn Forte break; 1726fcf3ce44SJohn Forte } 1727291a2b48SSukumar Swaminathan 1728fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1729fcf3ce44SJohn Forte 1730fcf3ce44SJohn Forte DELAYMS(1000); 1731fcf3ce44SJohn Forte } 1732fcf3ce44SJohn Forte 1733291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg, 1734291a2b48SSukumar Swaminathan "Going offline..."); 1735fcf3ce44SJohn Forte 1736fcf3ce44SJohn Forte if (port->ini_mode) { 1737*a9800bebSGarrett D'Amore if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 1738*a9800bebSGarrett D'Amore (void) emlxs_fcf_shutdown_notify(port, 1); 1739*a9800bebSGarrett D'Amore } else { 1740*a9800bebSGarrett D'Amore emlxs_linkdown(hba); 1741*a9800bebSGarrett D'Amore } 1742fcf3ce44SJohn Forte } 1743fcf3ce44SJohn Forte #ifdef SFCT_SUPPORT 1744fcf3ce44SJohn Forte else { 1745fcf3ce44SJohn Forte (void) emlxs_fct_port_shutdown(port); 1746fcf3ce44SJohn Forte } 1747291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 1748fcf3ce44SJohn Forte 1749fcf3ce44SJohn Forte /* Check if adapter was shutdown */ 1750fcf3ce44SJohn Forte if (hba->flag & FC_HARDWARE_ERROR) { 1751291a2b48SSukumar Swaminathan /* 1752291a2b48SSukumar Swaminathan * Force mailbox cleanup 1753291a2b48SSukumar Swaminathan * This will wake any sleeping or polling threads 1754291a2b48SSukumar Swaminathan */ 1755fcf3ce44SJohn Forte emlxs_mb_fini(hba, NULL, MBX_HARDWARE_ERROR); 1756fcf3ce44SJohn Forte } 1757291a2b48SSukumar Swaminathan 1758fcf3ce44SJohn Forte /* Pause here for the IO to settle */ 1759fcf3ce44SJohn Forte delay(drv_usectohz(1000000)); /* 1 sec */ 1760fcf3ce44SJohn Forte 1761fcf3ce44SJohn Forte /* Unregister all nodes */ 1762fcf3ce44SJohn Forte emlxs_ffcleanup(hba); 1763fcf3ce44SJohn Forte 1764fcf3ce44SJohn Forte if (hba->bus_type == SBUS_FC) { 176582527734SSukumar Swaminathan WRITE_SBUS_CSR_REG(hba, FC_SHS_REG(hba), 0x9A); 17664baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 176782527734SSukumar Swaminathan /* Access handle validation */ 176882527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.sbus_csr_handle); 17694baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 1770fcf3ce44SJohn Forte } 1771291a2b48SSukumar Swaminathan 1772fcf3ce44SJohn Forte /* Stop the timer */ 1773fcf3ce44SJohn Forte emlxs_timer_stop(hba); 1774fcf3ce44SJohn Forte 1775fcf3ce44SJohn Forte /* For safety flush every iotag list */ 1776fcf3ce44SJohn Forte if (emlxs_iotag_flush(hba)) { 1777fcf3ce44SJohn Forte /* Pause here for the IO to flush */ 1778728bdc9bSSukumar Swaminathan delay(drv_usectohz(1000)); 1779728bdc9bSSukumar Swaminathan } 1780728bdc9bSSukumar Swaminathan 1781728bdc9bSSukumar Swaminathan /* Wait for poll command request to settle */ 1782728bdc9bSSukumar Swaminathan while (hba->io_poll_count > 0) { 1783728bdc9bSSukumar Swaminathan delay(drv_usectohz(2000000)); /* 2 sec */ 1784fcf3ce44SJohn Forte } 1785728bdc9bSSukumar Swaminathan 178682527734SSukumar Swaminathan /* Shutdown the adapter interface */ 178782527734SSukumar Swaminathan EMLXS_SLI_OFFLINE(hba); 1788fcf3ce44SJohn Forte 1789fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 1790fcf3ce44SJohn Forte hba->flag |= FC_OFFLINE_MODE; 1791fcf3ce44SJohn Forte hba->flag &= ~FC_OFFLINING_MODE; 1792fcf3ce44SJohn Forte emlxs_diag_state = DDI_OFFDI; 1793fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1794fcf3ce44SJohn Forte 1795fcf3ce44SJohn Forte rval = 0; 1796fcf3ce44SJohn Forte 1797fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_offline_msg, NULL); 1798fcf3ce44SJohn Forte 1799fcf3ce44SJohn Forte done: 1800fcf3ce44SJohn Forte 1801fcf3ce44SJohn Forte return (rval); 1802fcf3ce44SJohn Forte 180382527734SSukumar Swaminathan } /* emlxs_offline() */ 1804fcf3ce44SJohn Forte 1805fcf3ce44SJohn Forte 1806fcf3ce44SJohn Forte 1807fcf3ce44SJohn Forte extern int 1808fcf3ce44SJohn Forte emlxs_power_down(emlxs_hba_t *hba) 1809fcf3ce44SJohn Forte { 18104baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 18114baa2c25SSukumar Swaminathan emlxs_port_t *port = &PPORT; 18124baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 1813fcf3ce44SJohn Forte int32_t rval = 0; 1814fcf3ce44SJohn Forte 1815fcf3ce44SJohn Forte if ((rval = emlxs_offline(hba))) { 1816fcf3ce44SJohn Forte return (rval); 1817fcf3ce44SJohn Forte } 181882527734SSukumar Swaminathan EMLXS_SLI_HBA_RESET(hba, 1, 1, 0); 1819291a2b48SSukumar Swaminathan 1820fcf3ce44SJohn Forte 18214baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 18224baa2c25SSukumar Swaminathan if (emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle) 18234baa2c25SSukumar Swaminathan != DDI_FM_OK) { 18244baa2c25SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 18254baa2c25SSukumar Swaminathan &emlxs_invalid_access_handle_msg, NULL); 18264baa2c25SSukumar Swaminathan return (1); 18274baa2c25SSukumar Swaminathan } 18284baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 18294baa2c25SSukumar Swaminathan 1830fcf3ce44SJohn Forte return (0); 1831fcf3ce44SJohn Forte 183282527734SSukumar Swaminathan } /* End emlxs_power_down */ 1833fcf3ce44SJohn Forte 1834fcf3ce44SJohn Forte 1835fcf3ce44SJohn Forte extern int 1836fcf3ce44SJohn Forte emlxs_power_up(emlxs_hba_t *hba) 1837fcf3ce44SJohn Forte { 18384baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 18394baa2c25SSukumar Swaminathan emlxs_port_t *port = &PPORT; 18404baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 1841fcf3ce44SJohn Forte int32_t rval = 0; 1842fcf3ce44SJohn Forte 1843fcf3ce44SJohn Forte 18444baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 18454baa2c25SSukumar Swaminathan if (emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle) 18464baa2c25SSukumar Swaminathan != DDI_FM_OK) { 18474baa2c25SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 18484baa2c25SSukumar Swaminathan &emlxs_invalid_access_handle_msg, NULL); 18494baa2c25SSukumar Swaminathan return (1); 18504baa2c25SSukumar Swaminathan } 18514baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 18524baa2c25SSukumar Swaminathan 1853fcf3ce44SJohn Forte /* Bring adapter online */ 1854fcf3ce44SJohn Forte if ((rval = emlxs_online(hba))) { 1855*a9800bebSGarrett D'Amore if (hba->pci_cap_offset[PCI_CAP_ID_PM]) { 1856*a9800bebSGarrett D'Amore /* Put chip in D3 state */ 1857*a9800bebSGarrett D'Amore (void) ddi_put8(hba->pci_acc_handle, 1858*a9800bebSGarrett D'Amore (uint8_t *)(hba->pci_addr + 1859*a9800bebSGarrett D'Amore hba->pci_cap_offset[PCI_CAP_ID_PM] + 1860*a9800bebSGarrett D'Amore PCI_PMCSR), 1861*a9800bebSGarrett D'Amore (uint8_t)PCI_PMCSR_D3HOT); 1862*a9800bebSGarrett D'Amore } 1863fcf3ce44SJohn Forte return (rval); 1864fcf3ce44SJohn Forte } 1865291a2b48SSukumar Swaminathan 1866fcf3ce44SJohn Forte return (rval); 1867fcf3ce44SJohn Forte 186882527734SSukumar Swaminathan } /* End emlxs_power_up */ 1869fcf3ce44SJohn Forte 1870fcf3ce44SJohn Forte 1871fcf3ce44SJohn Forte /* 1872291a2b48SSukumar Swaminathan * 1873fcf3ce44SJohn Forte * NAME: emlxs_ffcleanup 1874fcf3ce44SJohn Forte * 1875fcf3ce44SJohn Forte * FUNCTION: Cleanup all the Firefly resources used by configuring the adapter 1876fcf3ce44SJohn Forte * 1877fcf3ce44SJohn Forte * EXECUTION ENVIRONMENT: process only 1878fcf3ce44SJohn Forte * 1879fcf3ce44SJohn Forte * CALLED FROM: CFG_TERM 1880fcf3ce44SJohn Forte * 1881fcf3ce44SJohn Forte * INPUT: hba - pointer to the dev_ctl area. 1882fcf3ce44SJohn Forte * 1883fcf3ce44SJohn Forte * RETURNS: none 1884fcf3ce44SJohn Forte */ 1885fcf3ce44SJohn Forte extern void 1886fcf3ce44SJohn Forte emlxs_ffcleanup(emlxs_hba_t *hba) 1887fcf3ce44SJohn Forte { 1888fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 1889291a2b48SSukumar Swaminathan uint32_t i; 1890fcf3ce44SJohn Forte 1891fcf3ce44SJohn Forte /* Disable all but the mailbox interrupt */ 189282527734SSukumar Swaminathan EMLXS_SLI_DISABLE_INTR(hba, HC_MBINT_ENA); 1893fcf3ce44SJohn Forte 1894fcf3ce44SJohn Forte /* Make sure all port nodes are destroyed */ 1895291a2b48SSukumar Swaminathan for (i = 0; i < MAX_VPORTS; i++) { 1896291a2b48SSukumar Swaminathan port = &VPORT(i); 1897fcf3ce44SJohn Forte 1898fcf3ce44SJohn Forte if (port->node_count) { 1899*a9800bebSGarrett D'Amore (void) emlxs_mb_unreg_node(port, 0, 0, 0, 0); 1900fcf3ce44SJohn Forte } 1901fcf3ce44SJohn Forte } 1902fcf3ce44SJohn Forte 1903fcf3ce44SJohn Forte /* Clear all interrupt enable conditions */ 190482527734SSukumar Swaminathan EMLXS_SLI_DISABLE_INTR(hba, 0); 1905fcf3ce44SJohn Forte 1906fcf3ce44SJohn Forte return; 1907fcf3ce44SJohn Forte 190882527734SSukumar Swaminathan } /* emlxs_ffcleanup() */ 1909fcf3ce44SJohn Forte 1910fcf3ce44SJohn Forte 1911fcf3ce44SJohn Forte extern uint16_t 191282527734SSukumar Swaminathan emlxs_register_pkt(CHANNEL *cp, emlxs_buf_t *sbp) 1913fcf3ce44SJohn Forte { 1914fcf3ce44SJohn Forte emlxs_hba_t *hba; 1915fcf3ce44SJohn Forte emlxs_port_t *port; 1916fcf3ce44SJohn Forte uint16_t iotag; 1917fcf3ce44SJohn Forte uint32_t i; 1918fcf3ce44SJohn Forte 191982527734SSukumar Swaminathan hba = cp->hba; 1920fcf3ce44SJohn Forte 192182527734SSukumar Swaminathan mutex_enter(&EMLXS_FCTAB_LOCK); 1922fcf3ce44SJohn Forte 1923fcf3ce44SJohn Forte if (sbp->iotag != 0) { 1924fcf3ce44SJohn Forte port = &PPORT; 1925fcf3ce44SJohn Forte 1926fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 192782527734SSukumar Swaminathan "Pkt already registered! channel=%d iotag=%d sbp=%p", 192882527734SSukumar Swaminathan sbp->channel, sbp->iotag, sbp); 1929fcf3ce44SJohn Forte } 1930291a2b48SSukumar Swaminathan 1931fcf3ce44SJohn Forte iotag = 0; 193282527734SSukumar Swaminathan for (i = 0; i < hba->max_iotag; i++) { 193382527734SSukumar Swaminathan if (!hba->fc_iotag || hba->fc_iotag >= hba->max_iotag) { 193482527734SSukumar Swaminathan hba->fc_iotag = 1; 1935fcf3ce44SJohn Forte } 193682527734SSukumar Swaminathan iotag = hba->fc_iotag++; 1937fcf3ce44SJohn Forte 193882527734SSukumar Swaminathan if (hba->fc_table[iotag] == 0 || 193982527734SSukumar Swaminathan hba->fc_table[iotag] == STALE_PACKET) { 194082527734SSukumar Swaminathan hba->io_count++; 194182527734SSukumar Swaminathan hba->fc_table[iotag] = sbp; 1942fcf3ce44SJohn Forte 1943fcf3ce44SJohn Forte sbp->iotag = iotag; 194482527734SSukumar Swaminathan sbp->channel = cp; 1945fcf3ce44SJohn Forte 1946fcf3ce44SJohn Forte break; 1947fcf3ce44SJohn Forte } 1948fcf3ce44SJohn Forte iotag = 0; 1949fcf3ce44SJohn Forte } 1950fcf3ce44SJohn Forte 195182527734SSukumar Swaminathan mutex_exit(&EMLXS_FCTAB_LOCK); 1952fcf3ce44SJohn Forte 1953fcf3ce44SJohn Forte /* 1954fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 195582527734SSukumar Swaminathan * "emlxs_register_pkt: channel=%d iotag=%d sbp=%p", 195682527734SSukumar Swaminathan * cp->channelno, iotag, sbp); 1957fcf3ce44SJohn Forte */ 1958fcf3ce44SJohn Forte 1959fcf3ce44SJohn Forte return (iotag); 1960fcf3ce44SJohn Forte 196182527734SSukumar Swaminathan } /* emlxs_register_pkt() */ 1962fcf3ce44SJohn Forte 1963fcf3ce44SJohn Forte 1964fcf3ce44SJohn Forte 1965fcf3ce44SJohn Forte extern emlxs_buf_t * 196682527734SSukumar Swaminathan emlxs_unregister_pkt(CHANNEL *cp, uint16_t iotag, uint32_t forced) 1967fcf3ce44SJohn Forte { 1968fcf3ce44SJohn Forte emlxs_hba_t *hba; 1969fcf3ce44SJohn Forte emlxs_buf_t *sbp; 197082527734SSukumar Swaminathan 197182527734SSukumar Swaminathan sbp = NULL; 197282527734SSukumar Swaminathan hba = cp->hba; 1973fcf3ce44SJohn Forte 1974fcf3ce44SJohn Forte /* Check the iotag range */ 197582527734SSukumar Swaminathan if ((iotag == 0) || (iotag >= hba->max_iotag)) { 1976fcf3ce44SJohn Forte return (NULL); 1977fcf3ce44SJohn Forte } 1978291a2b48SSukumar Swaminathan 1979fcf3ce44SJohn Forte /* Remove the sbp from the table */ 198082527734SSukumar Swaminathan mutex_enter(&EMLXS_FCTAB_LOCK); 198182527734SSukumar Swaminathan sbp = hba->fc_table[iotag]; 1982fcf3ce44SJohn Forte 1983fcf3ce44SJohn Forte if (!sbp || (sbp == STALE_PACKET)) { 198482527734SSukumar Swaminathan mutex_exit(&EMLXS_FCTAB_LOCK); 1985fcf3ce44SJohn Forte return (sbp); 1986fcf3ce44SJohn Forte } 1987291a2b48SSukumar Swaminathan 198882527734SSukumar Swaminathan hba->fc_table[iotag] = ((forced) ? STALE_PACKET : NULL); 198982527734SSukumar Swaminathan hba->io_count--; 1990fcf3ce44SJohn Forte sbp->iotag = 0; 1991fcf3ce44SJohn Forte 199282527734SSukumar Swaminathan mutex_exit(&EMLXS_FCTAB_LOCK); 1993fcf3ce44SJohn Forte 1994fcf3ce44SJohn Forte 1995fcf3ce44SJohn Forte /* Clean up the sbp */ 1996fcf3ce44SJohn Forte mutex_enter(&sbp->mtx); 1997fcf3ce44SJohn Forte 1998fcf3ce44SJohn Forte if (sbp->pkt_flags & PACKET_IN_TXQ) { 1999fcf3ce44SJohn Forte sbp->pkt_flags &= ~PACKET_IN_TXQ; 200082527734SSukumar Swaminathan hba->channel_tx_count--; 2001fcf3ce44SJohn Forte } 2002291a2b48SSukumar Swaminathan 2003fcf3ce44SJohn Forte if (sbp->pkt_flags & PACKET_IN_CHIPQ) { 2004fcf3ce44SJohn Forte sbp->pkt_flags &= ~PACKET_IN_CHIPQ; 2005fcf3ce44SJohn Forte } 2006291a2b48SSukumar Swaminathan 2007fcf3ce44SJohn Forte if (sbp->bmp) { 2008*a9800bebSGarrett D'Amore emlxs_mem_put(hba, MEM_BPL, (void *)sbp->bmp); 2009fcf3ce44SJohn Forte sbp->bmp = 0; 2010fcf3ce44SJohn Forte } 2011fcf3ce44SJohn Forte 2012291a2b48SSukumar Swaminathan mutex_exit(&sbp->mtx); 2013fcf3ce44SJohn Forte 2014fcf3ce44SJohn Forte return (sbp); 2015fcf3ce44SJohn Forte 201682527734SSukumar Swaminathan } /* emlxs_unregister_pkt() */ 2017fcf3ce44SJohn Forte 2018fcf3ce44SJohn Forte 2019fcf3ce44SJohn Forte 202082527734SSukumar Swaminathan /* Flush all IO's to all nodes for a given IO Channel */ 2021fcf3ce44SJohn Forte extern uint32_t 202282527734SSukumar Swaminathan emlxs_tx_channel_flush(emlxs_hba_t *hba, CHANNEL *cp, emlxs_buf_t *fpkt) 2023fcf3ce44SJohn Forte { 2024fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 2025fcf3ce44SJohn Forte emlxs_buf_t *sbp; 2026fcf3ce44SJohn Forte IOCBQ *iocbq; 2027fcf3ce44SJohn Forte IOCBQ *next; 2028fcf3ce44SJohn Forte IOCB *iocb; 202982527734SSukumar Swaminathan uint32_t channelno; 2030fcf3ce44SJohn Forte Q abort; 2031fcf3ce44SJohn Forte NODELIST *ndlp; 2032fcf3ce44SJohn Forte IOCB *icmd; 2033fcf3ce44SJohn Forte MATCHMAP *mp; 2034fcf3ce44SJohn Forte uint32_t i; 203582527734SSukumar Swaminathan uint8_t flag[MAX_CHANNEL]; 2036fcf3ce44SJohn Forte 203782527734SSukumar Swaminathan channelno = cp->channelno; 2038fcf3ce44SJohn Forte bzero((void *)&abort, sizeof (Q)); 203982527734SSukumar Swaminathan bzero((void *)flag, MAX_CHANNEL * sizeof (uint8_t)); 2040fcf3ce44SJohn Forte 204182527734SSukumar Swaminathan mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 2042fcf3ce44SJohn Forte 2043fcf3ce44SJohn Forte /* While a node needs servicing */ 204482527734SSukumar Swaminathan while (cp->nodeq.q_first) { 204582527734SSukumar Swaminathan ndlp = (NODELIST *) cp->nodeq.q_first; 2046fcf3ce44SJohn Forte 2047fcf3ce44SJohn Forte /* Check if priority queue is not empty */ 204882527734SSukumar Swaminathan if (ndlp->nlp_ptx[channelno].q_first) { 2049fcf3ce44SJohn Forte /* Transfer all iocb's to local queue */ 2050fcf3ce44SJohn Forte if (abort.q_first == 0) { 205182527734SSukumar Swaminathan abort.q_first = 205282527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_first; 2053fcf3ce44SJohn Forte } else { 2054fcf3ce44SJohn Forte ((IOCBQ *)abort.q_last)->next = 205582527734SSukumar Swaminathan (IOCBQ *)ndlp->nlp_ptx[channelno].q_first; 2056fcf3ce44SJohn Forte } 205782527734SSukumar Swaminathan flag[channelno] = 1; 2058fcf3ce44SJohn Forte 205982527734SSukumar Swaminathan abort.q_last = ndlp->nlp_ptx[channelno].q_last; 206082527734SSukumar Swaminathan abort.q_cnt += ndlp->nlp_ptx[channelno].q_cnt; 2061fcf3ce44SJohn Forte } 2062291a2b48SSukumar Swaminathan 2063fcf3ce44SJohn Forte /* Check if tx queue is not empty */ 206482527734SSukumar Swaminathan if (ndlp->nlp_tx[channelno].q_first) { 2065fcf3ce44SJohn Forte /* Transfer all iocb's to local queue */ 2066fcf3ce44SJohn Forte if (abort.q_first == 0) { 206782527734SSukumar Swaminathan abort.q_first = ndlp->nlp_tx[channelno].q_first; 2068fcf3ce44SJohn Forte } else { 2069fcf3ce44SJohn Forte ((IOCBQ *)abort.q_last)->next = 207082527734SSukumar Swaminathan (IOCBQ *)ndlp->nlp_tx[channelno].q_first; 2071fcf3ce44SJohn Forte } 2072fcf3ce44SJohn Forte 207382527734SSukumar Swaminathan abort.q_last = ndlp->nlp_tx[channelno].q_last; 207482527734SSukumar Swaminathan abort.q_cnt += ndlp->nlp_tx[channelno].q_cnt; 2075fcf3ce44SJohn Forte } 2076291a2b48SSukumar Swaminathan 2077fcf3ce44SJohn Forte /* Clear the queue pointers */ 207882527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_first = NULL; 207982527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_last = NULL; 208082527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_cnt = 0; 2081fcf3ce44SJohn Forte 208282527734SSukumar Swaminathan ndlp->nlp_tx[channelno].q_first = NULL; 208382527734SSukumar Swaminathan ndlp->nlp_tx[channelno].q_last = NULL; 208482527734SSukumar Swaminathan ndlp->nlp_tx[channelno].q_cnt = 0; 2085fcf3ce44SJohn Forte 2086fcf3ce44SJohn Forte /* Remove node from service queue */ 2087fcf3ce44SJohn Forte 2088fcf3ce44SJohn Forte /* If this is the last node on list */ 208982527734SSukumar Swaminathan if (cp->nodeq.q_last == (void *)ndlp) { 209082527734SSukumar Swaminathan cp->nodeq.q_last = NULL; 209182527734SSukumar Swaminathan cp->nodeq.q_first = NULL; 209282527734SSukumar Swaminathan cp->nodeq.q_cnt = 0; 2093fcf3ce44SJohn Forte } else { 2094fcf3ce44SJohn Forte /* Remove node from head */ 209582527734SSukumar Swaminathan cp->nodeq.q_first = ndlp->nlp_next[channelno]; 209682527734SSukumar Swaminathan ((NODELIST *)cp->nodeq.q_last)->nlp_next[channelno] = 209782527734SSukumar Swaminathan cp->nodeq.q_first; 209882527734SSukumar Swaminathan cp->nodeq.q_cnt--; 2099fcf3ce44SJohn Forte } 2100fcf3ce44SJohn Forte 2101fcf3ce44SJohn Forte /* Clear node */ 210282527734SSukumar Swaminathan ndlp->nlp_next[channelno] = NULL; 2103fcf3ce44SJohn Forte } 2104fcf3ce44SJohn Forte 2105fcf3ce44SJohn Forte /* First cleanup the iocb's while still holding the lock */ 2106291a2b48SSukumar Swaminathan iocbq = (IOCBQ *) abort.q_first; 2107fcf3ce44SJohn Forte while (iocbq) { 2108fcf3ce44SJohn Forte /* Free the IoTag and the bmp */ 2109fcf3ce44SJohn Forte iocb = &iocbq->iocb; 211082527734SSukumar Swaminathan 211182527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 211282527734SSukumar Swaminathan sbp = iocbq->sbp; 211382527734SSukumar Swaminathan if (sbp) { 2114*a9800bebSGarrett D'Amore emlxs_sli4_free_xri(hba, sbp, sbp->xrip, 1); 211582527734SSukumar Swaminathan } 211682527734SSukumar Swaminathan } else { 211782527734SSukumar Swaminathan sbp = emlxs_unregister_pkt((CHANNEL *)iocbq->channel, 211882527734SSukumar Swaminathan iocb->ULPIOTAG, 0); 211982527734SSukumar Swaminathan } 2120fcf3ce44SJohn Forte 2121fcf3ce44SJohn Forte if (sbp && (sbp != STALE_PACKET)) { 2122fcf3ce44SJohn Forte mutex_enter(&sbp->mtx); 2123fcf3ce44SJohn Forte 2124fcf3ce44SJohn Forte sbp->pkt_flags |= PACKET_IN_FLUSH; 2125fcf3ce44SJohn Forte /* 2126fcf3ce44SJohn Forte * If the fpkt is already set, then we will leave it 2127291a2b48SSukumar Swaminathan * alone. This ensures that this pkt is only accounted 2128291a2b48SSukumar Swaminathan * for on one fpkt->flush_count 2129fcf3ce44SJohn Forte */ 2130fcf3ce44SJohn Forte if (!sbp->fpkt && fpkt) { 2131fcf3ce44SJohn Forte mutex_enter(&fpkt->mtx); 2132fcf3ce44SJohn Forte sbp->fpkt = fpkt; 2133fcf3ce44SJohn Forte fpkt->flush_count++; 2134fcf3ce44SJohn Forte mutex_exit(&fpkt->mtx); 2135fcf3ce44SJohn Forte } 2136291a2b48SSukumar Swaminathan 2137fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 2138fcf3ce44SJohn Forte } 2139291a2b48SSukumar Swaminathan 2140fcf3ce44SJohn Forte iocbq = (IOCBQ *)iocbq->next; 2141fcf3ce44SJohn Forte } /* end of while */ 2142fcf3ce44SJohn Forte 214382527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 2144fcf3ce44SJohn Forte 2145fcf3ce44SJohn Forte /* Now abort the iocb's */ 2146fcf3ce44SJohn Forte iocbq = (IOCBQ *)abort.q_first; 2147fcf3ce44SJohn Forte while (iocbq) { 2148fcf3ce44SJohn Forte /* Save the next iocbq for now */ 2149fcf3ce44SJohn Forte next = (IOCBQ *)iocbq->next; 2150fcf3ce44SJohn Forte 2151fcf3ce44SJohn Forte /* Unlink this iocbq */ 2152fcf3ce44SJohn Forte iocbq->next = NULL; 2153fcf3ce44SJohn Forte 2154fcf3ce44SJohn Forte /* Get the pkt */ 2155fcf3ce44SJohn Forte sbp = (emlxs_buf_t *)iocbq->sbp; 2156fcf3ce44SJohn Forte 2157fcf3ce44SJohn Forte if (sbp) { 2158fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flush_msg, 2159291a2b48SSukumar Swaminathan "tx: sbp=%p node=%p", sbp, sbp->node); 2160fcf3ce44SJohn Forte 2161fcf3ce44SJohn Forte if (hba->state >= FC_LINK_UP) { 2162fcf3ce44SJohn Forte emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 2163fcf3ce44SJohn Forte IOERR_ABORT_REQUESTED, 1); 2164fcf3ce44SJohn Forte } else { 2165fcf3ce44SJohn Forte emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 2166fcf3ce44SJohn Forte IOERR_LINK_DOWN, 1); 2167fcf3ce44SJohn Forte } 2168fcf3ce44SJohn Forte 2169fcf3ce44SJohn Forte } 2170fcf3ce44SJohn Forte /* Free the iocb and its associated buffers */ 2171fcf3ce44SJohn Forte else { 2172fcf3ce44SJohn Forte icmd = &iocbq->iocb; 217382527734SSukumar Swaminathan 217482527734SSukumar Swaminathan /* SLI3 */ 217582527734SSukumar Swaminathan if (icmd->ULPCOMMAND == CMD_QUE_RING_BUF64_CN || 217682527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_QUE_RING_BUF_CN || 217782527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_QUE_RING_LIST64_CN) { 2178fcf3ce44SJohn Forte if ((hba->flag & 2179fcf3ce44SJohn Forte (FC_ONLINE_MODE | FC_ONLINING_MODE)) == 0) { 2180fcf3ce44SJohn Forte /* HBA is detaching or offlining */ 218182527734SSukumar Swaminathan if (icmd->ULPCOMMAND != 2182fcf3ce44SJohn Forte CMD_QUE_RING_LIST64_CN) { 2183*a9800bebSGarrett D'Amore void *tmp; 218482527734SSukumar Swaminathan RING *rp; 2185fcf3ce44SJohn Forte 218682527734SSukumar Swaminathan rp = &hba->sli.sli3. 218782527734SSukumar Swaminathan ring[channelno]; 2188fcf3ce44SJohn Forte for (i = 0; 218982527734SSukumar Swaminathan i < icmd->ULPBDECOUNT; 2190fcf3ce44SJohn Forte i++) { 2191fcf3ce44SJohn Forte mp = EMLXS_GET_VADDR( 2192fcf3ce44SJohn Forte hba, rp, icmd); 2193fcf3ce44SJohn Forte 2194*a9800bebSGarrett D'Amore tmp = (void *)mp; 2195fcf3ce44SJohn Forte if (mp) { 2196*a9800bebSGarrett D'Amore emlxs_mem_put( 2197291a2b48SSukumar Swaminathan hba, MEM_BUF, tmp); 2198fcf3ce44SJohn Forte } 2199fcf3ce44SJohn Forte } 2200fcf3ce44SJohn Forte } 2201291a2b48SSukumar Swaminathan 2202*a9800bebSGarrett D'Amore emlxs_mem_put(hba, MEM_IOCB, 2203*a9800bebSGarrett D'Amore (void *)iocbq); 2204fcf3ce44SJohn Forte } else { 2205fcf3ce44SJohn Forte /* repost the unsolicited buffer */ 220682527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, 2207291a2b48SSukumar Swaminathan iocbq); 2208fcf3ce44SJohn Forte } 220982527734SSukumar Swaminathan } else if (icmd->ULPCOMMAND == CMD_CLOSE_XRI_CN || 221082527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_CLOSE_XRI_CX) { 221182527734SSukumar Swaminathan 221282527734SSukumar Swaminathan emlxs_tx_put(iocbq, 1); 2213fcf3ce44SJohn Forte } 2214fcf3ce44SJohn Forte } 2215fcf3ce44SJohn Forte 2216fcf3ce44SJohn Forte iocbq = next; 2217fcf3ce44SJohn Forte 2218fcf3ce44SJohn Forte } /* end of while */ 2219fcf3ce44SJohn Forte 222082527734SSukumar Swaminathan /* Now trigger channel service */ 222182527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 222282527734SSukumar Swaminathan if (!flag[channelno]) { 222382527734SSukumar Swaminathan continue; 222482527734SSukumar Swaminathan } 222582527734SSukumar Swaminathan 222682527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, &hba->chan[channelno], 0); 222782527734SSukumar Swaminathan } 222882527734SSukumar Swaminathan 2229fcf3ce44SJohn Forte return (abort.q_cnt); 2230fcf3ce44SJohn Forte 223182527734SSukumar Swaminathan } /* emlxs_tx_channel_flush() */ 2232fcf3ce44SJohn Forte 2233fcf3ce44SJohn Forte 2234fcf3ce44SJohn Forte /* Flush all IO's on all or a given ring for a given node */ 2235fcf3ce44SJohn Forte extern uint32_t 223682527734SSukumar Swaminathan emlxs_tx_node_flush(emlxs_port_t *port, NODELIST *ndlp, CHANNEL *chan, 2237fcf3ce44SJohn Forte uint32_t shutdown, emlxs_buf_t *fpkt) 2238fcf3ce44SJohn Forte { 2239fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 2240fcf3ce44SJohn Forte emlxs_buf_t *sbp; 224182527734SSukumar Swaminathan uint32_t channelno; 224282527734SSukumar Swaminathan CHANNEL *cp; 2243fcf3ce44SJohn Forte IOCB *icmd; 2244fcf3ce44SJohn Forte IOCBQ *iocbq; 2245fcf3ce44SJohn Forte NODELIST *prev; 2246fcf3ce44SJohn Forte IOCBQ *next; 2247fcf3ce44SJohn Forte IOCB *iocb; 2248fcf3ce44SJohn Forte Q abort; 2249fcf3ce44SJohn Forte uint32_t i; 2250fcf3ce44SJohn Forte MATCHMAP *mp; 225182527734SSukumar Swaminathan uint8_t flag[MAX_CHANNEL]; 2252fcf3ce44SJohn Forte 2253fcf3ce44SJohn Forte bzero((void *)&abort, sizeof (Q)); 2254fcf3ce44SJohn Forte 2255fcf3ce44SJohn Forte /* Flush all I/O's on tx queue to this target */ 225682527734SSukumar Swaminathan mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 2257fcf3ce44SJohn Forte 2258fcf3ce44SJohn Forte if (!ndlp->nlp_base && shutdown) { 2259fcf3ce44SJohn Forte ndlp->nlp_active = 0; 2260fcf3ce44SJohn Forte } 2261291a2b48SSukumar Swaminathan 226282527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 226382527734SSukumar Swaminathan cp = &hba->chan[channelno]; 2264fcf3ce44SJohn Forte 226582527734SSukumar Swaminathan if (chan && cp != chan) { 2266fcf3ce44SJohn Forte continue; 2267fcf3ce44SJohn Forte } 2268291a2b48SSukumar Swaminathan 2269fcf3ce44SJohn Forte if (!ndlp->nlp_base || shutdown) { 2270fcf3ce44SJohn Forte /* Check if priority queue is not empty */ 227182527734SSukumar Swaminathan if (ndlp->nlp_ptx[channelno].q_first) { 2272fcf3ce44SJohn Forte /* Transfer all iocb's to local queue */ 2273fcf3ce44SJohn Forte if (abort.q_first == 0) { 2274fcf3ce44SJohn Forte abort.q_first = 227582527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_first; 2276fcf3ce44SJohn Forte } else { 227782527734SSukumar Swaminathan ((IOCBQ *)(abort.q_last))->next = 227882527734SSukumar Swaminathan (IOCBQ *)ndlp->nlp_ptx[channelno]. 2279291a2b48SSukumar Swaminathan q_first; 2280fcf3ce44SJohn Forte } 2281fcf3ce44SJohn Forte 228282527734SSukumar Swaminathan flag[channelno] = 1; 228382527734SSukumar Swaminathan 228482527734SSukumar Swaminathan abort.q_last = ndlp->nlp_ptx[channelno].q_last; 228582527734SSukumar Swaminathan abort.q_cnt += ndlp->nlp_ptx[channelno].q_cnt; 2286fcf3ce44SJohn Forte } 2287fcf3ce44SJohn Forte } 2288291a2b48SSukumar Swaminathan 2289fcf3ce44SJohn Forte /* Check if tx queue is not empty */ 229082527734SSukumar Swaminathan if (ndlp->nlp_tx[channelno].q_first) { 229182527734SSukumar Swaminathan 2292fcf3ce44SJohn Forte /* Transfer all iocb's to local queue */ 2293fcf3ce44SJohn Forte if (abort.q_first == 0) { 229482527734SSukumar Swaminathan abort.q_first = ndlp->nlp_tx[channelno].q_first; 2295fcf3ce44SJohn Forte } else { 2296fcf3ce44SJohn Forte ((IOCBQ *)abort.q_last)->next = 229782527734SSukumar Swaminathan (IOCBQ *)ndlp->nlp_tx[channelno].q_first; 2298fcf3ce44SJohn Forte } 2299fcf3ce44SJohn Forte 230082527734SSukumar Swaminathan abort.q_last = ndlp->nlp_tx[channelno].q_last; 230182527734SSukumar Swaminathan abort.q_cnt += ndlp->nlp_tx[channelno].q_cnt; 2302fcf3ce44SJohn Forte } 2303291a2b48SSukumar Swaminathan 2304fcf3ce44SJohn Forte /* Clear the queue pointers */ 230582527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_first = NULL; 230682527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_last = NULL; 230782527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_cnt = 0; 2308fcf3ce44SJohn Forte 230982527734SSukumar Swaminathan ndlp->nlp_tx[channelno].q_first = NULL; 231082527734SSukumar Swaminathan ndlp->nlp_tx[channelno].q_last = NULL; 231182527734SSukumar Swaminathan ndlp->nlp_tx[channelno].q_cnt = 0; 2312fcf3ce44SJohn Forte 231382527734SSukumar Swaminathan /* If this node was on the channel queue, remove it */ 231482527734SSukumar Swaminathan if (ndlp->nlp_next[channelno]) { 2315fcf3ce44SJohn Forte /* If this is the only node on list */ 231682527734SSukumar Swaminathan if (cp->nodeq.q_first == (void *)ndlp && 231782527734SSukumar Swaminathan cp->nodeq.q_last == (void *)ndlp) { 231882527734SSukumar Swaminathan cp->nodeq.q_last = NULL; 231982527734SSukumar Swaminathan cp->nodeq.q_first = NULL; 232082527734SSukumar Swaminathan cp->nodeq.q_cnt = 0; 232182527734SSukumar Swaminathan } else if (cp->nodeq.q_first == (void *)ndlp) { 232282527734SSukumar Swaminathan cp->nodeq.q_first = ndlp->nlp_next[channelno]; 232382527734SSukumar Swaminathan ((NODELIST *) cp->nodeq.q_last)-> 232482527734SSukumar Swaminathan nlp_next[channelno] = cp->nodeq.q_first; 232582527734SSukumar Swaminathan cp->nodeq.q_cnt--; 2326291a2b48SSukumar Swaminathan } else { 2327fcf3ce44SJohn Forte /* 2328291a2b48SSukumar Swaminathan * This is a little more difficult find the 232982527734SSukumar Swaminathan * previous node in the circular channel queue 2330fcf3ce44SJohn Forte */ 2331fcf3ce44SJohn Forte prev = ndlp; 233282527734SSukumar Swaminathan while (prev->nlp_next[channelno] != ndlp) { 233382527734SSukumar Swaminathan prev = prev->nlp_next[channelno]; 2334fcf3ce44SJohn Forte } 2335fcf3ce44SJohn Forte 233682527734SSukumar Swaminathan prev->nlp_next[channelno] = 233782527734SSukumar Swaminathan ndlp->nlp_next[channelno]; 2338fcf3ce44SJohn Forte 233982527734SSukumar Swaminathan if (cp->nodeq.q_last == (void *)ndlp) { 234082527734SSukumar Swaminathan cp->nodeq.q_last = (void *)prev; 2341fcf3ce44SJohn Forte } 234282527734SSukumar Swaminathan cp->nodeq.q_cnt--; 2343fcf3ce44SJohn Forte 2344fcf3ce44SJohn Forte } 2345fcf3ce44SJohn Forte 2346fcf3ce44SJohn Forte /* Clear node */ 234782527734SSukumar Swaminathan ndlp->nlp_next[channelno] = NULL; 2348fcf3ce44SJohn Forte } 2349291a2b48SSukumar Swaminathan 2350fcf3ce44SJohn Forte } 2351fcf3ce44SJohn Forte 2352fcf3ce44SJohn Forte /* First cleanup the iocb's while still holding the lock */ 2353291a2b48SSukumar Swaminathan iocbq = (IOCBQ *) abort.q_first; 2354fcf3ce44SJohn Forte while (iocbq) { 2355fcf3ce44SJohn Forte /* Free the IoTag and the bmp */ 2356fcf3ce44SJohn Forte iocb = &iocbq->iocb; 235782527734SSukumar Swaminathan 235882527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 235982527734SSukumar Swaminathan sbp = iocbq->sbp; 236082527734SSukumar Swaminathan if (sbp) { 2361*a9800bebSGarrett D'Amore emlxs_sli4_free_xri(hba, sbp, sbp->xrip, 1); 236282527734SSukumar Swaminathan } 236382527734SSukumar Swaminathan } else { 236482527734SSukumar Swaminathan sbp = emlxs_unregister_pkt((CHANNEL *)iocbq->channel, 236582527734SSukumar Swaminathan iocb->ULPIOTAG, 0); 236682527734SSukumar Swaminathan } 2367fcf3ce44SJohn Forte 2368fcf3ce44SJohn Forte if (sbp && (sbp != STALE_PACKET)) { 2369fcf3ce44SJohn Forte mutex_enter(&sbp->mtx); 2370fcf3ce44SJohn Forte sbp->pkt_flags |= PACKET_IN_FLUSH; 2371fcf3ce44SJohn Forte /* 2372fcf3ce44SJohn Forte * If the fpkt is already set, then we will leave it 2373291a2b48SSukumar Swaminathan * alone. This ensures that this pkt is only accounted 2374291a2b48SSukumar Swaminathan * for on one fpkt->flush_count 2375fcf3ce44SJohn Forte */ 2376fcf3ce44SJohn Forte if (!sbp->fpkt && fpkt) { 2377fcf3ce44SJohn Forte mutex_enter(&fpkt->mtx); 2378fcf3ce44SJohn Forte sbp->fpkt = fpkt; 2379fcf3ce44SJohn Forte fpkt->flush_count++; 2380fcf3ce44SJohn Forte mutex_exit(&fpkt->mtx); 2381fcf3ce44SJohn Forte } 2382291a2b48SSukumar Swaminathan 2383fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 2384fcf3ce44SJohn Forte } 2385291a2b48SSukumar Swaminathan 2386291a2b48SSukumar Swaminathan iocbq = (IOCBQ *) iocbq->next; 2387fcf3ce44SJohn Forte 2388fcf3ce44SJohn Forte } /* end of while */ 2389fcf3ce44SJohn Forte 239082527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 2391fcf3ce44SJohn Forte 2392fcf3ce44SJohn Forte /* Now abort the iocb's outside the locks */ 2393fcf3ce44SJohn Forte iocbq = (IOCBQ *)abort.q_first; 2394fcf3ce44SJohn Forte while (iocbq) { 2395fcf3ce44SJohn Forte /* Save the next iocbq for now */ 2396fcf3ce44SJohn Forte next = (IOCBQ *)iocbq->next; 2397fcf3ce44SJohn Forte 2398fcf3ce44SJohn Forte /* Unlink this iocbq */ 2399fcf3ce44SJohn Forte iocbq->next = NULL; 2400fcf3ce44SJohn Forte 2401fcf3ce44SJohn Forte /* Get the pkt */ 2402fcf3ce44SJohn Forte sbp = (emlxs_buf_t *)iocbq->sbp; 2403fcf3ce44SJohn Forte 2404fcf3ce44SJohn Forte if (sbp) { 2405fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flush_msg, 2406291a2b48SSukumar Swaminathan "tx: sbp=%p node=%p", sbp, sbp->node); 2407fcf3ce44SJohn Forte 2408fcf3ce44SJohn Forte if (hba->state >= FC_LINK_UP) { 2409fcf3ce44SJohn Forte emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 2410fcf3ce44SJohn Forte IOERR_ABORT_REQUESTED, 1); 2411fcf3ce44SJohn Forte } else { 2412fcf3ce44SJohn Forte emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 2413fcf3ce44SJohn Forte IOERR_LINK_DOWN, 1); 2414fcf3ce44SJohn Forte } 2415fcf3ce44SJohn Forte 2416fcf3ce44SJohn Forte } 2417fcf3ce44SJohn Forte /* Free the iocb and its associated buffers */ 2418fcf3ce44SJohn Forte else { 241982527734SSukumar Swaminathan /* CMD_CLOSE_XRI_CN should also free the memory */ 2420fcf3ce44SJohn Forte icmd = &iocbq->iocb; 242182527734SSukumar Swaminathan 242282527734SSukumar Swaminathan /* SLI3 */ 242382527734SSukumar Swaminathan if (icmd->ULPCOMMAND == CMD_QUE_RING_BUF64_CN || 242482527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_QUE_RING_BUF_CN || 242582527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_QUE_RING_LIST64_CN) { 2426fcf3ce44SJohn Forte if ((hba->flag & 2427fcf3ce44SJohn Forte (FC_ONLINE_MODE | FC_ONLINING_MODE)) == 0) { 2428fcf3ce44SJohn Forte /* HBA is detaching or offlining */ 242982527734SSukumar Swaminathan if (icmd->ULPCOMMAND != 2430fcf3ce44SJohn Forte CMD_QUE_RING_LIST64_CN) { 2431*a9800bebSGarrett D'Amore void *tmp; 243282527734SSukumar Swaminathan RING *rp; 243382527734SSukumar Swaminathan int ch; 2434fcf3ce44SJohn Forte 243582527734SSukumar Swaminathan ch = ((CHANNEL *) 243682527734SSukumar Swaminathan iocbq->channel)->channelno; 243782527734SSukumar Swaminathan rp = &hba->sli.sli3.ring[ch]; 2438fcf3ce44SJohn Forte for (i = 0; 243982527734SSukumar Swaminathan i < icmd->ULPBDECOUNT; 2440fcf3ce44SJohn Forte i++) { 2441fcf3ce44SJohn Forte mp = EMLXS_GET_VADDR( 2442fcf3ce44SJohn Forte hba, rp, icmd); 2443fcf3ce44SJohn Forte 2444*a9800bebSGarrett D'Amore tmp = (void *)mp; 2445fcf3ce44SJohn Forte if (mp) { 2446*a9800bebSGarrett D'Amore emlxs_mem_put( 2447291a2b48SSukumar Swaminathan hba, MEM_BUF, tmp); 2448fcf3ce44SJohn Forte } 2449fcf3ce44SJohn Forte } 2450fcf3ce44SJohn Forte } 2451291a2b48SSukumar Swaminathan 2452*a9800bebSGarrett D'Amore emlxs_mem_put(hba, MEM_IOCB, 2453*a9800bebSGarrett D'Amore (void *)iocbq); 2454fcf3ce44SJohn Forte } else { 2455fcf3ce44SJohn Forte /* repost the unsolicited buffer */ 245682527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, 245782527734SSukumar Swaminathan (CHANNEL *)iocbq->channel, iocbq); 2458fcf3ce44SJohn Forte } 245982527734SSukumar Swaminathan } else if (icmd->ULPCOMMAND == CMD_CLOSE_XRI_CN || 246082527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_CLOSE_XRI_CX) { 246182527734SSukumar Swaminathan /* 246282527734SSukumar Swaminathan * Resend the abort iocbq if any 246382527734SSukumar Swaminathan */ 246482527734SSukumar Swaminathan emlxs_tx_put(iocbq, 1); 2465fcf3ce44SJohn Forte } 2466fcf3ce44SJohn Forte } 2467fcf3ce44SJohn Forte 2468fcf3ce44SJohn Forte iocbq = next; 2469fcf3ce44SJohn Forte 2470fcf3ce44SJohn Forte } /* end of while */ 2471fcf3ce44SJohn Forte 247282527734SSukumar Swaminathan /* Now trigger channel service */ 247382527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 247482527734SSukumar Swaminathan if (!flag[channelno]) { 247582527734SSukumar Swaminathan continue; 247682527734SSukumar Swaminathan } 247782527734SSukumar Swaminathan 247882527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, &hba->chan[channelno], 0); 247982527734SSukumar Swaminathan } 248082527734SSukumar Swaminathan 2481fcf3ce44SJohn Forte return (abort.q_cnt); 2482fcf3ce44SJohn Forte 248382527734SSukumar Swaminathan } /* emlxs_tx_node_flush() */ 2484fcf3ce44SJohn Forte 2485fcf3ce44SJohn Forte 2486fcf3ce44SJohn Forte /* Check for IO's on all or a given ring for a given node */ 2487fcf3ce44SJohn Forte extern uint32_t 248882527734SSukumar Swaminathan emlxs_tx_node_check(emlxs_port_t *port, NODELIST *ndlp, CHANNEL *chan) 2489fcf3ce44SJohn Forte { 2490fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 249182527734SSukumar Swaminathan uint32_t channelno; 249282527734SSukumar Swaminathan CHANNEL *cp; 2493fcf3ce44SJohn Forte uint32_t count; 2494fcf3ce44SJohn Forte 2495fcf3ce44SJohn Forte count = 0; 2496fcf3ce44SJohn Forte 2497fcf3ce44SJohn Forte /* Flush all I/O's on tx queue to this target */ 249882527734SSukumar Swaminathan mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 2499fcf3ce44SJohn Forte 250082527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 250182527734SSukumar Swaminathan cp = &hba->chan[channelno]; 2502fcf3ce44SJohn Forte 250382527734SSukumar Swaminathan if (chan && cp != chan) { 2504fcf3ce44SJohn Forte continue; 2505fcf3ce44SJohn Forte } 2506291a2b48SSukumar Swaminathan 2507fcf3ce44SJohn Forte /* Check if priority queue is not empty */ 250882527734SSukumar Swaminathan if (ndlp->nlp_ptx[channelno].q_first) { 250982527734SSukumar Swaminathan count += ndlp->nlp_ptx[channelno].q_cnt; 2510fcf3ce44SJohn Forte } 2511291a2b48SSukumar Swaminathan 2512fcf3ce44SJohn Forte /* Check if tx queue is not empty */ 251382527734SSukumar Swaminathan if (ndlp->nlp_tx[channelno].q_first) { 251482527734SSukumar Swaminathan count += ndlp->nlp_tx[channelno].q_cnt; 2515fcf3ce44SJohn Forte } 2516291a2b48SSukumar Swaminathan 2517fcf3ce44SJohn Forte } 2518fcf3ce44SJohn Forte 251982527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 2520fcf3ce44SJohn Forte 2521fcf3ce44SJohn Forte return (count); 2522fcf3ce44SJohn Forte 252382527734SSukumar Swaminathan } /* emlxs_tx_node_check() */ 2524fcf3ce44SJohn Forte 2525fcf3ce44SJohn Forte 2526fcf3ce44SJohn Forte 252782527734SSukumar Swaminathan /* Flush all IO's on the any ring for a given node's lun */ 2528fcf3ce44SJohn Forte extern uint32_t 2529291a2b48SSukumar Swaminathan emlxs_tx_lun_flush(emlxs_port_t *port, NODELIST *ndlp, uint32_t lun, 2530291a2b48SSukumar Swaminathan emlxs_buf_t *fpkt) 2531fcf3ce44SJohn Forte { 2532fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 2533fcf3ce44SJohn Forte emlxs_buf_t *sbp; 253482527734SSukumar Swaminathan uint32_t channelno; 2535fcf3ce44SJohn Forte IOCBQ *iocbq; 2536fcf3ce44SJohn Forte IOCBQ *prev; 2537fcf3ce44SJohn Forte IOCBQ *next; 2538fcf3ce44SJohn Forte IOCB *iocb; 2539fcf3ce44SJohn Forte IOCB *icmd; 2540fcf3ce44SJohn Forte Q abort; 2541fcf3ce44SJohn Forte uint32_t i; 2542fcf3ce44SJohn Forte MATCHMAP *mp; 254382527734SSukumar Swaminathan uint8_t flag[MAX_CHANNEL]; 2544fcf3ce44SJohn Forte 2545*a9800bebSGarrett D'Amore if (lun == EMLXS_LUN_NONE) { 2546*a9800bebSGarrett D'Amore return (0); 2547*a9800bebSGarrett D'Amore } 2548*a9800bebSGarrett D'Amore 2549fcf3ce44SJohn Forte bzero((void *)&abort, sizeof (Q)); 2550fcf3ce44SJohn Forte 2551fcf3ce44SJohn Forte /* Flush I/O's on txQ to this target's lun */ 255282527734SSukumar Swaminathan mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 2553fcf3ce44SJohn Forte 255482527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 2555291a2b48SSukumar Swaminathan 255682527734SSukumar Swaminathan /* Scan the priority queue first */ 255782527734SSukumar Swaminathan prev = NULL; 255882527734SSukumar Swaminathan iocbq = (IOCBQ *) ndlp->nlp_ptx[channelno].q_first; 2559fcf3ce44SJohn Forte 256082527734SSukumar Swaminathan while (iocbq) { 256182527734SSukumar Swaminathan next = (IOCBQ *)iocbq->next; 256282527734SSukumar Swaminathan iocb = &iocbq->iocb; 256382527734SSukumar Swaminathan sbp = (emlxs_buf_t *)iocbq->sbp; 256482527734SSukumar Swaminathan 256582527734SSukumar Swaminathan /* Check if this IO is for our lun */ 256682527734SSukumar Swaminathan if (sbp && (sbp->lun == lun)) { 256782527734SSukumar Swaminathan /* Remove iocb from the node's ptx queue */ 256882527734SSukumar Swaminathan if (next == 0) { 256982527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_last = 257082527734SSukumar Swaminathan (uint8_t *)prev; 257182527734SSukumar Swaminathan } 257282527734SSukumar Swaminathan 257382527734SSukumar Swaminathan if (prev == 0) { 257482527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_first = 257582527734SSukumar Swaminathan (uint8_t *)next; 257682527734SSukumar Swaminathan } else { 257782527734SSukumar Swaminathan prev->next = next; 257882527734SSukumar Swaminathan } 257982527734SSukumar Swaminathan 258082527734SSukumar Swaminathan iocbq->next = NULL; 258182527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_cnt--; 258282527734SSukumar Swaminathan 258382527734SSukumar Swaminathan /* 258482527734SSukumar Swaminathan * Add this iocb to our local abort Q 258582527734SSukumar Swaminathan */ 258682527734SSukumar Swaminathan if (abort.q_first) { 258782527734SSukumar Swaminathan ((IOCBQ *)abort.q_last)->next = iocbq; 258882527734SSukumar Swaminathan abort.q_last = (uint8_t *)iocbq; 258982527734SSukumar Swaminathan abort.q_cnt++; 259082527734SSukumar Swaminathan } else { 259182527734SSukumar Swaminathan abort.q_first = (uint8_t *)iocbq; 259282527734SSukumar Swaminathan abort.q_last = (uint8_t *)iocbq; 259382527734SSukumar Swaminathan abort.q_cnt = 1; 259482527734SSukumar Swaminathan } 259582527734SSukumar Swaminathan iocbq->next = NULL; 259682527734SSukumar Swaminathan flag[channelno] = 1; 2597fcf3ce44SJohn Forte 2598fcf3ce44SJohn Forte } else { 259982527734SSukumar Swaminathan prev = iocbq; 2600fcf3ce44SJohn Forte } 2601fcf3ce44SJohn Forte 260282527734SSukumar Swaminathan iocbq = next; 2603fcf3ce44SJohn Forte 260482527734SSukumar Swaminathan } /* while (iocbq) */ 2605fcf3ce44SJohn Forte 2606fcf3ce44SJohn Forte 260782527734SSukumar Swaminathan /* Scan the regular queue */ 260882527734SSukumar Swaminathan prev = NULL; 260982527734SSukumar Swaminathan iocbq = (IOCBQ *)ndlp->nlp_tx[channelno].q_first; 2610fcf3ce44SJohn Forte 261182527734SSukumar Swaminathan while (iocbq) { 261282527734SSukumar Swaminathan next = (IOCBQ *)iocbq->next; 261382527734SSukumar Swaminathan iocb = &iocbq->iocb; 261482527734SSukumar Swaminathan sbp = (emlxs_buf_t *)iocbq->sbp; 261582527734SSukumar Swaminathan 261682527734SSukumar Swaminathan /* Check if this IO is for our lun */ 261782527734SSukumar Swaminathan if (sbp && (sbp->lun == lun)) { 261882527734SSukumar Swaminathan /* Remove iocb from the node's tx queue */ 261982527734SSukumar Swaminathan if (next == 0) { 262082527734SSukumar Swaminathan ndlp->nlp_tx[channelno].q_last = 262182527734SSukumar Swaminathan (uint8_t *)prev; 262282527734SSukumar Swaminathan } 2623291a2b48SSukumar Swaminathan 262482527734SSukumar Swaminathan if (prev == 0) { 262582527734SSukumar Swaminathan ndlp->nlp_tx[channelno].q_first = 262682527734SSukumar Swaminathan (uint8_t *)next; 262782527734SSukumar Swaminathan } else { 262882527734SSukumar Swaminathan prev->next = next; 262982527734SSukumar Swaminathan } 2630fcf3ce44SJohn Forte 263182527734SSukumar Swaminathan iocbq->next = NULL; 263282527734SSukumar Swaminathan ndlp->nlp_tx[channelno].q_cnt--; 2633fcf3ce44SJohn Forte 263482527734SSukumar Swaminathan /* 263582527734SSukumar Swaminathan * Add this iocb to our local abort Q 263682527734SSukumar Swaminathan */ 263782527734SSukumar Swaminathan if (abort.q_first) { 263882527734SSukumar Swaminathan ((IOCBQ *) abort.q_last)->next = iocbq; 263982527734SSukumar Swaminathan abort.q_last = (uint8_t *)iocbq; 264082527734SSukumar Swaminathan abort.q_cnt++; 264182527734SSukumar Swaminathan } else { 264282527734SSukumar Swaminathan abort.q_first = (uint8_t *)iocbq; 264382527734SSukumar Swaminathan abort.q_last = (uint8_t *)iocbq; 264482527734SSukumar Swaminathan abort.q_cnt = 1; 264582527734SSukumar Swaminathan } 264682527734SSukumar Swaminathan iocbq->next = NULL; 2647fcf3ce44SJohn Forte } else { 264882527734SSukumar Swaminathan prev = iocbq; 2649fcf3ce44SJohn Forte } 2650fcf3ce44SJohn Forte 265182527734SSukumar Swaminathan iocbq = next; 2652fcf3ce44SJohn Forte 265382527734SSukumar Swaminathan } /* while (iocbq) */ 265482527734SSukumar Swaminathan } /* for loop */ 2655fcf3ce44SJohn Forte 2656fcf3ce44SJohn Forte /* First cleanup the iocb's while still holding the lock */ 2657fcf3ce44SJohn Forte iocbq = (IOCBQ *)abort.q_first; 2658fcf3ce44SJohn Forte while (iocbq) { 2659fcf3ce44SJohn Forte /* Free the IoTag and the bmp */ 2660fcf3ce44SJohn Forte iocb = &iocbq->iocb; 266182527734SSukumar Swaminathan 266282527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 266382527734SSukumar Swaminathan sbp = iocbq->sbp; 266482527734SSukumar Swaminathan if (sbp) { 2665*a9800bebSGarrett D'Amore emlxs_sli4_free_xri(hba, sbp, sbp->xrip, 1); 266682527734SSukumar Swaminathan } 266782527734SSukumar Swaminathan } else { 266882527734SSukumar Swaminathan sbp = emlxs_unregister_pkt((CHANNEL *)iocbq->channel, 266982527734SSukumar Swaminathan iocb->ULPIOTAG, 0); 267082527734SSukumar Swaminathan } 2671fcf3ce44SJohn Forte 2672fcf3ce44SJohn Forte if (sbp && (sbp != STALE_PACKET)) { 2673fcf3ce44SJohn Forte mutex_enter(&sbp->mtx); 2674fcf3ce44SJohn Forte sbp->pkt_flags |= PACKET_IN_FLUSH; 2675fcf3ce44SJohn Forte /* 2676fcf3ce44SJohn Forte * If the fpkt is already set, then we will leave it 2677291a2b48SSukumar Swaminathan * alone. This ensures that this pkt is only accounted 2678291a2b48SSukumar Swaminathan * for on one fpkt->flush_count 2679fcf3ce44SJohn Forte */ 2680fcf3ce44SJohn Forte if (!sbp->fpkt && fpkt) { 2681fcf3ce44SJohn Forte mutex_enter(&fpkt->mtx); 2682fcf3ce44SJohn Forte sbp->fpkt = fpkt; 2683fcf3ce44SJohn Forte fpkt->flush_count++; 2684fcf3ce44SJohn Forte mutex_exit(&fpkt->mtx); 2685fcf3ce44SJohn Forte } 2686291a2b48SSukumar Swaminathan 2687fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 2688fcf3ce44SJohn Forte } 2689291a2b48SSukumar Swaminathan 2690291a2b48SSukumar Swaminathan iocbq = (IOCBQ *) iocbq->next; 2691fcf3ce44SJohn Forte 2692fcf3ce44SJohn Forte } /* end of while */ 2693fcf3ce44SJohn Forte 269482527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 2695fcf3ce44SJohn Forte 2696fcf3ce44SJohn Forte /* Now abort the iocb's outside the locks */ 2697fcf3ce44SJohn Forte iocbq = (IOCBQ *)abort.q_first; 2698fcf3ce44SJohn Forte while (iocbq) { 2699fcf3ce44SJohn Forte /* Save the next iocbq for now */ 2700fcf3ce44SJohn Forte next = (IOCBQ *)iocbq->next; 2701fcf3ce44SJohn Forte 2702fcf3ce44SJohn Forte /* Unlink this iocbq */ 2703fcf3ce44SJohn Forte iocbq->next = NULL; 2704fcf3ce44SJohn Forte 2705fcf3ce44SJohn Forte /* Get the pkt */ 2706fcf3ce44SJohn Forte sbp = (emlxs_buf_t *)iocbq->sbp; 2707fcf3ce44SJohn Forte 2708fcf3ce44SJohn Forte if (sbp) { 2709fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flush_msg, 2710291a2b48SSukumar Swaminathan "tx: sbp=%p node=%p", sbp, sbp->node); 2711fcf3ce44SJohn Forte 2712fcf3ce44SJohn Forte if (hba->state >= FC_LINK_UP) { 2713fcf3ce44SJohn Forte emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 2714fcf3ce44SJohn Forte IOERR_ABORT_REQUESTED, 1); 2715fcf3ce44SJohn Forte } else { 2716fcf3ce44SJohn Forte emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 2717fcf3ce44SJohn Forte IOERR_LINK_DOWN, 1); 2718fcf3ce44SJohn Forte } 2719fcf3ce44SJohn Forte } 2720291a2b48SSukumar Swaminathan 2721fcf3ce44SJohn Forte /* Free the iocb and its associated buffers */ 2722fcf3ce44SJohn Forte else { 272382527734SSukumar Swaminathan /* Should never happen! */ 2724fcf3ce44SJohn Forte icmd = &iocbq->iocb; 2725fcf3ce44SJohn Forte 272682527734SSukumar Swaminathan /* SLI3 */ 272782527734SSukumar Swaminathan if (icmd->ULPCOMMAND == CMD_QUE_RING_BUF64_CN || 272882527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_QUE_RING_BUF_CN || 272982527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_QUE_RING_LIST64_CN) { 2730fcf3ce44SJohn Forte if ((hba->flag & 2731fcf3ce44SJohn Forte (FC_ONLINE_MODE | FC_ONLINING_MODE)) == 0) { 2732fcf3ce44SJohn Forte /* HBA is detaching or offlining */ 273382527734SSukumar Swaminathan if (icmd->ULPCOMMAND != 2734fcf3ce44SJohn Forte CMD_QUE_RING_LIST64_CN) { 2735*a9800bebSGarrett D'Amore void *tmp; 273682527734SSukumar Swaminathan RING *rp; 273782527734SSukumar Swaminathan int ch; 2738fcf3ce44SJohn Forte 273982527734SSukumar Swaminathan ch = ((CHANNEL *) 274082527734SSukumar Swaminathan iocbq->channel)->channelno; 274182527734SSukumar Swaminathan rp = &hba->sli.sli3.ring[ch]; 2742fcf3ce44SJohn Forte for (i = 0; 274382527734SSukumar Swaminathan i < icmd->ULPBDECOUNT; 2744fcf3ce44SJohn Forte i++) { 2745fcf3ce44SJohn Forte mp = EMLXS_GET_VADDR( 2746fcf3ce44SJohn Forte hba, rp, icmd); 2747fcf3ce44SJohn Forte 2748*a9800bebSGarrett D'Amore tmp = (void *)mp; 2749fcf3ce44SJohn Forte if (mp) { 2750*a9800bebSGarrett D'Amore emlxs_mem_put( 2751291a2b48SSukumar Swaminathan hba, MEM_BUF, tmp); 2752fcf3ce44SJohn Forte } 2753fcf3ce44SJohn Forte } 2754fcf3ce44SJohn Forte } 2755291a2b48SSukumar Swaminathan 2756*a9800bebSGarrett D'Amore emlxs_mem_put(hba, MEM_IOCB, 2757*a9800bebSGarrett D'Amore (void *)iocbq); 2758fcf3ce44SJohn Forte } else { 2759fcf3ce44SJohn Forte /* repost the unsolicited buffer */ 276082527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, 276182527734SSukumar Swaminathan (CHANNEL *)iocbq->channel, iocbq); 2762fcf3ce44SJohn Forte } 276382527734SSukumar Swaminathan } else if (icmd->ULPCOMMAND == CMD_CLOSE_XRI_CN || 276482527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_CLOSE_XRI_CX) { 276582527734SSukumar Swaminathan /* 276682527734SSukumar Swaminathan * Resend the abort iocbq if any 276782527734SSukumar Swaminathan */ 276882527734SSukumar Swaminathan emlxs_tx_put(iocbq, 1); 2769fcf3ce44SJohn Forte } 2770fcf3ce44SJohn Forte } 2771fcf3ce44SJohn Forte 2772fcf3ce44SJohn Forte iocbq = next; 2773fcf3ce44SJohn Forte 2774fcf3ce44SJohn Forte } /* end of while */ 2775fcf3ce44SJohn Forte 277682527734SSukumar Swaminathan /* Now trigger channel service */ 277782527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 277882527734SSukumar Swaminathan if (!flag[channelno]) { 277982527734SSukumar Swaminathan continue; 278082527734SSukumar Swaminathan } 278182527734SSukumar Swaminathan 278282527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, &hba->chan[channelno], 0); 278382527734SSukumar Swaminathan } 2784fcf3ce44SJohn Forte 2785fcf3ce44SJohn Forte return (abort.q_cnt); 2786fcf3ce44SJohn Forte 278782527734SSukumar Swaminathan } /* emlxs_tx_lun_flush() */ 2788fcf3ce44SJohn Forte 2789fcf3ce44SJohn Forte 2790fcf3ce44SJohn Forte extern void 2791fcf3ce44SJohn Forte emlxs_tx_put(IOCBQ *iocbq, uint32_t lock) 2792fcf3ce44SJohn Forte { 2793fcf3ce44SJohn Forte emlxs_hba_t *hba; 2794fcf3ce44SJohn Forte emlxs_port_t *port; 279582527734SSukumar Swaminathan uint32_t channelno; 2796fcf3ce44SJohn Forte NODELIST *nlp; 279782527734SSukumar Swaminathan CHANNEL *cp; 2798fcf3ce44SJohn Forte emlxs_buf_t *sbp; 2799fcf3ce44SJohn Forte 2800fcf3ce44SJohn Forte port = (emlxs_port_t *)iocbq->port; 2801fcf3ce44SJohn Forte hba = HBA; 280282527734SSukumar Swaminathan cp = (CHANNEL *)iocbq->channel; 2803fcf3ce44SJohn Forte nlp = (NODELIST *)iocbq->node; 280482527734SSukumar Swaminathan channelno = cp->channelno; 2805fcf3ce44SJohn Forte sbp = (emlxs_buf_t *)iocbq->sbp; 2806fcf3ce44SJohn Forte 280782527734SSukumar Swaminathan /* under what cases, nlp is NULL */ 2808fcf3ce44SJohn Forte if (nlp == NULL) { 2809fcf3ce44SJohn Forte /* Set node to base node by default */ 2810fcf3ce44SJohn Forte nlp = &port->node_base; 2811fcf3ce44SJohn Forte 2812fcf3ce44SJohn Forte iocbq->node = (void *)nlp; 2813fcf3ce44SJohn Forte 2814fcf3ce44SJohn Forte if (sbp) { 2815fcf3ce44SJohn Forte sbp->node = (void *)nlp; 2816fcf3ce44SJohn Forte } 2817fcf3ce44SJohn Forte } 2818291a2b48SSukumar Swaminathan 2819fcf3ce44SJohn Forte if (lock) { 282082527734SSukumar Swaminathan mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 2821fcf3ce44SJohn Forte } 2822291a2b48SSukumar Swaminathan 2823fcf3ce44SJohn Forte if (!nlp->nlp_active || (sbp && (sbp->pkt_flags & PACKET_IN_ABORT))) { 2824fcf3ce44SJohn Forte if (sbp) { 2825fcf3ce44SJohn Forte mutex_enter(&sbp->mtx); 2826fcf3ce44SJohn Forte sbp->pkt_flags |= PACKET_IN_FLUSH; 2827fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 2828fcf3ce44SJohn Forte 282982527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 2830*a9800bebSGarrett D'Amore emlxs_sli4_free_xri(hba, sbp, sbp->xrip, 1); 283182527734SSukumar Swaminathan } else { 283282527734SSukumar Swaminathan (void) emlxs_unregister_pkt(cp, sbp->iotag, 0); 283382527734SSukumar Swaminathan } 2834fcf3ce44SJohn Forte 2835fcf3ce44SJohn Forte if (lock) { 283682527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 2837fcf3ce44SJohn Forte } 2838291a2b48SSukumar Swaminathan 2839fcf3ce44SJohn Forte if (hba->state >= FC_LINK_UP) { 2840fcf3ce44SJohn Forte emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 2841fcf3ce44SJohn Forte IOERR_ABORT_REQUESTED, 1); 2842fcf3ce44SJohn Forte } else { 2843fcf3ce44SJohn Forte emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 2844fcf3ce44SJohn Forte IOERR_LINK_DOWN, 1); 2845fcf3ce44SJohn Forte } 2846fcf3ce44SJohn Forte return; 2847fcf3ce44SJohn Forte } else { 2848fcf3ce44SJohn Forte if (lock) { 284982527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 2850fcf3ce44SJohn Forte } 2851291a2b48SSukumar Swaminathan 2852*a9800bebSGarrett D'Amore emlxs_mem_put(hba, MEM_IOCB, (void *)iocbq); 2853fcf3ce44SJohn Forte } 2854fcf3ce44SJohn Forte 2855fcf3ce44SJohn Forte return; 2856fcf3ce44SJohn Forte } 2857291a2b48SSukumar Swaminathan 2858fcf3ce44SJohn Forte if (sbp) { 2859fcf3ce44SJohn Forte 2860fcf3ce44SJohn Forte mutex_enter(&sbp->mtx); 2861fcf3ce44SJohn Forte 2862291a2b48SSukumar Swaminathan if (sbp->pkt_flags & 2863291a2b48SSukumar Swaminathan (PACKET_IN_COMPLETION | PACKET_IN_CHIPQ | PACKET_IN_TXQ)) { 2864fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 2865fcf3ce44SJohn Forte if (lock) { 286682527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 2867fcf3ce44SJohn Forte } 2868fcf3ce44SJohn Forte return; 2869fcf3ce44SJohn Forte } 2870291a2b48SSukumar Swaminathan 2871fcf3ce44SJohn Forte sbp->pkt_flags |= PACKET_IN_TXQ; 287282527734SSukumar Swaminathan hba->channel_tx_count++; 2873fcf3ce44SJohn Forte 2874fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 2875fcf3ce44SJohn Forte } 2876291a2b48SSukumar Swaminathan 2877291a2b48SSukumar Swaminathan 2878fcf3ce44SJohn Forte /* Check iocbq priority */ 287982527734SSukumar Swaminathan /* Some IOCB has the high priority like reset/close xri etc */ 2880fcf3ce44SJohn Forte if (iocbq->flag & IOCB_PRIORITY) { 2881fcf3ce44SJohn Forte /* Add the iocb to the bottom of the node's ptx queue */ 288282527734SSukumar Swaminathan if (nlp->nlp_ptx[channelno].q_first) { 288382527734SSukumar Swaminathan ((IOCBQ *)nlp->nlp_ptx[channelno].q_last)->next = iocbq; 288482527734SSukumar Swaminathan nlp->nlp_ptx[channelno].q_last = (uint8_t *)iocbq; 288582527734SSukumar Swaminathan nlp->nlp_ptx[channelno].q_cnt++; 2886fcf3ce44SJohn Forte } else { 288782527734SSukumar Swaminathan nlp->nlp_ptx[channelno].q_first = (uint8_t *)iocbq; 288882527734SSukumar Swaminathan nlp->nlp_ptx[channelno].q_last = (uint8_t *)iocbq; 288982527734SSukumar Swaminathan nlp->nlp_ptx[channelno].q_cnt = 1; 2890fcf3ce44SJohn Forte } 2891fcf3ce44SJohn Forte 2892fcf3ce44SJohn Forte iocbq->next = NULL; 2893fcf3ce44SJohn Forte } else { /* Normal priority */ 2894fcf3ce44SJohn Forte 2895291a2b48SSukumar Swaminathan 2896fcf3ce44SJohn Forte /* Add the iocb to the bottom of the node's tx queue */ 289782527734SSukumar Swaminathan if (nlp->nlp_tx[channelno].q_first) { 289882527734SSukumar Swaminathan ((IOCBQ *)nlp->nlp_tx[channelno].q_last)->next = iocbq; 289982527734SSukumar Swaminathan nlp->nlp_tx[channelno].q_last = (uint8_t *)iocbq; 290082527734SSukumar Swaminathan nlp->nlp_tx[channelno].q_cnt++; 2901fcf3ce44SJohn Forte } else { 290282527734SSukumar Swaminathan nlp->nlp_tx[channelno].q_first = (uint8_t *)iocbq; 290382527734SSukumar Swaminathan nlp->nlp_tx[channelno].q_last = (uint8_t *)iocbq; 290482527734SSukumar Swaminathan nlp->nlp_tx[channelno].q_cnt = 1; 2905fcf3ce44SJohn Forte } 2906fcf3ce44SJohn Forte 2907fcf3ce44SJohn Forte iocbq->next = NULL; 2908fcf3ce44SJohn Forte } 2909fcf3ce44SJohn Forte 2910fcf3ce44SJohn Forte 2911fcf3ce44SJohn Forte /* 291282527734SSukumar Swaminathan * Check if the node is not already on channel queue and 2913291a2b48SSukumar Swaminathan * (is not closed or is a priority request) 2914fcf3ce44SJohn Forte */ 291582527734SSukumar Swaminathan if (!nlp->nlp_next[channelno] && 291682527734SSukumar Swaminathan (!(nlp->nlp_flag[channelno] & NLP_CLOSED) || 2917fcf3ce44SJohn Forte (iocbq->flag & IOCB_PRIORITY))) { 291882527734SSukumar Swaminathan /* If so, then add it to the channel queue */ 291982527734SSukumar Swaminathan if (cp->nodeq.q_first) { 292082527734SSukumar Swaminathan ((NODELIST *)cp->nodeq.q_last)->nlp_next[channelno] = 2921fcf3ce44SJohn Forte (uint8_t *)nlp; 292282527734SSukumar Swaminathan nlp->nlp_next[channelno] = cp->nodeq.q_first; 2923fcf3ce44SJohn Forte 2924fcf3ce44SJohn Forte /* 2925291a2b48SSukumar Swaminathan * If this is not the base node then add it 2926291a2b48SSukumar Swaminathan * to the tail 2927fcf3ce44SJohn Forte */ 2928fcf3ce44SJohn Forte if (!nlp->nlp_base) { 292982527734SSukumar Swaminathan cp->nodeq.q_last = (uint8_t *)nlp; 2930fcf3ce44SJohn Forte } else { /* Otherwise, add it to the head */ 2931291a2b48SSukumar Swaminathan 2932fcf3ce44SJohn Forte /* The command node always gets priority */ 293382527734SSukumar Swaminathan cp->nodeq.q_first = (uint8_t *)nlp; 2934fcf3ce44SJohn Forte } 2935fcf3ce44SJohn Forte 293682527734SSukumar Swaminathan cp->nodeq.q_cnt++; 2937fcf3ce44SJohn Forte } else { 293882527734SSukumar Swaminathan cp->nodeq.q_first = (uint8_t *)nlp; 293982527734SSukumar Swaminathan cp->nodeq.q_last = (uint8_t *)nlp; 294082527734SSukumar Swaminathan nlp->nlp_next[channelno] = nlp; 294182527734SSukumar Swaminathan cp->nodeq.q_cnt = 1; 2942fcf3ce44SJohn Forte } 2943fcf3ce44SJohn Forte } 2944291a2b48SSukumar Swaminathan 294582527734SSukumar Swaminathan HBASTATS.IocbTxPut[channelno]++; 2946fcf3ce44SJohn Forte 294782527734SSukumar Swaminathan /* Adjust the channel timeout timer */ 294882527734SSukumar Swaminathan cp->timeout = hba->timer_tics + 5; 2949fcf3ce44SJohn Forte 2950fcf3ce44SJohn Forte if (lock) { 295182527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 2952fcf3ce44SJohn Forte } 2953291a2b48SSukumar Swaminathan 2954fcf3ce44SJohn Forte return; 2955fcf3ce44SJohn Forte 295682527734SSukumar Swaminathan } /* emlxs_tx_put() */ 2957fcf3ce44SJohn Forte 2958fcf3ce44SJohn Forte 2959fcf3ce44SJohn Forte extern IOCBQ * 296082527734SSukumar Swaminathan emlxs_tx_get(CHANNEL *cp, uint32_t lock) 2961fcf3ce44SJohn Forte { 2962fcf3ce44SJohn Forte emlxs_hba_t *hba; 296382527734SSukumar Swaminathan uint32_t channelno; 2964fcf3ce44SJohn Forte IOCBQ *iocbq; 2965fcf3ce44SJohn Forte NODELIST *nlp; 2966fcf3ce44SJohn Forte emlxs_buf_t *sbp; 2967fcf3ce44SJohn Forte 296882527734SSukumar Swaminathan hba = cp->hba; 296982527734SSukumar Swaminathan channelno = cp->channelno; 2970fcf3ce44SJohn Forte 2971fcf3ce44SJohn Forte if (lock) { 297282527734SSukumar Swaminathan mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 2973fcf3ce44SJohn Forte } 2974291a2b48SSukumar Swaminathan 2975fcf3ce44SJohn Forte begin: 2976fcf3ce44SJohn Forte 2977fcf3ce44SJohn Forte iocbq = NULL; 2978fcf3ce44SJohn Forte 2979fcf3ce44SJohn Forte /* Check if a node needs servicing */ 298082527734SSukumar Swaminathan if (cp->nodeq.q_first) { 298182527734SSukumar Swaminathan nlp = (NODELIST *)cp->nodeq.q_first; 2982fcf3ce44SJohn Forte 2983fcf3ce44SJohn Forte /* Get next iocb from node's priority queue */ 2984fcf3ce44SJohn Forte 298582527734SSukumar Swaminathan if (nlp->nlp_ptx[channelno].q_first) { 298682527734SSukumar Swaminathan iocbq = (IOCBQ *)nlp->nlp_ptx[channelno].q_first; 2987fcf3ce44SJohn Forte 2988fcf3ce44SJohn Forte /* Check if this is last entry */ 298982527734SSukumar Swaminathan if (nlp->nlp_ptx[channelno].q_last == (void *)iocbq) { 299082527734SSukumar Swaminathan nlp->nlp_ptx[channelno].q_first = NULL; 299182527734SSukumar Swaminathan nlp->nlp_ptx[channelno].q_last = NULL; 299282527734SSukumar Swaminathan nlp->nlp_ptx[channelno].q_cnt = 0; 2993fcf3ce44SJohn Forte } else { 2994fcf3ce44SJohn Forte /* Remove iocb from head */ 299582527734SSukumar Swaminathan nlp->nlp_ptx[channelno].q_first = 2996fcf3ce44SJohn Forte (void *)iocbq->next; 299782527734SSukumar Swaminathan nlp->nlp_ptx[channelno].q_cnt--; 2998fcf3ce44SJohn Forte } 2999fcf3ce44SJohn Forte 3000fcf3ce44SJohn Forte iocbq->next = NULL; 3001fcf3ce44SJohn Forte } 3002291a2b48SSukumar Swaminathan 3003fcf3ce44SJohn Forte /* Get next iocb from node tx queue if node not closed */ 300482527734SSukumar Swaminathan else if (nlp->nlp_tx[channelno].q_first && 300582527734SSukumar Swaminathan !(nlp->nlp_flag[channelno] & NLP_CLOSED)) { 300682527734SSukumar Swaminathan iocbq = (IOCBQ *)nlp->nlp_tx[channelno].q_first; 3007fcf3ce44SJohn Forte 3008fcf3ce44SJohn Forte /* Check if this is last entry */ 300982527734SSukumar Swaminathan if (nlp->nlp_tx[channelno].q_last == (void *)iocbq) { 301082527734SSukumar Swaminathan nlp->nlp_tx[channelno].q_first = NULL; 301182527734SSukumar Swaminathan nlp->nlp_tx[channelno].q_last = NULL; 301282527734SSukumar Swaminathan nlp->nlp_tx[channelno].q_cnt = 0; 3013fcf3ce44SJohn Forte } else { 3014fcf3ce44SJohn Forte /* Remove iocb from head */ 301582527734SSukumar Swaminathan nlp->nlp_tx[channelno].q_first = 3016fcf3ce44SJohn Forte (void *)iocbq->next; 301782527734SSukumar Swaminathan nlp->nlp_tx[channelno].q_cnt--; 3018fcf3ce44SJohn Forte } 3019fcf3ce44SJohn Forte 3020fcf3ce44SJohn Forte iocbq->next = NULL; 3021fcf3ce44SJohn Forte } 3022291a2b48SSukumar Swaminathan 3023fcf3ce44SJohn Forte /* Now deal with node itself */ 3024fcf3ce44SJohn Forte 3025fcf3ce44SJohn Forte /* Check if node still needs servicing */ 302682527734SSukumar Swaminathan if ((nlp->nlp_ptx[channelno].q_first) || 302782527734SSukumar Swaminathan (nlp->nlp_tx[channelno].q_first && 302882527734SSukumar Swaminathan !(nlp->nlp_flag[channelno] & NLP_CLOSED))) { 3029fcf3ce44SJohn Forte 3030fcf3ce44SJohn Forte /* 3031fcf3ce44SJohn Forte * If this is the base node, then don't shift the 3032291a2b48SSukumar Swaminathan * pointers. We want to drain the base node before 3033291a2b48SSukumar Swaminathan * moving on 3034fcf3ce44SJohn Forte */ 3035fcf3ce44SJohn Forte if (!nlp->nlp_base) { 3036fcf3ce44SJohn Forte /* 303782527734SSukumar Swaminathan * Just shift channel queue pointers to next 3038fcf3ce44SJohn Forte * node 3039fcf3ce44SJohn Forte */ 304082527734SSukumar Swaminathan cp->nodeq.q_last = (void *)nlp; 304182527734SSukumar Swaminathan cp->nodeq.q_first = nlp->nlp_next[channelno]; 3042fcf3ce44SJohn Forte } 3043fcf3ce44SJohn Forte } else { 304482527734SSukumar Swaminathan /* Remove node from channel queue */ 3045fcf3ce44SJohn Forte 3046fcf3ce44SJohn Forte /* If this is the last node on list */ 304782527734SSukumar Swaminathan if (cp->nodeq.q_last == (void *)nlp) { 304882527734SSukumar Swaminathan cp->nodeq.q_last = NULL; 304982527734SSukumar Swaminathan cp->nodeq.q_first = NULL; 305082527734SSukumar Swaminathan cp->nodeq.q_cnt = 0; 3051fcf3ce44SJohn Forte } else { 3052fcf3ce44SJohn Forte /* Remove node from head */ 305382527734SSukumar Swaminathan cp->nodeq.q_first = nlp->nlp_next[channelno]; 305482527734SSukumar Swaminathan ((NODELIST *)cp->nodeq.q_last)-> 305582527734SSukumar Swaminathan nlp_next[channelno] = cp->nodeq.q_first; 305682527734SSukumar Swaminathan cp->nodeq.q_cnt--; 3057fcf3ce44SJohn Forte 3058fcf3ce44SJohn Forte } 3059fcf3ce44SJohn Forte 3060fcf3ce44SJohn Forte /* Clear node */ 306182527734SSukumar Swaminathan nlp->nlp_next[channelno] = NULL; 3062fcf3ce44SJohn Forte } 3063fcf3ce44SJohn Forte 3064fcf3ce44SJohn Forte /* 3065291a2b48SSukumar Swaminathan * If no iocbq was found on this node, then it will have 3066291a2b48SSukumar Swaminathan * been removed. So try again. 3067fcf3ce44SJohn Forte */ 3068fcf3ce44SJohn Forte if (!iocbq) { 3069fcf3ce44SJohn Forte goto begin; 3070fcf3ce44SJohn Forte } 3071291a2b48SSukumar Swaminathan 3072fcf3ce44SJohn Forte sbp = (emlxs_buf_t *)iocbq->sbp; 3073fcf3ce44SJohn Forte 3074fcf3ce44SJohn Forte if (sbp) { 3075fcf3ce44SJohn Forte /* 3076291a2b48SSukumar Swaminathan * Check flags before we enter mutex in case this 3077291a2b48SSukumar Swaminathan * has been flushed and destroyed 3078fcf3ce44SJohn Forte */ 3079fcf3ce44SJohn Forte if ((sbp->pkt_flags & 3080fcf3ce44SJohn Forte (PACKET_IN_COMPLETION | PACKET_IN_CHIPQ)) || 3081fcf3ce44SJohn Forte !(sbp->pkt_flags & PACKET_IN_TXQ)) { 3082fcf3ce44SJohn Forte goto begin; 3083fcf3ce44SJohn Forte } 3084291a2b48SSukumar Swaminathan 3085fcf3ce44SJohn Forte mutex_enter(&sbp->mtx); 3086fcf3ce44SJohn Forte 3087fcf3ce44SJohn Forte if ((sbp->pkt_flags & 3088fcf3ce44SJohn Forte (PACKET_IN_COMPLETION | PACKET_IN_CHIPQ)) || 3089fcf3ce44SJohn Forte !(sbp->pkt_flags & PACKET_IN_TXQ)) { 3090fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 3091fcf3ce44SJohn Forte goto begin; 3092fcf3ce44SJohn Forte } 3093291a2b48SSukumar Swaminathan 3094fcf3ce44SJohn Forte sbp->pkt_flags &= ~PACKET_IN_TXQ; 309582527734SSukumar Swaminathan hba->channel_tx_count--; 3096fcf3ce44SJohn Forte 3097fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 3098fcf3ce44SJohn Forte } 3099fcf3ce44SJohn Forte } 3100291a2b48SSukumar Swaminathan 3101fcf3ce44SJohn Forte if (iocbq) { 310282527734SSukumar Swaminathan HBASTATS.IocbTxGet[channelno]++; 3103fcf3ce44SJohn Forte } 3104291a2b48SSukumar Swaminathan 3105fcf3ce44SJohn Forte /* Adjust the ring timeout timer */ 310682527734SSukumar Swaminathan cp->timeout = (cp->nodeq.q_first) ? (hba->timer_tics + 5) : 0; 3107fcf3ce44SJohn Forte 3108fcf3ce44SJohn Forte if (lock) { 310982527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 3110fcf3ce44SJohn Forte } 3111291a2b48SSukumar Swaminathan 3112fcf3ce44SJohn Forte return (iocbq); 3113fcf3ce44SJohn Forte 311482527734SSukumar Swaminathan } /* emlxs_tx_get() */ 311582527734SSukumar Swaminathan 3116fcf3ce44SJohn Forte 311782527734SSukumar Swaminathan /* 311882527734SSukumar Swaminathan * Remove all cmd from from_rp's txq to to_rp's txq for ndlp. 311982527734SSukumar Swaminathan * The old IoTag has to be released, the new one has to be 312082527734SSukumar Swaminathan * allocated. Others no change 312182527734SSukumar Swaminathan * TX_CHANNEL lock is held 312282527734SSukumar Swaminathan */ 312382527734SSukumar Swaminathan extern void 312482527734SSukumar Swaminathan emlxs_tx_move(NODELIST *ndlp, CHANNEL *from_chan, CHANNEL *to_chan, 312582527734SSukumar Swaminathan uint32_t cmd, emlxs_buf_t *fpkt, uint32_t lock) 312682527734SSukumar Swaminathan { 312782527734SSukumar Swaminathan emlxs_hba_t *hba; 312882527734SSukumar Swaminathan emlxs_port_t *port; 312982527734SSukumar Swaminathan uint32_t fchanno, tchanno, i; 313082527734SSukumar Swaminathan 313182527734SSukumar Swaminathan IOCBQ *iocbq; 313282527734SSukumar Swaminathan IOCBQ *prev; 313382527734SSukumar Swaminathan IOCBQ *next; 313482527734SSukumar Swaminathan IOCB *iocb, *icmd; 313582527734SSukumar Swaminathan Q tbm; /* To Be Moved Q */ 313682527734SSukumar Swaminathan MATCHMAP *mp; 313782527734SSukumar Swaminathan 313882527734SSukumar Swaminathan NODELIST *nlp = ndlp; 313982527734SSukumar Swaminathan emlxs_buf_t *sbp; 314082527734SSukumar Swaminathan 314182527734SSukumar Swaminathan NODELIST *n_prev = NULL; 314282527734SSukumar Swaminathan NODELIST *n_next = NULL; 314382527734SSukumar Swaminathan uint16_t count = 0; 314482527734SSukumar Swaminathan 314582527734SSukumar Swaminathan hba = from_chan->hba; 314682527734SSukumar Swaminathan port = &PPORT; 314782527734SSukumar Swaminathan cmd = cmd; /* To pass lint */ 314882527734SSukumar Swaminathan 314982527734SSukumar Swaminathan fchanno = from_chan->channelno; 315082527734SSukumar Swaminathan tchanno = to_chan->channelno; 315182527734SSukumar Swaminathan 315282527734SSukumar Swaminathan if (lock) { 315382527734SSukumar Swaminathan mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 315482527734SSukumar Swaminathan } 315582527734SSukumar Swaminathan 315682527734SSukumar Swaminathan bzero((void *)&tbm, sizeof (Q)); 315782527734SSukumar Swaminathan 315882527734SSukumar Swaminathan /* Scan the ndlp's fchanno txq to get the iocb of fcp cmd */ 315982527734SSukumar Swaminathan prev = NULL; 316082527734SSukumar Swaminathan iocbq = (IOCBQ *)nlp->nlp_tx[fchanno].q_first; 316182527734SSukumar Swaminathan 316282527734SSukumar Swaminathan while (iocbq) { 316382527734SSukumar Swaminathan next = (IOCBQ *)iocbq->next; 316482527734SSukumar Swaminathan /* Check if this iocb is fcp cmd */ 316582527734SSukumar Swaminathan iocb = &iocbq->iocb; 316682527734SSukumar Swaminathan 316782527734SSukumar Swaminathan switch (iocb->ULPCOMMAND) { 316882527734SSukumar Swaminathan /* FCP commands */ 316982527734SSukumar Swaminathan case CMD_FCP_ICMND_CR: 317082527734SSukumar Swaminathan case CMD_FCP_ICMND_CX: 317182527734SSukumar Swaminathan case CMD_FCP_IREAD_CR: 317282527734SSukumar Swaminathan case CMD_FCP_IREAD_CX: 317382527734SSukumar Swaminathan case CMD_FCP_IWRITE_CR: 317482527734SSukumar Swaminathan case CMD_FCP_IWRITE_CX: 317582527734SSukumar Swaminathan case CMD_FCP_ICMND64_CR: 317682527734SSukumar Swaminathan case CMD_FCP_ICMND64_CX: 317782527734SSukumar Swaminathan case CMD_FCP_IREAD64_CR: 317882527734SSukumar Swaminathan case CMD_FCP_IREAD64_CX: 317982527734SSukumar Swaminathan case CMD_FCP_IWRITE64_CR: 318082527734SSukumar Swaminathan case CMD_FCP_IWRITE64_CX: 318182527734SSukumar Swaminathan /* We found a fcp cmd */ 318282527734SSukumar Swaminathan break; 318382527734SSukumar Swaminathan default: 318482527734SSukumar Swaminathan /* this is not fcp cmd continue */ 318582527734SSukumar Swaminathan prev = iocbq; 318682527734SSukumar Swaminathan iocbq = next; 318782527734SSukumar Swaminathan continue; 318882527734SSukumar Swaminathan } 318982527734SSukumar Swaminathan 319082527734SSukumar Swaminathan /* found a fcp cmd iocb in fchanno txq, now deque it */ 319182527734SSukumar Swaminathan if (next == NULL) { 319282527734SSukumar Swaminathan /* This is the last iocbq */ 319382527734SSukumar Swaminathan nlp->nlp_tx[fchanno].q_last = 319482527734SSukumar Swaminathan (uint8_t *)prev; 319582527734SSukumar Swaminathan } 319682527734SSukumar Swaminathan 319782527734SSukumar Swaminathan if (prev == NULL) { 319882527734SSukumar Swaminathan /* This is the first one then remove it from head */ 319982527734SSukumar Swaminathan nlp->nlp_tx[fchanno].q_first = 320082527734SSukumar Swaminathan (uint8_t *)next; 320182527734SSukumar Swaminathan } else { 320282527734SSukumar Swaminathan prev->next = next; 320382527734SSukumar Swaminathan } 320482527734SSukumar Swaminathan 320582527734SSukumar Swaminathan iocbq->next = NULL; 320682527734SSukumar Swaminathan nlp->nlp_tx[fchanno].q_cnt--; 320782527734SSukumar Swaminathan 320882527734SSukumar Swaminathan /* Add this iocb to our local toberemovedq */ 320982527734SSukumar Swaminathan /* This way we donot hold the TX_CHANNEL lock too long */ 321082527734SSukumar Swaminathan 321182527734SSukumar Swaminathan if (tbm.q_first) { 321282527734SSukumar Swaminathan ((IOCBQ *)tbm.q_last)->next = iocbq; 321382527734SSukumar Swaminathan tbm.q_last = (uint8_t *)iocbq; 321482527734SSukumar Swaminathan tbm.q_cnt++; 321582527734SSukumar Swaminathan } else { 321682527734SSukumar Swaminathan tbm.q_first = (uint8_t *)iocbq; 321782527734SSukumar Swaminathan tbm.q_last = (uint8_t *)iocbq; 321882527734SSukumar Swaminathan tbm.q_cnt = 1; 321982527734SSukumar Swaminathan } 322082527734SSukumar Swaminathan 322182527734SSukumar Swaminathan iocbq = next; 322282527734SSukumar Swaminathan 322382527734SSukumar Swaminathan } /* While (iocbq) */ 322482527734SSukumar Swaminathan 322582527734SSukumar Swaminathan if ((tchanno == hba->channel_fcp) && (tbm.q_cnt != 0)) { 322682527734SSukumar Swaminathan 322782527734SSukumar Swaminathan /* from_chan->nodeq.q_first must be non NULL */ 322882527734SSukumar Swaminathan if (from_chan->nodeq.q_first) { 322982527734SSukumar Swaminathan 323082527734SSukumar Swaminathan /* nodeq is not empty, now deal with the node itself */ 323182527734SSukumar Swaminathan if ((nlp->nlp_tx[fchanno].q_first)) { 323282527734SSukumar Swaminathan 323382527734SSukumar Swaminathan if (!nlp->nlp_base) { 323482527734SSukumar Swaminathan from_chan->nodeq.q_last = 323582527734SSukumar Swaminathan (void *)nlp; 323682527734SSukumar Swaminathan from_chan->nodeq.q_first = 323782527734SSukumar Swaminathan nlp->nlp_next[fchanno]; 323882527734SSukumar Swaminathan } 323982527734SSukumar Swaminathan 324082527734SSukumar Swaminathan } else { 324182527734SSukumar Swaminathan n_prev = (NODELIST *)from_chan->nodeq.q_first; 324282527734SSukumar Swaminathan count = from_chan->nodeq.q_cnt; 324382527734SSukumar Swaminathan 324482527734SSukumar Swaminathan if (n_prev == nlp) { 324582527734SSukumar Swaminathan 324682527734SSukumar Swaminathan /* If this is the only node on list */ 324782527734SSukumar Swaminathan if (from_chan->nodeq.q_last == 324882527734SSukumar Swaminathan (void *)nlp) { 324982527734SSukumar Swaminathan from_chan->nodeq.q_last = 325082527734SSukumar Swaminathan NULL; 325182527734SSukumar Swaminathan from_chan->nodeq.q_first = 325282527734SSukumar Swaminathan NULL; 325382527734SSukumar Swaminathan from_chan->nodeq.q_cnt = 0; 325482527734SSukumar Swaminathan } else { 325582527734SSukumar Swaminathan from_chan->nodeq.q_first = 325682527734SSukumar Swaminathan nlp->nlp_next[fchanno]; 325782527734SSukumar Swaminathan ((NODELIST *)from_chan-> 325882527734SSukumar Swaminathan nodeq.q_last)-> 325982527734SSukumar Swaminathan nlp_next[fchanno] = 326082527734SSukumar Swaminathan from_chan->nodeq.q_first; 326182527734SSukumar Swaminathan from_chan->nodeq.q_cnt--; 326282527734SSukumar Swaminathan } 326382527734SSukumar Swaminathan /* Clear node */ 326482527734SSukumar Swaminathan nlp->nlp_next[fchanno] = NULL; 326582527734SSukumar Swaminathan } else { 326682527734SSukumar Swaminathan count--; 326782527734SSukumar Swaminathan do { 326882527734SSukumar Swaminathan n_next = 326982527734SSukumar Swaminathan n_prev->nlp_next[fchanno]; 327082527734SSukumar Swaminathan if (n_next == nlp) { 327182527734SSukumar Swaminathan break; 327282527734SSukumar Swaminathan } 327382527734SSukumar Swaminathan n_prev = n_next; 327482527734SSukumar Swaminathan } while (count--); 327582527734SSukumar Swaminathan 327682527734SSukumar Swaminathan if (count != 0) { 327782527734SSukumar Swaminathan 327882527734SSukumar Swaminathan if (n_next == 327982527734SSukumar Swaminathan (NODELIST *)from_chan-> 328082527734SSukumar Swaminathan nodeq.q_last) { 328182527734SSukumar Swaminathan n_prev-> 328282527734SSukumar Swaminathan nlp_next[fchanno] 328382527734SSukumar Swaminathan = 328482527734SSukumar Swaminathan ((NODELIST *) 328582527734SSukumar Swaminathan from_chan-> 328682527734SSukumar Swaminathan nodeq.q_last)-> 328782527734SSukumar Swaminathan nlp_next 328882527734SSukumar Swaminathan [fchanno]; 328982527734SSukumar Swaminathan from_chan->nodeq.q_last 329082527734SSukumar Swaminathan = (uint8_t *)n_prev; 329182527734SSukumar Swaminathan } else { 329282527734SSukumar Swaminathan 329382527734SSukumar Swaminathan n_prev-> 329482527734SSukumar Swaminathan nlp_next[fchanno] 329582527734SSukumar Swaminathan = 329682527734SSukumar Swaminathan n_next-> nlp_next 329782527734SSukumar Swaminathan [fchanno]; 329882527734SSukumar Swaminathan } 329982527734SSukumar Swaminathan from_chan->nodeq.q_cnt--; 330082527734SSukumar Swaminathan /* Clear node */ 330182527734SSukumar Swaminathan nlp->nlp_next[fchanno] = 330282527734SSukumar Swaminathan NULL; 330382527734SSukumar Swaminathan } 330482527734SSukumar Swaminathan } 330582527734SSukumar Swaminathan } 330682527734SSukumar Swaminathan } 330782527734SSukumar Swaminathan } 330882527734SSukumar Swaminathan 330982527734SSukumar Swaminathan /* Now cleanup the iocb's */ 331082527734SSukumar Swaminathan prev = NULL; 331182527734SSukumar Swaminathan iocbq = (IOCBQ *)tbm.q_first; 331282527734SSukumar Swaminathan 331382527734SSukumar Swaminathan while (iocbq) { 331482527734SSukumar Swaminathan 331582527734SSukumar Swaminathan next = (IOCBQ *)iocbq->next; 331682527734SSukumar Swaminathan 331782527734SSukumar Swaminathan /* Free the IoTag and the bmp */ 331882527734SSukumar Swaminathan iocb = &iocbq->iocb; 331982527734SSukumar Swaminathan 332082527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 332182527734SSukumar Swaminathan sbp = iocbq->sbp; 332282527734SSukumar Swaminathan if (sbp) { 3323*a9800bebSGarrett D'Amore emlxs_sli4_free_xri(hba, sbp, sbp->xrip, 1); 332482527734SSukumar Swaminathan } 332582527734SSukumar Swaminathan } else { 332682527734SSukumar Swaminathan sbp = emlxs_unregister_pkt((CHANNEL *)iocbq->channel, 332782527734SSukumar Swaminathan iocb->ULPIOTAG, 0); 332882527734SSukumar Swaminathan } 332982527734SSukumar Swaminathan 333082527734SSukumar Swaminathan if (sbp && (sbp != STALE_PACKET)) { 333182527734SSukumar Swaminathan mutex_enter(&sbp->mtx); 333282527734SSukumar Swaminathan sbp->pkt_flags |= PACKET_IN_FLUSH; 333382527734SSukumar Swaminathan 333482527734SSukumar Swaminathan /* 333582527734SSukumar Swaminathan * If the fpkt is already set, then we will leave it 333682527734SSukumar Swaminathan * alone. This ensures that this pkt is only accounted 333782527734SSukumar Swaminathan * for on one fpkt->flush_count 333882527734SSukumar Swaminathan */ 333982527734SSukumar Swaminathan if (!sbp->fpkt && fpkt) { 334082527734SSukumar Swaminathan mutex_enter(&fpkt->mtx); 334182527734SSukumar Swaminathan sbp->fpkt = fpkt; 334282527734SSukumar Swaminathan fpkt->flush_count++; 334382527734SSukumar Swaminathan mutex_exit(&fpkt->mtx); 334482527734SSukumar Swaminathan } 334582527734SSukumar Swaminathan mutex_exit(&sbp->mtx); 334682527734SSukumar Swaminathan } 334782527734SSukumar Swaminathan iocbq = next; 334882527734SSukumar Swaminathan 334982527734SSukumar Swaminathan } /* end of while */ 335082527734SSukumar Swaminathan 335182527734SSukumar Swaminathan iocbq = (IOCBQ *)tbm.q_first; 335282527734SSukumar Swaminathan while (iocbq) { 335382527734SSukumar Swaminathan /* Save the next iocbq for now */ 335482527734SSukumar Swaminathan next = (IOCBQ *)iocbq->next; 335582527734SSukumar Swaminathan 335682527734SSukumar Swaminathan /* Unlink this iocbq */ 335782527734SSukumar Swaminathan iocbq->next = NULL; 335882527734SSukumar Swaminathan 335982527734SSukumar Swaminathan /* Get the pkt */ 336082527734SSukumar Swaminathan sbp = (emlxs_buf_t *)iocbq->sbp; 336182527734SSukumar Swaminathan 336282527734SSukumar Swaminathan if (sbp) { 336382527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flush_msg, 336482527734SSukumar Swaminathan "tx: sbp=%p node=%p", sbp, sbp->node); 336582527734SSukumar Swaminathan 336682527734SSukumar Swaminathan if (hba->state >= FC_LINK_UP) { 336782527734SSukumar Swaminathan emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 336882527734SSukumar Swaminathan IOERR_ABORT_REQUESTED, 1); 336982527734SSukumar Swaminathan } else { 337082527734SSukumar Swaminathan emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 337182527734SSukumar Swaminathan IOERR_LINK_DOWN, 1); 337282527734SSukumar Swaminathan } 337382527734SSukumar Swaminathan 337482527734SSukumar Swaminathan } 337582527734SSukumar Swaminathan /* Free the iocb and its associated buffers */ 337682527734SSukumar Swaminathan else { 337782527734SSukumar Swaminathan icmd = &iocbq->iocb; 337882527734SSukumar Swaminathan 337982527734SSukumar Swaminathan /* SLI3 */ 338082527734SSukumar Swaminathan if (icmd->ULPCOMMAND == CMD_QUE_RING_BUF64_CN || 338182527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_QUE_RING_BUF_CN || 338282527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_QUE_RING_LIST64_CN) { 338382527734SSukumar Swaminathan if ((hba->flag & 338482527734SSukumar Swaminathan (FC_ONLINE_MODE | FC_ONLINING_MODE)) == 0) { 338582527734SSukumar Swaminathan /* HBA is detaching or offlining */ 338682527734SSukumar Swaminathan if (icmd->ULPCOMMAND != 338782527734SSukumar Swaminathan CMD_QUE_RING_LIST64_CN) { 3388*a9800bebSGarrett D'Amore void *tmp; 338982527734SSukumar Swaminathan RING *rp; 339082527734SSukumar Swaminathan int ch; 339182527734SSukumar Swaminathan 339282527734SSukumar Swaminathan ch = from_chan->channelno; 339382527734SSukumar Swaminathan rp = &hba->sli.sli3.ring[ch]; 339482527734SSukumar Swaminathan 339582527734SSukumar Swaminathan for (i = 0; 339682527734SSukumar Swaminathan i < icmd->ULPBDECOUNT; 339782527734SSukumar Swaminathan i++) { 339882527734SSukumar Swaminathan mp = EMLXS_GET_VADDR( 339982527734SSukumar Swaminathan hba, rp, icmd); 340082527734SSukumar Swaminathan 3401*a9800bebSGarrett D'Amore tmp = (void *)mp; 340282527734SSukumar Swaminathan if (mp) { 3403*a9800bebSGarrett D'Amore emlxs_mem_put( 340482527734SSukumar Swaminathan hba, 340582527734SSukumar Swaminathan MEM_BUF, 340682527734SSukumar Swaminathan tmp); 340782527734SSukumar Swaminathan } 340882527734SSukumar Swaminathan } 340982527734SSukumar Swaminathan 341082527734SSukumar Swaminathan } 341182527734SSukumar Swaminathan 3412*a9800bebSGarrett D'Amore emlxs_mem_put(hba, MEM_IOCB, 3413*a9800bebSGarrett D'Amore (void *)iocbq); 341482527734SSukumar Swaminathan } else { 341582527734SSukumar Swaminathan /* repost the unsolicited buffer */ 341682527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, 341782527734SSukumar Swaminathan from_chan, iocbq); 341882527734SSukumar Swaminathan } 341982527734SSukumar Swaminathan } 342082527734SSukumar Swaminathan } 342182527734SSukumar Swaminathan 342282527734SSukumar Swaminathan iocbq = next; 342382527734SSukumar Swaminathan 342482527734SSukumar Swaminathan } /* end of while */ 342582527734SSukumar Swaminathan 342682527734SSukumar Swaminathan /* Now flush the chipq if any */ 342782527734SSukumar Swaminathan if (!(nlp->nlp_flag[fchanno] & NLP_CLOSED)) { 342882527734SSukumar Swaminathan 342982527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 343082527734SSukumar Swaminathan 343182527734SSukumar Swaminathan (void) emlxs_chipq_node_flush(port, from_chan, nlp, 0); 343282527734SSukumar Swaminathan 343382527734SSukumar Swaminathan mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 343482527734SSukumar Swaminathan } 343582527734SSukumar Swaminathan 343682527734SSukumar Swaminathan if (lock) { 343782527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 343882527734SSukumar Swaminathan } 343982527734SSukumar Swaminathan 344082527734SSukumar Swaminathan return; 344182527734SSukumar Swaminathan 344282527734SSukumar Swaminathan } /* emlxs_tx_move */ 3443fcf3ce44SJohn Forte 3444fcf3ce44SJohn Forte 3445fcf3ce44SJohn Forte extern uint32_t 344682527734SSukumar Swaminathan emlxs_chipq_node_flush(emlxs_port_t *port, CHANNEL *chan, NODELIST *ndlp, 3447291a2b48SSukumar Swaminathan emlxs_buf_t *fpkt) 3448fcf3ce44SJohn Forte { 3449fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 3450fcf3ce44SJohn Forte emlxs_buf_t *sbp; 3451fcf3ce44SJohn Forte IOCBQ *iocbq; 3452fcf3ce44SJohn Forte IOCBQ *next; 3453fcf3ce44SJohn Forte Q abort; 345482527734SSukumar Swaminathan CHANNEL *cp; 345582527734SSukumar Swaminathan uint32_t channelno; 345682527734SSukumar Swaminathan uint8_t flag[MAX_CHANNEL]; 3457fcf3ce44SJohn Forte uint32_t iotag; 3458fcf3ce44SJohn Forte 3459fcf3ce44SJohn Forte bzero((void *)&abort, sizeof (Q)); 3460fcf3ce44SJohn Forte bzero((void *)flag, sizeof (flag)); 3461fcf3ce44SJohn Forte 346282527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 346382527734SSukumar Swaminathan cp = &hba->chan[channelno]; 3464fcf3ce44SJohn Forte 346582527734SSukumar Swaminathan if (chan && cp != chan) { 3466fcf3ce44SJohn Forte continue; 3467fcf3ce44SJohn Forte } 3468291a2b48SSukumar Swaminathan 346982527734SSukumar Swaminathan mutex_enter(&EMLXS_FCTAB_LOCK); 3470fcf3ce44SJohn Forte 347182527734SSukumar Swaminathan for (iotag = 1; iotag < hba->max_iotag; iotag++) { 347282527734SSukumar Swaminathan sbp = hba->fc_table[iotag]; 3473fcf3ce44SJohn Forte 3474fcf3ce44SJohn Forte if (sbp && (sbp != STALE_PACKET) && 3475fcf3ce44SJohn Forte (sbp->pkt_flags & PACKET_IN_CHIPQ) && 3476fcf3ce44SJohn Forte (sbp->node == ndlp) && 347782527734SSukumar Swaminathan (sbp->channel == cp) && 3478fcf3ce44SJohn Forte !(sbp->pkt_flags & PACKET_XRI_CLOSED)) { 3479291a2b48SSukumar Swaminathan emlxs_sbp_abort_add(port, sbp, &abort, flag, 3480291a2b48SSukumar Swaminathan fpkt); 3481fcf3ce44SJohn Forte } 3482291a2b48SSukumar Swaminathan 3483fcf3ce44SJohn Forte } 348482527734SSukumar Swaminathan mutex_exit(&EMLXS_FCTAB_LOCK); 3485fcf3ce44SJohn Forte 3486fcf3ce44SJohn Forte } /* for */ 3487fcf3ce44SJohn Forte 3488fcf3ce44SJohn Forte /* Now put the iocb's on the tx queue */ 3489fcf3ce44SJohn Forte iocbq = (IOCBQ *)abort.q_first; 3490fcf3ce44SJohn Forte while (iocbq) { 3491fcf3ce44SJohn Forte /* Save the next iocbq for now */ 3492fcf3ce44SJohn Forte next = (IOCBQ *)iocbq->next; 3493fcf3ce44SJohn Forte 3494fcf3ce44SJohn Forte /* Unlink this iocbq */ 3495fcf3ce44SJohn Forte iocbq->next = NULL; 3496fcf3ce44SJohn Forte 3497fcf3ce44SJohn Forte /* Send this iocbq */ 3498fcf3ce44SJohn Forte emlxs_tx_put(iocbq, 1); 3499fcf3ce44SJohn Forte 3500fcf3ce44SJohn Forte iocbq = next; 3501fcf3ce44SJohn Forte } 3502fcf3ce44SJohn Forte 350382527734SSukumar Swaminathan /* Now trigger channel service */ 350482527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 350582527734SSukumar Swaminathan if (!flag[channelno]) { 3506fcf3ce44SJohn Forte continue; 3507fcf3ce44SJohn Forte } 3508291a2b48SSukumar Swaminathan 350982527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, &hba->chan[channelno], 0); 3510fcf3ce44SJohn Forte } 3511fcf3ce44SJohn Forte 3512fcf3ce44SJohn Forte return (abort.q_cnt); 3513fcf3ce44SJohn Forte 351482527734SSukumar Swaminathan } /* emlxs_chipq_node_flush() */ 3515fcf3ce44SJohn Forte 3516fcf3ce44SJohn Forte 3517fcf3ce44SJohn Forte /* Flush all IO's left on all iotag lists */ 351882527734SSukumar Swaminathan extern uint32_t 3519fcf3ce44SJohn Forte emlxs_iotag_flush(emlxs_hba_t *hba) 3520fcf3ce44SJohn Forte { 3521fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 3522fcf3ce44SJohn Forte emlxs_buf_t *sbp; 3523fcf3ce44SJohn Forte IOCBQ *iocbq; 3524fcf3ce44SJohn Forte IOCB *iocb; 3525fcf3ce44SJohn Forte Q abort; 352682527734SSukumar Swaminathan CHANNEL *cp; 352782527734SSukumar Swaminathan uint32_t channelno; 3528fcf3ce44SJohn Forte uint32_t iotag; 3529fcf3ce44SJohn Forte uint32_t count; 3530fcf3ce44SJohn Forte 3531fcf3ce44SJohn Forte count = 0; 353282527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 353382527734SSukumar Swaminathan cp = &hba->chan[channelno]; 3534fcf3ce44SJohn Forte 3535fcf3ce44SJohn Forte bzero((void *)&abort, sizeof (Q)); 3536fcf3ce44SJohn Forte 353782527734SSukumar Swaminathan mutex_enter(&EMLXS_FCTAB_LOCK); 3538fcf3ce44SJohn Forte 353982527734SSukumar Swaminathan for (iotag = 1; iotag < hba->max_iotag; iotag++) { 354082527734SSukumar Swaminathan sbp = hba->fc_table[iotag]; 3541fcf3ce44SJohn Forte 354282527734SSukumar Swaminathan /* Check if the slot is empty */ 3543fcf3ce44SJohn Forte if (!sbp || (sbp == STALE_PACKET)) { 3544fcf3ce44SJohn Forte continue; 3545fcf3ce44SJohn Forte } 3546291a2b48SSukumar Swaminathan 354782527734SSukumar Swaminathan /* We are building an abort list per channel */ 354882527734SSukumar Swaminathan if (sbp->channel != cp) { 354982527734SSukumar Swaminathan continue; 355082527734SSukumar Swaminathan } 3551fcf3ce44SJohn Forte 3552*a9800bebSGarrett D'Amore hba->fc_table[iotag] = STALE_PACKET; 3553*a9800bebSGarrett D'Amore hba->io_count--; 3554*a9800bebSGarrett D'Amore 3555*a9800bebSGarrett D'Amore /* Check if IO is valid */ 3556*a9800bebSGarrett D'Amore if (!(sbp->pkt_flags & PACKET_VALID) || 3557*a9800bebSGarrett D'Amore (sbp->pkt_flags & (PACKET_ULP_OWNED| 3558*a9800bebSGarrett D'Amore PACKET_COMPLETED|PACKET_IN_COMPLETION))) { 3559*a9800bebSGarrett D'Amore EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_debug_msg, 3560*a9800bebSGarrett D'Amore "iotag_flush: Invalid IO found. iotag=%x", 3561*a9800bebSGarrett D'Amore iotag); 3562*a9800bebSGarrett D'Amore 3563*a9800bebSGarrett D'Amore continue; 3564*a9800bebSGarrett D'Amore } 3565*a9800bebSGarrett D'Amore 3566*a9800bebSGarrett D'Amore sbp->iotag = 0; 3567*a9800bebSGarrett D'Amore 3568fcf3ce44SJohn Forte /* Set IOCB status */ 3569fcf3ce44SJohn Forte iocbq = &sbp->iocbq; 3570fcf3ce44SJohn Forte iocb = &iocbq->iocb; 3571fcf3ce44SJohn Forte 357282527734SSukumar Swaminathan iocb->ULPSTATUS = IOSTAT_LOCAL_REJECT; 3573fcf3ce44SJohn Forte iocb->un.grsp.perr.statLocalError = IOERR_LINK_DOWN; 357482527734SSukumar Swaminathan iocb->ULPLE = 1; 3575fcf3ce44SJohn Forte iocbq->next = NULL; 3576fcf3ce44SJohn Forte 357782527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 3578*a9800bebSGarrett D'Amore if (sbp->xrip) { 3579*a9800bebSGarrett D'Amore EMLXS_MSGF(EMLXS_CONTEXT, 3580*a9800bebSGarrett D'Amore &emlxs_sli_debug_msg, 3581*a9800bebSGarrett D'Amore "iotag_flush: iotag=%x sbp=%p " 3582*a9800bebSGarrett D'Amore "xrip=%p state=%x flag=%x", 3583*a9800bebSGarrett D'Amore iotag, sbp, sbp->xrip, 3584*a9800bebSGarrett D'Amore sbp->xrip->state, sbp->xrip->flag); 3585*a9800bebSGarrett D'Amore } else { 3586*a9800bebSGarrett D'Amore EMLXS_MSGF(EMLXS_CONTEXT, 3587*a9800bebSGarrett D'Amore &emlxs_sli_debug_msg, 3588*a9800bebSGarrett D'Amore "iotag_flush: iotag=%x sbp=%p " 3589*a9800bebSGarrett D'Amore "xrip=NULL", 3590*a9800bebSGarrett D'Amore iotag, sbp); 3591*a9800bebSGarrett D'Amore } 3592291a2b48SSukumar Swaminathan 3593*a9800bebSGarrett D'Amore emlxs_sli4_free_xri(hba, sbp, sbp->xrip, 0); 3594*a9800bebSGarrett D'Amore } else { 359582527734SSukumar Swaminathan /* Clean up the sbp */ 359682527734SSukumar Swaminathan mutex_enter(&sbp->mtx); 359782527734SSukumar Swaminathan 359882527734SSukumar Swaminathan if (sbp->pkt_flags & PACKET_IN_TXQ) { 359982527734SSukumar Swaminathan sbp->pkt_flags &= ~PACKET_IN_TXQ; 360082527734SSukumar Swaminathan hba->channel_tx_count --; 360182527734SSukumar Swaminathan } 360282527734SSukumar Swaminathan 360382527734SSukumar Swaminathan if (sbp->pkt_flags & PACKET_IN_CHIPQ) { 360482527734SSukumar Swaminathan sbp->pkt_flags &= ~PACKET_IN_CHIPQ; 360582527734SSukumar Swaminathan } 3606291a2b48SSukumar Swaminathan 360782527734SSukumar Swaminathan if (sbp->bmp) { 3608*a9800bebSGarrett D'Amore emlxs_mem_put(hba, MEM_BPL, 3609*a9800bebSGarrett D'Amore (void *)sbp->bmp); 361082527734SSukumar Swaminathan sbp->bmp = 0; 361182527734SSukumar Swaminathan } 361282527734SSukumar Swaminathan 361382527734SSukumar Swaminathan mutex_exit(&sbp->mtx); 3614fcf3ce44SJohn Forte } 3615291a2b48SSukumar Swaminathan 3616fcf3ce44SJohn Forte /* At this point all nodes are assumed destroyed */ 361782527734SSukumar Swaminathan mutex_enter(&sbp->mtx); 3618fcf3ce44SJohn Forte sbp->node = 0; 3619fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 3620fcf3ce44SJohn Forte 3621fcf3ce44SJohn Forte /* Add this iocb to our local abort Q */ 3622fcf3ce44SJohn Forte if (abort.q_first) { 3623291a2b48SSukumar Swaminathan ((IOCBQ *)abort.q_last)->next = iocbq; 3624fcf3ce44SJohn Forte abort.q_last = (uint8_t *)iocbq; 3625fcf3ce44SJohn Forte abort.q_cnt++; 3626fcf3ce44SJohn Forte } else { 3627fcf3ce44SJohn Forte abort.q_first = (uint8_t *)iocbq; 3628fcf3ce44SJohn Forte abort.q_last = (uint8_t *)iocbq; 3629fcf3ce44SJohn Forte abort.q_cnt = 1; 3630fcf3ce44SJohn Forte } 3631fcf3ce44SJohn Forte } 3632fcf3ce44SJohn Forte 363382527734SSukumar Swaminathan mutex_exit(&EMLXS_FCTAB_LOCK); 3634fcf3ce44SJohn Forte 3635fcf3ce44SJohn Forte /* Trigger deferred completion */ 3636fcf3ce44SJohn Forte if (abort.q_first) { 363782527734SSukumar Swaminathan mutex_enter(&cp->rsp_lock); 363882527734SSukumar Swaminathan if (cp->rsp_head == NULL) { 363982527734SSukumar Swaminathan cp->rsp_head = (IOCBQ *)abort.q_first; 364082527734SSukumar Swaminathan cp->rsp_tail = (IOCBQ *)abort.q_last; 3641fcf3ce44SJohn Forte } else { 364282527734SSukumar Swaminathan cp->rsp_tail->next = (IOCBQ *)abort.q_first; 364382527734SSukumar Swaminathan cp->rsp_tail = (IOCBQ *)abort.q_last; 3644fcf3ce44SJohn Forte } 364582527734SSukumar Swaminathan mutex_exit(&cp->rsp_lock); 3646fcf3ce44SJohn Forte 364782527734SSukumar Swaminathan emlxs_thread_trigger2(&cp->intr_thread, 364882527734SSukumar Swaminathan emlxs_proc_channel, cp); 3649fcf3ce44SJohn Forte 3650*a9800bebSGarrett D'Amore EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_debug_msg, 3651*a9800bebSGarrett D'Amore "iotag_flush: channel=%d count=%d", 365282527734SSukumar Swaminathan channelno, abort.q_cnt); 3653fcf3ce44SJohn Forte 3654fcf3ce44SJohn Forte count += abort.q_cnt; 3655fcf3ce44SJohn Forte } 3656fcf3ce44SJohn Forte } 3657fcf3ce44SJohn Forte 3658fcf3ce44SJohn Forte return (count); 3659fcf3ce44SJohn Forte 366082527734SSukumar Swaminathan } /* emlxs_iotag_flush() */ 3661fcf3ce44SJohn Forte 3662fcf3ce44SJohn Forte 3663fcf3ce44SJohn Forte 366482527734SSukumar Swaminathan /* Checks for IO's on all or a given channel for a given node */ 3665fcf3ce44SJohn Forte extern uint32_t 366682527734SSukumar Swaminathan emlxs_chipq_node_check(emlxs_port_t *port, CHANNEL *chan, NODELIST *ndlp) 3667fcf3ce44SJohn Forte { 3668fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 3669fcf3ce44SJohn Forte emlxs_buf_t *sbp; 367082527734SSukumar Swaminathan CHANNEL *cp; 367182527734SSukumar Swaminathan uint32_t channelno; 3672fcf3ce44SJohn Forte uint32_t count; 3673fcf3ce44SJohn Forte uint32_t iotag; 3674fcf3ce44SJohn Forte 3675fcf3ce44SJohn Forte count = 0; 3676fcf3ce44SJohn Forte 367782527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 367882527734SSukumar Swaminathan cp = &hba->chan[channelno]; 3679fcf3ce44SJohn Forte 368082527734SSukumar Swaminathan if (chan && cp != chan) { 3681fcf3ce44SJohn Forte continue; 3682fcf3ce44SJohn Forte } 3683291a2b48SSukumar Swaminathan 368482527734SSukumar Swaminathan mutex_enter(&EMLXS_FCTAB_LOCK); 3685fcf3ce44SJohn Forte 368682527734SSukumar Swaminathan for (iotag = 1; iotag < hba->max_iotag; iotag++) { 368782527734SSukumar Swaminathan sbp = hba->fc_table[iotag]; 3688fcf3ce44SJohn Forte 3689fcf3ce44SJohn Forte if (sbp && (sbp != STALE_PACKET) && 3690fcf3ce44SJohn Forte (sbp->pkt_flags & PACKET_IN_CHIPQ) && 3691fcf3ce44SJohn Forte (sbp->node == ndlp) && 369282527734SSukumar Swaminathan (sbp->channel == cp) && 3693fcf3ce44SJohn Forte !(sbp->pkt_flags & PACKET_XRI_CLOSED)) { 3694fcf3ce44SJohn Forte count++; 3695fcf3ce44SJohn Forte } 3696291a2b48SSukumar Swaminathan 3697fcf3ce44SJohn Forte } 369882527734SSukumar Swaminathan mutex_exit(&EMLXS_FCTAB_LOCK); 3699fcf3ce44SJohn Forte 3700fcf3ce44SJohn Forte } /* for */ 3701fcf3ce44SJohn Forte 3702fcf3ce44SJohn Forte return (count); 3703fcf3ce44SJohn Forte 370482527734SSukumar Swaminathan } /* emlxs_chipq_node_check() */ 3705fcf3ce44SJohn Forte 3706fcf3ce44SJohn Forte 3707fcf3ce44SJohn Forte 370882527734SSukumar Swaminathan /* Flush all IO's for a given node's lun (on any channel) */ 3709fcf3ce44SJohn Forte extern uint32_t 371082527734SSukumar Swaminathan emlxs_chipq_lun_flush(emlxs_port_t *port, NODELIST *ndlp, 371182527734SSukumar Swaminathan uint32_t lun, emlxs_buf_t *fpkt) 3712fcf3ce44SJohn Forte { 3713fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 3714fcf3ce44SJohn Forte emlxs_buf_t *sbp; 3715fcf3ce44SJohn Forte IOCBQ *iocbq; 3716fcf3ce44SJohn Forte IOCBQ *next; 3717fcf3ce44SJohn Forte Q abort; 3718fcf3ce44SJohn Forte uint32_t iotag; 371982527734SSukumar Swaminathan uint8_t flag[MAX_CHANNEL]; 372082527734SSukumar Swaminathan uint32_t channelno; 3721fcf3ce44SJohn Forte 3722*a9800bebSGarrett D'Amore if (lun == EMLXS_LUN_NONE) { 3723*a9800bebSGarrett D'Amore return (0); 3724*a9800bebSGarrett D'Amore } 3725*a9800bebSGarrett D'Amore 3726fcf3ce44SJohn Forte bzero((void *)flag, sizeof (flag)); 3727fcf3ce44SJohn Forte bzero((void *)&abort, sizeof (Q)); 3728fcf3ce44SJohn Forte 372982527734SSukumar Swaminathan mutex_enter(&EMLXS_FCTAB_LOCK); 373082527734SSukumar Swaminathan for (iotag = 1; iotag < hba->max_iotag; iotag++) { 373182527734SSukumar Swaminathan sbp = hba->fc_table[iotag]; 3732fcf3ce44SJohn Forte 3733fcf3ce44SJohn Forte if (sbp && (sbp != STALE_PACKET) && 3734fcf3ce44SJohn Forte sbp->pkt_flags & PACKET_IN_CHIPQ && 3735fcf3ce44SJohn Forte sbp->node == ndlp && 3736fcf3ce44SJohn Forte sbp->lun == lun && 3737fcf3ce44SJohn Forte !(sbp->pkt_flags & PACKET_XRI_CLOSED)) { 373882527734SSukumar Swaminathan emlxs_sbp_abort_add(port, sbp, 373982527734SSukumar Swaminathan &abort, flag, fpkt); 3740fcf3ce44SJohn Forte } 3741fcf3ce44SJohn Forte } 374282527734SSukumar Swaminathan mutex_exit(&EMLXS_FCTAB_LOCK); 3743fcf3ce44SJohn Forte 3744fcf3ce44SJohn Forte /* Now put the iocb's on the tx queue */ 3745fcf3ce44SJohn Forte iocbq = (IOCBQ *)abort.q_first; 3746fcf3ce44SJohn Forte while (iocbq) { 3747fcf3ce44SJohn Forte /* Save the next iocbq for now */ 3748fcf3ce44SJohn Forte next = (IOCBQ *)iocbq->next; 3749fcf3ce44SJohn Forte 3750fcf3ce44SJohn Forte /* Unlink this iocbq */ 3751fcf3ce44SJohn Forte iocbq->next = NULL; 3752fcf3ce44SJohn Forte 3753fcf3ce44SJohn Forte /* Send this iocbq */ 3754fcf3ce44SJohn Forte emlxs_tx_put(iocbq, 1); 3755fcf3ce44SJohn Forte 3756fcf3ce44SJohn Forte iocbq = next; 3757fcf3ce44SJohn Forte } 3758fcf3ce44SJohn Forte 375982527734SSukumar Swaminathan /* Now trigger channel service */ 376082527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 376182527734SSukumar Swaminathan if (!flag[channelno]) { 376282527734SSukumar Swaminathan continue; 376382527734SSukumar Swaminathan } 376482527734SSukumar Swaminathan 376582527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, &hba->chan[channelno], 0); 3766fcf3ce44SJohn Forte } 3767291a2b48SSukumar Swaminathan 3768fcf3ce44SJohn Forte return (abort.q_cnt); 3769fcf3ce44SJohn Forte 377082527734SSukumar Swaminathan } /* emlxs_chipq_lun_flush() */ 3771fcf3ce44SJohn Forte 3772fcf3ce44SJohn Forte 3773fcf3ce44SJohn Forte 3774fcf3ce44SJohn Forte /* 3775fcf3ce44SJohn Forte * Issue an ABORT_XRI_CN iocb command to abort an FCP command already issued. 3776fe199829SSukumar Swaminathan * This must be called while holding the EMLXS_FCTAB_LOCK 3777fcf3ce44SJohn Forte */ 3778fcf3ce44SJohn Forte extern IOCBQ * 3779291a2b48SSukumar Swaminathan emlxs_create_abort_xri_cn(emlxs_port_t *port, NODELIST *ndlp, 378082527734SSukumar Swaminathan uint16_t iotag, CHANNEL *cp, uint8_t class, int32_t flag) 3781fcf3ce44SJohn Forte { 3782fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 3783fcf3ce44SJohn Forte IOCBQ *iocbq; 3784fcf3ce44SJohn Forte IOCB *iocb; 378582527734SSukumar Swaminathan emlxs_wqe_t *wqe; 378682527734SSukumar Swaminathan emlxs_buf_t *sbp; 3787fcf3ce44SJohn Forte uint16_t abort_iotag; 3788fcf3ce44SJohn Forte 378982527734SSukumar Swaminathan if ((iocbq = (IOCBQ *)emlxs_mem_get(hba, MEM_IOCB, 0)) == NULL) { 3790fcf3ce44SJohn Forte return (NULL); 3791fcf3ce44SJohn Forte } 3792291a2b48SSukumar Swaminathan 379382527734SSukumar Swaminathan iocbq->channel = (void *)cp; 3794fcf3ce44SJohn Forte iocbq->port = (void *)port; 3795fcf3ce44SJohn Forte iocbq->node = (void *)ndlp; 3796fcf3ce44SJohn Forte iocbq->flag |= (IOCB_PRIORITY | IOCB_SPECIAL); 3797fcf3ce44SJohn Forte 3798fcf3ce44SJohn Forte /* 3799fcf3ce44SJohn Forte * set up an iotag using special Abort iotags 3800fcf3ce44SJohn Forte */ 380182527734SSukumar Swaminathan if ((hba->fc_oor_iotag >= EMLXS_MAX_ABORT_TAG)) { 380282527734SSukumar Swaminathan hba->fc_oor_iotag = hba->max_iotag; 3803fcf3ce44SJohn Forte } 380482527734SSukumar Swaminathan abort_iotag = hba->fc_oor_iotag++; 3805291a2b48SSukumar Swaminathan 3806fcf3ce44SJohn Forte 380782527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 380882527734SSukumar Swaminathan wqe = &iocbq->wqe; 380982527734SSukumar Swaminathan sbp = hba->fc_table[iotag]; 3810fcf3ce44SJohn Forte 381182527734SSukumar Swaminathan /* Try to issue abort by XRI if possible */ 3812*a9800bebSGarrett D'Amore if (sbp == NULL || sbp == STALE_PACKET || sbp->xrip == NULL) { 381382527734SSukumar Swaminathan wqe->un.Abort.Criteria = ABORT_REQ_TAG; 381482527734SSukumar Swaminathan wqe->AbortTag = iotag; 381582527734SSukumar Swaminathan } else { 381682527734SSukumar Swaminathan wqe->un.Abort.Criteria = ABORT_XRI_TAG; 3817*a9800bebSGarrett D'Amore wqe->AbortTag = sbp->xrip->XRI; 381882527734SSukumar Swaminathan } 381982527734SSukumar Swaminathan wqe->un.Abort.IA = 0; 382082527734SSukumar Swaminathan wqe->RequestTag = abort_iotag; 382182527734SSukumar Swaminathan wqe->Command = CMD_ABORT_XRI_CX; 382282527734SSukumar Swaminathan wqe->Class = CLASS3; 382382527734SSukumar Swaminathan wqe->CQId = 0x3ff; 382482527734SSukumar Swaminathan wqe->CmdType = WQE_TYPE_ABORT; 382582527734SSukumar Swaminathan } else { 382682527734SSukumar Swaminathan iocb = &iocbq->iocb; 382782527734SSukumar Swaminathan iocb->ULPIOTAG = abort_iotag; 382882527734SSukumar Swaminathan iocb->un.acxri.abortType = flag; 382982527734SSukumar Swaminathan iocb->un.acxri.abortContextTag = ndlp->nlp_Rpi; 383082527734SSukumar Swaminathan iocb->un.acxri.abortIoTag = iotag; 383182527734SSukumar Swaminathan iocb->ULPLE = 1; 383282527734SSukumar Swaminathan iocb->ULPCLASS = class; 383382527734SSukumar Swaminathan iocb->ULPCOMMAND = CMD_ABORT_XRI_CN; 383482527734SSukumar Swaminathan iocb->ULPOWNER = OWN_CHIP; 383582527734SSukumar Swaminathan } 3836fcf3ce44SJohn Forte 3837fcf3ce44SJohn Forte return (iocbq); 3838fcf3ce44SJohn Forte 383982527734SSukumar Swaminathan } /* emlxs_create_abort_xri_cn() */ 3840fcf3ce44SJohn Forte 3841fcf3ce44SJohn Forte 3842fe199829SSukumar Swaminathan /* This must be called while holding the EMLXS_FCTAB_LOCK */ 3843fcf3ce44SJohn Forte extern IOCBQ * 3844fcf3ce44SJohn Forte emlxs_create_abort_xri_cx(emlxs_port_t *port, NODELIST *ndlp, uint16_t xid, 384582527734SSukumar Swaminathan CHANNEL *cp, uint8_t class, int32_t flag) 3846fcf3ce44SJohn Forte { 3847fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 3848fcf3ce44SJohn Forte IOCBQ *iocbq; 3849fcf3ce44SJohn Forte IOCB *iocb; 385082527734SSukumar Swaminathan emlxs_wqe_t *wqe; 3851fcf3ce44SJohn Forte uint16_t abort_iotag; 3852fcf3ce44SJohn Forte 385382527734SSukumar Swaminathan if ((iocbq = (IOCBQ *)emlxs_mem_get(hba, MEM_IOCB, 0)) == NULL) { 3854fcf3ce44SJohn Forte return (NULL); 3855fcf3ce44SJohn Forte } 3856291a2b48SSukumar Swaminathan 385782527734SSukumar Swaminathan iocbq->channel = (void *)cp; 3858fcf3ce44SJohn Forte iocbq->port = (void *)port; 3859fcf3ce44SJohn Forte iocbq->node = (void *)ndlp; 3860fcf3ce44SJohn Forte iocbq->flag |= (IOCB_PRIORITY | IOCB_SPECIAL); 3861fcf3ce44SJohn Forte 3862fcf3ce44SJohn Forte /* 3863fcf3ce44SJohn Forte * set up an iotag using special Abort iotags 3864fcf3ce44SJohn Forte */ 386582527734SSukumar Swaminathan if ((hba->fc_oor_iotag >= EMLXS_MAX_ABORT_TAG)) { 386682527734SSukumar Swaminathan hba->fc_oor_iotag = hba->max_iotag; 386782527734SSukumar Swaminathan } 386882527734SSukumar Swaminathan abort_iotag = hba->fc_oor_iotag++; 386982527734SSukumar Swaminathan 387082527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 387182527734SSukumar Swaminathan wqe = &iocbq->wqe; 387282527734SSukumar Swaminathan wqe->un.Abort.Criteria = ABORT_XRI_TAG; 387382527734SSukumar Swaminathan wqe->un.Abort.IA = 0; 387482527734SSukumar Swaminathan wqe->RequestTag = abort_iotag; 387582527734SSukumar Swaminathan wqe->AbortTag = xid; 387682527734SSukumar Swaminathan wqe->Command = CMD_ABORT_XRI_CX; 387782527734SSukumar Swaminathan wqe->Class = CLASS3; 387882527734SSukumar Swaminathan wqe->CQId = 0x3ff; 387982527734SSukumar Swaminathan wqe->CmdType = WQE_TYPE_ABORT; 388082527734SSukumar Swaminathan } else { 388182527734SSukumar Swaminathan iocb = &iocbq->iocb; 388282527734SSukumar Swaminathan iocb->ULPCONTEXT = xid; 388382527734SSukumar Swaminathan iocb->ULPIOTAG = abort_iotag; 388482527734SSukumar Swaminathan iocb->un.acxri.abortType = flag; 388582527734SSukumar Swaminathan iocb->ULPLE = 1; 388682527734SSukumar Swaminathan iocb->ULPCLASS = class; 388782527734SSukumar Swaminathan iocb->ULPCOMMAND = CMD_ABORT_XRI_CX; 388882527734SSukumar Swaminathan iocb->ULPOWNER = OWN_CHIP; 3889fcf3ce44SJohn Forte } 3890291a2b48SSukumar Swaminathan 3891fcf3ce44SJohn Forte return (iocbq); 3892fcf3ce44SJohn Forte 389382527734SSukumar Swaminathan } /* emlxs_create_abort_xri_cx() */ 3894fcf3ce44SJohn Forte 3895fcf3ce44SJohn Forte 3896fcf3ce44SJohn Forte 3897fe199829SSukumar Swaminathan /* This must be called while holding the EMLXS_FCTAB_LOCK */ 3898fcf3ce44SJohn Forte extern IOCBQ * 3899fcf3ce44SJohn Forte emlxs_create_close_xri_cn(emlxs_port_t *port, NODELIST *ndlp, 390082527734SSukumar Swaminathan uint16_t iotag, CHANNEL *cp) 3901fcf3ce44SJohn Forte { 3902fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 3903fcf3ce44SJohn Forte IOCBQ *iocbq; 3904fcf3ce44SJohn Forte IOCB *iocb; 390582527734SSukumar Swaminathan emlxs_wqe_t *wqe; 390682527734SSukumar Swaminathan emlxs_buf_t *sbp; 3907fcf3ce44SJohn Forte uint16_t abort_iotag; 3908fcf3ce44SJohn Forte 390982527734SSukumar Swaminathan if ((iocbq = (IOCBQ *)emlxs_mem_get(hba, MEM_IOCB, 0)) == NULL) { 3910fcf3ce44SJohn Forte return (NULL); 3911fcf3ce44SJohn Forte } 3912291a2b48SSukumar Swaminathan 391382527734SSukumar Swaminathan iocbq->channel = (void *)cp; 3914fcf3ce44SJohn Forte iocbq->port = (void *)port; 3915fcf3ce44SJohn Forte iocbq->node = (void *)ndlp; 3916fcf3ce44SJohn Forte iocbq->flag |= (IOCB_PRIORITY | IOCB_SPECIAL); 3917fcf3ce44SJohn Forte 3918fcf3ce44SJohn Forte /* 3919fcf3ce44SJohn Forte * set up an iotag using special Abort iotags 3920fcf3ce44SJohn Forte */ 392182527734SSukumar Swaminathan if ((hba->fc_oor_iotag >= EMLXS_MAX_ABORT_TAG)) { 392282527734SSukumar Swaminathan hba->fc_oor_iotag = hba->max_iotag; 3923fcf3ce44SJohn Forte } 392482527734SSukumar Swaminathan abort_iotag = hba->fc_oor_iotag++; 3925291a2b48SSukumar Swaminathan 392682527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 392782527734SSukumar Swaminathan wqe = &iocbq->wqe; 392882527734SSukumar Swaminathan sbp = hba->fc_table[iotag]; 3929fcf3ce44SJohn Forte 393082527734SSukumar Swaminathan /* Try to issue close by XRI if possible */ 3931*a9800bebSGarrett D'Amore if (sbp == NULL || sbp == STALE_PACKET || sbp->xrip == NULL) { 393282527734SSukumar Swaminathan wqe->un.Abort.Criteria = ABORT_REQ_TAG; 393382527734SSukumar Swaminathan wqe->AbortTag = iotag; 393482527734SSukumar Swaminathan } else { 393582527734SSukumar Swaminathan wqe->un.Abort.Criteria = ABORT_XRI_TAG; 3936*a9800bebSGarrett D'Amore wqe->AbortTag = sbp->xrip->XRI; 393782527734SSukumar Swaminathan } 393882527734SSukumar Swaminathan wqe->un.Abort.IA = 1; 393982527734SSukumar Swaminathan wqe->RequestTag = abort_iotag; 394082527734SSukumar Swaminathan wqe->Command = CMD_ABORT_XRI_CX; 394182527734SSukumar Swaminathan wqe->Class = CLASS3; 394282527734SSukumar Swaminathan wqe->CQId = 0x3ff; 394382527734SSukumar Swaminathan wqe->CmdType = WQE_TYPE_ABORT; 394482527734SSukumar Swaminathan } else { 394582527734SSukumar Swaminathan iocb = &iocbq->iocb; 394682527734SSukumar Swaminathan iocb->ULPIOTAG = abort_iotag; 394782527734SSukumar Swaminathan iocb->un.acxri.abortType = 0; 394882527734SSukumar Swaminathan iocb->un.acxri.abortContextTag = ndlp->nlp_Rpi; 394982527734SSukumar Swaminathan iocb->un.acxri.abortIoTag = iotag; 395082527734SSukumar Swaminathan iocb->ULPLE = 1; 395182527734SSukumar Swaminathan iocb->ULPCLASS = 0; 395282527734SSukumar Swaminathan iocb->ULPCOMMAND = CMD_CLOSE_XRI_CN; 395382527734SSukumar Swaminathan iocb->ULPOWNER = OWN_CHIP; 395482527734SSukumar Swaminathan } 3955fcf3ce44SJohn Forte 3956fcf3ce44SJohn Forte return (iocbq); 3957fcf3ce44SJohn Forte 395882527734SSukumar Swaminathan } /* emlxs_create_close_xri_cn() */ 3959fcf3ce44SJohn Forte 3960fcf3ce44SJohn Forte 3961fe199829SSukumar Swaminathan /* This must be called while holding the EMLXS_FCTAB_LOCK */ 3962fcf3ce44SJohn Forte extern IOCBQ * 3963291a2b48SSukumar Swaminathan emlxs_create_close_xri_cx(emlxs_port_t *port, NODELIST *ndlp, uint16_t xid, 396482527734SSukumar Swaminathan CHANNEL *cp) 3965fcf3ce44SJohn Forte { 3966fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 3967fcf3ce44SJohn Forte IOCBQ *iocbq; 3968fcf3ce44SJohn Forte IOCB *iocb; 396982527734SSukumar Swaminathan emlxs_wqe_t *wqe; 3970fcf3ce44SJohn Forte uint16_t abort_iotag; 3971fcf3ce44SJohn Forte 397282527734SSukumar Swaminathan if ((iocbq = (IOCBQ *)emlxs_mem_get(hba, MEM_IOCB, 0)) == NULL) { 3973fcf3ce44SJohn Forte return (NULL); 3974fcf3ce44SJohn Forte } 3975291a2b48SSukumar Swaminathan 397682527734SSukumar Swaminathan iocbq->channel = (void *)cp; 3977fcf3ce44SJohn Forte iocbq->port = (void *)port; 3978fcf3ce44SJohn Forte iocbq->node = (void *)ndlp; 3979fcf3ce44SJohn Forte iocbq->flag |= (IOCB_PRIORITY | IOCB_SPECIAL); 3980fcf3ce44SJohn Forte 3981fcf3ce44SJohn Forte /* 3982fcf3ce44SJohn Forte * set up an iotag using special Abort iotags 3983fcf3ce44SJohn Forte */ 398482527734SSukumar Swaminathan if ((hba->fc_oor_iotag >= EMLXS_MAX_ABORT_TAG)) { 398582527734SSukumar Swaminathan hba->fc_oor_iotag = hba->max_iotag; 398682527734SSukumar Swaminathan } 398782527734SSukumar Swaminathan abort_iotag = hba->fc_oor_iotag++; 398882527734SSukumar Swaminathan 398982527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 399082527734SSukumar Swaminathan wqe = &iocbq->wqe; 399182527734SSukumar Swaminathan wqe->un.Abort.Criteria = ABORT_XRI_TAG; 399282527734SSukumar Swaminathan wqe->un.Abort.IA = 1; 399382527734SSukumar Swaminathan wqe->RequestTag = abort_iotag; 399482527734SSukumar Swaminathan wqe->AbortTag = xid; 399582527734SSukumar Swaminathan wqe->Command = CMD_ABORT_XRI_CX; 399682527734SSukumar Swaminathan wqe->Class = CLASS3; 399782527734SSukumar Swaminathan wqe->CQId = 0x3ff; 399882527734SSukumar Swaminathan wqe->CmdType = WQE_TYPE_ABORT; 399982527734SSukumar Swaminathan } else { 400082527734SSukumar Swaminathan iocb = &iocbq->iocb; 400182527734SSukumar Swaminathan iocb->ULPCONTEXT = xid; 400282527734SSukumar Swaminathan iocb->ULPIOTAG = abort_iotag; 400382527734SSukumar Swaminathan iocb->ULPLE = 1; 400482527734SSukumar Swaminathan iocb->ULPCLASS = 0; 400582527734SSukumar Swaminathan iocb->ULPCOMMAND = CMD_CLOSE_XRI_CX; 400682527734SSukumar Swaminathan iocb->ULPOWNER = OWN_CHIP; 4007fcf3ce44SJohn Forte } 4008291a2b48SSukumar Swaminathan 4009fcf3ce44SJohn Forte return (iocbq); 4010fcf3ce44SJohn Forte 401182527734SSukumar Swaminathan } /* emlxs_create_close_xri_cx() */ 4012fcf3ce44SJohn Forte 4013fcf3ce44SJohn Forte 4014fe199829SSukumar Swaminathan #ifdef SFCT_SUPPORT 4015fe199829SSukumar Swaminathan void 4016fe199829SSukumar Swaminathan emlxs_abort_fct_exchange(emlxs_hba_t *hba, emlxs_port_t *port, uint32_t rxid) 4017fe199829SSukumar Swaminathan { 4018fe199829SSukumar Swaminathan CHANNEL *cp; 4019fe199829SSukumar Swaminathan IOCBQ *iocbq; 4020fe199829SSukumar Swaminathan IOCB *iocb; 4021fe199829SSukumar Swaminathan 4022fe199829SSukumar Swaminathan if (rxid == 0 || rxid == 0xFFFF) { 4023fe199829SSukumar Swaminathan return; 4024fe199829SSukumar Swaminathan } 4025fe199829SSukumar Swaminathan 4026fe199829SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 4027fe199829SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4028fe199829SSukumar Swaminathan "Aborting FCT exchange: xid=%x", rxid); 4029fe199829SSukumar Swaminathan 4030*a9800bebSGarrett D'Amore if (emlxs_sli4_unreserve_xri(hba, rxid, 1) == 0) { 4031fe199829SSukumar Swaminathan /* We have no way to abort unsolicited exchanges */ 4032fe199829SSukumar Swaminathan /* that we have not responded to at this time */ 4033fe199829SSukumar Swaminathan /* So we will return for now */ 4034fe199829SSukumar Swaminathan return; 4035fe199829SSukumar Swaminathan } 4036fe199829SSukumar Swaminathan } 4037fe199829SSukumar Swaminathan 4038fe199829SSukumar Swaminathan cp = &hba->chan[hba->channel_fcp]; 4039fe199829SSukumar Swaminathan 4040fe199829SSukumar Swaminathan mutex_enter(&EMLXS_FCTAB_LOCK); 4041fe199829SSukumar Swaminathan 4042fe199829SSukumar Swaminathan /* Create the abort IOCB */ 4043fe199829SSukumar Swaminathan if (hba->state >= FC_LINK_UP) { 4044fe199829SSukumar Swaminathan iocbq = emlxs_create_abort_xri_cx(port, NULL, rxid, cp, 4045fe199829SSukumar Swaminathan CLASS3, ABORT_TYPE_ABTS); 4046fe199829SSukumar Swaminathan } else { 4047fe199829SSukumar Swaminathan iocbq = emlxs_create_close_xri_cx(port, NULL, rxid, cp); 4048fe199829SSukumar Swaminathan } 4049fe199829SSukumar Swaminathan 4050fe199829SSukumar Swaminathan mutex_exit(&EMLXS_FCTAB_LOCK); 4051fe199829SSukumar Swaminathan 4052fe199829SSukumar Swaminathan if (iocbq) { 4053fe199829SSukumar Swaminathan iocb = &iocbq->iocb; 4054fe199829SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4055fe199829SSukumar Swaminathan "Aborting FCT exchange: xid=%x iotag=%x", rxid, 4056fe199829SSukumar Swaminathan iocb->ULPIOTAG); 4057fe199829SSukumar Swaminathan 4058fe199829SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq); 4059fe199829SSukumar Swaminathan } 4060fe199829SSukumar Swaminathan 4061fe199829SSukumar Swaminathan } /* emlxs_abort_fct_exchange() */ 4062fe199829SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 4063fe199829SSukumar Swaminathan 4064fe199829SSukumar Swaminathan 4065*a9800bebSGarrett D'Amore void 4066*a9800bebSGarrett D'Amore emlxs_close_els_exchange(emlxs_hba_t *hba, emlxs_port_t *port, uint32_t rxid) 4067*a9800bebSGarrett D'Amore { 4068*a9800bebSGarrett D'Amore CHANNEL *cp; 4069*a9800bebSGarrett D'Amore IOCBQ *iocbq; 4070*a9800bebSGarrett D'Amore IOCB *iocb; 4071*a9800bebSGarrett D'Amore 4072*a9800bebSGarrett D'Amore if (rxid == 0 || rxid == 0xFFFF) { 4073*a9800bebSGarrett D'Amore return; 4074*a9800bebSGarrett D'Amore } 4075*a9800bebSGarrett D'Amore 4076*a9800bebSGarrett D'Amore if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 4077*a9800bebSGarrett D'Amore EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 4078*a9800bebSGarrett D'Amore "Closing ELS exchange: xid=%x", rxid); 4079*a9800bebSGarrett D'Amore 4080*a9800bebSGarrett D'Amore if (emlxs_sli4_unreserve_xri(hba, rxid, 1) == 0) { 4081*a9800bebSGarrett D'Amore return; 4082*a9800bebSGarrett D'Amore } 4083*a9800bebSGarrett D'Amore } 4084*a9800bebSGarrett D'Amore 4085*a9800bebSGarrett D'Amore cp = &hba->chan[hba->channel_els]; 4086*a9800bebSGarrett D'Amore 4087*a9800bebSGarrett D'Amore mutex_enter(&EMLXS_FCTAB_LOCK); 4088*a9800bebSGarrett D'Amore 4089*a9800bebSGarrett D'Amore /* Create the abort IOCB */ 4090*a9800bebSGarrett D'Amore iocbq = emlxs_create_close_xri_cx(port, NULL, rxid, cp); 4091*a9800bebSGarrett D'Amore 4092*a9800bebSGarrett D'Amore mutex_exit(&EMLXS_FCTAB_LOCK); 4093*a9800bebSGarrett D'Amore 4094*a9800bebSGarrett D'Amore if (iocbq) { 4095*a9800bebSGarrett D'Amore iocb = &iocbq->iocb; 4096*a9800bebSGarrett D'Amore EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 4097*a9800bebSGarrett D'Amore "Closing ELS exchange: xid=%x iotag=%x", rxid, 4098*a9800bebSGarrett D'Amore iocb->ULPIOTAG); 4099*a9800bebSGarrett D'Amore 4100*a9800bebSGarrett D'Amore EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq); 4101*a9800bebSGarrett D'Amore } 4102*a9800bebSGarrett D'Amore 4103*a9800bebSGarrett D'Amore } /* emlxs_close_els_exchange() */ 4104*a9800bebSGarrett D'Amore 4105*a9800bebSGarrett D'Amore 4106fe199829SSukumar Swaminathan void 4107fe199829SSukumar Swaminathan emlxs_abort_els_exchange(emlxs_hba_t *hba, emlxs_port_t *port, uint32_t rxid) 4108fe199829SSukumar Swaminathan { 4109fe199829SSukumar Swaminathan CHANNEL *cp; 4110fe199829SSukumar Swaminathan IOCBQ *iocbq; 4111fe199829SSukumar Swaminathan IOCB *iocb; 4112fe199829SSukumar Swaminathan 4113fe199829SSukumar Swaminathan if (rxid == 0 || rxid == 0xFFFF) { 4114fe199829SSukumar Swaminathan return; 4115fe199829SSukumar Swaminathan } 4116fe199829SSukumar Swaminathan 4117fe199829SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 4118fe199829SSukumar Swaminathan 4119fe199829SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 4120fe199829SSukumar Swaminathan "Aborting ELS exchange: xid=%x", rxid); 4121fe199829SSukumar Swaminathan 4122*a9800bebSGarrett D'Amore if (emlxs_sli4_unreserve_xri(hba, rxid, 1) == 0) { 4123fe199829SSukumar Swaminathan /* We have no way to abort unsolicited exchanges */ 4124fe199829SSukumar Swaminathan /* that we have not responded to at this time */ 4125fe199829SSukumar Swaminathan /* So we will return for now */ 4126fe199829SSukumar Swaminathan return; 4127fe199829SSukumar Swaminathan } 4128fe199829SSukumar Swaminathan } 4129fe199829SSukumar Swaminathan 4130fe199829SSukumar Swaminathan cp = &hba->chan[hba->channel_els]; 4131fe199829SSukumar Swaminathan 4132fe199829SSukumar Swaminathan mutex_enter(&EMLXS_FCTAB_LOCK); 4133fe199829SSukumar Swaminathan 4134fe199829SSukumar Swaminathan /* Create the abort IOCB */ 4135fe199829SSukumar Swaminathan if (hba->state >= FC_LINK_UP) { 4136fe199829SSukumar Swaminathan iocbq = emlxs_create_abort_xri_cx(port, NULL, rxid, cp, 4137fe199829SSukumar Swaminathan CLASS3, ABORT_TYPE_ABTS); 4138fe199829SSukumar Swaminathan } else { 4139fe199829SSukumar Swaminathan iocbq = emlxs_create_close_xri_cx(port, NULL, rxid, cp); 4140fe199829SSukumar Swaminathan } 4141fe199829SSukumar Swaminathan 4142fe199829SSukumar Swaminathan mutex_exit(&EMLXS_FCTAB_LOCK); 4143fe199829SSukumar Swaminathan 4144fe199829SSukumar Swaminathan if (iocbq) { 4145fe199829SSukumar Swaminathan iocb = &iocbq->iocb; 4146fe199829SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 4147fe199829SSukumar Swaminathan "Aborting ELS exchange: xid=%x iotag=%x", rxid, 4148fe199829SSukumar Swaminathan iocb->ULPIOTAG); 4149fe199829SSukumar Swaminathan 4150fe199829SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq); 4151fe199829SSukumar Swaminathan } 4152fe199829SSukumar Swaminathan 4153fe199829SSukumar Swaminathan } /* emlxs_abort_els_exchange() */ 4154fe199829SSukumar Swaminathan 4155fe199829SSukumar Swaminathan 4156728bdc9bSSukumar Swaminathan void 4157bb63f56eSSukumar Swaminathan emlxs_abort_ct_exchange(emlxs_hba_t *hba, emlxs_port_t *port, uint32_t rxid) 4158728bdc9bSSukumar Swaminathan { 415982527734SSukumar Swaminathan CHANNEL *cp; 4160728bdc9bSSukumar Swaminathan IOCBQ *iocbq; 4161fe199829SSukumar Swaminathan IOCB *iocb; 4162728bdc9bSSukumar Swaminathan 4163fe199829SSukumar Swaminathan if (rxid == 0 || rxid == 0xFFFF) { 4164fe199829SSukumar Swaminathan return; 4165fe199829SSukumar Swaminathan } 416682527734SSukumar Swaminathan 416782527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 4168fe199829SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_ct_msg, 4169fe199829SSukumar Swaminathan "Aborting CT exchange: xid=%x", rxid); 4170fe199829SSukumar Swaminathan 4171*a9800bebSGarrett D'Amore if (emlxs_sli4_unreserve_xri(hba, rxid, 1) == 0) { 417282527734SSukumar Swaminathan /* We have no way to abort unsolicited exchanges */ 417382527734SSukumar Swaminathan /* that we have not responded to at this time */ 417482527734SSukumar Swaminathan /* So we will return for now */ 417582527734SSukumar Swaminathan return; 417682527734SSukumar Swaminathan } 417782527734SSukumar Swaminathan } 417882527734SSukumar Swaminathan 417982527734SSukumar Swaminathan cp = &hba->chan[hba->channel_ct]; 4180728bdc9bSSukumar Swaminathan 4181fe199829SSukumar Swaminathan mutex_enter(&EMLXS_FCTAB_LOCK); 4182fe199829SSukumar Swaminathan 4183728bdc9bSSukumar Swaminathan /* Create the abort IOCB */ 4184728bdc9bSSukumar Swaminathan if (hba->state >= FC_LINK_UP) { 4185fe199829SSukumar Swaminathan iocbq = emlxs_create_abort_xri_cx(port, NULL, rxid, cp, 4186fe199829SSukumar Swaminathan CLASS3, ABORT_TYPE_ABTS); 4187291a2b48SSukumar Swaminathan } else { 418882527734SSukumar Swaminathan iocbq = emlxs_create_close_xri_cx(port, NULL, rxid, cp); 4189728bdc9bSSukumar Swaminathan } 419082527734SSukumar Swaminathan 4191fe199829SSukumar Swaminathan mutex_exit(&EMLXS_FCTAB_LOCK); 4192fe199829SSukumar Swaminathan 4193bb63f56eSSukumar Swaminathan if (iocbq) { 4194fe199829SSukumar Swaminathan iocb = &iocbq->iocb; 4195fe199829SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 4196fe199829SSukumar Swaminathan "Aborting CT exchange: xid=%x iotag=%x", rxid, 4197fe199829SSukumar Swaminathan iocb->ULPIOTAG); 4198fe199829SSukumar Swaminathan 419982527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq); 4200bb63f56eSSukumar Swaminathan } 420182527734SSukumar Swaminathan 420282527734SSukumar Swaminathan } /* emlxs_abort_ct_exchange() */ 4203728bdc9bSSukumar Swaminathan 4204fcf3ce44SJohn Forte 4205fe199829SSukumar Swaminathan /* This must be called while holding the EMLXS_FCTAB_LOCK */ 4206fcf3ce44SJohn Forte static void 4207fcf3ce44SJohn Forte emlxs_sbp_abort_add(emlxs_port_t *port, emlxs_buf_t *sbp, Q *abort, 4208fcf3ce44SJohn Forte uint8_t *flag, emlxs_buf_t *fpkt) 4209fcf3ce44SJohn Forte { 4210fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 4211fcf3ce44SJohn Forte IOCBQ *iocbq; 421282527734SSukumar Swaminathan CHANNEL *cp; 4213fcf3ce44SJohn Forte NODELIST *ndlp; 4214fcf3ce44SJohn Forte 421582527734SSukumar Swaminathan cp = (CHANNEL *)sbp->channel; 4216fcf3ce44SJohn Forte ndlp = sbp->node; 4217fcf3ce44SJohn Forte 4218fcf3ce44SJohn Forte /* Create the close XRI IOCB */ 4219*a9800bebSGarrett D'Amore if (hba->state >= FC_LINK_UP) { 4220*a9800bebSGarrett D'Amore iocbq = emlxs_create_abort_xri_cn(port, ndlp, sbp->iotag, cp, 4221*a9800bebSGarrett D'Amore CLASS3, ABORT_TYPE_ABTS); 4222*a9800bebSGarrett D'Amore } else { 4223*a9800bebSGarrett D'Amore iocbq = emlxs_create_close_xri_cn(port, ndlp, sbp->iotag, cp); 4224*a9800bebSGarrett D'Amore } 4225291a2b48SSukumar Swaminathan /* 4226291a2b48SSukumar Swaminathan * Add this iocb to our local abort Q 4227291a2b48SSukumar Swaminathan * This way we don't hold the CHIPQ lock too long 4228291a2b48SSukumar Swaminathan */ 4229fcf3ce44SJohn Forte if (iocbq) { 4230fcf3ce44SJohn Forte if (abort->q_first) { 4231291a2b48SSukumar Swaminathan ((IOCBQ *)abort->q_last)->next = iocbq; 4232fcf3ce44SJohn Forte abort->q_last = (uint8_t *)iocbq; 4233fcf3ce44SJohn Forte abort->q_cnt++; 4234fcf3ce44SJohn Forte } else { 4235fcf3ce44SJohn Forte abort->q_first = (uint8_t *)iocbq; 4236fcf3ce44SJohn Forte abort->q_last = (uint8_t *)iocbq; 4237fcf3ce44SJohn Forte abort->q_cnt = 1; 4238fcf3ce44SJohn Forte } 4239fcf3ce44SJohn Forte iocbq->next = NULL; 4240fcf3ce44SJohn Forte } 4241291a2b48SSukumar Swaminathan 4242fcf3ce44SJohn Forte /* set the flags */ 4243fcf3ce44SJohn Forte mutex_enter(&sbp->mtx); 4244fcf3ce44SJohn Forte 4245fcf3ce44SJohn Forte sbp->pkt_flags |= (PACKET_IN_FLUSH | PACKET_XRI_CLOSED); 424682527734SSukumar Swaminathan 4247fcf3ce44SJohn Forte sbp->ticks = hba->timer_tics + 10; 4248fcf3ce44SJohn Forte sbp->abort_attempts++; 4249fcf3ce44SJohn Forte 425082527734SSukumar Swaminathan flag[cp->channelno] = 1; 4251fcf3ce44SJohn Forte 4252fcf3ce44SJohn Forte /* 4253291a2b48SSukumar Swaminathan * If the fpkt is already set, then we will leave it alone 4254fcf3ce44SJohn Forte * This ensures that this pkt is only accounted for on one 4255fcf3ce44SJohn Forte * fpkt->flush_count 4256fcf3ce44SJohn Forte */ 4257fcf3ce44SJohn Forte if (!sbp->fpkt && fpkt) { 4258fcf3ce44SJohn Forte mutex_enter(&fpkt->mtx); 4259fcf3ce44SJohn Forte sbp->fpkt = fpkt; 4260fcf3ce44SJohn Forte fpkt->flush_count++; 4261fcf3ce44SJohn Forte mutex_exit(&fpkt->mtx); 4262fcf3ce44SJohn Forte } 4263291a2b48SSukumar Swaminathan 4264fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 4265fcf3ce44SJohn Forte 4266fcf3ce44SJohn Forte return; 4267fcf3ce44SJohn Forte 426882527734SSukumar Swaminathan } /* emlxs_sbp_abort_add() */ 4269