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 /* 23291a2b48SSukumar Swaminathan * Copyright 2009 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 */ 161*b3660a96SSukumar Swaminathan 162*b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT 163*b3660a96SSukumar Swaminathan emlxs_check_dma(hba, sbp); 164*b3660a96SSukumar Swaminathan #endif /* FMA_SUPPORT */ 165*b3660a96SSukumar Swaminathan 16682527734SSukumar Swaminathan cp->ulpCmplCmd++; 167fcf3ce44SJohn Forte (*pkt->pkt_comp) (pkt); 168fcf3ce44SJohn Forte 169*b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT 170*b3660a96SSukumar Swaminathan if (hba->flag & FC_DMA_CHECK_ERROR) { 171*b3660a96SSukumar Swaminathan emlxs_thread_spawn(hba, emlxs_restart_thread, 172*b3660a96SSukumar Swaminathan NULL, NULL); 173*b3660a96SSukumar Swaminathan } 174*b3660a96SSukumar Swaminathan #endif /* FMA_SUPPORT */ 175*b3660a96SSukumar 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 */ 214fcf3ce44SJohn Forte if (scsi_status == SCSI_STAT_TASK_ABORT) { 215fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 216fcf3ce44SJohn Forte &emlxs_fcp_completion_error_msg, 217291a2b48SSukumar Swaminathan "Task Abort. " 218291a2b48SSukumar Swaminathan "Fixed.did=0x%06x sbp=%p cmd=%02x dl=%d", 219fcf3ce44SJohn Forte did, sbp, scsi_opcode, pkt->pkt_datalen); 220fcf3ce44SJohn Forte 221fcf3ce44SJohn Forte rsp->fcp_u.fcp_status.scsi_status = 222fcf3ce44SJohn Forte SCSI_STAT_CHECK_COND; 223fcf3ce44SJohn Forte rsp->fcp_u.fcp_status.rsp_len_set = 0; 224fcf3ce44SJohn Forte rsp->fcp_u.fcp_status.sense_len_set = 0; 225fcf3ce44SJohn Forte rsp->fcp_u.fcp_status.resid_over = 0; 226fcf3ce44SJohn Forte 227fcf3ce44SJohn Forte if (pkt->pkt_datalen) { 228fcf3ce44SJohn Forte rsp->fcp_u.fcp_status.resid_under = 1; 229291a2b48SSukumar Swaminathan rsp->fcp_resid = 23082527734SSukumar Swaminathan LE_SWAP32(pkt->pkt_datalen); 231fcf3ce44SJohn Forte } else { 232fcf3ce44SJohn Forte rsp->fcp_u.fcp_status.resid_under = 0; 233fcf3ce44SJohn Forte rsp->fcp_resid = 0; 234fcf3ce44SJohn Forte } 235fcf3ce44SJohn Forte 236fcf3ce44SJohn Forte scsi_status = SCSI_STAT_CHECK_COND; 237fcf3ce44SJohn Forte } 238291a2b48SSukumar Swaminathan 239fcf3ce44SJohn Forte /* 240291a2b48SSukumar Swaminathan * We only need to check underrun if data could 241291a2b48SSukumar Swaminathan * have been sent 242fcf3ce44SJohn Forte */ 243fcf3ce44SJohn Forte 244fcf3ce44SJohn Forte /* Always check underrun if status is good */ 245fcf3ce44SJohn Forte if (scsi_status == SCSI_STAT_GOOD) { 246fcf3ce44SJohn Forte check_underrun = 1; 247fcf3ce44SJohn Forte } 248fcf3ce44SJohn Forte /* Check the sense codes if this is a check condition */ 249fcf3ce44SJohn Forte else if (scsi_status == SCSI_STAT_CHECK_COND) { 250fcf3ce44SJohn Forte check_underrun = 1; 251fcf3ce44SJohn Forte 252fcf3ce44SJohn Forte /* Check if sense data was provided */ 25382527734SSukumar Swaminathan if (LE_SWAP32(rsp->fcp_sense_len) >= 14) { 254fcf3ce44SJohn Forte sense = *((uint8_t *)rsp + 32 + 2); 255fcf3ce44SJohn Forte asc = *((uint8_t *)rsp + 32 + 12); 256fcf3ce44SJohn Forte ascq = *((uint8_t *)rsp + 32 + 13); 257fcf3ce44SJohn Forte } 258291a2b48SSukumar Swaminathan 259291a2b48SSukumar Swaminathan #ifdef SAN_DIAG_SUPPORT 260291a2b48SSukumar Swaminathan emlxs_log_sd_scsi_check_event(port, 261291a2b48SSukumar Swaminathan (HBA_WWN *)&ndlp->nlp_portname, sbp->lun, 262291a2b48SSukumar Swaminathan scsi_opcode, sense, asc, ascq); 263291a2b48SSukumar Swaminathan #endif 264fcf3ce44SJohn Forte } 265fcf3ce44SJohn Forte /* Status is not good and this is not a check condition */ 266fcf3ce44SJohn Forte /* No data should have been sent */ 267fcf3ce44SJohn Forte else { 268fcf3ce44SJohn Forte check_underrun = 0; 269fcf3ce44SJohn Forte } 270fcf3ce44SJohn Forte 271fcf3ce44SJohn Forte /* Get the residual underrun count reported by the SCSI reply */ 272fcf3ce44SJohn Forte rsp_data_resid = (pkt->pkt_datalen && 27382527734SSukumar Swaminathan rsp->fcp_u.fcp_status.resid_under) ? LE_SWAP32(rsp-> 274291a2b48SSukumar Swaminathan fcp_resid) : 0; 275fcf3ce44SJohn Forte 276fcf3ce44SJohn Forte /* Set the pkt resp_resid field */ 277fcf3ce44SJohn Forte pkt->pkt_resp_resid = 0; 278fcf3ce44SJohn Forte 279fcf3ce44SJohn Forte /* Set the pkt data_resid field */ 280fcf3ce44SJohn Forte if (pkt->pkt_datalen && 281fcf3ce44SJohn Forte (pkt->pkt_tran_type == FC_PKT_FCP_READ)) { 282fcf3ce44SJohn Forte /* 283291a2b48SSukumar Swaminathan * Get the residual underrun count reported by 284291a2b48SSukumar Swaminathan * our adapter 285fcf3ce44SJohn Forte */ 286fcf3ce44SJohn Forte pkt->pkt_data_resid = cmd->un.fcpi.fcpi_parm; 287fcf3ce44SJohn Forte 288291a2b48SSukumar Swaminathan #ifdef SAN_DIAG_SUPPORT 289291a2b48SSukumar Swaminathan if ((rsp_data_resid == 0) && (pkt->pkt_data_resid)) { 290291a2b48SSukumar Swaminathan emlxs_log_sd_fc_rdchk_event(port, 291291a2b48SSukumar Swaminathan (HBA_WWN *)&ndlp->nlp_portname, sbp->lun, 292291a2b48SSukumar Swaminathan scsi_opcode, pkt->pkt_data_resid); 293291a2b48SSukumar Swaminathan } 294291a2b48SSukumar Swaminathan #endif 295291a2b48SSukumar Swaminathan 296fcf3ce44SJohn Forte /* Get the actual amount of data transferred */ 297fcf3ce44SJohn Forte data_rx = pkt->pkt_datalen - pkt->pkt_data_resid; 298fcf3ce44SJohn Forte 299fcf3ce44SJohn Forte /* 300fcf3ce44SJohn Forte * If the residual being reported by the adapter is 301fcf3ce44SJohn Forte * greater than the residual being reported in the 302fcf3ce44SJohn Forte * reply, then we have a true underrun. 303fcf3ce44SJohn Forte */ 304fcf3ce44SJohn Forte if (check_underrun && 305fcf3ce44SJohn Forte (pkt->pkt_data_resid > rsp_data_resid)) { 306fcf3ce44SJohn Forte switch (scsi_opcode) { 307fcf3ce44SJohn Forte case SCSI_INQUIRY: 308fcf3ce44SJohn Forte scsi_dl = scsi_cmd[16]; 309fcf3ce44SJohn Forte break; 310fcf3ce44SJohn Forte 311fcf3ce44SJohn Forte case SCSI_RX_DIAG: 312291a2b48SSukumar Swaminathan scsi_dl = 313291a2b48SSukumar Swaminathan (scsi_cmd[15] * 0x100) + 314fcf3ce44SJohn Forte scsi_cmd[16]; 315fcf3ce44SJohn Forte break; 316fcf3ce44SJohn Forte 317fcf3ce44SJohn Forte default: 318fcf3ce44SJohn Forte scsi_dl = pkt->pkt_datalen; 319fcf3ce44SJohn Forte } 320fcf3ce44SJohn Forte 321fcf3ce44SJohn Forte #ifdef FCP_UNDERRUN_PATCH1 32282527734SSukumar Swaminathan if (cfg[CFG_ENABLE_PATCH].current & FCP_UNDERRUN_PATCH1) { 323fcf3ce44SJohn Forte /* 324fcf3ce44SJohn Forte * If status is not good and no data was 325291a2b48SSukumar Swaminathan * actually transferred, then we must fix 326291a2b48SSukumar Swaminathan * the issue 327fcf3ce44SJohn Forte */ 328fcf3ce44SJohn Forte if ((scsi_status != SCSI_STAT_GOOD) && 329fcf3ce44SJohn Forte (data_rx == 0)) { 330fcf3ce44SJohn Forte fix_it = 1; 331fcf3ce44SJohn Forte 332fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 333fcf3ce44SJohn Forte &emlxs_fcp_completion_error_msg, 334291a2b48SSukumar Swaminathan "Underrun(1). Fixed. " 335291a2b48SSukumar Swaminathan "did=0x%06x sbp=%p cmd=%02x " 336291a2b48SSukumar Swaminathan "dl=%d,%d rx=%d rsp=%d", 337fcf3ce44SJohn Forte did, sbp, scsi_opcode, 338fcf3ce44SJohn Forte pkt->pkt_datalen, scsi_dl, 339fcf3ce44SJohn Forte (pkt->pkt_datalen - 340fcf3ce44SJohn Forte cmd->un.fcpi.fcpi_parm), 341fcf3ce44SJohn Forte rsp_data_resid); 342fcf3ce44SJohn Forte 343fcf3ce44SJohn Forte } 34482527734SSukumar Swaminathan } 345291a2b48SSukumar Swaminathan #endif /* FCP_UNDERRUN_PATCH1 */ 346fcf3ce44SJohn Forte 347fcf3ce44SJohn Forte 348fcf3ce44SJohn Forte #ifdef FCP_UNDERRUN_PATCH2 34982527734SSukumar Swaminathan if (cfg[CFG_ENABLE_PATCH].current & FCP_UNDERRUN_PATCH2) { 350fcf3ce44SJohn Forte if ((scsi_status == SCSI_STAT_GOOD)) { 351291a2b48SSukumar Swaminathan emlxs_msg_t *msg; 352fcf3ce44SJohn Forte 353fcf3ce44SJohn Forte msg = &emlxs_fcp_completion_error_msg; 354fcf3ce44SJohn Forte /* 355fcf3ce44SJohn Forte * If status is good and this is an 356fcf3ce44SJohn Forte * inquiry request and the amount of 357fcf3ce44SJohn Forte * data 358fcf3ce44SJohn Forte */ 359fcf3ce44SJohn Forte /* 360291a2b48SSukumar Swaminathan * requested <= data received, then we 361291a2b48SSukumar Swaminathan * must fix the issue. 362fcf3ce44SJohn Forte */ 363fcf3ce44SJohn Forte 364fcf3ce44SJohn Forte if ((scsi_opcode == SCSI_INQUIRY) && 365fcf3ce44SJohn Forte (pkt->pkt_datalen >= data_rx) && 366fcf3ce44SJohn Forte (scsi_dl <= data_rx)) { 367fcf3ce44SJohn Forte fix_it = 1; 368fcf3ce44SJohn Forte 369291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, msg, 370fcf3ce44SJohn Forte "Underrun(2). Fixed. " 371fcf3ce44SJohn Forte "did=0x%06x sbp=%p " 372fcf3ce44SJohn Forte "cmd=%02x dl=%d,%d " 373fcf3ce44SJohn Forte "rx=%d rsp=%d", 374fcf3ce44SJohn Forte did, sbp, scsi_opcode, 375fcf3ce44SJohn Forte pkt->pkt_datalen, scsi_dl, 376fcf3ce44SJohn Forte data_rx, rsp_data_resid); 377fcf3ce44SJohn Forte 378fcf3ce44SJohn Forte } 379291a2b48SSukumar Swaminathan 380fcf3ce44SJohn Forte /* 381fcf3ce44SJohn Forte * If status is good and this is an 382fcf3ce44SJohn Forte * inquiry request and the amount of 383291a2b48SSukumar Swaminathan * data requested >= 128 bytes, but 384291a2b48SSukumar Swaminathan * only 128 bytes were received, 385291a2b48SSukumar Swaminathan * then we must fix the issue. 386fcf3ce44SJohn Forte */ 387291a2b48SSukumar Swaminathan else if ((scsi_opcode == 388291a2b48SSukumar Swaminathan SCSI_INQUIRY) && 389fcf3ce44SJohn Forte (pkt->pkt_datalen >= 128) && 390fcf3ce44SJohn Forte (scsi_dl >= 128) && 391fcf3ce44SJohn Forte (data_rx == 128)) { 392fcf3ce44SJohn Forte fix_it = 1; 393fcf3ce44SJohn Forte 394291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, msg, 395fcf3ce44SJohn Forte "Underrun(3). Fixed. " 396fcf3ce44SJohn Forte "did=0x%06x sbp=%p " 397291a2b48SSukumar Swaminathan "cmd=%02x dl=%d,%d " 398291a2b48SSukumar Swaminathan "rx=%d rsp=%d", 399fcf3ce44SJohn Forte did, sbp, scsi_opcode, 400fcf3ce44SJohn Forte pkt->pkt_datalen, scsi_dl, 401fcf3ce44SJohn Forte data_rx, rsp_data_resid); 402fcf3ce44SJohn Forte 403fcf3ce44SJohn Forte } 404291a2b48SSukumar Swaminathan 405fcf3ce44SJohn Forte } 40682527734SSukumar Swaminathan } 407291a2b48SSukumar Swaminathan #endif /* FCP_UNDERRUN_PATCH2 */ 408fcf3ce44SJohn Forte 409fcf3ce44SJohn Forte /* 410fcf3ce44SJohn Forte * Check if SCSI response payload should be 411291a2b48SSukumar Swaminathan * fixed or if a DATA_UNDERRUN should be 412291a2b48SSukumar Swaminathan * reported 413fcf3ce44SJohn Forte */ 414fcf3ce44SJohn Forte if (fix_it) { 415fcf3ce44SJohn Forte /* 416291a2b48SSukumar Swaminathan * Fix the SCSI response payload itself 417fcf3ce44SJohn Forte */ 418fcf3ce44SJohn Forte rsp->fcp_u.fcp_status.resid_under = 1; 419fcf3ce44SJohn Forte rsp->fcp_resid = 42082527734SSukumar Swaminathan LE_SWAP32(pkt->pkt_data_resid); 421fcf3ce44SJohn Forte } else { 422fcf3ce44SJohn Forte /* 423fcf3ce44SJohn Forte * Change the status from 424fcf3ce44SJohn Forte * IOSTAT_FCP_RSP_ERROR to 425fcf3ce44SJohn Forte * IOSTAT_DATA_UNDERRUN 426fcf3ce44SJohn Forte */ 427fcf3ce44SJohn Forte iostat = IOSTAT_DATA_UNDERRUN; 428291a2b48SSukumar Swaminathan pkt->pkt_data_resid = 429291a2b48SSukumar Swaminathan pkt->pkt_datalen; 430fcf3ce44SJohn Forte } 431fcf3ce44SJohn Forte } 432291a2b48SSukumar Swaminathan 433fcf3ce44SJohn Forte /* 434fcf3ce44SJohn Forte * If the residual being reported by the adapter is 435291a2b48SSukumar Swaminathan * less than the residual being reported in the reply, 436291a2b48SSukumar Swaminathan * then we have a true overrun. Since we don't know 437291a2b48SSukumar Swaminathan * where the extra data came from or went to then we 438291a2b48SSukumar Swaminathan * cannot trust anything we received 439fcf3ce44SJohn Forte */ 440fcf3ce44SJohn Forte else if (rsp_data_resid > pkt->pkt_data_resid) { 441fcf3ce44SJohn Forte /* 442fcf3ce44SJohn Forte * Change the status from 443fcf3ce44SJohn Forte * IOSTAT_FCP_RSP_ERROR to 444fcf3ce44SJohn Forte * IOSTAT_DATA_OVERRUN 445fcf3ce44SJohn Forte */ 446fcf3ce44SJohn Forte iostat = IOSTAT_DATA_OVERRUN; 447fcf3ce44SJohn Forte pkt->pkt_data_resid = pkt->pkt_datalen; 448fcf3ce44SJohn Forte } 449fcf3ce44SJohn Forte } else { /* pkt->pkt_datalen==0 or FC_PKT_FCP_WRITE */ 450291a2b48SSukumar Swaminathan 451fcf3ce44SJohn Forte /* Report whatever the target reported */ 452fcf3ce44SJohn Forte pkt->pkt_data_resid = rsp_data_resid; 453fcf3ce44SJohn Forte } 454fcf3ce44SJohn Forte } 455291a2b48SSukumar Swaminathan 456fcf3ce44SJohn Forte /* Print completion message */ 457fcf3ce44SJohn Forte switch (iostat) { 458fcf3ce44SJohn Forte case IOSTAT_SUCCESS: 459fcf3ce44SJohn Forte /* Build SCSI GOOD status */ 460fcf3ce44SJohn Forte if (pkt->pkt_rsplen) { 461fcf3ce44SJohn Forte bzero((uint8_t *)pkt->pkt_resp, pkt->pkt_rsplen); 462fcf3ce44SJohn Forte } 463fcf3ce44SJohn Forte break; 464fcf3ce44SJohn Forte 465fcf3ce44SJohn Forte case IOSTAT_FCP_RSP_ERROR: 466fcf3ce44SJohn Forte break; 467fcf3ce44SJohn Forte 468fcf3ce44SJohn Forte case IOSTAT_REMOTE_STOP: 469fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, 470291a2b48SSukumar Swaminathan "Remote Stop. did=0x%06x sbp=%p cmd=%02x", did, sbp, 471291a2b48SSukumar Swaminathan scsi_opcode); 472fcf3ce44SJohn Forte break; 473fcf3ce44SJohn Forte 474fcf3ce44SJohn Forte case IOSTAT_LOCAL_REJECT: 475fcf3ce44SJohn Forte localstat = cmd->un.grsp.perr.statLocalError; 476fcf3ce44SJohn Forte 477fcf3ce44SJohn Forte switch (localstat) { 478fcf3ce44SJohn Forte case IOERR_SEQUENCE_TIMEOUT: 479fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 480fcf3ce44SJohn Forte &emlxs_fcp_completion_error_msg, 481291a2b48SSukumar Swaminathan "Local reject. " 482291a2b48SSukumar Swaminathan "%s did=0x%06x sbp=%p cmd=%02x tmo=%d ", 483fcf3ce44SJohn Forte emlxs_error_xlate(localstat), did, sbp, 484fcf3ce44SJohn Forte scsi_opcode, pkt->pkt_timeout); 485fcf3ce44SJohn Forte break; 486fcf3ce44SJohn Forte 487fcf3ce44SJohn Forte default: 488fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 489fcf3ce44SJohn Forte &emlxs_fcp_completion_error_msg, 490fcf3ce44SJohn Forte "Local reject. %s did=0x%06x sbp=%p cmd=%02x", 491291a2b48SSukumar Swaminathan emlxs_error_xlate(localstat), did, sbp, 492291a2b48SSukumar Swaminathan scsi_opcode); 493fcf3ce44SJohn Forte } 494fcf3ce44SJohn Forte 495fcf3ce44SJohn Forte break; 496fcf3ce44SJohn Forte 497fcf3ce44SJohn Forte case IOSTAT_NPORT_RJT: 498fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, 499291a2b48SSukumar Swaminathan "Nport reject. did=0x%06x sbp=%p cmd=%02x", did, sbp, 500291a2b48SSukumar Swaminathan scsi_opcode); 501fcf3ce44SJohn Forte break; 502fcf3ce44SJohn Forte 503fcf3ce44SJohn Forte case IOSTAT_FABRIC_RJT: 504fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, 505291a2b48SSukumar Swaminathan "Fabric reject. did=0x%06x sbp=%p cmd=%02x", did, sbp, 506291a2b48SSukumar Swaminathan scsi_opcode); 507fcf3ce44SJohn Forte break; 508fcf3ce44SJohn Forte 509fcf3ce44SJohn Forte case IOSTAT_NPORT_BSY: 510291a2b48SSukumar Swaminathan #ifdef SAN_DIAG_SUPPORT 511291a2b48SSukumar Swaminathan ndlp = (NODELIST *)iocbq->node; 512291a2b48SSukumar Swaminathan emlxs_log_sd_fc_bsy_event(port, (HBA_WWN *)&ndlp->nlp_portname); 513291a2b48SSukumar Swaminathan #endif 514291a2b48SSukumar Swaminathan 515fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, 516291a2b48SSukumar Swaminathan "Nport busy. did=0x%06x sbp=%p cmd=%02x", did, sbp, 517291a2b48SSukumar Swaminathan scsi_opcode); 518fcf3ce44SJohn Forte break; 519fcf3ce44SJohn Forte 520fcf3ce44SJohn Forte case IOSTAT_FABRIC_BSY: 521291a2b48SSukumar Swaminathan #ifdef SAN_DIAG_SUPPORT 522291a2b48SSukumar Swaminathan ndlp = (NODELIST *)iocbq->node; 523291a2b48SSukumar Swaminathan emlxs_log_sd_fc_bsy_event(port, NULL); 524291a2b48SSukumar Swaminathan #endif 525291a2b48SSukumar Swaminathan 526fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, 527291a2b48SSukumar Swaminathan "Fabric busy. did=0x%06x sbp=%p cmd=%02x", did, sbp, 528291a2b48SSukumar Swaminathan scsi_opcode); 529fcf3ce44SJohn Forte break; 530fcf3ce44SJohn Forte 531fcf3ce44SJohn Forte case IOSTAT_INTERMED_RSP: 532fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, 533291a2b48SSukumar Swaminathan "Intermediate response. did=0x%06x sbp=%p cmd=%02x", did, 534291a2b48SSukumar Swaminathan sbp, scsi_opcode); 535fcf3ce44SJohn Forte break; 536fcf3ce44SJohn Forte 537fcf3ce44SJohn Forte case IOSTAT_LS_RJT: 538fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, 539291a2b48SSukumar Swaminathan "LS Reject. did=0x%06x sbp=%p cmd=%02x", did, sbp, 540291a2b48SSukumar Swaminathan scsi_opcode); 541fcf3ce44SJohn Forte break; 542fcf3ce44SJohn Forte 543fcf3ce44SJohn Forte case IOSTAT_DATA_UNDERRUN: 544fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, 545291a2b48SSukumar Swaminathan "Underrun. did=0x%06x sbp=%p cmd=%02x " 546291a2b48SSukumar Swaminathan "dl=%d,%d rx=%d rsp=%d (%02x,%02x,%02x,%02x)", 547291a2b48SSukumar Swaminathan did, sbp, scsi_opcode, pkt->pkt_datalen, scsi_dl, data_rx, 548291a2b48SSukumar Swaminathan rsp_data_resid, scsi_status, sense, asc, ascq); 549fcf3ce44SJohn Forte break; 550fcf3ce44SJohn Forte 551fcf3ce44SJohn Forte case IOSTAT_DATA_OVERRUN: 552fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, 553291a2b48SSukumar Swaminathan "Overrun. did=0x%06x sbp=%p cmd=%02x " 554291a2b48SSukumar Swaminathan "dl=%d,%d rx=%d rsp=%d (%02x,%02x,%02x,%02x)", 555291a2b48SSukumar Swaminathan did, sbp, scsi_opcode, pkt->pkt_datalen, scsi_dl, data_rx, 556291a2b48SSukumar Swaminathan rsp_data_resid, scsi_status, sense, asc, ascq); 557fcf3ce44SJohn Forte break; 558fcf3ce44SJohn Forte 559fcf3ce44SJohn Forte default: 560fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, 561fcf3ce44SJohn Forte "Unknown status=%x reason=%x did=0x%06x sbp=%p cmd=%02x", 562291a2b48SSukumar Swaminathan iostat, cmd->un.grsp.perr.statLocalError, did, sbp, 563291a2b48SSukumar Swaminathan scsi_opcode); 564fcf3ce44SJohn Forte break; 565fcf3ce44SJohn Forte } 566fcf3ce44SJohn Forte 567fcf3ce44SJohn Forte done: 568fcf3ce44SJohn Forte 569fcf3ce44SJohn Forte if (iostat == IOSTAT_SUCCESS) { 570fcf3ce44SJohn Forte HBASTATS.FcpGood++; 571fcf3ce44SJohn Forte } else { 572fcf3ce44SJohn Forte HBASTATS.FcpError++; 573fcf3ce44SJohn Forte } 574fcf3ce44SJohn Forte 575fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 576fcf3ce44SJohn Forte 577fcf3ce44SJohn Forte emlxs_pkt_complete(sbp, iostat, localstat, 0); 578fcf3ce44SJohn Forte 579fcf3ce44SJohn Forte return; 580fcf3ce44SJohn Forte 58182527734SSukumar Swaminathan } /* emlxs_handle_fcp_event() */ 582fcf3ce44SJohn Forte 583fcf3ce44SJohn Forte 584fcf3ce44SJohn Forte 585fcf3ce44SJohn Forte /* 586fcf3ce44SJohn Forte * emlxs_post_buffer 587fcf3ce44SJohn Forte * 588fcf3ce44SJohn Forte * This routine will post count buffers to the 589fcf3ce44SJohn Forte * ring with the QUE_RING_BUF_CN command. This 590fcf3ce44SJohn Forte * allows 2 buffers / command to be posted. 591fcf3ce44SJohn Forte * Returns the number of buffers NOT posted. 592fcf3ce44SJohn Forte */ 59382527734SSukumar Swaminathan /* SLI3 */ 594fcf3ce44SJohn Forte extern int 595fcf3ce44SJohn Forte emlxs_post_buffer(emlxs_hba_t *hba, RING *rp, int16_t cnt) 596fcf3ce44SJohn Forte { 597fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 598fcf3ce44SJohn Forte IOCB *icmd; 599fcf3ce44SJohn Forte IOCBQ *iocbq; 600fcf3ce44SJohn Forte MATCHMAP *mp; 601fcf3ce44SJohn Forte uint16_t tag; 602fcf3ce44SJohn Forte uint32_t maxqbuf; 603fcf3ce44SJohn Forte int32_t i; 604fcf3ce44SJohn Forte int32_t j; 605fcf3ce44SJohn Forte uint32_t seg; 606fcf3ce44SJohn Forte uint32_t size; 607fcf3ce44SJohn Forte 608fcf3ce44SJohn Forte mp = 0; 609fcf3ce44SJohn Forte maxqbuf = 2; 610fcf3ce44SJohn Forte tag = (uint16_t)cnt; 611fcf3ce44SJohn Forte cnt += rp->fc_missbufcnt; 612fcf3ce44SJohn Forte 61382527734SSukumar Swaminathan if (rp->ringno == hba->channel_els) { 614fcf3ce44SJohn Forte seg = MEM_BUF; 615fcf3ce44SJohn Forte size = MEM_ELSBUF_SIZE; 61682527734SSukumar Swaminathan } else if (rp->ringno == hba->channel_ip) { 617fcf3ce44SJohn Forte seg = MEM_IPBUF; 618fcf3ce44SJohn Forte size = MEM_IPBUF_SIZE; 61982527734SSukumar Swaminathan } else if (rp->ringno == hba->channel_ct) { 620fcf3ce44SJohn Forte seg = MEM_CTBUF; 621fcf3ce44SJohn Forte size = MEM_CTBUF_SIZE; 622fcf3ce44SJohn Forte } 623fcf3ce44SJohn Forte #ifdef SFCT_SUPPORT 62482527734SSukumar Swaminathan else if (rp->ringno == hba->CHANNEL_FCT) { 625fcf3ce44SJohn Forte seg = MEM_FCTBUF; 626fcf3ce44SJohn Forte size = MEM_FCTBUF_SIZE; 627fcf3ce44SJohn Forte } 628291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 629fcf3ce44SJohn Forte else { 630fcf3ce44SJohn Forte return (0); 631fcf3ce44SJohn Forte } 632fcf3ce44SJohn Forte 633fcf3ce44SJohn Forte /* 634fcf3ce44SJohn Forte * While there are buffers to post 635fcf3ce44SJohn Forte */ 636fcf3ce44SJohn Forte while (cnt) { 63782527734SSukumar Swaminathan if ((iocbq = (IOCBQ *)emlxs_mem_get(hba, MEM_IOCB, 0)) == 0) { 638fcf3ce44SJohn Forte rp->fc_missbufcnt = cnt; 639fcf3ce44SJohn Forte return (cnt); 640fcf3ce44SJohn Forte } 641291a2b48SSukumar Swaminathan 64282527734SSukumar Swaminathan iocbq->channel = (void *)&hba->chan[rp->ringno]; 643fcf3ce44SJohn Forte iocbq->port = (void *)port; 644fcf3ce44SJohn Forte iocbq->flag |= (IOCB_PRIORITY | IOCB_SPECIAL); 645fcf3ce44SJohn Forte 646fcf3ce44SJohn Forte icmd = &iocbq->iocb; 647fcf3ce44SJohn Forte 648fcf3ce44SJohn Forte /* 649fcf3ce44SJohn Forte * Max buffers can be posted per command 650fcf3ce44SJohn Forte */ 651fcf3ce44SJohn Forte for (i = 0; i < maxqbuf; i++) { 652fcf3ce44SJohn Forte if (cnt <= 0) 653fcf3ce44SJohn Forte break; 654fcf3ce44SJohn Forte 655fcf3ce44SJohn Forte /* fill in BDEs for command */ 65682527734SSukumar Swaminathan if ((mp = (MATCHMAP *)emlxs_mem_get(hba, seg, 1)) 65782527734SSukumar Swaminathan == 0) { 65882527734SSukumar Swaminathan icmd->ULPBDECOUNT = i; 659fcf3ce44SJohn Forte for (j = 0; j < i; j++) { 660291a2b48SSukumar Swaminathan mp = EMLXS_GET_VADDR(hba, rp, icmd); 661fcf3ce44SJohn Forte if (mp) { 662fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, seg, 663fcf3ce44SJohn Forte (uint8_t *)mp); 664fcf3ce44SJohn Forte } 665fcf3ce44SJohn Forte } 666fcf3ce44SJohn Forte 667fcf3ce44SJohn Forte rp->fc_missbufcnt = cnt + i; 668fcf3ce44SJohn Forte 669fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_IOCB, 670fcf3ce44SJohn Forte (uint8_t *)iocbq); 671fcf3ce44SJohn Forte 672fcf3ce44SJohn Forte return (cnt + i); 673fcf3ce44SJohn Forte } 674291a2b48SSukumar Swaminathan 675fcf3ce44SJohn Forte /* 676fcf3ce44SJohn Forte * map that page and save the address pair for lookup 677fcf3ce44SJohn Forte * later 678fcf3ce44SJohn Forte */ 679291a2b48SSukumar Swaminathan emlxs_mem_map_vaddr(hba, 680291a2b48SSukumar Swaminathan rp, 681291a2b48SSukumar Swaminathan mp, 682fcf3ce44SJohn Forte (uint32_t *)&icmd->un.cont64[i].addrHigh, 683fcf3ce44SJohn Forte (uint32_t *)&icmd->un.cont64[i].addrLow); 684fcf3ce44SJohn Forte 685fcf3ce44SJohn Forte icmd->un.cont64[i].tus.f.bdeSize = size; 68682527734SSukumar Swaminathan icmd->ULPCOMMAND = CMD_QUE_RING_BUF64_CN; 687fcf3ce44SJohn Forte 688291a2b48SSukumar Swaminathan /* 689291a2b48SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 690291a2b48SSukumar Swaminathan * "UB Post: ring=%d addr=%08x%08x size=%d", 691291a2b48SSukumar Swaminathan * rp->ringno, icmd->un.cont64[i].addrHigh, 692291a2b48SSukumar Swaminathan * icmd->un.cont64[i].addrLow, size); 693291a2b48SSukumar Swaminathan */ 694fcf3ce44SJohn Forte 695fcf3ce44SJohn Forte cnt--; 696fcf3ce44SJohn Forte } 697fcf3ce44SJohn Forte 69882527734SSukumar Swaminathan icmd->ULPIOTAG = tag; 69982527734SSukumar Swaminathan icmd->ULPBDECOUNT = i; 70082527734SSukumar Swaminathan icmd->ULPLE = 1; 70182527734SSukumar Swaminathan icmd->ULPOWNER = OWN_CHIP; 702291a2b48SSukumar Swaminathan /* used for delimiter between commands */ 703291a2b48SSukumar Swaminathan iocbq->bp = (uint8_t *)mp; 704fcf3ce44SJohn Forte 70582527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, &hba->chan[rp->ringno], iocbq); 706fcf3ce44SJohn Forte } 707fcf3ce44SJohn Forte 708fcf3ce44SJohn Forte rp->fc_missbufcnt = 0; 709fcf3ce44SJohn Forte 710fcf3ce44SJohn Forte return (0); 711fcf3ce44SJohn Forte 71282527734SSukumar Swaminathan } /* emlxs_post_buffer() */ 713fcf3ce44SJohn Forte 714fcf3ce44SJohn Forte 715fcf3ce44SJohn Forte extern int 716fcf3ce44SJohn Forte emlxs_port_offline(emlxs_port_t *port, uint32_t scope) 717fcf3ce44SJohn Forte { 718fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 719fcf3ce44SJohn Forte emlxs_config_t *cfg; 720fcf3ce44SJohn Forte NODELIST *nlp; 721fcf3ce44SJohn Forte fc_affected_id_t *aid; 722fcf3ce44SJohn Forte uint32_t mask; 723fcf3ce44SJohn Forte uint32_t aff_d_id; 724fcf3ce44SJohn Forte uint32_t linkdown; 725fcf3ce44SJohn Forte uint32_t vlinkdown; 726fcf3ce44SJohn Forte uint32_t action; 727fcf3ce44SJohn Forte int i; 728fcf3ce44SJohn Forte uint32_t unreg_vpi; 729fcf3ce44SJohn Forte uint32_t update; 730fcf3ce44SJohn Forte uint32_t adisc_support; 7313be114edSSukumar Swaminathan uint8_t format; 732fcf3ce44SJohn Forte 733fcf3ce44SJohn Forte /* Target mode only uses this routine for linkdowns */ 734fcf3ce44SJohn Forte if (port->tgt_mode && (scope != 0xffffffff) && (scope != 0xfeffffff)) { 735fcf3ce44SJohn Forte return (0); 736fcf3ce44SJohn Forte } 737291a2b48SSukumar Swaminathan 738fcf3ce44SJohn Forte cfg = &CFG; 739fcf3ce44SJohn Forte aid = (fc_affected_id_t *)&scope; 740fcf3ce44SJohn Forte linkdown = 0; 741fcf3ce44SJohn Forte vlinkdown = 0; 742fcf3ce44SJohn Forte unreg_vpi = 0; 743fcf3ce44SJohn Forte update = 0; 744fcf3ce44SJohn Forte 745fcf3ce44SJohn Forte if (!(port->flag & EMLXS_PORT_BOUND)) { 746fcf3ce44SJohn Forte return (0); 747fcf3ce44SJohn Forte } 748291a2b48SSukumar Swaminathan 7493be114edSSukumar Swaminathan format = aid->aff_format; 7503be114edSSukumar Swaminathan 7513be114edSSukumar Swaminathan switch (format) { 752fcf3ce44SJohn Forte case 0: /* Port */ 753fcf3ce44SJohn Forte mask = 0x00ffffff; 754fcf3ce44SJohn Forte break; 755fcf3ce44SJohn Forte 756fcf3ce44SJohn Forte case 1: /* Area */ 757fcf3ce44SJohn Forte mask = 0x00ffff00; 758fcf3ce44SJohn Forte break; 759fcf3ce44SJohn Forte 760fcf3ce44SJohn Forte case 2: /* Domain */ 761fcf3ce44SJohn Forte mask = 0x00ff0000; 762fcf3ce44SJohn Forte break; 763fcf3ce44SJohn Forte 764fcf3ce44SJohn Forte case 3: /* Network */ 765fcf3ce44SJohn Forte mask = 0x00000000; 766fcf3ce44SJohn Forte break; 767fcf3ce44SJohn Forte 768fcf3ce44SJohn Forte #ifdef DHCHAP_SUPPORT 769fcf3ce44SJohn Forte case 0xfe: /* Virtual link down */ 770fcf3ce44SJohn Forte mask = 0x00000000; 771fcf3ce44SJohn Forte vlinkdown = 1; 772fcf3ce44SJohn Forte break; 773291a2b48SSukumar Swaminathan #endif /* DHCHAP_SUPPORT */ 774fcf3ce44SJohn Forte 775fcf3ce44SJohn Forte case 0xff: /* link is down */ 776fcf3ce44SJohn Forte mask = 0x00000000; 777fcf3ce44SJohn Forte linkdown = 1; 778fcf3ce44SJohn Forte break; 779fcf3ce44SJohn Forte 780fcf3ce44SJohn Forte } 781fcf3ce44SJohn Forte 782fcf3ce44SJohn Forte aff_d_id = aid->aff_d_id & mask; 783fcf3ce44SJohn Forte 784fcf3ce44SJohn Forte 785fcf3ce44SJohn Forte /* 786291a2b48SSukumar Swaminathan * If link is down then this is a hard shutdown and flush 787291a2b48SSukumar Swaminathan * If link not down then this is a soft shutdown and flush 788291a2b48SSukumar Swaminathan * (e.g. RSCN) 789fcf3ce44SJohn Forte */ 790fcf3ce44SJohn Forte if (linkdown) { 791fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 792fcf3ce44SJohn Forte 793fcf3ce44SJohn Forte port->flag &= EMLXS_PORT_LINKDOWN_MASK; 794fcf3ce44SJohn Forte port->prev_did = port->did; 795fcf3ce44SJohn Forte port->did = 0; 796fcf3ce44SJohn Forte 797fcf3ce44SJohn Forte if (port->ulp_statec != FC_STATE_OFFLINE) { 798fcf3ce44SJohn Forte port->ulp_statec = FC_STATE_OFFLINE; 799fcf3ce44SJohn Forte update = 1; 800fcf3ce44SJohn Forte } 801291a2b48SSukumar Swaminathan 802fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 803fcf3ce44SJohn Forte 804fcf3ce44SJohn Forte /* Tell ULP about it */ 805fcf3ce44SJohn Forte if (update) { 806fcf3ce44SJohn Forte if (port->flag & EMLXS_PORT_BOUND) { 807fcf3ce44SJohn Forte if (port->vpi == 0) { 808fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 809291a2b48SSukumar Swaminathan &emlxs_link_down_msg, NULL); 810fcf3ce44SJohn Forte } 811291a2b48SSukumar Swaminathan 8123be114edSSukumar Swaminathan if (port->ini_mode) { 8133be114edSSukumar Swaminathan port->ulp_statec_cb(port->ulp_handle, 8143be114edSSukumar Swaminathan FC_STATE_OFFLINE); 8153be114edSSukumar Swaminathan } 816291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT 8173be114edSSukumar Swaminathan else if (port->tgt_mode) { 818fcf3ce44SJohn Forte emlxs_fct_link_down(port); 8193be114edSSukumar Swaminathan } 820291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 821fcf3ce44SJohn Forte 822fcf3ce44SJohn Forte } else { 823fcf3ce44SJohn Forte if (port->vpi == 0) { 824fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 825291a2b48SSukumar Swaminathan &emlxs_link_down_msg, "*"); 826fcf3ce44SJohn Forte } 827fcf3ce44SJohn Forte } 828fcf3ce44SJohn Forte 829fcf3ce44SJohn Forte 830fcf3ce44SJohn Forte } 831291a2b48SSukumar Swaminathan 832fcf3ce44SJohn Forte unreg_vpi = 1; 833fcf3ce44SJohn Forte 834fcf3ce44SJohn Forte #ifdef DHCHAP_SUPPORT 835fcf3ce44SJohn Forte /* Stop authentication with all nodes */ 836fcf3ce44SJohn Forte emlxs_dhc_auth_stop(port, NULL); 837291a2b48SSukumar Swaminathan #endif /* DHCHAP_SUPPORT */ 838fcf3ce44SJohn Forte 839fcf3ce44SJohn Forte /* Flush the base node */ 840fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, &port->node_base, 0, 0, 0); 841fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 0, &port->node_base, 0); 842fcf3ce44SJohn Forte 843fcf3ce44SJohn Forte /* Flush any pending ub buffers */ 844fcf3ce44SJohn Forte emlxs_ub_flush(port); 845fcf3ce44SJohn Forte } 846fcf3ce44SJohn Forte #ifdef DHCHAP_SUPPORT 847fcf3ce44SJohn Forte /* virtual link down */ 848fcf3ce44SJohn Forte else if (vlinkdown) { 849fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 850fcf3ce44SJohn Forte 851fcf3ce44SJohn Forte if (port->ulp_statec != FC_STATE_OFFLINE) { 852fcf3ce44SJohn Forte port->ulp_statec = FC_STATE_OFFLINE; 853fcf3ce44SJohn Forte update = 1; 854fcf3ce44SJohn Forte } 855291a2b48SSukumar Swaminathan 856fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 857fcf3ce44SJohn Forte 858fcf3ce44SJohn Forte /* Tell ULP about it */ 859fcf3ce44SJohn Forte if (update) { 860fcf3ce44SJohn Forte if (port->flag & EMLXS_PORT_BOUND) { 861fcf3ce44SJohn Forte if (port->vpi == 0) { 862fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 863fcf3ce44SJohn Forte &emlxs_link_down_msg, 864fcf3ce44SJohn Forte "Switch authentication failed."); 865fcf3ce44SJohn Forte } 866291a2b48SSukumar Swaminathan 867fcf3ce44SJohn Forte #ifdef SFCT_SUPPORT 868fcf3ce44SJohn Forte if (port->tgt_mode) { 869fcf3ce44SJohn Forte emlxs_fct_link_down(port); 870291a2b48SSukumar Swaminathan 871fcf3ce44SJohn Forte } else if (port->ini_mode) { 872fcf3ce44SJohn Forte port->ulp_statec_cb(port->ulp_handle, 873fcf3ce44SJohn Forte FC_STATE_OFFLINE); 874fcf3ce44SJohn Forte } 875fcf3ce44SJohn Forte #else 876fcf3ce44SJohn Forte port->ulp_statec_cb(port->ulp_handle, 877fcf3ce44SJohn Forte FC_STATE_OFFLINE); 878fcf3ce44SJohn Forte #endif /* SFCT_SUPPORT */ 879fcf3ce44SJohn Forte } else { 880fcf3ce44SJohn Forte if (port->vpi == 0) { 881fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 882fcf3ce44SJohn Forte &emlxs_link_down_msg, 883fcf3ce44SJohn Forte "Switch authentication failed. *"); 884fcf3ce44SJohn Forte } 885fcf3ce44SJohn Forte } 886fcf3ce44SJohn Forte 887fcf3ce44SJohn Forte 888fcf3ce44SJohn Forte } 889291a2b48SSukumar Swaminathan 890fcf3ce44SJohn Forte /* Flush the base node */ 891fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, &port->node_base, 0, 0, 0); 892fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 0, &port->node_base, 0); 893fcf3ce44SJohn Forte } 894291a2b48SSukumar Swaminathan #endif /* DHCHAP_SUPPORT */ 895fcf3ce44SJohn Forte 896fcf3ce44SJohn Forte if (port->tgt_mode) { 897fcf3ce44SJohn Forte goto done; 898fcf3ce44SJohn Forte } 899291a2b48SSukumar Swaminathan 900fcf3ce44SJohn Forte /* Set the node tags */ 901fcf3ce44SJohn Forte /* We will process all nodes with this tag */ 902fcf3ce44SJohn Forte rw_enter(&port->node_rwlock, RW_READER); 903fcf3ce44SJohn Forte for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 904fcf3ce44SJohn Forte nlp = port->node_table[i]; 905fcf3ce44SJohn Forte while (nlp != NULL) { 906fcf3ce44SJohn Forte nlp->nlp_tag = 1; 907fcf3ce44SJohn Forte nlp = nlp->nlp_list_next; 908fcf3ce44SJohn Forte } 909fcf3ce44SJohn Forte } 910fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 911fcf3ce44SJohn Forte 912fcf3ce44SJohn Forte if (hba->flag & FC_ONLINE_MODE) { 913fcf3ce44SJohn Forte adisc_support = cfg[CFG_ADISC_SUPPORT].current; 914fcf3ce44SJohn Forte } else { 915fcf3ce44SJohn Forte adisc_support = 0; 916fcf3ce44SJohn Forte } 917fcf3ce44SJohn Forte 918fcf3ce44SJohn Forte /* Check ADISC support level */ 919fcf3ce44SJohn Forte switch (adisc_support) { 920fcf3ce44SJohn Forte case 0: /* No support - Flush all IO to all matching nodes */ 921fcf3ce44SJohn Forte 922291a2b48SSukumar Swaminathan for (;;) { 923fcf3ce44SJohn Forte /* 924fcf3ce44SJohn Forte * We need to hold the locks this way because 925291a2b48SSukumar Swaminathan * emlxs_mb_unreg_did and the flush routines enter the 926291a2b48SSukumar Swaminathan * same locks. Also, when we release the lock the list 927291a2b48SSukumar Swaminathan * can change out from under us. 928fcf3ce44SJohn Forte */ 929fcf3ce44SJohn Forte 930fcf3ce44SJohn Forte /* Find first node */ 931fcf3ce44SJohn Forte rw_enter(&port->node_rwlock, RW_READER); 932fcf3ce44SJohn Forte action = 0; 933fcf3ce44SJohn Forte for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 934fcf3ce44SJohn Forte nlp = port->node_table[i]; 935fcf3ce44SJohn Forte while (nlp != NULL) { 936fcf3ce44SJohn Forte if (!nlp->nlp_tag) { 937fcf3ce44SJohn Forte nlp = nlp->nlp_list_next; 938fcf3ce44SJohn Forte continue; 939fcf3ce44SJohn Forte } 940fcf3ce44SJohn Forte nlp->nlp_tag = 0; 941fcf3ce44SJohn Forte 942fcf3ce44SJohn Forte /* 943fcf3ce44SJohn Forte * Check for any device that matches 944fcf3ce44SJohn Forte * our mask 945fcf3ce44SJohn Forte */ 946fcf3ce44SJohn Forte if ((nlp->nlp_DID & mask) == aff_d_id) { 947fcf3ce44SJohn Forte if (linkdown) { 948fcf3ce44SJohn Forte action = 1; 949fcf3ce44SJohn Forte break; 950291a2b48SSukumar Swaminathan } else { /* Must be an RCSN */ 951291a2b48SSukumar Swaminathan 952fcf3ce44SJohn Forte action = 2; 953fcf3ce44SJohn Forte break; 954fcf3ce44SJohn Forte } 955fcf3ce44SJohn Forte } 956fcf3ce44SJohn Forte nlp = nlp->nlp_list_next; 957fcf3ce44SJohn Forte } 958fcf3ce44SJohn Forte 959fcf3ce44SJohn Forte if (action) { 960fcf3ce44SJohn Forte break; 961fcf3ce44SJohn Forte } 962fcf3ce44SJohn Forte } 963fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 964fcf3ce44SJohn Forte 965fcf3ce44SJohn Forte 966fcf3ce44SJohn Forte /* Check if nothing was found */ 967fcf3ce44SJohn Forte if (action == 0) { 968fcf3ce44SJohn Forte break; 969fcf3ce44SJohn Forte } else if (action == 1) { 970fcf3ce44SJohn Forte (void) emlxs_mb_unreg_did(port, nlp->nlp_DID, 971fcf3ce44SJohn Forte NULL, NULL, NULL); 972fcf3ce44SJohn Forte } else if (action == 2) { 973fcf3ce44SJohn Forte #ifdef DHCHAP_SUPPORT 974fcf3ce44SJohn Forte emlxs_dhc_auth_stop(port, nlp); 975291a2b48SSukumar Swaminathan #endif /* DHCHAP_SUPPORT */ 976fcf3ce44SJohn Forte 977291a2b48SSukumar Swaminathan /* 978291a2b48SSukumar Swaminathan * Close the node for any further normal IO 979291a2b48SSukumar Swaminathan * A PLOGI with reopen the node 980291a2b48SSukumar Swaminathan */ 98182527734SSukumar Swaminathan emlxs_node_close(port, nlp, 98282527734SSukumar Swaminathan hba->channel_fcp, 60); 98382527734SSukumar Swaminathan emlxs_node_close(port, nlp, 98482527734SSukumar Swaminathan hba->channel_ip, 60); 985fcf3ce44SJohn Forte 986fcf3ce44SJohn Forte /* Flush tx queue */ 987fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, nlp, 0, 0, 0); 988fcf3ce44SJohn Forte 989fcf3ce44SJohn Forte /* Flush chip queue */ 990fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 0, nlp, 0); 991fcf3ce44SJohn Forte } 992291a2b48SSukumar Swaminathan 993fcf3ce44SJohn Forte } 994fcf3ce44SJohn Forte 995fcf3ce44SJohn Forte break; 996fcf3ce44SJohn Forte 997291a2b48SSukumar Swaminathan case 1: /* Partial support - Flush IO for non-FCP2 matching nodes */ 998fcf3ce44SJohn Forte 999fcf3ce44SJohn Forte for (;;) { 1000fcf3ce44SJohn Forte 1001fcf3ce44SJohn Forte /* 1002fcf3ce44SJohn Forte * We need to hold the locks this way because 1003291a2b48SSukumar Swaminathan * emlxs_mb_unreg_did and the flush routines enter the 1004291a2b48SSukumar Swaminathan * same locks. Also, when we release the lock the list 1005291a2b48SSukumar Swaminathan * can change out from under us. 1006fcf3ce44SJohn Forte */ 1007fcf3ce44SJohn Forte rw_enter(&port->node_rwlock, RW_READER); 1008fcf3ce44SJohn Forte action = 0; 1009fcf3ce44SJohn Forte for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 1010fcf3ce44SJohn Forte nlp = port->node_table[i]; 1011fcf3ce44SJohn Forte while (nlp != NULL) { 1012fcf3ce44SJohn Forte if (!nlp->nlp_tag) { 1013fcf3ce44SJohn Forte nlp = nlp->nlp_list_next; 1014fcf3ce44SJohn Forte continue; 1015fcf3ce44SJohn Forte } 1016fcf3ce44SJohn Forte nlp->nlp_tag = 0; 1017fcf3ce44SJohn Forte 1018fcf3ce44SJohn Forte /* 1019291a2b48SSukumar Swaminathan * Check for special FCP2 target device 1020291a2b48SSukumar Swaminathan * that matches our mask 1021fcf3ce44SJohn Forte */ 1022fcf3ce44SJohn Forte if ((nlp->nlp_fcp_info & 1023fcf3ce44SJohn Forte NLP_FCP_TGT_DEVICE) && 1024291a2b48SSukumar Swaminathan (nlp-> nlp_fcp_info & 1025fcf3ce44SJohn Forte NLP_FCP_2_DEVICE) && 1026291a2b48SSukumar Swaminathan (nlp->nlp_DID & mask) == 1027291a2b48SSukumar Swaminathan aff_d_id) { 1028fcf3ce44SJohn Forte action = 3; 1029fcf3ce44SJohn Forte break; 1030fcf3ce44SJohn Forte } 1031291a2b48SSukumar Swaminathan 1032fcf3ce44SJohn Forte /* 1033fcf3ce44SJohn Forte * Check for any other device that 1034fcf3ce44SJohn Forte * matches our mask 1035fcf3ce44SJohn Forte */ 1036fcf3ce44SJohn Forte else if ((nlp->nlp_DID & mask) == 1037fcf3ce44SJohn Forte aff_d_id) { 1038fcf3ce44SJohn Forte if (linkdown) { 1039fcf3ce44SJohn Forte action = 1; 1040fcf3ce44SJohn Forte break; 1041291a2b48SSukumar Swaminathan } else { /* Must be an RSCN */ 1042291a2b48SSukumar Swaminathan 1043fcf3ce44SJohn Forte action = 2; 1044fcf3ce44SJohn Forte break; 1045fcf3ce44SJohn Forte } 1046fcf3ce44SJohn Forte } 1047291a2b48SSukumar Swaminathan 1048fcf3ce44SJohn Forte nlp = nlp->nlp_list_next; 1049fcf3ce44SJohn Forte } 1050fcf3ce44SJohn Forte 1051fcf3ce44SJohn Forte if (action) { 1052fcf3ce44SJohn Forte break; 1053fcf3ce44SJohn Forte } 1054fcf3ce44SJohn Forte } 1055fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 1056fcf3ce44SJohn Forte 1057fcf3ce44SJohn Forte /* Check if nothing was found */ 1058fcf3ce44SJohn Forte if (action == 0) { 1059fcf3ce44SJohn Forte break; 1060fcf3ce44SJohn Forte } else if (action == 1) { 1061fcf3ce44SJohn Forte (void) emlxs_mb_unreg_did(port, nlp->nlp_DID, 1062fcf3ce44SJohn Forte NULL, NULL, NULL); 1063fcf3ce44SJohn Forte } else if (action == 2) { 1064fcf3ce44SJohn Forte #ifdef DHCHAP_SUPPORT 1065fcf3ce44SJohn Forte emlxs_dhc_auth_stop(port, nlp); 1066291a2b48SSukumar Swaminathan #endif /* DHCHAP_SUPPORT */ 1067fcf3ce44SJohn Forte 1068291a2b48SSukumar Swaminathan /* 1069291a2b48SSukumar Swaminathan * Close the node for any further normal IO 1070291a2b48SSukumar Swaminathan * A PLOGI with reopen the node 1071291a2b48SSukumar Swaminathan */ 107282527734SSukumar Swaminathan emlxs_node_close(port, nlp, 107382527734SSukumar Swaminathan hba->channel_fcp, 60); 107482527734SSukumar Swaminathan emlxs_node_close(port, nlp, 107582527734SSukumar Swaminathan hba->channel_ip, 60); 1076fcf3ce44SJohn Forte 1077fcf3ce44SJohn Forte /* Flush tx queue */ 1078fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, nlp, 0, 0, 0); 1079fcf3ce44SJohn Forte 1080fcf3ce44SJohn Forte /* Flush chip queue */ 1081fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 0, nlp, 0); 1082291a2b48SSukumar Swaminathan 1083fcf3ce44SJohn Forte } else if (action == 3) { /* FCP2 devices */ 1084fcf3ce44SJohn Forte unreg_vpi = 0; 1085fcf3ce44SJohn Forte 1086fcf3ce44SJohn Forte #ifdef DHCHAP_SUPPORT 1087fcf3ce44SJohn Forte emlxs_dhc_auth_stop(port, nlp); 1088291a2b48SSukumar Swaminathan #endif /* DHCHAP_SUPPORT */ 1089fcf3ce44SJohn Forte 1090291a2b48SSukumar Swaminathan /* 1091291a2b48SSukumar Swaminathan * Close the node for any further normal IO 1092291a2b48SSukumar Swaminathan * An ADISC or a PLOGI with reopen the node 1093291a2b48SSukumar Swaminathan */ 109482527734SSukumar Swaminathan emlxs_node_close(port, nlp, 109582527734SSukumar Swaminathan hba->channel_fcp, -1); 109682527734SSukumar Swaminathan emlxs_node_close(port, nlp, hba->channel_ip, 1097fcf3ce44SJohn Forte ((linkdown) ? 0 : 60)); 1098fcf3ce44SJohn Forte 1099fcf3ce44SJohn Forte /* Flush tx queues except for FCP ring */ 1100fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, nlp, 110182527734SSukumar Swaminathan &hba->chan[hba->channel_ct], 0, 0); 1102fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, nlp, 110382527734SSukumar Swaminathan &hba->chan[hba->channel_els], 0, 0); 1104fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, nlp, 110582527734SSukumar Swaminathan &hba->chan[hba->channel_ip], 0, 0); 1106fcf3ce44SJohn Forte 1107fcf3ce44SJohn Forte /* Flush chip queues except for FCP ring */ 1108fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 110982527734SSukumar Swaminathan &hba->chan[hba->channel_ct], nlp, 0); 1110fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 111182527734SSukumar Swaminathan &hba->chan[hba->channel_els], nlp, 0); 1112fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 111382527734SSukumar Swaminathan &hba->chan[hba->channel_ip], nlp, 0); 1114fcf3ce44SJohn Forte } 1115fcf3ce44SJohn Forte } 1116fcf3ce44SJohn Forte break; 1117fcf3ce44SJohn Forte 1118fcf3ce44SJohn Forte case 2: /* Full support - Hold FCP IO to FCP target matching nodes */ 1119fcf3ce44SJohn Forte 1120fcf3ce44SJohn Forte if (!linkdown && !vlinkdown) { 1121fcf3ce44SJohn Forte break; 1122fcf3ce44SJohn Forte } 1123291a2b48SSukumar Swaminathan 1124fcf3ce44SJohn Forte for (;;) { 1125fcf3ce44SJohn Forte /* 1126fcf3ce44SJohn Forte * We need to hold the locks this way because 1127291a2b48SSukumar Swaminathan * emlxs_mb_unreg_did and the flush routines enter the 1128291a2b48SSukumar Swaminathan * same locks. Also, when we release the lock the list 1129291a2b48SSukumar Swaminathan * can change out from under us. 1130fcf3ce44SJohn Forte */ 1131fcf3ce44SJohn Forte rw_enter(&port->node_rwlock, RW_READER); 1132fcf3ce44SJohn Forte action = 0; 1133fcf3ce44SJohn Forte for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 1134fcf3ce44SJohn Forte nlp = port->node_table[i]; 1135fcf3ce44SJohn Forte while (nlp != NULL) { 1136fcf3ce44SJohn Forte if (!nlp->nlp_tag) { 1137fcf3ce44SJohn Forte nlp = nlp->nlp_list_next; 1138fcf3ce44SJohn Forte continue; 1139fcf3ce44SJohn Forte } 1140fcf3ce44SJohn Forte nlp->nlp_tag = 0; 1141fcf3ce44SJohn Forte 1142fcf3ce44SJohn Forte /* 1143fcf3ce44SJohn Forte * Check for FCP target device that 1144fcf3ce44SJohn Forte * matches our mask 1145fcf3ce44SJohn Forte */ 1146291a2b48SSukumar Swaminathan if ((nlp-> nlp_fcp_info & 1147fcf3ce44SJohn Forte NLP_FCP_TGT_DEVICE) && 1148291a2b48SSukumar Swaminathan (nlp->nlp_DID & mask) == 1149291a2b48SSukumar Swaminathan aff_d_id) { 1150fcf3ce44SJohn Forte action = 3; 1151fcf3ce44SJohn Forte break; 1152fcf3ce44SJohn Forte } 1153291a2b48SSukumar Swaminathan 1154fcf3ce44SJohn Forte /* 1155fcf3ce44SJohn Forte * Check for any other device that 1156fcf3ce44SJohn Forte * matches our mask 1157fcf3ce44SJohn Forte */ 1158fcf3ce44SJohn Forte else if ((nlp->nlp_DID & mask) == 1159fcf3ce44SJohn Forte aff_d_id) { 1160fcf3ce44SJohn Forte if (linkdown) { 1161fcf3ce44SJohn Forte action = 1; 1162fcf3ce44SJohn Forte break; 1163fcf3ce44SJohn Forte } else { /* Must be an RSCN */ 1164291a2b48SSukumar Swaminathan 1165fcf3ce44SJohn Forte action = 2; 1166fcf3ce44SJohn Forte break; 1167fcf3ce44SJohn Forte } 1168fcf3ce44SJohn Forte } 1169291a2b48SSukumar Swaminathan 1170fcf3ce44SJohn Forte nlp = nlp->nlp_list_next; 1171fcf3ce44SJohn Forte } 1172fcf3ce44SJohn Forte if (action) { 1173fcf3ce44SJohn Forte break; 1174fcf3ce44SJohn Forte } 1175fcf3ce44SJohn Forte } 1176fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 1177fcf3ce44SJohn Forte 1178fcf3ce44SJohn Forte /* Check if nothing was found */ 1179fcf3ce44SJohn Forte if (action == 0) { 1180fcf3ce44SJohn Forte break; 1181fcf3ce44SJohn Forte } else if (action == 1) { 1182fcf3ce44SJohn Forte (void) emlxs_mb_unreg_did(port, nlp->nlp_DID, 1183fcf3ce44SJohn Forte NULL, NULL, NULL); 1184fcf3ce44SJohn Forte } else if (action == 2) { 1185291a2b48SSukumar Swaminathan /* 1186291a2b48SSukumar Swaminathan * Close the node for any further normal IO 1187291a2b48SSukumar Swaminathan * A PLOGI with reopen the node 1188291a2b48SSukumar Swaminathan */ 118982527734SSukumar Swaminathan emlxs_node_close(port, nlp, 119082527734SSukumar Swaminathan hba->channel_fcp, 60); 119182527734SSukumar Swaminathan emlxs_node_close(port, nlp, 119282527734SSukumar Swaminathan hba->channel_ip, 60); 1193fcf3ce44SJohn Forte 1194fcf3ce44SJohn Forte /* Flush tx queue */ 1195fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, nlp, 0, 0, 0); 1196fcf3ce44SJohn Forte 1197fcf3ce44SJohn Forte /* Flush chip queue */ 1198fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 0, nlp, 0); 1199fcf3ce44SJohn Forte 1200fcf3ce44SJohn Forte } else if (action == 3) { /* FCP2 devices */ 1201fcf3ce44SJohn Forte unreg_vpi = 0; 1202fcf3ce44SJohn Forte 1203291a2b48SSukumar Swaminathan /* 1204291a2b48SSukumar Swaminathan * Close the node for any further normal IO 1205291a2b48SSukumar Swaminathan * An ADISC or a PLOGI with reopen the node 1206291a2b48SSukumar Swaminathan */ 120782527734SSukumar Swaminathan emlxs_node_close(port, nlp, 120882527734SSukumar Swaminathan hba->channel_fcp, -1); 120982527734SSukumar Swaminathan emlxs_node_close(port, nlp, hba->channel_ip, 1210fcf3ce44SJohn Forte ((linkdown) ? 0 : 60)); 1211fcf3ce44SJohn Forte 1212fcf3ce44SJohn Forte /* Flush tx queues except for FCP ring */ 1213fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, nlp, 121482527734SSukumar Swaminathan &hba->chan[hba->channel_ct], 0, 0); 1215fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, nlp, 121682527734SSukumar Swaminathan &hba->chan[hba->channel_els], 0, 0); 1217fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, nlp, 121882527734SSukumar Swaminathan &hba->chan[hba->channel_ip], 0, 0); 1219fcf3ce44SJohn Forte 1220fcf3ce44SJohn Forte /* Flush chip queues except for FCP ring */ 1221fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 122282527734SSukumar Swaminathan &hba->chan[hba->channel_ct], nlp, 0); 1223fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 122482527734SSukumar Swaminathan &hba->chan[hba->channel_els], nlp, 0); 1225fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 122682527734SSukumar Swaminathan &hba->chan[hba->channel_ip], nlp, 0); 1227fcf3ce44SJohn Forte } 1228fcf3ce44SJohn Forte } 1229fcf3ce44SJohn Forte 1230fcf3ce44SJohn Forte break; 1231fcf3ce44SJohn Forte 1232fcf3ce44SJohn Forte } /* switch() */ 1233fcf3ce44SJohn Forte 1234fcf3ce44SJohn Forte done: 1235fcf3ce44SJohn Forte 123682527734SSukumar Swaminathan if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) { 123782527734SSukumar Swaminathan if (unreg_vpi) { 123882527734SSukumar Swaminathan (void) emlxs_mb_unreg_vpi(port); 123982527734SSukumar Swaminathan } 1240fcf3ce44SJohn Forte } 1241fcf3ce44SJohn Forte 1242291a2b48SSukumar Swaminathan return (0); 1243fcf3ce44SJohn Forte 124482527734SSukumar Swaminathan } /* emlxs_port_offline() */ 1245fcf3ce44SJohn Forte 1246fcf3ce44SJohn Forte 1247fcf3ce44SJohn Forte extern void 1248fcf3ce44SJohn Forte emlxs_port_online(emlxs_port_t *vport) 1249fcf3ce44SJohn Forte { 1250fcf3ce44SJohn Forte emlxs_hba_t *hba = vport->hba; 1251fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 1252fcf3ce44SJohn Forte uint32_t state; 1253fcf3ce44SJohn Forte uint32_t update; 1254fcf3ce44SJohn Forte uint32_t npiv_linkup; 1255fcf3ce44SJohn Forte char topology[32]; 1256fcf3ce44SJohn Forte char linkspeed[32]; 1257fcf3ce44SJohn Forte char mode[32]; 1258fcf3ce44SJohn Forte 1259fcf3ce44SJohn Forte /* 1260291a2b48SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_up_msg, 1261291a2b48SSukumar Swaminathan * "linkup_callback. vpi=%d fc_flag=%x", vport->vpi, hba->flag); 1262fcf3ce44SJohn Forte */ 1263fcf3ce44SJohn Forte 1264fcf3ce44SJohn Forte if ((vport->vpi > 0) && 1265fcf3ce44SJohn Forte (!(hba->flag & FC_NPIV_ENABLED) || 1266fcf3ce44SJohn Forte !(hba->flag & FC_NPIV_SUPPORTED))) { 1267fcf3ce44SJohn Forte return; 1268fcf3ce44SJohn Forte } 1269291a2b48SSukumar Swaminathan 1270fcf3ce44SJohn Forte if (!(vport->flag & EMLXS_PORT_BOUND) || 1271fcf3ce44SJohn Forte !(vport->flag & EMLXS_PORT_ENABLE)) { 1272fcf3ce44SJohn Forte return; 1273fcf3ce44SJohn Forte } 1274291a2b48SSukumar Swaminathan 1275fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 1276fcf3ce44SJohn Forte 1277fcf3ce44SJohn Forte /* Check for mode */ 1278fcf3ce44SJohn Forte if (port->tgt_mode) { 1279fcf3ce44SJohn Forte (void) strcpy(mode, ", target"); 1280fcf3ce44SJohn Forte } else if (port->ini_mode) { 1281fcf3ce44SJohn Forte (void) strcpy(mode, ", initiator"); 1282fcf3ce44SJohn Forte } else { 1283fcf3ce44SJohn Forte (void) strcpy(mode, ""); 1284fcf3ce44SJohn Forte } 1285fcf3ce44SJohn Forte 1286fcf3ce44SJohn Forte /* Check for loop topology */ 1287fcf3ce44SJohn Forte if (hba->topology == TOPOLOGY_LOOP) { 1288fcf3ce44SJohn Forte state = FC_STATE_LOOP; 1289fcf3ce44SJohn Forte (void) strcpy(topology, ", loop"); 1290fcf3ce44SJohn Forte } else { 1291fcf3ce44SJohn Forte state = FC_STATE_ONLINE; 1292fcf3ce44SJohn Forte (void) strcpy(topology, ", fabric"); 1293fcf3ce44SJohn Forte } 1294fcf3ce44SJohn Forte 1295fcf3ce44SJohn Forte /* Set the link speed */ 1296fcf3ce44SJohn Forte switch (hba->linkspeed) { 1297fcf3ce44SJohn Forte case 0: 1298fcf3ce44SJohn Forte (void) strcpy(linkspeed, "Gb"); 1299fcf3ce44SJohn Forte state |= FC_STATE_1GBIT_SPEED; 1300fcf3ce44SJohn Forte break; 1301fcf3ce44SJohn Forte 1302fcf3ce44SJohn Forte case LA_1GHZ_LINK: 1303fcf3ce44SJohn Forte (void) strcpy(linkspeed, "1Gb"); 1304fcf3ce44SJohn Forte state |= FC_STATE_1GBIT_SPEED; 1305fcf3ce44SJohn Forte break; 1306fcf3ce44SJohn Forte case LA_2GHZ_LINK: 1307fcf3ce44SJohn Forte (void) strcpy(linkspeed, "2Gb"); 1308fcf3ce44SJohn Forte state |= FC_STATE_2GBIT_SPEED; 1309fcf3ce44SJohn Forte break; 1310fcf3ce44SJohn Forte case LA_4GHZ_LINK: 1311fcf3ce44SJohn Forte (void) strcpy(linkspeed, "4Gb"); 1312fcf3ce44SJohn Forte state |= FC_STATE_4GBIT_SPEED; 1313fcf3ce44SJohn Forte break; 1314fcf3ce44SJohn Forte case LA_8GHZ_LINK: 1315fcf3ce44SJohn Forte (void) strcpy(linkspeed, "8Gb"); 1316fcf3ce44SJohn Forte state |= FC_STATE_8GBIT_SPEED; 1317fcf3ce44SJohn Forte break; 1318fcf3ce44SJohn Forte case LA_10GHZ_LINK: 1319fcf3ce44SJohn Forte (void) strcpy(linkspeed, "10Gb"); 1320fcf3ce44SJohn Forte state |= FC_STATE_10GBIT_SPEED; 1321fcf3ce44SJohn Forte break; 1322fcf3ce44SJohn Forte default: 1323fcf3ce44SJohn Forte (void) sprintf(linkspeed, "unknown(0x%x)", hba->linkspeed); 1324fcf3ce44SJohn Forte break; 1325fcf3ce44SJohn Forte } 1326fcf3ce44SJohn Forte 1327fcf3ce44SJohn Forte npiv_linkup = 0; 1328fcf3ce44SJohn Forte update = 0; 1329fcf3ce44SJohn Forte 1330fcf3ce44SJohn Forte if ((hba->state >= FC_LINK_UP) && 1331291a2b48SSukumar Swaminathan !(hba->flag & FC_LOOPBACK_MODE) && (vport->ulp_statec != state)) { 1332fcf3ce44SJohn Forte update = 1; 1333fcf3ce44SJohn Forte vport->ulp_statec = state; 1334fcf3ce44SJohn Forte 1335fcf3ce44SJohn Forte if ((vport->vpi > 0) && !(hba->flag & FC_NPIV_LINKUP)) { 1336fcf3ce44SJohn Forte hba->flag |= FC_NPIV_LINKUP; 1337fcf3ce44SJohn Forte npiv_linkup = 1; 1338fcf3ce44SJohn Forte } 1339fcf3ce44SJohn Forte } 1340291a2b48SSukumar Swaminathan 1341fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1342fcf3ce44SJohn Forte 134382527734SSukumar Swaminathan 1344fcf3ce44SJohn Forte /* 1345291a2b48SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_up_msg, 134682527734SSukumar Swaminathan * "linkup_callback: update=%d vpi=%d flag=%d fc_flag=%x state=%x" 134782527734SSukumar Swaminathan * "statec=%x", update, vport->vpi, npiv_linkup, hba->flag, 1348291a2b48SSukumar Swaminathan * hba->state, vport->ulp_statec); 1349fcf3ce44SJohn Forte */ 135082527734SSukumar Swaminathan 1351fcf3ce44SJohn Forte if (update) { 1352fcf3ce44SJohn Forte if (vport->flag & EMLXS_PORT_BOUND) { 1353fcf3ce44SJohn Forte if (vport->vpi == 0) { 1354fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_up_msg, 1355291a2b48SSukumar Swaminathan "%s%s%s", linkspeed, topology, mode); 1356fcf3ce44SJohn Forte } else if (npiv_linkup) { 1357fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 1358291a2b48SSukumar Swaminathan &emlxs_npiv_link_up_msg, "%s%s%s", 1359fcf3ce44SJohn Forte linkspeed, topology, mode); 1360fcf3ce44SJohn Forte } 1361291a2b48SSukumar Swaminathan 13623be114edSSukumar Swaminathan if (vport->ini_mode) { 1363291a2b48SSukumar Swaminathan vport->ulp_statec_cb(vport->ulp_handle, 1364291a2b48SSukumar Swaminathan state); 1365fcf3ce44SJohn Forte } 13663be114edSSukumar Swaminathan #ifdef SFCT_SUPPORT 13673be114edSSukumar Swaminathan else if (vport->tgt_mode) { 13683be114edSSukumar Swaminathan emlxs_fct_link_up(vport); 13693be114edSSukumar Swaminathan } 13703be114edSSukumar Swaminathan #endif /* SFCT_SUPPORT */ 1371fcf3ce44SJohn Forte } else { 1372fcf3ce44SJohn Forte if (vport->vpi == 0) { 1373fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_up_msg, 1374291a2b48SSukumar Swaminathan "%s%s%s *", linkspeed, topology, mode); 1375fcf3ce44SJohn Forte } else if (npiv_linkup) { 1376fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 1377291a2b48SSukumar Swaminathan &emlxs_npiv_link_up_msg, "%s%s%s *", 1378fcf3ce44SJohn Forte linkspeed, topology, mode); 1379fcf3ce44SJohn Forte } 1380fcf3ce44SJohn Forte } 1381fcf3ce44SJohn Forte 1382fcf3ce44SJohn Forte /* Check for waiting threads */ 1383fcf3ce44SJohn Forte if (vport->vpi == 0) { 1384fcf3ce44SJohn Forte mutex_enter(&EMLXS_LINKUP_LOCK); 1385fcf3ce44SJohn Forte if (hba->linkup_wait_flag == TRUE) { 1386fcf3ce44SJohn Forte hba->linkup_wait_flag = FALSE; 1387fcf3ce44SJohn Forte cv_broadcast(&EMLXS_LINKUP_CV); 1388fcf3ce44SJohn Forte } 1389fcf3ce44SJohn Forte mutex_exit(&EMLXS_LINKUP_LOCK); 1390fcf3ce44SJohn Forte } 1391291a2b48SSukumar Swaminathan 1392fcf3ce44SJohn Forte /* Flush any pending ub buffers */ 1393fcf3ce44SJohn Forte emlxs_ub_flush(vport); 1394fcf3ce44SJohn Forte } 1395291a2b48SSukumar Swaminathan 1396fcf3ce44SJohn Forte return; 1397fcf3ce44SJohn Forte 139882527734SSukumar Swaminathan } /* emlxs_port_online() */ 1399fcf3ce44SJohn Forte 1400fcf3ce44SJohn Forte 1401fcf3ce44SJohn Forte extern void 1402fcf3ce44SJohn Forte emlxs_linkdown(emlxs_hba_t *hba) 1403fcf3ce44SJohn Forte { 1404fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 140582527734SSukumar Swaminathan RPIobj_t *rp; 1406fcf3ce44SJohn Forte int i; 1407fcf3ce44SJohn Forte 1408fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 1409fcf3ce44SJohn Forte 141082527734SSukumar Swaminathan if (hba->state > FC_LINK_DOWN) { 141182527734SSukumar Swaminathan HBASTATS.LinkDown++; 141282527734SSukumar Swaminathan EMLXS_STATE_CHANGE_LOCKED(hba, FC_LINK_DOWN); 141382527734SSukumar Swaminathan } 1414fcf3ce44SJohn Forte 1415fcf3ce44SJohn Forte /* Filter hba flags */ 1416fcf3ce44SJohn Forte hba->flag &= FC_LINKDOWN_MASK; 1417fcf3ce44SJohn Forte hba->discovery_timer = 0; 1418fcf3ce44SJohn Forte hba->linkup_timer = 0; 1419fcf3ce44SJohn Forte 142082527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 142182527734SSukumar Swaminathan rp = hba->sli.sli4.RPIp; 142282527734SSukumar Swaminathan for (i = 0; i < hba->sli.sli4.RPICount; i++) { 142382527734SSukumar Swaminathan if (rp->state & RESOURCE_ALLOCATED) { 142482527734SSukumar Swaminathan rp->state |= RESOURCE_RPI_PAUSED; 142582527734SSukumar Swaminathan } 142682527734SSukumar Swaminathan rp++; 142782527734SSukumar Swaminathan } 142882527734SSukumar Swaminathan } 142982527734SSukumar Swaminathan 1430fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1431fcf3ce44SJohn Forte 1432fcf3ce44SJohn Forte for (i = 0; i < MAX_VPORTS; i++) { 1433fcf3ce44SJohn Forte port = &VPORT(i); 1434fcf3ce44SJohn Forte 1435fcf3ce44SJohn Forte if (!(port->flag & EMLXS_PORT_BOUND)) { 1436fcf3ce44SJohn Forte continue; 1437fcf3ce44SJohn Forte } 1438291a2b48SSukumar Swaminathan 1439fcf3ce44SJohn Forte (void) emlxs_port_offline(port, 0xffffffff); 1440fcf3ce44SJohn Forte 1441fcf3ce44SJohn Forte } 1442fcf3ce44SJohn Forte 1443fcf3ce44SJohn Forte return; 1444fcf3ce44SJohn Forte 144582527734SSukumar Swaminathan } /* emlxs_linkdown() */ 1446fcf3ce44SJohn Forte 1447fcf3ce44SJohn Forte 1448fcf3ce44SJohn Forte extern void 1449fcf3ce44SJohn Forte emlxs_linkup(emlxs_hba_t *hba) 1450fcf3ce44SJohn Forte { 1451fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 1452fcf3ce44SJohn Forte emlxs_config_t *cfg = &CFG; 1453fcf3ce44SJohn Forte 1454fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 1455fcf3ce44SJohn Forte 1456fcf3ce44SJohn Forte HBASTATS.LinkUp++; 145782527734SSukumar Swaminathan EMLXS_STATE_CHANGE_LOCKED(hba, FC_LINK_UP); 1458fcf3ce44SJohn Forte 1459fcf3ce44SJohn Forte #ifdef MENLO_SUPPORT 1460fcf3ce44SJohn Forte if (hba->flag & FC_MENLO_MODE) { 1461fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1462fcf3ce44SJohn Forte 1463fcf3ce44SJohn Forte /* 1464fcf3ce44SJohn Forte * Trigger linkup CV and don't start linkup & discovery 1465fcf3ce44SJohn Forte * timers 1466fcf3ce44SJohn Forte */ 1467fcf3ce44SJohn Forte mutex_enter(&EMLXS_LINKUP_LOCK); 1468fcf3ce44SJohn Forte cv_broadcast(&EMLXS_LINKUP_CV); 1469fcf3ce44SJohn Forte mutex_exit(&EMLXS_LINKUP_LOCK); 1470fcf3ce44SJohn Forte 1471fcf3ce44SJohn Forte return; 1472fcf3ce44SJohn Forte } 1473291a2b48SSukumar Swaminathan #endif /* MENLO_SUPPORT */ 1474fcf3ce44SJohn Forte 1475fcf3ce44SJohn Forte /* Set the linkup & discovery timers */ 1476fcf3ce44SJohn Forte hba->linkup_timer = hba->timer_tics + cfg[CFG_LINKUP_TIMEOUT].current; 1477291a2b48SSukumar Swaminathan hba->discovery_timer = 1478291a2b48SSukumar Swaminathan hba->timer_tics + cfg[CFG_LINKUP_TIMEOUT].current + 1479291a2b48SSukumar Swaminathan cfg[CFG_DISC_TIMEOUT].current; 1480fcf3ce44SJohn Forte 1481fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1482fcf3ce44SJohn Forte 1483fcf3ce44SJohn Forte return; 1484fcf3ce44SJohn Forte 148582527734SSukumar Swaminathan } /* emlxs_linkup() */ 1486fcf3ce44SJohn Forte 1487fcf3ce44SJohn Forte 1488fcf3ce44SJohn Forte /* 1489fcf3ce44SJohn Forte * emlxs_reset_link 1490fcf3ce44SJohn Forte * 1491fcf3ce44SJohn Forte * Description: 1492fcf3ce44SJohn Forte * Called to reset the link with an init_link 1493fcf3ce44SJohn Forte * 1494fcf3ce44SJohn Forte * Returns: 1495fcf3ce44SJohn Forte * 1496fcf3ce44SJohn Forte */ 1497fcf3ce44SJohn Forte extern int 149882527734SSukumar Swaminathan emlxs_reset_link(emlxs_hba_t *hba, uint32_t linkup, uint32_t wait) 1499fcf3ce44SJohn Forte { 1500fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 1501fcf3ce44SJohn Forte emlxs_config_t *cfg; 150282527734SSukumar Swaminathan MAILBOXQ *mbq = NULL; 150382527734SSukumar Swaminathan MAILBOX *mb = NULL; 150482527734SSukumar Swaminathan int rval = 0; 150582527734SSukumar Swaminathan int rc; 1506fcf3ce44SJohn Forte 1507fcf3ce44SJohn Forte /* 1508fcf3ce44SJohn Forte * Get a buffer to use for the mailbox command 1509fcf3ce44SJohn Forte */ 151082527734SSukumar Swaminathan if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1)) 151182527734SSukumar Swaminathan == NULL) { 1512fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_reset_failed_msg, 1513fcf3ce44SJohn Forte "Unable to allocate mailbox buffer."); 151482527734SSukumar Swaminathan rval = 1; 151582527734SSukumar Swaminathan goto reset_link_fail; 151682527734SSukumar Swaminathan } 1517fcf3ce44SJohn Forte 151882527734SSukumar Swaminathan mb = (MAILBOX *)mbq; 151982527734SSukumar Swaminathan 152082527734SSukumar Swaminathan /* Bring link down first */ 152182527734SSukumar Swaminathan emlxs_mb_down_link(hba, mbq); 152282527734SSukumar Swaminathan 152382527734SSukumar Swaminathan #define MBXERR_LINK_DOWN 0x33 152482527734SSukumar Swaminathan 152582527734SSukumar Swaminathan if (wait) { 152682527734SSukumar Swaminathan wait = MBX_WAIT; 152782527734SSukumar Swaminathan } else { 152882527734SSukumar Swaminathan wait = MBX_NOWAIT; 152982527734SSukumar Swaminathan } 153082527734SSukumar Swaminathan rc = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, wait, 0); 153182527734SSukumar Swaminathan if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS) && 153282527734SSukumar Swaminathan (rc != MBXERR_LINK_DOWN)) { 153382527734SSukumar Swaminathan rval = 1; 153482527734SSukumar Swaminathan goto reset_link_fail; 1535fcf3ce44SJohn Forte } 1536291a2b48SSukumar Swaminathan 153782527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_reset_msg, 153882527734SSukumar Swaminathan "Disabling link..."); 1539fcf3ce44SJohn Forte 1540fcf3ce44SJohn Forte if (linkup) { 1541fcf3ce44SJohn Forte /* 1542fcf3ce44SJohn Forte * Setup and issue mailbox INITIALIZE LINK command 1543fcf3ce44SJohn Forte */ 1544fcf3ce44SJohn Forte 154582527734SSukumar Swaminathan if (wait == MBX_NOWAIT) { 154682527734SSukumar Swaminathan if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1)) 154782527734SSukumar Swaminathan == NULL) { 154882527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 154982527734SSukumar Swaminathan &emlxs_link_reset_failed_msg, 155082527734SSukumar Swaminathan "Unable to allocate mailbox buffer."); 155182527734SSukumar Swaminathan rval = 1; 155282527734SSukumar Swaminathan goto reset_link_fail; 155382527734SSukumar Swaminathan } 155482527734SSukumar Swaminathan mb = (MAILBOX *)mbq; 155582527734SSukumar Swaminathan } else { 155682527734SSukumar Swaminathan /* Reuse mbq from previous mbox */ 155782527734SSukumar Swaminathan mb = (MAILBOX *)mbq; 155882527734SSukumar Swaminathan } 155982527734SSukumar Swaminathan cfg = &CFG; 156082527734SSukumar Swaminathan 156182527734SSukumar Swaminathan emlxs_mb_init_link(hba, mbq, 1562fcf3ce44SJohn Forte cfg[CFG_TOPOLOGY].current, cfg[CFG_LINK_SPEED].current); 1563fcf3ce44SJohn Forte 1564fcf3ce44SJohn Forte mb->un.varInitLnk.lipsr_AL_PA = 0; 1565fcf3ce44SJohn Forte 1566fcf3ce44SJohn Forte /* Clear the loopback mode */ 1567fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 1568fcf3ce44SJohn Forte hba->flag &= ~FC_LOOPBACK_MODE; 1569291a2b48SSukumar Swaminathan hba->loopback_tics = 0; 1570fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1571fcf3ce44SJohn Forte 157282527734SSukumar Swaminathan rc = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, wait, 0); 157382527734SSukumar Swaminathan if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { 157482527734SSukumar Swaminathan rval = 1; 157582527734SSukumar Swaminathan goto reset_link_fail; 1576fcf3ce44SJohn Forte } 1577291a2b48SSukumar Swaminathan 1578fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_reset_msg, NULL); 157982527734SSukumar Swaminathan } 1580fcf3ce44SJohn Forte 158182527734SSukumar Swaminathan reset_link_fail: 1582291a2b48SSukumar Swaminathan 158382527734SSukumar Swaminathan if ((wait == MBX_WAIT) && mbq) { 158482527734SSukumar Swaminathan (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); 1585fcf3ce44SJohn Forte } 1586fcf3ce44SJohn Forte 158782527734SSukumar Swaminathan return (rval); 158882527734SSukumar Swaminathan } /* emlxs_reset_link() */ 1589fcf3ce44SJohn Forte 1590fcf3ce44SJohn Forte 1591fcf3ce44SJohn Forte extern int 1592fcf3ce44SJohn Forte emlxs_online(emlxs_hba_t *hba) 1593fcf3ce44SJohn Forte { 1594fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 1595fcf3ce44SJohn Forte int32_t rval = 0; 1596fcf3ce44SJohn Forte uint32_t i = 0; 1597fcf3ce44SJohn Forte 1598fcf3ce44SJohn Forte /* Make sure adapter is offline or exit trying (30 seconds) */ 1599291a2b48SSukumar Swaminathan while (i++ < 30) { 1600fcf3ce44SJohn Forte /* Check if adapter is already going online */ 1601fcf3ce44SJohn Forte if (hba->flag & (FC_ONLINE_MODE | FC_ONLINING_MODE)) { 1602fcf3ce44SJohn Forte return (0); 1603fcf3ce44SJohn Forte } 1604291a2b48SSukumar Swaminathan 1605fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 1606fcf3ce44SJohn Forte 1607fcf3ce44SJohn Forte /* Check again */ 1608fcf3ce44SJohn Forte if (hba->flag & (FC_ONLINE_MODE | FC_ONLINING_MODE)) { 1609fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1610fcf3ce44SJohn Forte return (0); 1611fcf3ce44SJohn Forte } 1612291a2b48SSukumar Swaminathan 1613fcf3ce44SJohn Forte /* Check if adapter is offline */ 1614fcf3ce44SJohn Forte if (hba->flag & FC_OFFLINE_MODE) { 1615fcf3ce44SJohn Forte /* Mark it going online */ 1616fcf3ce44SJohn Forte hba->flag &= ~FC_OFFLINE_MODE; 1617fcf3ce44SJohn Forte hba->flag |= FC_ONLINING_MODE; 1618fcf3ce44SJohn Forte 1619fcf3ce44SJohn Forte /* Currently !FC_ONLINE_MODE and !FC_OFFLINE_MODE */ 1620fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1621fcf3ce44SJohn Forte break; 1622fcf3ce44SJohn Forte } 1623291a2b48SSukumar Swaminathan 1624fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1625fcf3ce44SJohn Forte 1626fcf3ce44SJohn Forte DELAYMS(1000); 1627fcf3ce44SJohn Forte } 1628fcf3ce44SJohn Forte 1629fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg, 1630fcf3ce44SJohn Forte "Going online..."); 1631fcf3ce44SJohn Forte 163282527734SSukumar Swaminathan if (rval = EMLXS_SLI_ONLINE(hba)) { 1633291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, "status=%x", 1634fcf3ce44SJohn Forte rval); 1635fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_offline_msg, NULL); 1636fcf3ce44SJohn Forte 1637fcf3ce44SJohn Forte /* Set FC_OFFLINE_MODE */ 1638fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 1639fcf3ce44SJohn Forte emlxs_diag_state = DDI_OFFDI; 1640fcf3ce44SJohn Forte hba->flag |= FC_OFFLINE_MODE; 1641fcf3ce44SJohn Forte hba->flag &= ~FC_ONLINING_MODE; 1642fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1643fcf3ce44SJohn Forte 1644fcf3ce44SJohn Forte return (rval); 1645fcf3ce44SJohn Forte } 1646291a2b48SSukumar Swaminathan 1647fcf3ce44SJohn Forte /* Start the timer */ 1648fcf3ce44SJohn Forte emlxs_timer_start(hba); 1649fcf3ce44SJohn Forte 1650fcf3ce44SJohn Forte /* Set FC_ONLINE_MODE */ 1651fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 1652fcf3ce44SJohn Forte emlxs_diag_state = DDI_ONDI; 1653fcf3ce44SJohn Forte hba->flag |= FC_ONLINE_MODE; 1654fcf3ce44SJohn Forte hba->flag &= ~FC_ONLINING_MODE; 1655fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1656fcf3ce44SJohn Forte 1657fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_online_msg, NULL); 1658fcf3ce44SJohn Forte 1659fcf3ce44SJohn Forte #ifdef SFCT_SUPPORT 1660fcf3ce44SJohn Forte (void) emlxs_fct_port_initialize(port); 1661291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 1662fcf3ce44SJohn Forte 1663fcf3ce44SJohn Forte return (rval); 1664fcf3ce44SJohn Forte 166582527734SSukumar Swaminathan } /* emlxs_online() */ 1666fcf3ce44SJohn Forte 1667fcf3ce44SJohn Forte 1668fcf3ce44SJohn Forte extern int 1669fcf3ce44SJohn Forte emlxs_offline(emlxs_hba_t *hba) 1670fcf3ce44SJohn Forte { 1671fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 1672fcf3ce44SJohn Forte uint32_t i = 0; 1673fcf3ce44SJohn Forte int rval = 1; 1674fcf3ce44SJohn Forte 1675fcf3ce44SJohn Forte /* Make sure adapter is online or exit trying (30 seconds) */ 1676291a2b48SSukumar Swaminathan while (i++ < 30) { 1677fcf3ce44SJohn Forte /* Check if adapter is already going offline */ 1678fcf3ce44SJohn Forte if (hba->flag & (FC_OFFLINE_MODE | FC_OFFLINING_MODE)) { 1679fcf3ce44SJohn Forte return (0); 1680fcf3ce44SJohn Forte } 1681291a2b48SSukumar Swaminathan 1682fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 1683fcf3ce44SJohn Forte 1684fcf3ce44SJohn Forte /* Check again */ 1685fcf3ce44SJohn Forte if (hba->flag & (FC_OFFLINE_MODE | FC_OFFLINING_MODE)) { 1686fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1687fcf3ce44SJohn Forte return (0); 1688fcf3ce44SJohn Forte } 1689291a2b48SSukumar Swaminathan 1690fcf3ce44SJohn Forte /* Check if adapter is online */ 1691fcf3ce44SJohn Forte if (hba->flag & FC_ONLINE_MODE) { 1692fcf3ce44SJohn Forte /* Mark it going offline */ 1693fcf3ce44SJohn Forte hba->flag &= ~FC_ONLINE_MODE; 1694fcf3ce44SJohn Forte hba->flag |= FC_OFFLINING_MODE; 1695fcf3ce44SJohn Forte 1696fcf3ce44SJohn Forte /* Currently !FC_ONLINE_MODE and !FC_OFFLINE_MODE */ 1697fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1698fcf3ce44SJohn Forte break; 1699fcf3ce44SJohn Forte } 1700291a2b48SSukumar Swaminathan 1701fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1702fcf3ce44SJohn Forte 1703fcf3ce44SJohn Forte DELAYMS(1000); 1704fcf3ce44SJohn Forte } 1705fcf3ce44SJohn Forte 1706291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg, 1707291a2b48SSukumar Swaminathan "Going offline..."); 1708fcf3ce44SJohn Forte 1709fcf3ce44SJohn Forte if (port->ini_mode) { 1710fcf3ce44SJohn Forte /* Flush all IO */ 1711fcf3ce44SJohn Forte emlxs_linkdown(hba); 1712fcf3ce44SJohn Forte } 1713fcf3ce44SJohn Forte #ifdef SFCT_SUPPORT 1714fcf3ce44SJohn Forte else { 1715fcf3ce44SJohn Forte (void) emlxs_fct_port_shutdown(port); 1716fcf3ce44SJohn Forte } 1717291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 1718fcf3ce44SJohn Forte 1719fcf3ce44SJohn Forte /* Check if adapter was shutdown */ 1720fcf3ce44SJohn Forte if (hba->flag & FC_HARDWARE_ERROR) { 1721291a2b48SSukumar Swaminathan /* 1722291a2b48SSukumar Swaminathan * Force mailbox cleanup 1723291a2b48SSukumar Swaminathan * This will wake any sleeping or polling threads 1724291a2b48SSukumar Swaminathan */ 1725fcf3ce44SJohn Forte emlxs_mb_fini(hba, NULL, MBX_HARDWARE_ERROR); 1726fcf3ce44SJohn Forte } 1727291a2b48SSukumar Swaminathan 1728fcf3ce44SJohn Forte /* Pause here for the IO to settle */ 1729fcf3ce44SJohn Forte delay(drv_usectohz(1000000)); /* 1 sec */ 1730fcf3ce44SJohn Forte 1731fcf3ce44SJohn Forte /* Unregister all nodes */ 1732fcf3ce44SJohn Forte emlxs_ffcleanup(hba); 1733fcf3ce44SJohn Forte 1734fcf3ce44SJohn Forte if (hba->bus_type == SBUS_FC) { 173582527734SSukumar Swaminathan WRITE_SBUS_CSR_REG(hba, FC_SHS_REG(hba), 0x9A); 17364baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 173782527734SSukumar Swaminathan /* Access handle validation */ 173882527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.sbus_csr_handle); 17394baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 1740fcf3ce44SJohn Forte } 1741291a2b48SSukumar Swaminathan 1742fcf3ce44SJohn Forte /* Stop the timer */ 1743fcf3ce44SJohn Forte emlxs_timer_stop(hba); 1744fcf3ce44SJohn Forte 1745fcf3ce44SJohn Forte /* For safety flush every iotag list */ 1746fcf3ce44SJohn Forte if (emlxs_iotag_flush(hba)) { 1747fcf3ce44SJohn Forte /* Pause here for the IO to flush */ 1748728bdc9bSSukumar Swaminathan delay(drv_usectohz(1000)); 1749728bdc9bSSukumar Swaminathan } 1750728bdc9bSSukumar Swaminathan 1751728bdc9bSSukumar Swaminathan /* Wait for poll command request to settle */ 1752728bdc9bSSukumar Swaminathan while (hba->io_poll_count > 0) { 1753728bdc9bSSukumar Swaminathan delay(drv_usectohz(2000000)); /* 2 sec */ 1754fcf3ce44SJohn Forte } 1755728bdc9bSSukumar Swaminathan 175682527734SSukumar Swaminathan /* Shutdown the adapter interface */ 175782527734SSukumar Swaminathan EMLXS_SLI_OFFLINE(hba); 1758fcf3ce44SJohn Forte 1759fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 1760fcf3ce44SJohn Forte hba->flag |= FC_OFFLINE_MODE; 1761fcf3ce44SJohn Forte hba->flag &= ~FC_OFFLINING_MODE; 1762fcf3ce44SJohn Forte emlxs_diag_state = DDI_OFFDI; 1763fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1764fcf3ce44SJohn Forte 1765fcf3ce44SJohn Forte rval = 0; 1766fcf3ce44SJohn Forte 1767fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_offline_msg, NULL); 1768fcf3ce44SJohn Forte 1769fcf3ce44SJohn Forte done: 1770fcf3ce44SJohn Forte 1771fcf3ce44SJohn Forte return (rval); 1772fcf3ce44SJohn Forte 177382527734SSukumar Swaminathan } /* emlxs_offline() */ 1774fcf3ce44SJohn Forte 1775fcf3ce44SJohn Forte 1776fcf3ce44SJohn Forte 1777fcf3ce44SJohn Forte extern int 1778fcf3ce44SJohn Forte emlxs_power_down(emlxs_hba_t *hba) 1779fcf3ce44SJohn Forte { 17804baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 17814baa2c25SSukumar Swaminathan emlxs_port_t *port = &PPORT; 17824baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 1783fcf3ce44SJohn Forte int32_t rval = 0; 1784fcf3ce44SJohn Forte uint32_t *ptr; 1785fcf3ce44SJohn Forte uint32_t i; 1786fcf3ce44SJohn Forte 1787fcf3ce44SJohn Forte if ((rval = emlxs_offline(hba))) { 1788fcf3ce44SJohn Forte return (rval); 1789fcf3ce44SJohn Forte } 179082527734SSukumar Swaminathan EMLXS_SLI_HBA_RESET(hba, 1, 1, 0); 1791291a2b48SSukumar Swaminathan 1792fcf3ce44SJohn Forte /* Save pci config space */ 1793fcf3ce44SJohn Forte ptr = (uint32_t *)hba->pm_config; 1794fcf3ce44SJohn Forte for (i = 0; i < PCI_CONFIG_SIZE; i += 4, ptr++) { 1795291a2b48SSukumar Swaminathan *ptr = 1796291a2b48SSukumar Swaminathan ddi_get32(hba->pci_acc_handle, 1797fcf3ce44SJohn Forte (uint32_t *)(hba->pci_addr + i)); 1798fcf3ce44SJohn Forte } 1799fcf3ce44SJohn Forte 1800fcf3ce44SJohn Forte /* Put chip in D3 state */ 1801fcf3ce44SJohn Forte (void) ddi_put8(hba->pci_acc_handle, 1802fcf3ce44SJohn Forte (uint8_t *)(hba->pci_addr + PCI_PM_CONTROL_REGISTER), 1803fcf3ce44SJohn Forte (uint8_t)PCI_PM_D3_STATE); 1804fcf3ce44SJohn Forte 18054baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 18064baa2c25SSukumar Swaminathan if (emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle) 18074baa2c25SSukumar Swaminathan != DDI_FM_OK) { 18084baa2c25SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 18094baa2c25SSukumar Swaminathan &emlxs_invalid_access_handle_msg, NULL); 18104baa2c25SSukumar Swaminathan return (1); 18114baa2c25SSukumar Swaminathan } 18124baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 18134baa2c25SSukumar Swaminathan 1814fcf3ce44SJohn Forte return (0); 1815fcf3ce44SJohn Forte 181682527734SSukumar Swaminathan } /* End emlxs_power_down */ 1817fcf3ce44SJohn Forte 1818fcf3ce44SJohn Forte 1819fcf3ce44SJohn Forte extern int 1820fcf3ce44SJohn Forte emlxs_power_up(emlxs_hba_t *hba) 1821fcf3ce44SJohn Forte { 18224baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 18234baa2c25SSukumar Swaminathan emlxs_port_t *port = &PPORT; 18244baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 1825fcf3ce44SJohn Forte int32_t rval = 0; 1826fcf3ce44SJohn Forte uint32_t *ptr; 1827fcf3ce44SJohn Forte uint32_t i; 1828fcf3ce44SJohn Forte 1829fcf3ce44SJohn Forte 1830fcf3ce44SJohn Forte /* Take chip out of D3 state */ 1831fcf3ce44SJohn Forte (void) ddi_put8(hba->pci_acc_handle, 1832fcf3ce44SJohn Forte (uint8_t *)(hba->pci_addr + PCI_PM_CONTROL_REGISTER), 1833fcf3ce44SJohn Forte (uint8_t)PCI_PM_D0_STATE); 1834fcf3ce44SJohn Forte 1835fcf3ce44SJohn Forte /* Must have at least 10 ms delay here */ 1836fcf3ce44SJohn Forte DELAYMS(100); 1837fcf3ce44SJohn Forte 1838fcf3ce44SJohn Forte /* Restore pci config space */ 1839fcf3ce44SJohn Forte ptr = (uint32_t *)hba->pm_config; 1840fcf3ce44SJohn Forte for (i = 0; i < PCI_CONFIG_SIZE; i += 4, ptr++) { 1841fcf3ce44SJohn Forte (void) ddi_put32(hba->pci_acc_handle, 1842fcf3ce44SJohn Forte (uint32_t *)(hba->pci_addr + i), *ptr); 1843fcf3ce44SJohn Forte } 1844fcf3ce44SJohn Forte 18454baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 18464baa2c25SSukumar Swaminathan if (emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle) 18474baa2c25SSukumar Swaminathan != DDI_FM_OK) { 18484baa2c25SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 18494baa2c25SSukumar Swaminathan &emlxs_invalid_access_handle_msg, NULL); 18504baa2c25SSukumar Swaminathan return (1); 18514baa2c25SSukumar Swaminathan } 18524baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 18534baa2c25SSukumar Swaminathan 1854fcf3ce44SJohn Forte /* Bring adapter online */ 1855fcf3ce44SJohn Forte if ((rval = emlxs_online(hba))) { 1856fcf3ce44SJohn Forte (void) ddi_put8(hba->pci_acc_handle, 1857fcf3ce44SJohn Forte (uint8_t *)(hba->pci_addr + PCI_PM_CONTROL_REGISTER), 1858fcf3ce44SJohn Forte (uint8_t)PCI_PM_D3_STATE); 1859fcf3ce44SJohn Forte 1860fcf3ce44SJohn Forte return (rval); 1861fcf3ce44SJohn Forte } 1862291a2b48SSukumar Swaminathan 1863fcf3ce44SJohn Forte return (rval); 1864fcf3ce44SJohn Forte 186582527734SSukumar Swaminathan } /* End emlxs_power_up */ 1866fcf3ce44SJohn Forte 1867fcf3ce44SJohn Forte 1868fcf3ce44SJohn Forte /* 1869291a2b48SSukumar Swaminathan * 1870fcf3ce44SJohn Forte * NAME: emlxs_ffcleanup 1871fcf3ce44SJohn Forte * 1872fcf3ce44SJohn Forte * FUNCTION: Cleanup all the Firefly resources used by configuring the adapter 1873fcf3ce44SJohn Forte * 1874fcf3ce44SJohn Forte * EXECUTION ENVIRONMENT: process only 1875fcf3ce44SJohn Forte * 1876fcf3ce44SJohn Forte * CALLED FROM: CFG_TERM 1877fcf3ce44SJohn Forte * 1878fcf3ce44SJohn Forte * INPUT: hba - pointer to the dev_ctl area. 1879fcf3ce44SJohn Forte * 1880fcf3ce44SJohn Forte * RETURNS: none 1881fcf3ce44SJohn Forte */ 1882fcf3ce44SJohn Forte extern void 1883fcf3ce44SJohn Forte emlxs_ffcleanup(emlxs_hba_t *hba) 1884fcf3ce44SJohn Forte { 1885fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 1886291a2b48SSukumar Swaminathan uint32_t i; 1887fcf3ce44SJohn Forte 1888fcf3ce44SJohn Forte /* Disable all but the mailbox interrupt */ 188982527734SSukumar Swaminathan EMLXS_SLI_DISABLE_INTR(hba, HC_MBINT_ENA); 1890fcf3ce44SJohn Forte 1891fcf3ce44SJohn Forte /* Make sure all port nodes are destroyed */ 1892291a2b48SSukumar Swaminathan for (i = 0; i < MAX_VPORTS; i++) { 1893291a2b48SSukumar Swaminathan port = &VPORT(i); 1894fcf3ce44SJohn Forte 1895fcf3ce44SJohn Forte if (port->node_count) { 189682527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 189782527734SSukumar Swaminathan (void) emlxs_sli4_unreg_all_rpi_by_port(port); 189882527734SSukumar Swaminathan } else { 189982527734SSukumar Swaminathan (void) emlxs_mb_unreg_rpi(port, 0xffff, 0, 0, 190082527734SSukumar Swaminathan 0); 190182527734SSukumar Swaminathan } 1902fcf3ce44SJohn Forte } 1903fcf3ce44SJohn Forte } 1904fcf3ce44SJohn Forte 1905fcf3ce44SJohn Forte /* Clear all interrupt enable conditions */ 190682527734SSukumar Swaminathan EMLXS_SLI_DISABLE_INTR(hba, 0); 1907fcf3ce44SJohn Forte 1908fcf3ce44SJohn Forte return; 1909fcf3ce44SJohn Forte 191082527734SSukumar Swaminathan } /* emlxs_ffcleanup() */ 1911fcf3ce44SJohn Forte 1912fcf3ce44SJohn Forte 1913fcf3ce44SJohn Forte extern uint16_t 191482527734SSukumar Swaminathan emlxs_register_pkt(CHANNEL *cp, emlxs_buf_t *sbp) 1915fcf3ce44SJohn Forte { 1916fcf3ce44SJohn Forte emlxs_hba_t *hba; 1917fcf3ce44SJohn Forte emlxs_port_t *port; 1918fcf3ce44SJohn Forte uint16_t iotag; 1919fcf3ce44SJohn Forte uint32_t i; 1920fcf3ce44SJohn Forte 192182527734SSukumar Swaminathan hba = cp->hba; 1922fcf3ce44SJohn Forte 192382527734SSukumar Swaminathan mutex_enter(&EMLXS_FCTAB_LOCK); 1924fcf3ce44SJohn Forte 1925fcf3ce44SJohn Forte if (sbp->iotag != 0) { 1926fcf3ce44SJohn Forte port = &PPORT; 1927fcf3ce44SJohn Forte 1928fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 192982527734SSukumar Swaminathan "Pkt already registered! channel=%d iotag=%d sbp=%p", 193082527734SSukumar Swaminathan sbp->channel, sbp->iotag, sbp); 1931fcf3ce44SJohn Forte } 1932291a2b48SSukumar Swaminathan 1933fcf3ce44SJohn Forte iotag = 0; 193482527734SSukumar Swaminathan for (i = 0; i < hba->max_iotag; i++) { 193582527734SSukumar Swaminathan if (!hba->fc_iotag || hba->fc_iotag >= hba->max_iotag) { 193682527734SSukumar Swaminathan hba->fc_iotag = 1; 1937fcf3ce44SJohn Forte } 193882527734SSukumar Swaminathan iotag = hba->fc_iotag++; 1939fcf3ce44SJohn Forte 194082527734SSukumar Swaminathan if (hba->fc_table[iotag] == 0 || 194182527734SSukumar Swaminathan hba->fc_table[iotag] == STALE_PACKET) { 194282527734SSukumar Swaminathan hba->io_count++; 194382527734SSukumar Swaminathan hba->fc_table[iotag] = sbp; 1944fcf3ce44SJohn Forte 1945fcf3ce44SJohn Forte sbp->iotag = iotag; 194682527734SSukumar Swaminathan sbp->channel = cp; 1947fcf3ce44SJohn Forte 1948fcf3ce44SJohn Forte break; 1949fcf3ce44SJohn Forte } 1950fcf3ce44SJohn Forte iotag = 0; 1951fcf3ce44SJohn Forte } 1952fcf3ce44SJohn Forte 195382527734SSukumar Swaminathan mutex_exit(&EMLXS_FCTAB_LOCK); 1954fcf3ce44SJohn Forte 1955fcf3ce44SJohn Forte /* 1956fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 195782527734SSukumar Swaminathan * "emlxs_register_pkt: channel=%d iotag=%d sbp=%p", 195882527734SSukumar Swaminathan * cp->channelno, iotag, sbp); 1959fcf3ce44SJohn Forte */ 1960fcf3ce44SJohn Forte 1961fcf3ce44SJohn Forte return (iotag); 1962fcf3ce44SJohn Forte 196382527734SSukumar Swaminathan } /* emlxs_register_pkt() */ 1964fcf3ce44SJohn Forte 1965fcf3ce44SJohn Forte 1966fcf3ce44SJohn Forte 1967fcf3ce44SJohn Forte extern emlxs_buf_t * 196882527734SSukumar Swaminathan emlxs_unregister_pkt(CHANNEL *cp, uint16_t iotag, uint32_t forced) 1969fcf3ce44SJohn Forte { 1970fcf3ce44SJohn Forte emlxs_hba_t *hba; 1971fcf3ce44SJohn Forte emlxs_buf_t *sbp; 197282527734SSukumar Swaminathan 197382527734SSukumar Swaminathan sbp = NULL; 197482527734SSukumar Swaminathan hba = cp->hba; 1975fcf3ce44SJohn Forte 1976fcf3ce44SJohn Forte /* Check the iotag range */ 197782527734SSukumar Swaminathan if ((iotag == 0) || (iotag >= hba->max_iotag)) { 1978fcf3ce44SJohn Forte return (NULL); 1979fcf3ce44SJohn Forte } 1980291a2b48SSukumar Swaminathan 1981fcf3ce44SJohn Forte /* Remove the sbp from the table */ 198282527734SSukumar Swaminathan mutex_enter(&EMLXS_FCTAB_LOCK); 198382527734SSukumar Swaminathan sbp = hba->fc_table[iotag]; 1984fcf3ce44SJohn Forte 1985fcf3ce44SJohn Forte if (!sbp || (sbp == STALE_PACKET)) { 198682527734SSukumar Swaminathan mutex_exit(&EMLXS_FCTAB_LOCK); 1987fcf3ce44SJohn Forte return (sbp); 1988fcf3ce44SJohn Forte } 1989291a2b48SSukumar Swaminathan 199082527734SSukumar Swaminathan hba->fc_table[iotag] = ((forced) ? STALE_PACKET : NULL); 199182527734SSukumar Swaminathan hba->io_count--; 1992fcf3ce44SJohn Forte sbp->iotag = 0; 1993fcf3ce44SJohn Forte 199482527734SSukumar Swaminathan mutex_exit(&EMLXS_FCTAB_LOCK); 1995fcf3ce44SJohn Forte 1996fcf3ce44SJohn Forte 1997fcf3ce44SJohn Forte /* Clean up the sbp */ 1998fcf3ce44SJohn Forte mutex_enter(&sbp->mtx); 1999fcf3ce44SJohn Forte 2000fcf3ce44SJohn Forte if (sbp->pkt_flags & PACKET_IN_TXQ) { 2001fcf3ce44SJohn Forte sbp->pkt_flags &= ~PACKET_IN_TXQ; 200282527734SSukumar Swaminathan hba->channel_tx_count--; 2003fcf3ce44SJohn Forte } 2004291a2b48SSukumar Swaminathan 2005fcf3ce44SJohn Forte if (sbp->pkt_flags & PACKET_IN_CHIPQ) { 2006fcf3ce44SJohn Forte sbp->pkt_flags &= ~PACKET_IN_CHIPQ; 2007fcf3ce44SJohn Forte } 2008291a2b48SSukumar Swaminathan 2009fcf3ce44SJohn Forte if (sbp->bmp) { 2010fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_BPL, (uint8_t *)sbp->bmp); 2011fcf3ce44SJohn Forte sbp->bmp = 0; 2012fcf3ce44SJohn Forte } 2013fcf3ce44SJohn Forte 2014291a2b48SSukumar Swaminathan mutex_exit(&sbp->mtx); 2015fcf3ce44SJohn Forte 2016fcf3ce44SJohn Forte return (sbp); 2017fcf3ce44SJohn Forte 201882527734SSukumar Swaminathan } /* emlxs_unregister_pkt() */ 2019fcf3ce44SJohn Forte 2020fcf3ce44SJohn Forte 2021fcf3ce44SJohn Forte 202282527734SSukumar Swaminathan /* Flush all IO's to all nodes for a given IO Channel */ 2023fcf3ce44SJohn Forte extern uint32_t 202482527734SSukumar Swaminathan emlxs_tx_channel_flush(emlxs_hba_t *hba, CHANNEL *cp, emlxs_buf_t *fpkt) 2025fcf3ce44SJohn Forte { 2026fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 2027fcf3ce44SJohn Forte emlxs_buf_t *sbp; 2028fcf3ce44SJohn Forte IOCBQ *iocbq; 2029fcf3ce44SJohn Forte IOCBQ *next; 2030fcf3ce44SJohn Forte IOCB *iocb; 203182527734SSukumar Swaminathan uint32_t channelno; 2032fcf3ce44SJohn Forte Q abort; 2033fcf3ce44SJohn Forte NODELIST *ndlp; 2034fcf3ce44SJohn Forte IOCB *icmd; 2035fcf3ce44SJohn Forte MATCHMAP *mp; 2036fcf3ce44SJohn Forte uint32_t i; 203782527734SSukumar Swaminathan uint8_t flag[MAX_CHANNEL]; 2038fcf3ce44SJohn Forte 203982527734SSukumar Swaminathan channelno = cp->channelno; 2040fcf3ce44SJohn Forte bzero((void *)&abort, sizeof (Q)); 204182527734SSukumar Swaminathan bzero((void *)flag, MAX_CHANNEL * sizeof (uint8_t)); 2042fcf3ce44SJohn Forte 204382527734SSukumar Swaminathan mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 2044fcf3ce44SJohn Forte 2045fcf3ce44SJohn Forte /* While a node needs servicing */ 204682527734SSukumar Swaminathan while (cp->nodeq.q_first) { 204782527734SSukumar Swaminathan ndlp = (NODELIST *) cp->nodeq.q_first; 2048fcf3ce44SJohn Forte 2049fcf3ce44SJohn Forte /* Check if priority queue is not empty */ 205082527734SSukumar Swaminathan if (ndlp->nlp_ptx[channelno].q_first) { 2051fcf3ce44SJohn Forte /* Transfer all iocb's to local queue */ 2052fcf3ce44SJohn Forte if (abort.q_first == 0) { 205382527734SSukumar Swaminathan abort.q_first = 205482527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_first; 2055fcf3ce44SJohn Forte } else { 2056fcf3ce44SJohn Forte ((IOCBQ *)abort.q_last)->next = 205782527734SSukumar Swaminathan (IOCBQ *)ndlp->nlp_ptx[channelno].q_first; 2058fcf3ce44SJohn Forte } 205982527734SSukumar Swaminathan flag[channelno] = 1; 2060fcf3ce44SJohn Forte 206182527734SSukumar Swaminathan abort.q_last = ndlp->nlp_ptx[channelno].q_last; 206282527734SSukumar Swaminathan abort.q_cnt += ndlp->nlp_ptx[channelno].q_cnt; 2063fcf3ce44SJohn Forte } 2064291a2b48SSukumar Swaminathan 2065fcf3ce44SJohn Forte /* Check if tx queue is not empty */ 206682527734SSukumar Swaminathan if (ndlp->nlp_tx[channelno].q_first) { 2067fcf3ce44SJohn Forte /* Transfer all iocb's to local queue */ 2068fcf3ce44SJohn Forte if (abort.q_first == 0) { 206982527734SSukumar Swaminathan abort.q_first = ndlp->nlp_tx[channelno].q_first; 2070fcf3ce44SJohn Forte } else { 2071fcf3ce44SJohn Forte ((IOCBQ *)abort.q_last)->next = 207282527734SSukumar Swaminathan (IOCBQ *)ndlp->nlp_tx[channelno].q_first; 2073fcf3ce44SJohn Forte } 2074fcf3ce44SJohn Forte 207582527734SSukumar Swaminathan abort.q_last = ndlp->nlp_tx[channelno].q_last; 207682527734SSukumar Swaminathan abort.q_cnt += ndlp->nlp_tx[channelno].q_cnt; 2077fcf3ce44SJohn Forte } 2078291a2b48SSukumar Swaminathan 2079fcf3ce44SJohn Forte /* Clear the queue pointers */ 208082527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_first = NULL; 208182527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_last = NULL; 208282527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_cnt = 0; 2083fcf3ce44SJohn Forte 208482527734SSukumar Swaminathan ndlp->nlp_tx[channelno].q_first = NULL; 208582527734SSukumar Swaminathan ndlp->nlp_tx[channelno].q_last = NULL; 208682527734SSukumar Swaminathan ndlp->nlp_tx[channelno].q_cnt = 0; 2087fcf3ce44SJohn Forte 2088fcf3ce44SJohn Forte /* Remove node from service queue */ 2089fcf3ce44SJohn Forte 2090fcf3ce44SJohn Forte /* If this is the last node on list */ 209182527734SSukumar Swaminathan if (cp->nodeq.q_last == (void *)ndlp) { 209282527734SSukumar Swaminathan cp->nodeq.q_last = NULL; 209382527734SSukumar Swaminathan cp->nodeq.q_first = NULL; 209482527734SSukumar Swaminathan cp->nodeq.q_cnt = 0; 2095fcf3ce44SJohn Forte } else { 2096fcf3ce44SJohn Forte /* Remove node from head */ 209782527734SSukumar Swaminathan cp->nodeq.q_first = ndlp->nlp_next[channelno]; 209882527734SSukumar Swaminathan ((NODELIST *)cp->nodeq.q_last)->nlp_next[channelno] = 209982527734SSukumar Swaminathan cp->nodeq.q_first; 210082527734SSukumar Swaminathan cp->nodeq.q_cnt--; 2101fcf3ce44SJohn Forte } 2102fcf3ce44SJohn Forte 2103fcf3ce44SJohn Forte /* Clear node */ 210482527734SSukumar Swaminathan ndlp->nlp_next[channelno] = NULL; 2105fcf3ce44SJohn Forte } 2106fcf3ce44SJohn Forte 2107fcf3ce44SJohn Forte /* First cleanup the iocb's while still holding the lock */ 2108291a2b48SSukumar Swaminathan iocbq = (IOCBQ *) abort.q_first; 2109fcf3ce44SJohn Forte while (iocbq) { 2110fcf3ce44SJohn Forte /* Free the IoTag and the bmp */ 2111fcf3ce44SJohn Forte iocb = &iocbq->iocb; 211282527734SSukumar Swaminathan 211382527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 211482527734SSukumar Swaminathan sbp = iocbq->sbp; 211582527734SSukumar Swaminathan if (sbp) { 211682527734SSukumar Swaminathan hba->fc_table[sbp->iotag] = NULL; 211782527734SSukumar Swaminathan emlxs_sli4_free_xri(hba, sbp, sbp->xp); 211882527734SSukumar Swaminathan } 211982527734SSukumar Swaminathan } else { 212082527734SSukumar Swaminathan sbp = emlxs_unregister_pkt((CHANNEL *)iocbq->channel, 212182527734SSukumar Swaminathan iocb->ULPIOTAG, 0); 212282527734SSukumar Swaminathan } 2123fcf3ce44SJohn Forte 2124fcf3ce44SJohn Forte if (sbp && (sbp != STALE_PACKET)) { 2125fcf3ce44SJohn Forte mutex_enter(&sbp->mtx); 2126fcf3ce44SJohn Forte 2127fcf3ce44SJohn Forte sbp->pkt_flags |= PACKET_IN_FLUSH; 2128fcf3ce44SJohn Forte /* 2129fcf3ce44SJohn Forte * If the fpkt is already set, then we will leave it 2130291a2b48SSukumar Swaminathan * alone. This ensures that this pkt is only accounted 2131291a2b48SSukumar Swaminathan * for on one fpkt->flush_count 2132fcf3ce44SJohn Forte */ 2133fcf3ce44SJohn Forte if (!sbp->fpkt && fpkt) { 2134fcf3ce44SJohn Forte mutex_enter(&fpkt->mtx); 2135fcf3ce44SJohn Forte sbp->fpkt = fpkt; 2136fcf3ce44SJohn Forte fpkt->flush_count++; 2137fcf3ce44SJohn Forte mutex_exit(&fpkt->mtx); 2138fcf3ce44SJohn Forte } 2139291a2b48SSukumar Swaminathan 2140fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 2141fcf3ce44SJohn Forte } 2142291a2b48SSukumar Swaminathan 2143fcf3ce44SJohn Forte iocbq = (IOCBQ *)iocbq->next; 2144fcf3ce44SJohn Forte } /* end of while */ 2145fcf3ce44SJohn Forte 214682527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 2147fcf3ce44SJohn Forte 2148fcf3ce44SJohn Forte /* Now abort the iocb's */ 2149fcf3ce44SJohn Forte iocbq = (IOCBQ *)abort.q_first; 2150fcf3ce44SJohn Forte while (iocbq) { 2151fcf3ce44SJohn Forte /* Save the next iocbq for now */ 2152fcf3ce44SJohn Forte next = (IOCBQ *)iocbq->next; 2153fcf3ce44SJohn Forte 2154fcf3ce44SJohn Forte /* Unlink this iocbq */ 2155fcf3ce44SJohn Forte iocbq->next = NULL; 2156fcf3ce44SJohn Forte 2157fcf3ce44SJohn Forte /* Get the pkt */ 2158fcf3ce44SJohn Forte sbp = (emlxs_buf_t *)iocbq->sbp; 2159fcf3ce44SJohn Forte 2160fcf3ce44SJohn Forte if (sbp) { 2161fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flush_msg, 2162291a2b48SSukumar Swaminathan "tx: sbp=%p node=%p", sbp, sbp->node); 2163fcf3ce44SJohn Forte 2164fcf3ce44SJohn Forte if (hba->state >= FC_LINK_UP) { 2165fcf3ce44SJohn Forte emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 2166fcf3ce44SJohn Forte IOERR_ABORT_REQUESTED, 1); 2167fcf3ce44SJohn Forte } else { 2168fcf3ce44SJohn Forte emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 2169fcf3ce44SJohn Forte IOERR_LINK_DOWN, 1); 2170fcf3ce44SJohn Forte } 2171fcf3ce44SJohn Forte 2172fcf3ce44SJohn Forte } 2173fcf3ce44SJohn Forte /* Free the iocb and its associated buffers */ 2174fcf3ce44SJohn Forte else { 2175fcf3ce44SJohn Forte icmd = &iocbq->iocb; 217682527734SSukumar Swaminathan 217782527734SSukumar Swaminathan /* SLI3 */ 217882527734SSukumar Swaminathan if (icmd->ULPCOMMAND == CMD_QUE_RING_BUF64_CN || 217982527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_QUE_RING_BUF_CN || 218082527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_QUE_RING_LIST64_CN) { 2181fcf3ce44SJohn Forte if ((hba->flag & 2182fcf3ce44SJohn Forte (FC_ONLINE_MODE | FC_ONLINING_MODE)) == 0) { 2183fcf3ce44SJohn Forte /* HBA is detaching or offlining */ 218482527734SSukumar Swaminathan if (icmd->ULPCOMMAND != 2185fcf3ce44SJohn Forte CMD_QUE_RING_LIST64_CN) { 2186291a2b48SSukumar Swaminathan uint8_t *tmp; 218782527734SSukumar Swaminathan RING *rp; 2188fcf3ce44SJohn Forte 218982527734SSukumar Swaminathan rp = &hba->sli.sli3. 219082527734SSukumar Swaminathan ring[channelno]; 2191fcf3ce44SJohn Forte for (i = 0; 219282527734SSukumar Swaminathan i < icmd->ULPBDECOUNT; 2193fcf3ce44SJohn Forte i++) { 2194fcf3ce44SJohn Forte mp = EMLXS_GET_VADDR( 2195fcf3ce44SJohn Forte hba, rp, icmd); 2196fcf3ce44SJohn Forte 2197fcf3ce44SJohn Forte tmp = (uint8_t *)mp; 2198fcf3ce44SJohn Forte if (mp) { 2199291a2b48SSukumar Swaminathan (void) emlxs_mem_put( 2200291a2b48SSukumar Swaminathan hba, MEM_BUF, tmp); 2201fcf3ce44SJohn Forte } 2202fcf3ce44SJohn Forte } 2203fcf3ce44SJohn Forte } 2204291a2b48SSukumar Swaminathan 2205fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_IOCB, 2206fcf3ce44SJohn Forte (uint8_t *)iocbq); 2207fcf3ce44SJohn Forte } else { 2208fcf3ce44SJohn Forte /* repost the unsolicited buffer */ 220982527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, 2210291a2b48SSukumar Swaminathan iocbq); 2211fcf3ce44SJohn Forte } 221282527734SSukumar Swaminathan } else if (icmd->ULPCOMMAND == CMD_CLOSE_XRI_CN || 221382527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_CLOSE_XRI_CX) { 221482527734SSukumar Swaminathan 221582527734SSukumar Swaminathan emlxs_tx_put(iocbq, 1); 2216fcf3ce44SJohn Forte } 2217fcf3ce44SJohn Forte } 2218fcf3ce44SJohn Forte 2219fcf3ce44SJohn Forte iocbq = next; 2220fcf3ce44SJohn Forte 2221fcf3ce44SJohn Forte } /* end of while */ 2222fcf3ce44SJohn Forte 222382527734SSukumar Swaminathan /* Now trigger channel service */ 222482527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 222582527734SSukumar Swaminathan if (!flag[channelno]) { 222682527734SSukumar Swaminathan continue; 222782527734SSukumar Swaminathan } 222882527734SSukumar Swaminathan 222982527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, &hba->chan[channelno], 0); 223082527734SSukumar Swaminathan } 223182527734SSukumar Swaminathan 2232fcf3ce44SJohn Forte return (abort.q_cnt); 2233fcf3ce44SJohn Forte 223482527734SSukumar Swaminathan } /* emlxs_tx_channel_flush() */ 2235fcf3ce44SJohn Forte 2236fcf3ce44SJohn Forte 2237fcf3ce44SJohn Forte /* Flush all IO's on all or a given ring for a given node */ 2238fcf3ce44SJohn Forte extern uint32_t 223982527734SSukumar Swaminathan emlxs_tx_node_flush(emlxs_port_t *port, NODELIST *ndlp, CHANNEL *chan, 2240fcf3ce44SJohn Forte uint32_t shutdown, emlxs_buf_t *fpkt) 2241fcf3ce44SJohn Forte { 2242fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 2243fcf3ce44SJohn Forte emlxs_buf_t *sbp; 224482527734SSukumar Swaminathan uint32_t channelno; 224582527734SSukumar Swaminathan CHANNEL *cp; 2246fcf3ce44SJohn Forte IOCB *icmd; 2247fcf3ce44SJohn Forte IOCBQ *iocbq; 2248fcf3ce44SJohn Forte NODELIST *prev; 2249fcf3ce44SJohn Forte IOCBQ *next; 2250fcf3ce44SJohn Forte IOCB *iocb; 2251fcf3ce44SJohn Forte Q abort; 2252fcf3ce44SJohn Forte uint32_t i; 2253fcf3ce44SJohn Forte MATCHMAP *mp; 225482527734SSukumar Swaminathan uint8_t flag[MAX_CHANNEL]; 2255fcf3ce44SJohn Forte 2256fcf3ce44SJohn Forte bzero((void *)&abort, sizeof (Q)); 2257fcf3ce44SJohn Forte 2258fcf3ce44SJohn Forte /* Flush all I/O's on tx queue to this target */ 225982527734SSukumar Swaminathan mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 2260fcf3ce44SJohn Forte 2261fcf3ce44SJohn Forte if (!ndlp->nlp_base && shutdown) { 2262fcf3ce44SJohn Forte ndlp->nlp_active = 0; 2263fcf3ce44SJohn Forte } 2264291a2b48SSukumar Swaminathan 226582527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 226682527734SSukumar Swaminathan cp = &hba->chan[channelno]; 2267fcf3ce44SJohn Forte 226882527734SSukumar Swaminathan if (chan && cp != chan) { 2269fcf3ce44SJohn Forte continue; 2270fcf3ce44SJohn Forte } 2271291a2b48SSukumar Swaminathan 2272fcf3ce44SJohn Forte if (!ndlp->nlp_base || shutdown) { 2273fcf3ce44SJohn Forte /* Check if priority queue is not empty */ 227482527734SSukumar Swaminathan if (ndlp->nlp_ptx[channelno].q_first) { 2275fcf3ce44SJohn Forte /* Transfer all iocb's to local queue */ 2276fcf3ce44SJohn Forte if (abort.q_first == 0) { 2277fcf3ce44SJohn Forte abort.q_first = 227882527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_first; 2279fcf3ce44SJohn Forte } else { 228082527734SSukumar Swaminathan ((IOCBQ *)(abort.q_last))->next = 228182527734SSukumar Swaminathan (IOCBQ *)ndlp->nlp_ptx[channelno]. 2282291a2b48SSukumar Swaminathan q_first; 2283fcf3ce44SJohn Forte } 2284fcf3ce44SJohn Forte 228582527734SSukumar Swaminathan flag[channelno] = 1; 228682527734SSukumar Swaminathan 228782527734SSukumar Swaminathan abort.q_last = ndlp->nlp_ptx[channelno].q_last; 228882527734SSukumar Swaminathan abort.q_cnt += ndlp->nlp_ptx[channelno].q_cnt; 2289fcf3ce44SJohn Forte } 2290fcf3ce44SJohn Forte } 2291291a2b48SSukumar Swaminathan 2292fcf3ce44SJohn Forte /* Check if tx queue is not empty */ 229382527734SSukumar Swaminathan if (ndlp->nlp_tx[channelno].q_first) { 229482527734SSukumar Swaminathan 2295fcf3ce44SJohn Forte /* Transfer all iocb's to local queue */ 2296fcf3ce44SJohn Forte if (abort.q_first == 0) { 229782527734SSukumar Swaminathan abort.q_first = ndlp->nlp_tx[channelno].q_first; 2298fcf3ce44SJohn Forte } else { 2299fcf3ce44SJohn Forte ((IOCBQ *)abort.q_last)->next = 230082527734SSukumar Swaminathan (IOCBQ *)ndlp->nlp_tx[channelno].q_first; 2301fcf3ce44SJohn Forte } 2302fcf3ce44SJohn Forte 230382527734SSukumar Swaminathan abort.q_last = ndlp->nlp_tx[channelno].q_last; 230482527734SSukumar Swaminathan abort.q_cnt += ndlp->nlp_tx[channelno].q_cnt; 2305fcf3ce44SJohn Forte } 2306291a2b48SSukumar Swaminathan 2307fcf3ce44SJohn Forte /* Clear the queue pointers */ 230882527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_first = NULL; 230982527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_last = NULL; 231082527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_cnt = 0; 2311fcf3ce44SJohn Forte 231282527734SSukumar Swaminathan ndlp->nlp_tx[channelno].q_first = NULL; 231382527734SSukumar Swaminathan ndlp->nlp_tx[channelno].q_last = NULL; 231482527734SSukumar Swaminathan ndlp->nlp_tx[channelno].q_cnt = 0; 2315fcf3ce44SJohn Forte 231682527734SSukumar Swaminathan /* If this node was on the channel queue, remove it */ 231782527734SSukumar Swaminathan if (ndlp->nlp_next[channelno]) { 2318fcf3ce44SJohn Forte /* If this is the only node on list */ 231982527734SSukumar Swaminathan if (cp->nodeq.q_first == (void *)ndlp && 232082527734SSukumar Swaminathan cp->nodeq.q_last == (void *)ndlp) { 232182527734SSukumar Swaminathan cp->nodeq.q_last = NULL; 232282527734SSukumar Swaminathan cp->nodeq.q_first = NULL; 232382527734SSukumar Swaminathan cp->nodeq.q_cnt = 0; 232482527734SSukumar Swaminathan } else if (cp->nodeq.q_first == (void *)ndlp) { 232582527734SSukumar Swaminathan cp->nodeq.q_first = ndlp->nlp_next[channelno]; 232682527734SSukumar Swaminathan ((NODELIST *) cp->nodeq.q_last)-> 232782527734SSukumar Swaminathan nlp_next[channelno] = cp->nodeq.q_first; 232882527734SSukumar Swaminathan cp->nodeq.q_cnt--; 2329291a2b48SSukumar Swaminathan } else { 2330fcf3ce44SJohn Forte /* 2331291a2b48SSukumar Swaminathan * This is a little more difficult find the 233282527734SSukumar Swaminathan * previous node in the circular channel queue 2333fcf3ce44SJohn Forte */ 2334fcf3ce44SJohn Forte prev = ndlp; 233582527734SSukumar Swaminathan while (prev->nlp_next[channelno] != ndlp) { 233682527734SSukumar Swaminathan prev = prev->nlp_next[channelno]; 2337fcf3ce44SJohn Forte } 2338fcf3ce44SJohn Forte 233982527734SSukumar Swaminathan prev->nlp_next[channelno] = 234082527734SSukumar Swaminathan ndlp->nlp_next[channelno]; 2341fcf3ce44SJohn Forte 234282527734SSukumar Swaminathan if (cp->nodeq.q_last == (void *)ndlp) { 234382527734SSukumar Swaminathan cp->nodeq.q_last = (void *)prev; 2344fcf3ce44SJohn Forte } 234582527734SSukumar Swaminathan cp->nodeq.q_cnt--; 2346fcf3ce44SJohn Forte 2347fcf3ce44SJohn Forte } 2348fcf3ce44SJohn Forte 2349fcf3ce44SJohn Forte /* Clear node */ 235082527734SSukumar Swaminathan ndlp->nlp_next[channelno] = NULL; 2351fcf3ce44SJohn Forte } 2352291a2b48SSukumar Swaminathan 2353fcf3ce44SJohn Forte } 2354fcf3ce44SJohn Forte 2355fcf3ce44SJohn Forte /* First cleanup the iocb's while still holding the lock */ 2356291a2b48SSukumar Swaminathan iocbq = (IOCBQ *) abort.q_first; 2357fcf3ce44SJohn Forte while (iocbq) { 2358fcf3ce44SJohn Forte /* Free the IoTag and the bmp */ 2359fcf3ce44SJohn Forte iocb = &iocbq->iocb; 236082527734SSukumar Swaminathan 236182527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 236282527734SSukumar Swaminathan sbp = iocbq->sbp; 236382527734SSukumar Swaminathan if (sbp) { 236482527734SSukumar Swaminathan hba->fc_table[sbp->iotag] = NULL; 236582527734SSukumar Swaminathan emlxs_sli4_free_xri(hba, sbp, sbp->xp); 236682527734SSukumar Swaminathan } 236782527734SSukumar Swaminathan } else { 236882527734SSukumar Swaminathan sbp = emlxs_unregister_pkt((CHANNEL *)iocbq->channel, 236982527734SSukumar Swaminathan iocb->ULPIOTAG, 0); 237082527734SSukumar Swaminathan } 2371fcf3ce44SJohn Forte 2372fcf3ce44SJohn Forte if (sbp && (sbp != STALE_PACKET)) { 2373fcf3ce44SJohn Forte mutex_enter(&sbp->mtx); 2374fcf3ce44SJohn Forte sbp->pkt_flags |= PACKET_IN_FLUSH; 2375fcf3ce44SJohn Forte /* 2376fcf3ce44SJohn Forte * If the fpkt is already set, then we will leave it 2377291a2b48SSukumar Swaminathan * alone. This ensures that this pkt is only accounted 2378291a2b48SSukumar Swaminathan * for on one fpkt->flush_count 2379fcf3ce44SJohn Forte */ 2380fcf3ce44SJohn Forte if (!sbp->fpkt && fpkt) { 2381fcf3ce44SJohn Forte mutex_enter(&fpkt->mtx); 2382fcf3ce44SJohn Forte sbp->fpkt = fpkt; 2383fcf3ce44SJohn Forte fpkt->flush_count++; 2384fcf3ce44SJohn Forte mutex_exit(&fpkt->mtx); 2385fcf3ce44SJohn Forte } 2386291a2b48SSukumar Swaminathan 2387fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 2388fcf3ce44SJohn Forte } 2389291a2b48SSukumar Swaminathan 2390291a2b48SSukumar Swaminathan iocbq = (IOCBQ *) iocbq->next; 2391fcf3ce44SJohn Forte 2392fcf3ce44SJohn Forte } /* end of while */ 2393fcf3ce44SJohn Forte 239482527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 2395fcf3ce44SJohn Forte 2396fcf3ce44SJohn Forte /* Now abort the iocb's outside the locks */ 2397fcf3ce44SJohn Forte iocbq = (IOCBQ *)abort.q_first; 2398fcf3ce44SJohn Forte while (iocbq) { 2399fcf3ce44SJohn Forte /* Save the next iocbq for now */ 2400fcf3ce44SJohn Forte next = (IOCBQ *)iocbq->next; 2401fcf3ce44SJohn Forte 2402fcf3ce44SJohn Forte /* Unlink this iocbq */ 2403fcf3ce44SJohn Forte iocbq->next = NULL; 2404fcf3ce44SJohn Forte 2405fcf3ce44SJohn Forte /* Get the pkt */ 2406fcf3ce44SJohn Forte sbp = (emlxs_buf_t *)iocbq->sbp; 2407fcf3ce44SJohn Forte 2408fcf3ce44SJohn Forte if (sbp) { 2409fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flush_msg, 2410291a2b48SSukumar Swaminathan "tx: sbp=%p node=%p", sbp, sbp->node); 2411fcf3ce44SJohn Forte 2412fcf3ce44SJohn Forte if (hba->state >= FC_LINK_UP) { 2413fcf3ce44SJohn Forte emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 2414fcf3ce44SJohn Forte IOERR_ABORT_REQUESTED, 1); 2415fcf3ce44SJohn Forte } else { 2416fcf3ce44SJohn Forte emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 2417fcf3ce44SJohn Forte IOERR_LINK_DOWN, 1); 2418fcf3ce44SJohn Forte } 2419fcf3ce44SJohn Forte 2420fcf3ce44SJohn Forte } 2421fcf3ce44SJohn Forte /* Free the iocb and its associated buffers */ 2422fcf3ce44SJohn Forte else { 242382527734SSukumar Swaminathan /* CMD_CLOSE_XRI_CN should also free the memory */ 2424fcf3ce44SJohn Forte icmd = &iocbq->iocb; 242582527734SSukumar Swaminathan 242682527734SSukumar Swaminathan /* SLI3 */ 242782527734SSukumar Swaminathan if (icmd->ULPCOMMAND == CMD_QUE_RING_BUF64_CN || 242882527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_QUE_RING_BUF_CN || 242982527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_QUE_RING_LIST64_CN) { 2430fcf3ce44SJohn Forte if ((hba->flag & 2431fcf3ce44SJohn Forte (FC_ONLINE_MODE | FC_ONLINING_MODE)) == 0) { 2432fcf3ce44SJohn Forte /* HBA is detaching or offlining */ 243382527734SSukumar Swaminathan if (icmd->ULPCOMMAND != 2434fcf3ce44SJohn Forte CMD_QUE_RING_LIST64_CN) { 2435291a2b48SSukumar Swaminathan uint8_t *tmp; 243682527734SSukumar Swaminathan RING *rp; 243782527734SSukumar Swaminathan int ch; 2438fcf3ce44SJohn Forte 243982527734SSukumar Swaminathan ch = ((CHANNEL *) 244082527734SSukumar Swaminathan iocbq->channel)->channelno; 244182527734SSukumar Swaminathan rp = &hba->sli.sli3.ring[ch]; 2442fcf3ce44SJohn Forte for (i = 0; 244382527734SSukumar Swaminathan i < icmd->ULPBDECOUNT; 2444fcf3ce44SJohn Forte i++) { 2445fcf3ce44SJohn Forte mp = EMLXS_GET_VADDR( 2446fcf3ce44SJohn Forte hba, rp, icmd); 2447fcf3ce44SJohn Forte 2448fcf3ce44SJohn Forte tmp = (uint8_t *)mp; 2449fcf3ce44SJohn Forte if (mp) { 2450291a2b48SSukumar Swaminathan (void) emlxs_mem_put( 2451291a2b48SSukumar Swaminathan hba, MEM_BUF, tmp); 2452fcf3ce44SJohn Forte } 2453fcf3ce44SJohn Forte } 2454fcf3ce44SJohn Forte } 2455291a2b48SSukumar Swaminathan 2456fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_IOCB, 2457fcf3ce44SJohn Forte (uint8_t *)iocbq); 2458fcf3ce44SJohn Forte } else { 2459fcf3ce44SJohn Forte /* repost the unsolicited buffer */ 246082527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, 246182527734SSukumar Swaminathan (CHANNEL *)iocbq->channel, iocbq); 2462fcf3ce44SJohn Forte } 246382527734SSukumar Swaminathan } else if (icmd->ULPCOMMAND == CMD_CLOSE_XRI_CN || 246482527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_CLOSE_XRI_CX) { 246582527734SSukumar Swaminathan /* 246682527734SSukumar Swaminathan * Resend the abort iocbq if any 246782527734SSukumar Swaminathan */ 246882527734SSukumar Swaminathan emlxs_tx_put(iocbq, 1); 2469fcf3ce44SJohn Forte } 2470fcf3ce44SJohn Forte } 2471fcf3ce44SJohn Forte 2472fcf3ce44SJohn Forte iocbq = next; 2473fcf3ce44SJohn Forte 2474fcf3ce44SJohn Forte } /* end of while */ 2475fcf3ce44SJohn Forte 247682527734SSukumar Swaminathan /* Now trigger channel service */ 247782527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 247882527734SSukumar Swaminathan if (!flag[channelno]) { 247982527734SSukumar Swaminathan continue; 248082527734SSukumar Swaminathan } 248182527734SSukumar Swaminathan 248282527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, &hba->chan[channelno], 0); 248382527734SSukumar Swaminathan } 248482527734SSukumar Swaminathan 2485fcf3ce44SJohn Forte return (abort.q_cnt); 2486fcf3ce44SJohn Forte 248782527734SSukumar Swaminathan } /* emlxs_tx_node_flush() */ 2488fcf3ce44SJohn Forte 2489fcf3ce44SJohn Forte 2490fcf3ce44SJohn Forte /* Check for IO's on all or a given ring for a given node */ 2491fcf3ce44SJohn Forte extern uint32_t 249282527734SSukumar Swaminathan emlxs_tx_node_check(emlxs_port_t *port, NODELIST *ndlp, CHANNEL *chan) 2493fcf3ce44SJohn Forte { 2494fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 249582527734SSukumar Swaminathan uint32_t channelno; 249682527734SSukumar Swaminathan CHANNEL *cp; 2497fcf3ce44SJohn Forte uint32_t count; 2498fcf3ce44SJohn Forte 2499fcf3ce44SJohn Forte count = 0; 2500fcf3ce44SJohn Forte 2501fcf3ce44SJohn Forte /* Flush all I/O's on tx queue to this target */ 250282527734SSukumar Swaminathan mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 2503fcf3ce44SJohn Forte 250482527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 250582527734SSukumar Swaminathan cp = &hba->chan[channelno]; 2506fcf3ce44SJohn Forte 250782527734SSukumar Swaminathan if (chan && cp != chan) { 2508fcf3ce44SJohn Forte continue; 2509fcf3ce44SJohn Forte } 2510291a2b48SSukumar Swaminathan 2511fcf3ce44SJohn Forte /* Check if priority queue is not empty */ 251282527734SSukumar Swaminathan if (ndlp->nlp_ptx[channelno].q_first) { 251382527734SSukumar Swaminathan count += ndlp->nlp_ptx[channelno].q_cnt; 2514fcf3ce44SJohn Forte } 2515291a2b48SSukumar Swaminathan 2516fcf3ce44SJohn Forte /* Check if tx queue is not empty */ 251782527734SSukumar Swaminathan if (ndlp->nlp_tx[channelno].q_first) { 251882527734SSukumar Swaminathan count += ndlp->nlp_tx[channelno].q_cnt; 2519fcf3ce44SJohn Forte } 2520291a2b48SSukumar Swaminathan 2521fcf3ce44SJohn Forte } 2522fcf3ce44SJohn Forte 252382527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 2524fcf3ce44SJohn Forte 2525fcf3ce44SJohn Forte return (count); 2526fcf3ce44SJohn Forte 252782527734SSukumar Swaminathan } /* emlxs_tx_node_check() */ 2528fcf3ce44SJohn Forte 2529fcf3ce44SJohn Forte 2530fcf3ce44SJohn Forte 253182527734SSukumar Swaminathan /* Flush all IO's on the any ring for a given node's lun */ 2532fcf3ce44SJohn Forte extern uint32_t 2533291a2b48SSukumar Swaminathan emlxs_tx_lun_flush(emlxs_port_t *port, NODELIST *ndlp, uint32_t lun, 2534291a2b48SSukumar Swaminathan emlxs_buf_t *fpkt) 2535fcf3ce44SJohn Forte { 2536fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 2537fcf3ce44SJohn Forte emlxs_buf_t *sbp; 253882527734SSukumar Swaminathan uint32_t channelno; 2539fcf3ce44SJohn Forte IOCBQ *iocbq; 2540fcf3ce44SJohn Forte IOCBQ *prev; 2541fcf3ce44SJohn Forte IOCBQ *next; 2542fcf3ce44SJohn Forte IOCB *iocb; 2543fcf3ce44SJohn Forte IOCB *icmd; 2544fcf3ce44SJohn Forte Q abort; 2545fcf3ce44SJohn Forte uint32_t i; 2546fcf3ce44SJohn Forte MATCHMAP *mp; 254782527734SSukumar Swaminathan CHANNEL *cp; 254882527734SSukumar Swaminathan CHANNEL *channel; 254982527734SSukumar Swaminathan uint8_t flag[MAX_CHANNEL]; 2550fcf3ce44SJohn Forte 2551fcf3ce44SJohn Forte bzero((void *)&abort, sizeof (Q)); 2552fcf3ce44SJohn Forte 2553fcf3ce44SJohn Forte /* Flush I/O's on txQ to this target's lun */ 255482527734SSukumar Swaminathan mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 2555fcf3ce44SJohn Forte 255682527734SSukumar Swaminathan channel = &hba->chan[hba->channel_fcp]; 2557fcf3ce44SJohn Forte 255882527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 255982527734SSukumar Swaminathan cp = &hba->chan[channelno]; 2560fcf3ce44SJohn Forte 256182527734SSukumar Swaminathan if (channel && cp != channel) { 256282527734SSukumar Swaminathan continue; 256382527734SSukumar Swaminathan } 2564291a2b48SSukumar Swaminathan 256582527734SSukumar Swaminathan /* Scan the priority queue first */ 256682527734SSukumar Swaminathan prev = NULL; 256782527734SSukumar Swaminathan iocbq = (IOCBQ *) ndlp->nlp_ptx[channelno].q_first; 2568fcf3ce44SJohn Forte 256982527734SSukumar Swaminathan while (iocbq) { 257082527734SSukumar Swaminathan next = (IOCBQ *)iocbq->next; 257182527734SSukumar Swaminathan iocb = &iocbq->iocb; 257282527734SSukumar Swaminathan sbp = (emlxs_buf_t *)iocbq->sbp; 257382527734SSukumar Swaminathan 257482527734SSukumar Swaminathan /* Check if this IO is for our lun */ 257582527734SSukumar Swaminathan if (sbp && (sbp->lun == lun)) { 257682527734SSukumar Swaminathan /* Remove iocb from the node's ptx queue */ 257782527734SSukumar Swaminathan if (next == 0) { 257882527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_last = 257982527734SSukumar Swaminathan (uint8_t *)prev; 258082527734SSukumar Swaminathan } 258182527734SSukumar Swaminathan 258282527734SSukumar Swaminathan if (prev == 0) { 258382527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_first = 258482527734SSukumar Swaminathan (uint8_t *)next; 258582527734SSukumar Swaminathan } else { 258682527734SSukumar Swaminathan prev->next = next; 258782527734SSukumar Swaminathan } 258882527734SSukumar Swaminathan 258982527734SSukumar Swaminathan iocbq->next = NULL; 259082527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_cnt--; 259182527734SSukumar Swaminathan 259282527734SSukumar Swaminathan /* 259382527734SSukumar Swaminathan * Add this iocb to our local abort Q 259482527734SSukumar Swaminathan */ 259582527734SSukumar Swaminathan if (abort.q_first) { 259682527734SSukumar Swaminathan ((IOCBQ *)abort.q_last)->next = iocbq; 259782527734SSukumar Swaminathan abort.q_last = (uint8_t *)iocbq; 259882527734SSukumar Swaminathan abort.q_cnt++; 259982527734SSukumar Swaminathan } else { 260082527734SSukumar Swaminathan abort.q_first = (uint8_t *)iocbq; 260182527734SSukumar Swaminathan abort.q_last = (uint8_t *)iocbq; 260282527734SSukumar Swaminathan abort.q_cnt = 1; 260382527734SSukumar Swaminathan } 260482527734SSukumar Swaminathan iocbq->next = NULL; 260582527734SSukumar Swaminathan flag[channelno] = 1; 2606fcf3ce44SJohn Forte 2607fcf3ce44SJohn Forte } else { 260882527734SSukumar Swaminathan prev = iocbq; 2609fcf3ce44SJohn Forte } 2610fcf3ce44SJohn Forte 261182527734SSukumar Swaminathan iocbq = next; 2612fcf3ce44SJohn Forte 261382527734SSukumar Swaminathan } /* while (iocbq) */ 2614fcf3ce44SJohn Forte 2615fcf3ce44SJohn Forte 261682527734SSukumar Swaminathan /* Scan the regular queue */ 261782527734SSukumar Swaminathan prev = NULL; 261882527734SSukumar Swaminathan iocbq = (IOCBQ *)ndlp->nlp_tx[channelno].q_first; 2619fcf3ce44SJohn Forte 262082527734SSukumar Swaminathan while (iocbq) { 262182527734SSukumar Swaminathan next = (IOCBQ *)iocbq->next; 262282527734SSukumar Swaminathan iocb = &iocbq->iocb; 262382527734SSukumar Swaminathan sbp = (emlxs_buf_t *)iocbq->sbp; 262482527734SSukumar Swaminathan 262582527734SSukumar Swaminathan /* Check if this IO is for our lun */ 262682527734SSukumar Swaminathan if (sbp && (sbp->lun == lun)) { 262782527734SSukumar Swaminathan /* Remove iocb from the node's tx queue */ 262882527734SSukumar Swaminathan if (next == 0) { 262982527734SSukumar Swaminathan ndlp->nlp_tx[channelno].q_last = 263082527734SSukumar Swaminathan (uint8_t *)prev; 263182527734SSukumar Swaminathan } 2632291a2b48SSukumar Swaminathan 263382527734SSukumar Swaminathan if (prev == 0) { 263482527734SSukumar Swaminathan ndlp->nlp_tx[channelno].q_first = 263582527734SSukumar Swaminathan (uint8_t *)next; 263682527734SSukumar Swaminathan } else { 263782527734SSukumar Swaminathan prev->next = next; 263882527734SSukumar Swaminathan } 2639fcf3ce44SJohn Forte 264082527734SSukumar Swaminathan iocbq->next = NULL; 264182527734SSukumar Swaminathan ndlp->nlp_tx[channelno].q_cnt--; 2642fcf3ce44SJohn Forte 264382527734SSukumar Swaminathan /* 264482527734SSukumar Swaminathan * Add this iocb to our local abort Q 264582527734SSukumar Swaminathan */ 264682527734SSukumar Swaminathan if (abort.q_first) { 264782527734SSukumar Swaminathan ((IOCBQ *) abort.q_last)->next = iocbq; 264882527734SSukumar Swaminathan abort.q_last = (uint8_t *)iocbq; 264982527734SSukumar Swaminathan abort.q_cnt++; 265082527734SSukumar Swaminathan } else { 265182527734SSukumar Swaminathan abort.q_first = (uint8_t *)iocbq; 265282527734SSukumar Swaminathan abort.q_last = (uint8_t *)iocbq; 265382527734SSukumar Swaminathan abort.q_cnt = 1; 265482527734SSukumar Swaminathan } 265582527734SSukumar Swaminathan iocbq->next = NULL; 2656fcf3ce44SJohn Forte } else { 265782527734SSukumar Swaminathan prev = iocbq; 2658fcf3ce44SJohn Forte } 2659fcf3ce44SJohn Forte 266082527734SSukumar Swaminathan iocbq = next; 2661fcf3ce44SJohn Forte 266282527734SSukumar Swaminathan } /* while (iocbq) */ 266382527734SSukumar Swaminathan } /* for loop */ 2664fcf3ce44SJohn Forte 2665fcf3ce44SJohn Forte /* First cleanup the iocb's while still holding the lock */ 2666fcf3ce44SJohn Forte iocbq = (IOCBQ *)abort.q_first; 2667fcf3ce44SJohn Forte while (iocbq) { 2668fcf3ce44SJohn Forte /* Free the IoTag and the bmp */ 2669fcf3ce44SJohn Forte iocb = &iocbq->iocb; 267082527734SSukumar Swaminathan 267182527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 267282527734SSukumar Swaminathan sbp = iocbq->sbp; 267382527734SSukumar Swaminathan if (sbp) { 267482527734SSukumar Swaminathan hba->fc_table[sbp->iotag] = NULL; 267582527734SSukumar Swaminathan emlxs_sli4_free_xri(hba, sbp, sbp->xp); 267682527734SSukumar Swaminathan } 267782527734SSukumar Swaminathan } else { 267882527734SSukumar Swaminathan sbp = emlxs_unregister_pkt((CHANNEL *)iocbq->channel, 267982527734SSukumar Swaminathan iocb->ULPIOTAG, 0); 268082527734SSukumar Swaminathan } 2681fcf3ce44SJohn Forte 2682fcf3ce44SJohn Forte if (sbp && (sbp != STALE_PACKET)) { 2683fcf3ce44SJohn Forte mutex_enter(&sbp->mtx); 2684fcf3ce44SJohn Forte sbp->pkt_flags |= PACKET_IN_FLUSH; 2685fcf3ce44SJohn Forte /* 2686fcf3ce44SJohn Forte * If the fpkt is already set, then we will leave it 2687291a2b48SSukumar Swaminathan * alone. This ensures that this pkt is only accounted 2688291a2b48SSukumar Swaminathan * for on one fpkt->flush_count 2689fcf3ce44SJohn Forte */ 2690fcf3ce44SJohn Forte if (!sbp->fpkt && fpkt) { 2691fcf3ce44SJohn Forte mutex_enter(&fpkt->mtx); 2692fcf3ce44SJohn Forte sbp->fpkt = fpkt; 2693fcf3ce44SJohn Forte fpkt->flush_count++; 2694fcf3ce44SJohn Forte mutex_exit(&fpkt->mtx); 2695fcf3ce44SJohn Forte } 2696291a2b48SSukumar Swaminathan 2697fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 2698fcf3ce44SJohn Forte } 2699291a2b48SSukumar Swaminathan 2700291a2b48SSukumar Swaminathan iocbq = (IOCBQ *) iocbq->next; 2701fcf3ce44SJohn Forte 2702fcf3ce44SJohn Forte } /* end of while */ 2703fcf3ce44SJohn Forte 270482527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 2705fcf3ce44SJohn Forte 2706fcf3ce44SJohn Forte /* Now abort the iocb's outside the locks */ 2707fcf3ce44SJohn Forte iocbq = (IOCBQ *)abort.q_first; 2708fcf3ce44SJohn Forte while (iocbq) { 2709fcf3ce44SJohn Forte /* Save the next iocbq for now */ 2710fcf3ce44SJohn Forte next = (IOCBQ *)iocbq->next; 2711fcf3ce44SJohn Forte 2712fcf3ce44SJohn Forte /* Unlink this iocbq */ 2713fcf3ce44SJohn Forte iocbq->next = NULL; 2714fcf3ce44SJohn Forte 2715fcf3ce44SJohn Forte /* Get the pkt */ 2716fcf3ce44SJohn Forte sbp = (emlxs_buf_t *)iocbq->sbp; 2717fcf3ce44SJohn Forte 2718fcf3ce44SJohn Forte if (sbp) { 2719fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flush_msg, 2720291a2b48SSukumar Swaminathan "tx: sbp=%p node=%p", sbp, sbp->node); 2721fcf3ce44SJohn Forte 2722fcf3ce44SJohn Forte if (hba->state >= FC_LINK_UP) { 2723fcf3ce44SJohn Forte emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 2724fcf3ce44SJohn Forte IOERR_ABORT_REQUESTED, 1); 2725fcf3ce44SJohn Forte } else { 2726fcf3ce44SJohn Forte emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 2727fcf3ce44SJohn Forte IOERR_LINK_DOWN, 1); 2728fcf3ce44SJohn Forte } 2729fcf3ce44SJohn Forte } 2730291a2b48SSukumar Swaminathan 2731fcf3ce44SJohn Forte /* Free the iocb and its associated buffers */ 2732fcf3ce44SJohn Forte else { 273382527734SSukumar Swaminathan /* Should never happen! */ 2734fcf3ce44SJohn Forte icmd = &iocbq->iocb; 2735fcf3ce44SJohn Forte 273682527734SSukumar Swaminathan /* SLI3 */ 273782527734SSukumar Swaminathan if (icmd->ULPCOMMAND == CMD_QUE_RING_BUF64_CN || 273882527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_QUE_RING_BUF_CN || 273982527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_QUE_RING_LIST64_CN) { 2740fcf3ce44SJohn Forte if ((hba->flag & 2741fcf3ce44SJohn Forte (FC_ONLINE_MODE | FC_ONLINING_MODE)) == 0) { 2742fcf3ce44SJohn Forte /* HBA is detaching or offlining */ 274382527734SSukumar Swaminathan if (icmd->ULPCOMMAND != 2744fcf3ce44SJohn Forte CMD_QUE_RING_LIST64_CN) { 2745291a2b48SSukumar Swaminathan uint8_t *tmp; 274682527734SSukumar Swaminathan RING *rp; 274782527734SSukumar Swaminathan int ch; 2748fcf3ce44SJohn Forte 274982527734SSukumar Swaminathan ch = ((CHANNEL *) 275082527734SSukumar Swaminathan iocbq->channel)->channelno; 275182527734SSukumar Swaminathan rp = &hba->sli.sli3.ring[ch]; 2752fcf3ce44SJohn Forte for (i = 0; 275382527734SSukumar Swaminathan i < icmd->ULPBDECOUNT; 2754fcf3ce44SJohn Forte i++) { 2755fcf3ce44SJohn Forte mp = EMLXS_GET_VADDR( 2756fcf3ce44SJohn Forte hba, rp, icmd); 2757fcf3ce44SJohn Forte 2758fcf3ce44SJohn Forte tmp = (uint8_t *)mp; 2759fcf3ce44SJohn Forte if (mp) { 2760291a2b48SSukumar Swaminathan (void) emlxs_mem_put( 2761291a2b48SSukumar Swaminathan hba, MEM_BUF, tmp); 2762fcf3ce44SJohn Forte } 2763fcf3ce44SJohn Forte } 2764fcf3ce44SJohn Forte } 2765291a2b48SSukumar Swaminathan 2766fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_IOCB, 2767fcf3ce44SJohn Forte (uint8_t *)iocbq); 2768fcf3ce44SJohn Forte } else { 2769fcf3ce44SJohn Forte /* repost the unsolicited buffer */ 277082527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, 277182527734SSukumar Swaminathan (CHANNEL *)iocbq->channel, iocbq); 2772fcf3ce44SJohn Forte } 277382527734SSukumar Swaminathan } else if (icmd->ULPCOMMAND == CMD_CLOSE_XRI_CN || 277482527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_CLOSE_XRI_CX) { 277582527734SSukumar Swaminathan /* 277682527734SSukumar Swaminathan * Resend the abort iocbq if any 277782527734SSukumar Swaminathan */ 277882527734SSukumar Swaminathan emlxs_tx_put(iocbq, 1); 2779fcf3ce44SJohn Forte } 2780fcf3ce44SJohn Forte } 2781fcf3ce44SJohn Forte 2782fcf3ce44SJohn Forte iocbq = next; 2783fcf3ce44SJohn Forte 2784fcf3ce44SJohn Forte } /* end of while */ 2785fcf3ce44SJohn Forte 278682527734SSukumar Swaminathan /* Now trigger channel service */ 278782527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 278882527734SSukumar Swaminathan if (!flag[channelno]) { 278982527734SSukumar Swaminathan continue; 279082527734SSukumar Swaminathan } 279182527734SSukumar Swaminathan 279282527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, &hba->chan[channelno], 0); 279382527734SSukumar Swaminathan } 2794fcf3ce44SJohn Forte 2795fcf3ce44SJohn Forte return (abort.q_cnt); 2796fcf3ce44SJohn Forte 279782527734SSukumar Swaminathan } /* emlxs_tx_lun_flush() */ 2798fcf3ce44SJohn Forte 2799fcf3ce44SJohn Forte 2800fcf3ce44SJohn Forte extern void 2801fcf3ce44SJohn Forte emlxs_tx_put(IOCBQ *iocbq, uint32_t lock) 2802fcf3ce44SJohn Forte { 2803fcf3ce44SJohn Forte emlxs_hba_t *hba; 2804fcf3ce44SJohn Forte emlxs_port_t *port; 280582527734SSukumar Swaminathan uint32_t channelno; 2806fcf3ce44SJohn Forte NODELIST *nlp; 280782527734SSukumar Swaminathan CHANNEL *cp; 2808fcf3ce44SJohn Forte emlxs_buf_t *sbp; 2809fcf3ce44SJohn Forte 2810fcf3ce44SJohn Forte port = (emlxs_port_t *)iocbq->port; 2811fcf3ce44SJohn Forte hba = HBA; 281282527734SSukumar Swaminathan cp = (CHANNEL *)iocbq->channel; 2813fcf3ce44SJohn Forte nlp = (NODELIST *)iocbq->node; 281482527734SSukumar Swaminathan channelno = cp->channelno; 2815fcf3ce44SJohn Forte sbp = (emlxs_buf_t *)iocbq->sbp; 2816fcf3ce44SJohn Forte 281782527734SSukumar Swaminathan /* under what cases, nlp is NULL */ 2818fcf3ce44SJohn Forte if (nlp == NULL) { 2819fcf3ce44SJohn Forte /* Set node to base node by default */ 2820fcf3ce44SJohn Forte nlp = &port->node_base; 2821fcf3ce44SJohn Forte 2822fcf3ce44SJohn Forte iocbq->node = (void *)nlp; 2823fcf3ce44SJohn Forte 2824fcf3ce44SJohn Forte if (sbp) { 2825fcf3ce44SJohn Forte sbp->node = (void *)nlp; 2826fcf3ce44SJohn Forte } 2827fcf3ce44SJohn Forte } 2828291a2b48SSukumar Swaminathan 2829fcf3ce44SJohn Forte if (lock) { 283082527734SSukumar Swaminathan mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 2831fcf3ce44SJohn Forte } 2832291a2b48SSukumar Swaminathan 2833fcf3ce44SJohn Forte if (!nlp->nlp_active || (sbp && (sbp->pkt_flags & PACKET_IN_ABORT))) { 2834fcf3ce44SJohn Forte if (sbp) { 2835fcf3ce44SJohn Forte mutex_enter(&sbp->mtx); 2836fcf3ce44SJohn Forte sbp->pkt_flags |= PACKET_IN_FLUSH; 2837fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 2838fcf3ce44SJohn Forte 283982527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 284082527734SSukumar Swaminathan hba->fc_table[sbp->iotag] = NULL; 284182527734SSukumar Swaminathan emlxs_sli4_free_xri(hba, sbp, sbp->xp); 284282527734SSukumar Swaminathan } else { 284382527734SSukumar Swaminathan (void) emlxs_unregister_pkt(cp, sbp->iotag, 0); 284482527734SSukumar Swaminathan } 2845fcf3ce44SJohn Forte 2846fcf3ce44SJohn Forte if (lock) { 284782527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 2848fcf3ce44SJohn Forte } 2849291a2b48SSukumar Swaminathan 2850fcf3ce44SJohn Forte if (hba->state >= FC_LINK_UP) { 2851fcf3ce44SJohn Forte emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 2852fcf3ce44SJohn Forte IOERR_ABORT_REQUESTED, 1); 2853fcf3ce44SJohn Forte } else { 2854fcf3ce44SJohn Forte emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 2855fcf3ce44SJohn Forte IOERR_LINK_DOWN, 1); 2856fcf3ce44SJohn Forte } 2857fcf3ce44SJohn Forte return; 2858fcf3ce44SJohn Forte } else { 2859fcf3ce44SJohn Forte if (lock) { 286082527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 2861fcf3ce44SJohn Forte } 2862291a2b48SSukumar Swaminathan 2863fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_IOCB, (uint8_t *)iocbq); 2864fcf3ce44SJohn Forte } 2865fcf3ce44SJohn Forte 2866fcf3ce44SJohn Forte return; 2867fcf3ce44SJohn Forte } 2868291a2b48SSukumar Swaminathan 2869fcf3ce44SJohn Forte if (sbp) { 2870fcf3ce44SJohn Forte 2871fcf3ce44SJohn Forte mutex_enter(&sbp->mtx); 2872fcf3ce44SJohn Forte 2873291a2b48SSukumar Swaminathan if (sbp->pkt_flags & 2874291a2b48SSukumar Swaminathan (PACKET_IN_COMPLETION | PACKET_IN_CHIPQ | PACKET_IN_TXQ)) { 2875fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 2876fcf3ce44SJohn Forte if (lock) { 287782527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 2878fcf3ce44SJohn Forte } 2879fcf3ce44SJohn Forte return; 2880fcf3ce44SJohn Forte } 2881291a2b48SSukumar Swaminathan 2882fcf3ce44SJohn Forte sbp->pkt_flags |= PACKET_IN_TXQ; 288382527734SSukumar Swaminathan hba->channel_tx_count++; 2884fcf3ce44SJohn Forte 2885fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 2886fcf3ce44SJohn Forte } 2887291a2b48SSukumar Swaminathan 2888291a2b48SSukumar Swaminathan 2889fcf3ce44SJohn Forte /* Check iocbq priority */ 289082527734SSukumar Swaminathan /* Some IOCB has the high priority like reset/close xri etc */ 2891fcf3ce44SJohn Forte if (iocbq->flag & IOCB_PRIORITY) { 2892fcf3ce44SJohn Forte /* Add the iocb to the bottom of the node's ptx queue */ 289382527734SSukumar Swaminathan if (nlp->nlp_ptx[channelno].q_first) { 289482527734SSukumar Swaminathan ((IOCBQ *)nlp->nlp_ptx[channelno].q_last)->next = iocbq; 289582527734SSukumar Swaminathan nlp->nlp_ptx[channelno].q_last = (uint8_t *)iocbq; 289682527734SSukumar Swaminathan nlp->nlp_ptx[channelno].q_cnt++; 2897fcf3ce44SJohn Forte } else { 289882527734SSukumar Swaminathan nlp->nlp_ptx[channelno].q_first = (uint8_t *)iocbq; 289982527734SSukumar Swaminathan nlp->nlp_ptx[channelno].q_last = (uint8_t *)iocbq; 290082527734SSukumar Swaminathan nlp->nlp_ptx[channelno].q_cnt = 1; 2901fcf3ce44SJohn Forte } 2902fcf3ce44SJohn Forte 2903fcf3ce44SJohn Forte iocbq->next = NULL; 2904fcf3ce44SJohn Forte } else { /* Normal priority */ 2905fcf3ce44SJohn Forte 2906291a2b48SSukumar Swaminathan 2907fcf3ce44SJohn Forte /* Add the iocb to the bottom of the node's tx queue */ 290882527734SSukumar Swaminathan if (nlp->nlp_tx[channelno].q_first) { 290982527734SSukumar Swaminathan ((IOCBQ *)nlp->nlp_tx[channelno].q_last)->next = iocbq; 291082527734SSukumar Swaminathan nlp->nlp_tx[channelno].q_last = (uint8_t *)iocbq; 291182527734SSukumar Swaminathan nlp->nlp_tx[channelno].q_cnt++; 2912fcf3ce44SJohn Forte } else { 291382527734SSukumar Swaminathan nlp->nlp_tx[channelno].q_first = (uint8_t *)iocbq; 291482527734SSukumar Swaminathan nlp->nlp_tx[channelno].q_last = (uint8_t *)iocbq; 291582527734SSukumar Swaminathan nlp->nlp_tx[channelno].q_cnt = 1; 2916fcf3ce44SJohn Forte } 2917fcf3ce44SJohn Forte 2918fcf3ce44SJohn Forte iocbq->next = NULL; 2919fcf3ce44SJohn Forte } 2920fcf3ce44SJohn Forte 2921fcf3ce44SJohn Forte 2922fcf3ce44SJohn Forte /* 292382527734SSukumar Swaminathan * Check if the node is not already on channel queue and 2924291a2b48SSukumar Swaminathan * (is not closed or is a priority request) 2925fcf3ce44SJohn Forte */ 292682527734SSukumar Swaminathan if (!nlp->nlp_next[channelno] && 292782527734SSukumar Swaminathan (!(nlp->nlp_flag[channelno] & NLP_CLOSED) || 2928fcf3ce44SJohn Forte (iocbq->flag & IOCB_PRIORITY))) { 292982527734SSukumar Swaminathan /* If so, then add it to the channel queue */ 293082527734SSukumar Swaminathan if (cp->nodeq.q_first) { 293182527734SSukumar Swaminathan ((NODELIST *)cp->nodeq.q_last)->nlp_next[channelno] = 2932fcf3ce44SJohn Forte (uint8_t *)nlp; 293382527734SSukumar Swaminathan nlp->nlp_next[channelno] = cp->nodeq.q_first; 2934fcf3ce44SJohn Forte 2935fcf3ce44SJohn Forte /* 2936291a2b48SSukumar Swaminathan * If this is not the base node then add it 2937291a2b48SSukumar Swaminathan * to the tail 2938fcf3ce44SJohn Forte */ 2939fcf3ce44SJohn Forte if (!nlp->nlp_base) { 294082527734SSukumar Swaminathan cp->nodeq.q_last = (uint8_t *)nlp; 2941fcf3ce44SJohn Forte } else { /* Otherwise, add it to the head */ 2942291a2b48SSukumar Swaminathan 2943fcf3ce44SJohn Forte /* The command node always gets priority */ 294482527734SSukumar Swaminathan cp->nodeq.q_first = (uint8_t *)nlp; 2945fcf3ce44SJohn Forte } 2946fcf3ce44SJohn Forte 294782527734SSukumar Swaminathan cp->nodeq.q_cnt++; 2948fcf3ce44SJohn Forte } else { 294982527734SSukumar Swaminathan cp->nodeq.q_first = (uint8_t *)nlp; 295082527734SSukumar Swaminathan cp->nodeq.q_last = (uint8_t *)nlp; 295182527734SSukumar Swaminathan nlp->nlp_next[channelno] = nlp; 295282527734SSukumar Swaminathan cp->nodeq.q_cnt = 1; 2953fcf3ce44SJohn Forte } 2954fcf3ce44SJohn Forte } 2955291a2b48SSukumar Swaminathan 295682527734SSukumar Swaminathan HBASTATS.IocbTxPut[channelno]++; 2957fcf3ce44SJohn Forte 295882527734SSukumar Swaminathan /* Adjust the channel timeout timer */ 295982527734SSukumar Swaminathan cp->timeout = hba->timer_tics + 5; 2960fcf3ce44SJohn Forte 2961fcf3ce44SJohn Forte if (lock) { 296282527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 2963fcf3ce44SJohn Forte } 2964291a2b48SSukumar Swaminathan 2965fcf3ce44SJohn Forte return; 2966fcf3ce44SJohn Forte 296782527734SSukumar Swaminathan } /* emlxs_tx_put() */ 2968fcf3ce44SJohn Forte 2969fcf3ce44SJohn Forte 2970fcf3ce44SJohn Forte extern IOCBQ * 297182527734SSukumar Swaminathan emlxs_tx_get(CHANNEL *cp, uint32_t lock) 2972fcf3ce44SJohn Forte { 2973fcf3ce44SJohn Forte emlxs_hba_t *hba; 297482527734SSukumar Swaminathan uint32_t channelno; 2975fcf3ce44SJohn Forte IOCBQ *iocbq; 2976fcf3ce44SJohn Forte NODELIST *nlp; 2977fcf3ce44SJohn Forte emlxs_buf_t *sbp; 2978fcf3ce44SJohn Forte 297982527734SSukumar Swaminathan hba = cp->hba; 298082527734SSukumar Swaminathan channelno = cp->channelno; 2981fcf3ce44SJohn Forte 2982fcf3ce44SJohn Forte if (lock) { 298382527734SSukumar Swaminathan mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 2984fcf3ce44SJohn Forte } 2985291a2b48SSukumar Swaminathan 2986fcf3ce44SJohn Forte begin: 2987fcf3ce44SJohn Forte 2988fcf3ce44SJohn Forte iocbq = NULL; 2989fcf3ce44SJohn Forte 2990fcf3ce44SJohn Forte /* Check if a node needs servicing */ 299182527734SSukumar Swaminathan if (cp->nodeq.q_first) { 299282527734SSukumar Swaminathan nlp = (NODELIST *)cp->nodeq.q_first; 2993fcf3ce44SJohn Forte 2994fcf3ce44SJohn Forte /* Get next iocb from node's priority queue */ 2995fcf3ce44SJohn Forte 299682527734SSukumar Swaminathan if (nlp->nlp_ptx[channelno].q_first) { 299782527734SSukumar Swaminathan iocbq = (IOCBQ *)nlp->nlp_ptx[channelno].q_first; 2998fcf3ce44SJohn Forte 2999fcf3ce44SJohn Forte /* Check if this is last entry */ 300082527734SSukumar Swaminathan if (nlp->nlp_ptx[channelno].q_last == (void *)iocbq) { 300182527734SSukumar Swaminathan nlp->nlp_ptx[channelno].q_first = NULL; 300282527734SSukumar Swaminathan nlp->nlp_ptx[channelno].q_last = NULL; 300382527734SSukumar Swaminathan nlp->nlp_ptx[channelno].q_cnt = 0; 3004fcf3ce44SJohn Forte } else { 3005fcf3ce44SJohn Forte /* Remove iocb from head */ 300682527734SSukumar Swaminathan nlp->nlp_ptx[channelno].q_first = 3007fcf3ce44SJohn Forte (void *)iocbq->next; 300882527734SSukumar Swaminathan nlp->nlp_ptx[channelno].q_cnt--; 3009fcf3ce44SJohn Forte } 3010fcf3ce44SJohn Forte 3011fcf3ce44SJohn Forte iocbq->next = NULL; 3012fcf3ce44SJohn Forte } 3013291a2b48SSukumar Swaminathan 3014fcf3ce44SJohn Forte /* Get next iocb from node tx queue if node not closed */ 301582527734SSukumar Swaminathan else if (nlp->nlp_tx[channelno].q_first && 301682527734SSukumar Swaminathan !(nlp->nlp_flag[channelno] & NLP_CLOSED)) { 301782527734SSukumar Swaminathan iocbq = (IOCBQ *)nlp->nlp_tx[channelno].q_first; 3018fcf3ce44SJohn Forte 3019fcf3ce44SJohn Forte /* Check if this is last entry */ 302082527734SSukumar Swaminathan if (nlp->nlp_tx[channelno].q_last == (void *)iocbq) { 302182527734SSukumar Swaminathan nlp->nlp_tx[channelno].q_first = NULL; 302282527734SSukumar Swaminathan nlp->nlp_tx[channelno].q_last = NULL; 302382527734SSukumar Swaminathan nlp->nlp_tx[channelno].q_cnt = 0; 3024fcf3ce44SJohn Forte } else { 3025fcf3ce44SJohn Forte /* Remove iocb from head */ 302682527734SSukumar Swaminathan nlp->nlp_tx[channelno].q_first = 3027fcf3ce44SJohn Forte (void *)iocbq->next; 302882527734SSukumar Swaminathan nlp->nlp_tx[channelno].q_cnt--; 3029fcf3ce44SJohn Forte } 3030fcf3ce44SJohn Forte 3031fcf3ce44SJohn Forte iocbq->next = NULL; 3032fcf3ce44SJohn Forte } 3033291a2b48SSukumar Swaminathan 3034fcf3ce44SJohn Forte /* Now deal with node itself */ 3035fcf3ce44SJohn Forte 3036fcf3ce44SJohn Forte /* Check if node still needs servicing */ 303782527734SSukumar Swaminathan if ((nlp->nlp_ptx[channelno].q_first) || 303882527734SSukumar Swaminathan (nlp->nlp_tx[channelno].q_first && 303982527734SSukumar Swaminathan !(nlp->nlp_flag[channelno] & NLP_CLOSED))) { 3040fcf3ce44SJohn Forte 3041fcf3ce44SJohn Forte /* 3042fcf3ce44SJohn Forte * If this is the base node, then don't shift the 3043291a2b48SSukumar Swaminathan * pointers. We want to drain the base node before 3044291a2b48SSukumar Swaminathan * moving on 3045fcf3ce44SJohn Forte */ 3046fcf3ce44SJohn Forte if (!nlp->nlp_base) { 3047fcf3ce44SJohn Forte /* 304882527734SSukumar Swaminathan * Just shift channel queue pointers to next 3049fcf3ce44SJohn Forte * node 3050fcf3ce44SJohn Forte */ 305182527734SSukumar Swaminathan cp->nodeq.q_last = (void *)nlp; 305282527734SSukumar Swaminathan cp->nodeq.q_first = nlp->nlp_next[channelno]; 3053fcf3ce44SJohn Forte } 3054fcf3ce44SJohn Forte } else { 305582527734SSukumar Swaminathan /* Remove node from channel queue */ 3056fcf3ce44SJohn Forte 3057fcf3ce44SJohn Forte /* If this is the last node on list */ 305882527734SSukumar Swaminathan if (cp->nodeq.q_last == (void *)nlp) { 305982527734SSukumar Swaminathan cp->nodeq.q_last = NULL; 306082527734SSukumar Swaminathan cp->nodeq.q_first = NULL; 306182527734SSukumar Swaminathan cp->nodeq.q_cnt = 0; 3062fcf3ce44SJohn Forte } else { 3063fcf3ce44SJohn Forte /* Remove node from head */ 306482527734SSukumar Swaminathan cp->nodeq.q_first = nlp->nlp_next[channelno]; 306582527734SSukumar Swaminathan ((NODELIST *)cp->nodeq.q_last)-> 306682527734SSukumar Swaminathan nlp_next[channelno] = cp->nodeq.q_first; 306782527734SSukumar Swaminathan cp->nodeq.q_cnt--; 3068fcf3ce44SJohn Forte 3069fcf3ce44SJohn Forte } 3070fcf3ce44SJohn Forte 3071fcf3ce44SJohn Forte /* Clear node */ 307282527734SSukumar Swaminathan nlp->nlp_next[channelno] = NULL; 3073fcf3ce44SJohn Forte } 3074fcf3ce44SJohn Forte 3075fcf3ce44SJohn Forte /* 3076291a2b48SSukumar Swaminathan * If no iocbq was found on this node, then it will have 3077291a2b48SSukumar Swaminathan * been removed. So try again. 3078fcf3ce44SJohn Forte */ 3079fcf3ce44SJohn Forte if (!iocbq) { 3080fcf3ce44SJohn Forte goto begin; 3081fcf3ce44SJohn Forte } 3082291a2b48SSukumar Swaminathan 3083fcf3ce44SJohn Forte sbp = (emlxs_buf_t *)iocbq->sbp; 3084fcf3ce44SJohn Forte 3085fcf3ce44SJohn Forte if (sbp) { 3086fcf3ce44SJohn Forte /* 3087291a2b48SSukumar Swaminathan * Check flags before we enter mutex in case this 3088291a2b48SSukumar Swaminathan * has been flushed and destroyed 3089fcf3ce44SJohn Forte */ 3090fcf3ce44SJohn Forte if ((sbp->pkt_flags & 3091fcf3ce44SJohn Forte (PACKET_IN_COMPLETION | PACKET_IN_CHIPQ)) || 3092fcf3ce44SJohn Forte !(sbp->pkt_flags & PACKET_IN_TXQ)) { 3093fcf3ce44SJohn Forte goto begin; 3094fcf3ce44SJohn Forte } 3095291a2b48SSukumar Swaminathan 3096fcf3ce44SJohn Forte mutex_enter(&sbp->mtx); 3097fcf3ce44SJohn Forte 3098fcf3ce44SJohn Forte if ((sbp->pkt_flags & 3099fcf3ce44SJohn Forte (PACKET_IN_COMPLETION | PACKET_IN_CHIPQ)) || 3100fcf3ce44SJohn Forte !(sbp->pkt_flags & PACKET_IN_TXQ)) { 3101fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 3102fcf3ce44SJohn Forte goto begin; 3103fcf3ce44SJohn Forte } 3104291a2b48SSukumar Swaminathan 3105fcf3ce44SJohn Forte sbp->pkt_flags &= ~PACKET_IN_TXQ; 310682527734SSukumar Swaminathan hba->channel_tx_count--; 3107fcf3ce44SJohn Forte 3108fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 3109fcf3ce44SJohn Forte } 3110fcf3ce44SJohn Forte } 3111291a2b48SSukumar Swaminathan 3112fcf3ce44SJohn Forte if (iocbq) { 311382527734SSukumar Swaminathan HBASTATS.IocbTxGet[channelno]++; 3114fcf3ce44SJohn Forte } 3115291a2b48SSukumar Swaminathan 3116fcf3ce44SJohn Forte /* Adjust the ring timeout timer */ 311782527734SSukumar Swaminathan cp->timeout = (cp->nodeq.q_first) ? (hba->timer_tics + 5) : 0; 3118fcf3ce44SJohn Forte 3119fcf3ce44SJohn Forte if (lock) { 312082527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 3121fcf3ce44SJohn Forte } 3122291a2b48SSukumar Swaminathan 3123fcf3ce44SJohn Forte return (iocbq); 3124fcf3ce44SJohn Forte 312582527734SSukumar Swaminathan } /* emlxs_tx_get() */ 312682527734SSukumar Swaminathan 3127fcf3ce44SJohn Forte 312882527734SSukumar Swaminathan /* 312982527734SSukumar Swaminathan * Remove all cmd from from_rp's txq to to_rp's txq for ndlp. 313082527734SSukumar Swaminathan * The old IoTag has to be released, the new one has to be 313182527734SSukumar Swaminathan * allocated. Others no change 313282527734SSukumar Swaminathan * TX_CHANNEL lock is held 313382527734SSukumar Swaminathan */ 313482527734SSukumar Swaminathan extern void 313582527734SSukumar Swaminathan emlxs_tx_move(NODELIST *ndlp, CHANNEL *from_chan, CHANNEL *to_chan, 313682527734SSukumar Swaminathan uint32_t cmd, emlxs_buf_t *fpkt, uint32_t lock) 313782527734SSukumar Swaminathan { 313882527734SSukumar Swaminathan emlxs_hba_t *hba; 313982527734SSukumar Swaminathan emlxs_port_t *port; 314082527734SSukumar Swaminathan uint32_t fchanno, tchanno, i; 314182527734SSukumar Swaminathan 314282527734SSukumar Swaminathan IOCBQ *iocbq; 314382527734SSukumar Swaminathan IOCBQ *prev; 314482527734SSukumar Swaminathan IOCBQ *next; 314582527734SSukumar Swaminathan IOCB *iocb, *icmd; 314682527734SSukumar Swaminathan Q tbm; /* To Be Moved Q */ 314782527734SSukumar Swaminathan MATCHMAP *mp; 314882527734SSukumar Swaminathan 314982527734SSukumar Swaminathan NODELIST *nlp = ndlp; 315082527734SSukumar Swaminathan emlxs_buf_t *sbp; 315182527734SSukumar Swaminathan 315282527734SSukumar Swaminathan NODELIST *n_prev = NULL; 315382527734SSukumar Swaminathan NODELIST *n_next = NULL; 315482527734SSukumar Swaminathan uint16_t count = 0; 315582527734SSukumar Swaminathan 315682527734SSukumar Swaminathan hba = from_chan->hba; 315782527734SSukumar Swaminathan port = &PPORT; 315882527734SSukumar Swaminathan cmd = cmd; /* To pass lint */ 315982527734SSukumar Swaminathan 316082527734SSukumar Swaminathan fchanno = from_chan->channelno; 316182527734SSukumar Swaminathan tchanno = to_chan->channelno; 316282527734SSukumar Swaminathan 316382527734SSukumar Swaminathan if (lock) { 316482527734SSukumar Swaminathan mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 316582527734SSukumar Swaminathan } 316682527734SSukumar Swaminathan 316782527734SSukumar Swaminathan bzero((void *)&tbm, sizeof (Q)); 316882527734SSukumar Swaminathan 316982527734SSukumar Swaminathan /* Scan the ndlp's fchanno txq to get the iocb of fcp cmd */ 317082527734SSukumar Swaminathan prev = NULL; 317182527734SSukumar Swaminathan iocbq = (IOCBQ *)nlp->nlp_tx[fchanno].q_first; 317282527734SSukumar Swaminathan 317382527734SSukumar Swaminathan while (iocbq) { 317482527734SSukumar Swaminathan next = (IOCBQ *)iocbq->next; 317582527734SSukumar Swaminathan /* Check if this iocb is fcp cmd */ 317682527734SSukumar Swaminathan iocb = &iocbq->iocb; 317782527734SSukumar Swaminathan 317882527734SSukumar Swaminathan switch (iocb->ULPCOMMAND) { 317982527734SSukumar Swaminathan /* FCP commands */ 318082527734SSukumar Swaminathan case CMD_FCP_ICMND_CR: 318182527734SSukumar Swaminathan case CMD_FCP_ICMND_CX: 318282527734SSukumar Swaminathan case CMD_FCP_IREAD_CR: 318382527734SSukumar Swaminathan case CMD_FCP_IREAD_CX: 318482527734SSukumar Swaminathan case CMD_FCP_IWRITE_CR: 318582527734SSukumar Swaminathan case CMD_FCP_IWRITE_CX: 318682527734SSukumar Swaminathan case CMD_FCP_ICMND64_CR: 318782527734SSukumar Swaminathan case CMD_FCP_ICMND64_CX: 318882527734SSukumar Swaminathan case CMD_FCP_IREAD64_CR: 318982527734SSukumar Swaminathan case CMD_FCP_IREAD64_CX: 319082527734SSukumar Swaminathan case CMD_FCP_IWRITE64_CR: 319182527734SSukumar Swaminathan case CMD_FCP_IWRITE64_CX: 319282527734SSukumar Swaminathan /* We found a fcp cmd */ 319382527734SSukumar Swaminathan break; 319482527734SSukumar Swaminathan default: 319582527734SSukumar Swaminathan /* this is not fcp cmd continue */ 319682527734SSukumar Swaminathan prev = iocbq; 319782527734SSukumar Swaminathan iocbq = next; 319882527734SSukumar Swaminathan continue; 319982527734SSukumar Swaminathan } 320082527734SSukumar Swaminathan 320182527734SSukumar Swaminathan /* found a fcp cmd iocb in fchanno txq, now deque it */ 320282527734SSukumar Swaminathan if (next == NULL) { 320382527734SSukumar Swaminathan /* This is the last iocbq */ 320482527734SSukumar Swaminathan nlp->nlp_tx[fchanno].q_last = 320582527734SSukumar Swaminathan (uint8_t *)prev; 320682527734SSukumar Swaminathan } 320782527734SSukumar Swaminathan 320882527734SSukumar Swaminathan if (prev == NULL) { 320982527734SSukumar Swaminathan /* This is the first one then remove it from head */ 321082527734SSukumar Swaminathan nlp->nlp_tx[fchanno].q_first = 321182527734SSukumar Swaminathan (uint8_t *)next; 321282527734SSukumar Swaminathan } else { 321382527734SSukumar Swaminathan prev->next = next; 321482527734SSukumar Swaminathan } 321582527734SSukumar Swaminathan 321682527734SSukumar Swaminathan iocbq->next = NULL; 321782527734SSukumar Swaminathan nlp->nlp_tx[fchanno].q_cnt--; 321882527734SSukumar Swaminathan 321982527734SSukumar Swaminathan /* Add this iocb to our local toberemovedq */ 322082527734SSukumar Swaminathan /* This way we donot hold the TX_CHANNEL lock too long */ 322182527734SSukumar Swaminathan 322282527734SSukumar Swaminathan if (tbm.q_first) { 322382527734SSukumar Swaminathan ((IOCBQ *)tbm.q_last)->next = iocbq; 322482527734SSukumar Swaminathan tbm.q_last = (uint8_t *)iocbq; 322582527734SSukumar Swaminathan tbm.q_cnt++; 322682527734SSukumar Swaminathan } else { 322782527734SSukumar Swaminathan tbm.q_first = (uint8_t *)iocbq; 322882527734SSukumar Swaminathan tbm.q_last = (uint8_t *)iocbq; 322982527734SSukumar Swaminathan tbm.q_cnt = 1; 323082527734SSukumar Swaminathan } 323182527734SSukumar Swaminathan 323282527734SSukumar Swaminathan iocbq = next; 323382527734SSukumar Swaminathan 323482527734SSukumar Swaminathan } /* While (iocbq) */ 323582527734SSukumar Swaminathan 323682527734SSukumar Swaminathan if ((tchanno == hba->channel_fcp) && (tbm.q_cnt != 0)) { 323782527734SSukumar Swaminathan 323882527734SSukumar Swaminathan /* from_chan->nodeq.q_first must be non NULL */ 323982527734SSukumar Swaminathan if (from_chan->nodeq.q_first) { 324082527734SSukumar Swaminathan 324182527734SSukumar Swaminathan /* nodeq is not empty, now deal with the node itself */ 324282527734SSukumar Swaminathan if ((nlp->nlp_tx[fchanno].q_first)) { 324382527734SSukumar Swaminathan 324482527734SSukumar Swaminathan if (!nlp->nlp_base) { 324582527734SSukumar Swaminathan from_chan->nodeq.q_last = 324682527734SSukumar Swaminathan (void *)nlp; 324782527734SSukumar Swaminathan from_chan->nodeq.q_first = 324882527734SSukumar Swaminathan nlp->nlp_next[fchanno]; 324982527734SSukumar Swaminathan } 325082527734SSukumar Swaminathan 325182527734SSukumar Swaminathan } else { 325282527734SSukumar Swaminathan n_prev = (NODELIST *)from_chan->nodeq.q_first; 325382527734SSukumar Swaminathan count = from_chan->nodeq.q_cnt; 325482527734SSukumar Swaminathan 325582527734SSukumar Swaminathan if (n_prev == nlp) { 325682527734SSukumar Swaminathan 325782527734SSukumar Swaminathan /* If this is the only node on list */ 325882527734SSukumar Swaminathan if (from_chan->nodeq.q_last == 325982527734SSukumar Swaminathan (void *)nlp) { 326082527734SSukumar Swaminathan from_chan->nodeq.q_last = 326182527734SSukumar Swaminathan NULL; 326282527734SSukumar Swaminathan from_chan->nodeq.q_first = 326382527734SSukumar Swaminathan NULL; 326482527734SSukumar Swaminathan from_chan->nodeq.q_cnt = 0; 326582527734SSukumar Swaminathan } else { 326682527734SSukumar Swaminathan from_chan->nodeq.q_first = 326782527734SSukumar Swaminathan nlp->nlp_next[fchanno]; 326882527734SSukumar Swaminathan ((NODELIST *)from_chan-> 326982527734SSukumar Swaminathan nodeq.q_last)-> 327082527734SSukumar Swaminathan nlp_next[fchanno] = 327182527734SSukumar Swaminathan from_chan->nodeq.q_first; 327282527734SSukumar Swaminathan from_chan->nodeq.q_cnt--; 327382527734SSukumar Swaminathan } 327482527734SSukumar Swaminathan /* Clear node */ 327582527734SSukumar Swaminathan nlp->nlp_next[fchanno] = NULL; 327682527734SSukumar Swaminathan } else { 327782527734SSukumar Swaminathan count--; 327882527734SSukumar Swaminathan do { 327982527734SSukumar Swaminathan n_next = 328082527734SSukumar Swaminathan n_prev->nlp_next[fchanno]; 328182527734SSukumar Swaminathan if (n_next == nlp) { 328282527734SSukumar Swaminathan break; 328382527734SSukumar Swaminathan } 328482527734SSukumar Swaminathan n_prev = n_next; 328582527734SSukumar Swaminathan } while (count--); 328682527734SSukumar Swaminathan 328782527734SSukumar Swaminathan if (count != 0) { 328882527734SSukumar Swaminathan 328982527734SSukumar Swaminathan if (n_next == 329082527734SSukumar Swaminathan (NODELIST *)from_chan-> 329182527734SSukumar Swaminathan nodeq.q_last) { 329282527734SSukumar Swaminathan n_prev-> 329382527734SSukumar Swaminathan nlp_next[fchanno] 329482527734SSukumar Swaminathan = 329582527734SSukumar Swaminathan ((NODELIST *) 329682527734SSukumar Swaminathan from_chan-> 329782527734SSukumar Swaminathan nodeq.q_last)-> 329882527734SSukumar Swaminathan nlp_next 329982527734SSukumar Swaminathan [fchanno]; 330082527734SSukumar Swaminathan from_chan->nodeq.q_last 330182527734SSukumar Swaminathan = (uint8_t *)n_prev; 330282527734SSukumar Swaminathan } else { 330382527734SSukumar Swaminathan 330482527734SSukumar Swaminathan n_prev-> 330582527734SSukumar Swaminathan nlp_next[fchanno] 330682527734SSukumar Swaminathan = 330782527734SSukumar Swaminathan n_next-> nlp_next 330882527734SSukumar Swaminathan [fchanno]; 330982527734SSukumar Swaminathan } 331082527734SSukumar Swaminathan from_chan->nodeq.q_cnt--; 331182527734SSukumar Swaminathan /* Clear node */ 331282527734SSukumar Swaminathan nlp->nlp_next[fchanno] = 331382527734SSukumar Swaminathan NULL; 331482527734SSukumar Swaminathan } 331582527734SSukumar Swaminathan } 331682527734SSukumar Swaminathan } 331782527734SSukumar Swaminathan } 331882527734SSukumar Swaminathan } 331982527734SSukumar Swaminathan 332082527734SSukumar Swaminathan /* Now cleanup the iocb's */ 332182527734SSukumar Swaminathan prev = NULL; 332282527734SSukumar Swaminathan iocbq = (IOCBQ *)tbm.q_first; 332382527734SSukumar Swaminathan 332482527734SSukumar Swaminathan while (iocbq) { 332582527734SSukumar Swaminathan 332682527734SSukumar Swaminathan next = (IOCBQ *)iocbq->next; 332782527734SSukumar Swaminathan 332882527734SSukumar Swaminathan /* Free the IoTag and the bmp */ 332982527734SSukumar Swaminathan iocb = &iocbq->iocb; 333082527734SSukumar Swaminathan 333182527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 333282527734SSukumar Swaminathan sbp = iocbq->sbp; 333382527734SSukumar Swaminathan if (sbp) { 333482527734SSukumar Swaminathan hba->fc_table[sbp->iotag] = NULL; 333582527734SSukumar Swaminathan emlxs_sli4_free_xri(hba, sbp, sbp->xp); 333682527734SSukumar Swaminathan } 333782527734SSukumar Swaminathan } else { 333882527734SSukumar Swaminathan sbp = emlxs_unregister_pkt((CHANNEL *)iocbq->channel, 333982527734SSukumar Swaminathan iocb->ULPIOTAG, 0); 334082527734SSukumar Swaminathan } 334182527734SSukumar Swaminathan 334282527734SSukumar Swaminathan if (sbp && (sbp != STALE_PACKET)) { 334382527734SSukumar Swaminathan mutex_enter(&sbp->mtx); 334482527734SSukumar Swaminathan sbp->pkt_flags |= PACKET_IN_FLUSH; 334582527734SSukumar Swaminathan 334682527734SSukumar Swaminathan /* 334782527734SSukumar Swaminathan * If the fpkt is already set, then we will leave it 334882527734SSukumar Swaminathan * alone. This ensures that this pkt is only accounted 334982527734SSukumar Swaminathan * for on one fpkt->flush_count 335082527734SSukumar Swaminathan */ 335182527734SSukumar Swaminathan if (!sbp->fpkt && fpkt) { 335282527734SSukumar Swaminathan mutex_enter(&fpkt->mtx); 335382527734SSukumar Swaminathan sbp->fpkt = fpkt; 335482527734SSukumar Swaminathan fpkt->flush_count++; 335582527734SSukumar Swaminathan mutex_exit(&fpkt->mtx); 335682527734SSukumar Swaminathan } 335782527734SSukumar Swaminathan mutex_exit(&sbp->mtx); 335882527734SSukumar Swaminathan } 335982527734SSukumar Swaminathan iocbq = next; 336082527734SSukumar Swaminathan 336182527734SSukumar Swaminathan } /* end of while */ 336282527734SSukumar Swaminathan 336382527734SSukumar Swaminathan iocbq = (IOCBQ *)tbm.q_first; 336482527734SSukumar Swaminathan while (iocbq) { 336582527734SSukumar Swaminathan /* Save the next iocbq for now */ 336682527734SSukumar Swaminathan next = (IOCBQ *)iocbq->next; 336782527734SSukumar Swaminathan 336882527734SSukumar Swaminathan /* Unlink this iocbq */ 336982527734SSukumar Swaminathan iocbq->next = NULL; 337082527734SSukumar Swaminathan 337182527734SSukumar Swaminathan /* Get the pkt */ 337282527734SSukumar Swaminathan sbp = (emlxs_buf_t *)iocbq->sbp; 337382527734SSukumar Swaminathan 337482527734SSukumar Swaminathan if (sbp) { 337582527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flush_msg, 337682527734SSukumar Swaminathan "tx: sbp=%p node=%p", sbp, sbp->node); 337782527734SSukumar Swaminathan 337882527734SSukumar Swaminathan if (hba->state >= FC_LINK_UP) { 337982527734SSukumar Swaminathan emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 338082527734SSukumar Swaminathan IOERR_ABORT_REQUESTED, 1); 338182527734SSukumar Swaminathan } else { 338282527734SSukumar Swaminathan emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 338382527734SSukumar Swaminathan IOERR_LINK_DOWN, 1); 338482527734SSukumar Swaminathan } 338582527734SSukumar Swaminathan 338682527734SSukumar Swaminathan } 338782527734SSukumar Swaminathan /* Free the iocb and its associated buffers */ 338882527734SSukumar Swaminathan else { 338982527734SSukumar Swaminathan icmd = &iocbq->iocb; 339082527734SSukumar Swaminathan 339182527734SSukumar Swaminathan /* SLI3 */ 339282527734SSukumar Swaminathan if (icmd->ULPCOMMAND == CMD_QUE_RING_BUF64_CN || 339382527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_QUE_RING_BUF_CN || 339482527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_QUE_RING_LIST64_CN) { 339582527734SSukumar Swaminathan if ((hba->flag & 339682527734SSukumar Swaminathan (FC_ONLINE_MODE | FC_ONLINING_MODE)) == 0) { 339782527734SSukumar Swaminathan /* HBA is detaching or offlining */ 339882527734SSukumar Swaminathan if (icmd->ULPCOMMAND != 339982527734SSukumar Swaminathan CMD_QUE_RING_LIST64_CN) { 340082527734SSukumar Swaminathan uint8_t *tmp; 340182527734SSukumar Swaminathan RING *rp; 340282527734SSukumar Swaminathan int ch; 340382527734SSukumar Swaminathan 340482527734SSukumar Swaminathan ch = from_chan->channelno; 340582527734SSukumar Swaminathan rp = &hba->sli.sli3.ring[ch]; 340682527734SSukumar Swaminathan 340782527734SSukumar Swaminathan for (i = 0; 340882527734SSukumar Swaminathan i < icmd->ULPBDECOUNT; 340982527734SSukumar Swaminathan i++) { 341082527734SSukumar Swaminathan mp = EMLXS_GET_VADDR( 341182527734SSukumar Swaminathan hba, rp, icmd); 341282527734SSukumar Swaminathan 341382527734SSukumar Swaminathan tmp = (uint8_t *)mp; 341482527734SSukumar Swaminathan if (mp) { 341582527734SSukumar Swaminathan (void) emlxs_mem_put( 341682527734SSukumar Swaminathan hba, 341782527734SSukumar Swaminathan MEM_BUF, 341882527734SSukumar Swaminathan tmp); 341982527734SSukumar Swaminathan } 342082527734SSukumar Swaminathan } 342182527734SSukumar Swaminathan 342282527734SSukumar Swaminathan } 342382527734SSukumar Swaminathan 342482527734SSukumar Swaminathan (void) emlxs_mem_put(hba, MEM_IOCB, 342582527734SSukumar Swaminathan (uint8_t *)iocbq); 342682527734SSukumar Swaminathan } else { 342782527734SSukumar Swaminathan /* repost the unsolicited buffer */ 342882527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, 342982527734SSukumar Swaminathan from_chan, iocbq); 343082527734SSukumar Swaminathan } 343182527734SSukumar Swaminathan } 343282527734SSukumar Swaminathan } 343382527734SSukumar Swaminathan 343482527734SSukumar Swaminathan iocbq = next; 343582527734SSukumar Swaminathan 343682527734SSukumar Swaminathan } /* end of while */ 343782527734SSukumar Swaminathan 343882527734SSukumar Swaminathan /* Now flush the chipq if any */ 343982527734SSukumar Swaminathan if (!(nlp->nlp_flag[fchanno] & NLP_CLOSED)) { 344082527734SSukumar Swaminathan 344182527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 344282527734SSukumar Swaminathan 344382527734SSukumar Swaminathan (void) emlxs_chipq_node_flush(port, from_chan, nlp, 0); 344482527734SSukumar Swaminathan 344582527734SSukumar Swaminathan mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 344682527734SSukumar Swaminathan } 344782527734SSukumar Swaminathan 344882527734SSukumar Swaminathan if (lock) { 344982527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 345082527734SSukumar Swaminathan } 345182527734SSukumar Swaminathan 345282527734SSukumar Swaminathan return; 345382527734SSukumar Swaminathan 345482527734SSukumar Swaminathan } /* emlxs_tx_move */ 3455fcf3ce44SJohn Forte 3456fcf3ce44SJohn Forte 3457fcf3ce44SJohn Forte extern uint32_t 345882527734SSukumar Swaminathan emlxs_chipq_node_flush(emlxs_port_t *port, CHANNEL *chan, NODELIST *ndlp, 3459291a2b48SSukumar Swaminathan emlxs_buf_t *fpkt) 3460fcf3ce44SJohn Forte { 3461fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 3462fcf3ce44SJohn Forte emlxs_buf_t *sbp; 3463fcf3ce44SJohn Forte IOCBQ *iocbq; 3464fcf3ce44SJohn Forte IOCBQ *next; 3465fcf3ce44SJohn Forte Q abort; 346682527734SSukumar Swaminathan CHANNEL *cp; 346782527734SSukumar Swaminathan uint32_t channelno; 346882527734SSukumar Swaminathan uint8_t flag[MAX_CHANNEL]; 3469fcf3ce44SJohn Forte uint32_t iotag; 3470fcf3ce44SJohn Forte 3471fcf3ce44SJohn Forte bzero((void *)&abort, sizeof (Q)); 3472fcf3ce44SJohn Forte bzero((void *)flag, sizeof (flag)); 3473fcf3ce44SJohn Forte 347482527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 347582527734SSukumar Swaminathan cp = &hba->chan[channelno]; 3476fcf3ce44SJohn Forte 347782527734SSukumar Swaminathan if (chan && cp != chan) { 3478fcf3ce44SJohn Forte continue; 3479fcf3ce44SJohn Forte } 3480291a2b48SSukumar Swaminathan 348182527734SSukumar Swaminathan mutex_enter(&EMLXS_FCTAB_LOCK); 3482fcf3ce44SJohn Forte 348382527734SSukumar Swaminathan for (iotag = 1; iotag < hba->max_iotag; iotag++) { 348482527734SSukumar Swaminathan sbp = hba->fc_table[iotag]; 3485fcf3ce44SJohn Forte 3486fcf3ce44SJohn Forte if (sbp && (sbp != STALE_PACKET) && 3487fcf3ce44SJohn Forte (sbp->pkt_flags & PACKET_IN_CHIPQ) && 3488fcf3ce44SJohn Forte (sbp->node == ndlp) && 348982527734SSukumar Swaminathan (sbp->channel == cp) && 3490fcf3ce44SJohn Forte !(sbp->pkt_flags & PACKET_XRI_CLOSED)) { 3491291a2b48SSukumar Swaminathan emlxs_sbp_abort_add(port, sbp, &abort, flag, 3492291a2b48SSukumar Swaminathan fpkt); 3493fcf3ce44SJohn Forte } 3494291a2b48SSukumar Swaminathan 3495fcf3ce44SJohn Forte } 349682527734SSukumar Swaminathan mutex_exit(&EMLXS_FCTAB_LOCK); 3497fcf3ce44SJohn Forte 3498fcf3ce44SJohn Forte } /* for */ 3499fcf3ce44SJohn Forte 3500fcf3ce44SJohn Forte /* Now put the iocb's on the tx queue */ 3501fcf3ce44SJohn Forte iocbq = (IOCBQ *)abort.q_first; 3502fcf3ce44SJohn Forte while (iocbq) { 3503fcf3ce44SJohn Forte /* Save the next iocbq for now */ 3504fcf3ce44SJohn Forte next = (IOCBQ *)iocbq->next; 3505fcf3ce44SJohn Forte 3506fcf3ce44SJohn Forte /* Unlink this iocbq */ 3507fcf3ce44SJohn Forte iocbq->next = NULL; 3508fcf3ce44SJohn Forte 3509fcf3ce44SJohn Forte /* Send this iocbq */ 3510fcf3ce44SJohn Forte emlxs_tx_put(iocbq, 1); 3511fcf3ce44SJohn Forte 3512fcf3ce44SJohn Forte iocbq = next; 3513fcf3ce44SJohn Forte } 3514fcf3ce44SJohn Forte 351582527734SSukumar Swaminathan /* Now trigger channel service */ 351682527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 351782527734SSukumar Swaminathan if (!flag[channelno]) { 3518fcf3ce44SJohn Forte continue; 3519fcf3ce44SJohn Forte } 3520291a2b48SSukumar Swaminathan 352182527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, &hba->chan[channelno], 0); 3522fcf3ce44SJohn Forte } 3523fcf3ce44SJohn Forte 3524fcf3ce44SJohn Forte return (abort.q_cnt); 3525fcf3ce44SJohn Forte 352682527734SSukumar Swaminathan } /* emlxs_chipq_node_flush() */ 3527fcf3ce44SJohn Forte 3528fcf3ce44SJohn Forte 3529fcf3ce44SJohn Forte /* Flush all IO's left on all iotag lists */ 353082527734SSukumar Swaminathan extern uint32_t 3531fcf3ce44SJohn Forte emlxs_iotag_flush(emlxs_hba_t *hba) 3532fcf3ce44SJohn Forte { 3533fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 3534fcf3ce44SJohn Forte emlxs_buf_t *sbp; 3535fcf3ce44SJohn Forte IOCBQ *iocbq; 3536fcf3ce44SJohn Forte IOCB *iocb; 3537fcf3ce44SJohn Forte Q abort; 353882527734SSukumar Swaminathan CHANNEL *cp; 353982527734SSukumar Swaminathan uint32_t channelno; 3540fcf3ce44SJohn Forte uint32_t iotag; 3541fcf3ce44SJohn Forte uint32_t count; 3542fcf3ce44SJohn Forte 3543fcf3ce44SJohn Forte count = 0; 354482527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 354582527734SSukumar Swaminathan cp = &hba->chan[channelno]; 3546fcf3ce44SJohn Forte 3547fcf3ce44SJohn Forte bzero((void *)&abort, sizeof (Q)); 3548fcf3ce44SJohn Forte 354982527734SSukumar Swaminathan mutex_enter(&EMLXS_FCTAB_LOCK); 3550fcf3ce44SJohn Forte 355182527734SSukumar Swaminathan for (iotag = 1; iotag < hba->max_iotag; iotag++) { 355282527734SSukumar Swaminathan sbp = hba->fc_table[iotag]; 3553fcf3ce44SJohn Forte 355482527734SSukumar Swaminathan /* Check if the slot is empty */ 3555fcf3ce44SJohn Forte if (!sbp || (sbp == STALE_PACKET)) { 3556fcf3ce44SJohn Forte continue; 3557fcf3ce44SJohn Forte } 3558291a2b48SSukumar Swaminathan 355982527734SSukumar Swaminathan /* We are building an abort list per channel */ 356082527734SSukumar Swaminathan if (sbp->channel != cp) { 356182527734SSukumar Swaminathan continue; 356282527734SSukumar Swaminathan } 3563fcf3ce44SJohn Forte 3564fcf3ce44SJohn Forte /* Set IOCB status */ 3565fcf3ce44SJohn Forte iocbq = &sbp->iocbq; 3566fcf3ce44SJohn Forte iocb = &iocbq->iocb; 3567fcf3ce44SJohn Forte 356882527734SSukumar Swaminathan iocb->ULPSTATUS = IOSTAT_LOCAL_REJECT; 3569fcf3ce44SJohn Forte iocb->un.grsp.perr.statLocalError = IOERR_LINK_DOWN; 357082527734SSukumar Swaminathan iocb->ULPLE = 1; 3571fcf3ce44SJohn Forte iocbq->next = NULL; 3572fcf3ce44SJohn Forte 357382527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 357482527734SSukumar Swaminathan hba->fc_table[iotag] = NULL; 357582527734SSukumar Swaminathan emlxs_sli4_free_xri(hba, sbp, sbp->xp); 357682527734SSukumar Swaminathan } else { 357782527734SSukumar Swaminathan hba->fc_table[iotag] = STALE_PACKET; 357882527734SSukumar Swaminathan hba->io_count --; 357982527734SSukumar Swaminathan sbp->iotag = 0; 3580291a2b48SSukumar Swaminathan 358182527734SSukumar Swaminathan /* Clean up the sbp */ 358282527734SSukumar Swaminathan mutex_enter(&sbp->mtx); 358382527734SSukumar Swaminathan 358482527734SSukumar Swaminathan if (sbp->pkt_flags & PACKET_IN_TXQ) { 358582527734SSukumar Swaminathan sbp->pkt_flags &= ~PACKET_IN_TXQ; 358682527734SSukumar Swaminathan hba->channel_tx_count --; 358782527734SSukumar Swaminathan } 358882527734SSukumar Swaminathan 358982527734SSukumar Swaminathan if (sbp->pkt_flags & PACKET_IN_CHIPQ) { 359082527734SSukumar Swaminathan sbp->pkt_flags &= ~PACKET_IN_CHIPQ; 359182527734SSukumar Swaminathan } 3592291a2b48SSukumar Swaminathan 359382527734SSukumar Swaminathan if (sbp->bmp) { 359482527734SSukumar Swaminathan (void) emlxs_mem_put(hba, MEM_BPL, 359582527734SSukumar Swaminathan (uint8_t *)sbp->bmp); 359682527734SSukumar Swaminathan sbp->bmp = 0; 359782527734SSukumar Swaminathan } 359882527734SSukumar Swaminathan 359982527734SSukumar Swaminathan mutex_exit(&sbp->mtx); 3600fcf3ce44SJohn Forte } 3601291a2b48SSukumar Swaminathan 3602fcf3ce44SJohn Forte /* At this point all nodes are assumed destroyed */ 360382527734SSukumar Swaminathan mutex_enter(&sbp->mtx); 3604fcf3ce44SJohn Forte sbp->node = 0; 3605fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 3606fcf3ce44SJohn Forte 3607fcf3ce44SJohn Forte /* Add this iocb to our local abort Q */ 3608fcf3ce44SJohn Forte if (abort.q_first) { 3609291a2b48SSukumar Swaminathan ((IOCBQ *)abort.q_last)->next = iocbq; 3610fcf3ce44SJohn Forte abort.q_last = (uint8_t *)iocbq; 3611fcf3ce44SJohn Forte abort.q_cnt++; 3612fcf3ce44SJohn Forte } else { 3613fcf3ce44SJohn Forte abort.q_first = (uint8_t *)iocbq; 3614fcf3ce44SJohn Forte abort.q_last = (uint8_t *)iocbq; 3615fcf3ce44SJohn Forte abort.q_cnt = 1; 3616fcf3ce44SJohn Forte } 3617fcf3ce44SJohn Forte } 3618fcf3ce44SJohn Forte 361982527734SSukumar Swaminathan mutex_exit(&EMLXS_FCTAB_LOCK); 3620fcf3ce44SJohn Forte 3621fcf3ce44SJohn Forte /* Trigger deferred completion */ 3622fcf3ce44SJohn Forte if (abort.q_first) { 362382527734SSukumar Swaminathan mutex_enter(&cp->rsp_lock); 362482527734SSukumar Swaminathan if (cp->rsp_head == NULL) { 362582527734SSukumar Swaminathan cp->rsp_head = (IOCBQ *)abort.q_first; 362682527734SSukumar Swaminathan cp->rsp_tail = (IOCBQ *)abort.q_last; 3627fcf3ce44SJohn Forte } else { 362882527734SSukumar Swaminathan cp->rsp_tail->next = (IOCBQ *)abort.q_first; 362982527734SSukumar Swaminathan cp->rsp_tail = (IOCBQ *)abort.q_last; 3630fcf3ce44SJohn Forte } 363182527734SSukumar Swaminathan mutex_exit(&cp->rsp_lock); 3632fcf3ce44SJohn Forte 363382527734SSukumar Swaminathan emlxs_thread_trigger2(&cp->intr_thread, 363482527734SSukumar Swaminathan emlxs_proc_channel, cp); 3635fcf3ce44SJohn Forte 363682527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg, 363782527734SSukumar Swaminathan "Forced iotag completion. channel=%d count=%d", 363882527734SSukumar Swaminathan channelno, abort.q_cnt); 3639fcf3ce44SJohn Forte 3640fcf3ce44SJohn Forte count += abort.q_cnt; 3641fcf3ce44SJohn Forte } 3642fcf3ce44SJohn Forte } 3643fcf3ce44SJohn Forte 3644fcf3ce44SJohn Forte return (count); 3645fcf3ce44SJohn Forte 364682527734SSukumar Swaminathan } /* emlxs_iotag_flush() */ 3647fcf3ce44SJohn Forte 3648fcf3ce44SJohn Forte 3649fcf3ce44SJohn Forte 365082527734SSukumar Swaminathan /* Checks for IO's on all or a given channel for a given node */ 3651fcf3ce44SJohn Forte extern uint32_t 365282527734SSukumar Swaminathan emlxs_chipq_node_check(emlxs_port_t *port, CHANNEL *chan, NODELIST *ndlp) 3653fcf3ce44SJohn Forte { 3654fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 3655fcf3ce44SJohn Forte emlxs_buf_t *sbp; 365682527734SSukumar Swaminathan CHANNEL *cp; 365782527734SSukumar Swaminathan uint32_t channelno; 3658fcf3ce44SJohn Forte uint32_t count; 3659fcf3ce44SJohn Forte uint32_t iotag; 3660fcf3ce44SJohn Forte 3661fcf3ce44SJohn Forte count = 0; 3662fcf3ce44SJohn Forte 366382527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 366482527734SSukumar Swaminathan cp = &hba->chan[channelno]; 3665fcf3ce44SJohn Forte 366682527734SSukumar Swaminathan if (chan && cp != chan) { 3667fcf3ce44SJohn Forte continue; 3668fcf3ce44SJohn Forte } 3669291a2b48SSukumar Swaminathan 367082527734SSukumar Swaminathan mutex_enter(&EMLXS_FCTAB_LOCK); 3671fcf3ce44SJohn Forte 367282527734SSukumar Swaminathan for (iotag = 1; iotag < hba->max_iotag; iotag++) { 367382527734SSukumar Swaminathan sbp = hba->fc_table[iotag]; 3674fcf3ce44SJohn Forte 3675fcf3ce44SJohn Forte if (sbp && (sbp != STALE_PACKET) && 3676fcf3ce44SJohn Forte (sbp->pkt_flags & PACKET_IN_CHIPQ) && 3677fcf3ce44SJohn Forte (sbp->node == ndlp) && 367882527734SSukumar Swaminathan (sbp->channel == cp) && 3679fcf3ce44SJohn Forte !(sbp->pkt_flags & PACKET_XRI_CLOSED)) { 3680fcf3ce44SJohn Forte count++; 3681fcf3ce44SJohn Forte } 3682291a2b48SSukumar Swaminathan 3683fcf3ce44SJohn Forte } 368482527734SSukumar Swaminathan mutex_exit(&EMLXS_FCTAB_LOCK); 3685fcf3ce44SJohn Forte 3686fcf3ce44SJohn Forte } /* for */ 3687fcf3ce44SJohn Forte 3688fcf3ce44SJohn Forte return (count); 3689fcf3ce44SJohn Forte 369082527734SSukumar Swaminathan } /* emlxs_chipq_node_check() */ 3691fcf3ce44SJohn Forte 3692fcf3ce44SJohn Forte 3693fcf3ce44SJohn Forte 369482527734SSukumar Swaminathan /* Flush all IO's for a given node's lun (on any channel) */ 3695fcf3ce44SJohn Forte extern uint32_t 369682527734SSukumar Swaminathan emlxs_chipq_lun_flush(emlxs_port_t *port, NODELIST *ndlp, 369782527734SSukumar Swaminathan uint32_t lun, emlxs_buf_t *fpkt) 3698fcf3ce44SJohn Forte { 3699fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 3700fcf3ce44SJohn Forte emlxs_buf_t *sbp; 3701fcf3ce44SJohn Forte IOCBQ *iocbq; 3702fcf3ce44SJohn Forte IOCBQ *next; 3703fcf3ce44SJohn Forte Q abort; 3704fcf3ce44SJohn Forte uint32_t iotag; 370582527734SSukumar Swaminathan uint8_t flag[MAX_CHANNEL]; 370682527734SSukumar Swaminathan uint32_t channelno; 3707fcf3ce44SJohn Forte 3708fcf3ce44SJohn Forte bzero((void *)flag, sizeof (flag)); 3709fcf3ce44SJohn Forte bzero((void *)&abort, sizeof (Q)); 3710fcf3ce44SJohn Forte 371182527734SSukumar Swaminathan mutex_enter(&EMLXS_FCTAB_LOCK); 371282527734SSukumar Swaminathan for (iotag = 1; iotag < hba->max_iotag; iotag++) { 371382527734SSukumar Swaminathan sbp = hba->fc_table[iotag]; 3714fcf3ce44SJohn Forte 3715fcf3ce44SJohn Forte if (sbp && (sbp != STALE_PACKET) && 3716fcf3ce44SJohn Forte sbp->pkt_flags & PACKET_IN_CHIPQ && 3717fcf3ce44SJohn Forte sbp->node == ndlp && 3718fcf3ce44SJohn Forte sbp->lun == lun && 3719fcf3ce44SJohn Forte !(sbp->pkt_flags & PACKET_XRI_CLOSED)) { 372082527734SSukumar Swaminathan emlxs_sbp_abort_add(port, sbp, 372182527734SSukumar Swaminathan &abort, flag, fpkt); 3722fcf3ce44SJohn Forte } 3723fcf3ce44SJohn Forte } 372482527734SSukumar Swaminathan mutex_exit(&EMLXS_FCTAB_LOCK); 3725fcf3ce44SJohn Forte 3726fcf3ce44SJohn Forte /* Now put the iocb's on the tx queue */ 3727fcf3ce44SJohn Forte iocbq = (IOCBQ *)abort.q_first; 3728fcf3ce44SJohn Forte while (iocbq) { 3729fcf3ce44SJohn Forte /* Save the next iocbq for now */ 3730fcf3ce44SJohn Forte next = (IOCBQ *)iocbq->next; 3731fcf3ce44SJohn Forte 3732fcf3ce44SJohn Forte /* Unlink this iocbq */ 3733fcf3ce44SJohn Forte iocbq->next = NULL; 3734fcf3ce44SJohn Forte 3735fcf3ce44SJohn Forte /* Send this iocbq */ 3736fcf3ce44SJohn Forte emlxs_tx_put(iocbq, 1); 3737fcf3ce44SJohn Forte 3738fcf3ce44SJohn Forte iocbq = next; 3739fcf3ce44SJohn Forte } 3740fcf3ce44SJohn Forte 374182527734SSukumar Swaminathan /* Now trigger channel service */ 374282527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 374382527734SSukumar Swaminathan if (!flag[channelno]) { 374482527734SSukumar Swaminathan continue; 374582527734SSukumar Swaminathan } 374682527734SSukumar Swaminathan 374782527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, &hba->chan[channelno], 0); 3748fcf3ce44SJohn Forte } 3749291a2b48SSukumar Swaminathan 3750fcf3ce44SJohn Forte return (abort.q_cnt); 3751fcf3ce44SJohn Forte 375282527734SSukumar Swaminathan } /* emlxs_chipq_lun_flush() */ 3753fcf3ce44SJohn Forte 3754fcf3ce44SJohn Forte 3755fcf3ce44SJohn Forte 3756fcf3ce44SJohn Forte /* 3757fcf3ce44SJohn Forte * Issue an ABORT_XRI_CN iocb command to abort an FCP command already issued. 3758fe199829SSukumar Swaminathan * This must be called while holding the EMLXS_FCTAB_LOCK 3759fcf3ce44SJohn Forte */ 3760fcf3ce44SJohn Forte extern IOCBQ * 3761291a2b48SSukumar Swaminathan emlxs_create_abort_xri_cn(emlxs_port_t *port, NODELIST *ndlp, 376282527734SSukumar Swaminathan uint16_t iotag, CHANNEL *cp, uint8_t class, int32_t flag) 3763fcf3ce44SJohn Forte { 3764fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 3765fcf3ce44SJohn Forte IOCBQ *iocbq; 3766fcf3ce44SJohn Forte IOCB *iocb; 376782527734SSukumar Swaminathan emlxs_wqe_t *wqe; 376882527734SSukumar Swaminathan emlxs_buf_t *sbp; 3769fcf3ce44SJohn Forte uint16_t abort_iotag; 3770fcf3ce44SJohn Forte 377182527734SSukumar Swaminathan if ((iocbq = (IOCBQ *)emlxs_mem_get(hba, MEM_IOCB, 0)) == NULL) { 3772fcf3ce44SJohn Forte return (NULL); 3773fcf3ce44SJohn Forte } 3774291a2b48SSukumar Swaminathan 377582527734SSukumar Swaminathan iocbq->channel = (void *)cp; 3776fcf3ce44SJohn Forte iocbq->port = (void *)port; 3777fcf3ce44SJohn Forte iocbq->node = (void *)ndlp; 3778fcf3ce44SJohn Forte iocbq->flag |= (IOCB_PRIORITY | IOCB_SPECIAL); 3779fcf3ce44SJohn Forte 3780fcf3ce44SJohn Forte /* 3781fcf3ce44SJohn Forte * set up an iotag using special Abort iotags 3782fcf3ce44SJohn Forte */ 378382527734SSukumar Swaminathan if ((hba->fc_oor_iotag >= EMLXS_MAX_ABORT_TAG)) { 378482527734SSukumar Swaminathan hba->fc_oor_iotag = hba->max_iotag; 3785fcf3ce44SJohn Forte } 378682527734SSukumar Swaminathan abort_iotag = hba->fc_oor_iotag++; 3787291a2b48SSukumar Swaminathan 3788fcf3ce44SJohn Forte 378982527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 379082527734SSukumar Swaminathan wqe = &iocbq->wqe; 379182527734SSukumar Swaminathan sbp = hba->fc_table[iotag]; 3792fcf3ce44SJohn Forte 379382527734SSukumar Swaminathan /* Try to issue abort by XRI if possible */ 379482527734SSukumar Swaminathan if (sbp == NULL || sbp == STALE_PACKET || sbp->xp == NULL) { 379582527734SSukumar Swaminathan wqe->un.Abort.Criteria = ABORT_REQ_TAG; 379682527734SSukumar Swaminathan wqe->AbortTag = iotag; 379782527734SSukumar Swaminathan } else { 379882527734SSukumar Swaminathan wqe->un.Abort.Criteria = ABORT_XRI_TAG; 379982527734SSukumar Swaminathan wqe->AbortTag = sbp->xp->XRI; 380082527734SSukumar Swaminathan } 380182527734SSukumar Swaminathan wqe->un.Abort.IA = 0; 380282527734SSukumar Swaminathan wqe->RequestTag = abort_iotag; 380382527734SSukumar Swaminathan wqe->Command = CMD_ABORT_XRI_CX; 380482527734SSukumar Swaminathan wqe->Class = CLASS3; 380582527734SSukumar Swaminathan wqe->CQId = 0x3ff; 380682527734SSukumar Swaminathan wqe->CmdType = WQE_TYPE_ABORT; 380782527734SSukumar Swaminathan } else { 380882527734SSukumar Swaminathan iocb = &iocbq->iocb; 380982527734SSukumar Swaminathan iocb->ULPIOTAG = abort_iotag; 381082527734SSukumar Swaminathan iocb->un.acxri.abortType = flag; 381182527734SSukumar Swaminathan iocb->un.acxri.abortContextTag = ndlp->nlp_Rpi; 381282527734SSukumar Swaminathan iocb->un.acxri.abortIoTag = iotag; 381382527734SSukumar Swaminathan iocb->ULPLE = 1; 381482527734SSukumar Swaminathan iocb->ULPCLASS = class; 381582527734SSukumar Swaminathan iocb->ULPCOMMAND = CMD_ABORT_XRI_CN; 381682527734SSukumar Swaminathan iocb->ULPOWNER = OWN_CHIP; 381782527734SSukumar Swaminathan } 3818fcf3ce44SJohn Forte 3819fcf3ce44SJohn Forte return (iocbq); 3820fcf3ce44SJohn Forte 382182527734SSukumar Swaminathan } /* emlxs_create_abort_xri_cn() */ 3822fcf3ce44SJohn Forte 3823fcf3ce44SJohn Forte 3824fe199829SSukumar Swaminathan /* This must be called while holding the EMLXS_FCTAB_LOCK */ 3825fcf3ce44SJohn Forte extern IOCBQ * 3826fcf3ce44SJohn Forte emlxs_create_abort_xri_cx(emlxs_port_t *port, NODELIST *ndlp, uint16_t xid, 382782527734SSukumar Swaminathan CHANNEL *cp, uint8_t class, int32_t flag) 3828fcf3ce44SJohn Forte { 3829fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 3830fcf3ce44SJohn Forte IOCBQ *iocbq; 3831fcf3ce44SJohn Forte IOCB *iocb; 383282527734SSukumar Swaminathan emlxs_wqe_t *wqe; 3833fcf3ce44SJohn Forte uint16_t abort_iotag; 3834fcf3ce44SJohn Forte 383582527734SSukumar Swaminathan if ((iocbq = (IOCBQ *)emlxs_mem_get(hba, MEM_IOCB, 0)) == NULL) { 3836fcf3ce44SJohn Forte return (NULL); 3837fcf3ce44SJohn Forte } 3838291a2b48SSukumar Swaminathan 383982527734SSukumar Swaminathan iocbq->channel = (void *)cp; 3840fcf3ce44SJohn Forte iocbq->port = (void *)port; 3841fcf3ce44SJohn Forte iocbq->node = (void *)ndlp; 3842fcf3ce44SJohn Forte iocbq->flag |= (IOCB_PRIORITY | IOCB_SPECIAL); 3843fcf3ce44SJohn Forte 3844fcf3ce44SJohn Forte /* 3845fcf3ce44SJohn Forte * set up an iotag using special Abort iotags 3846fcf3ce44SJohn Forte */ 384782527734SSukumar Swaminathan if ((hba->fc_oor_iotag >= EMLXS_MAX_ABORT_TAG)) { 384882527734SSukumar Swaminathan hba->fc_oor_iotag = hba->max_iotag; 384982527734SSukumar Swaminathan } 385082527734SSukumar Swaminathan abort_iotag = hba->fc_oor_iotag++; 385182527734SSukumar Swaminathan 385282527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 385382527734SSukumar Swaminathan wqe = &iocbq->wqe; 385482527734SSukumar Swaminathan wqe->un.Abort.Criteria = ABORT_XRI_TAG; 385582527734SSukumar Swaminathan wqe->un.Abort.IA = 0; 385682527734SSukumar Swaminathan wqe->RequestTag = abort_iotag; 385782527734SSukumar Swaminathan wqe->AbortTag = xid; 385882527734SSukumar Swaminathan wqe->Command = CMD_ABORT_XRI_CX; 385982527734SSukumar Swaminathan wqe->Class = CLASS3; 386082527734SSukumar Swaminathan wqe->CQId = 0x3ff; 386182527734SSukumar Swaminathan wqe->CmdType = WQE_TYPE_ABORT; 386282527734SSukumar Swaminathan } else { 386382527734SSukumar Swaminathan iocb = &iocbq->iocb; 386482527734SSukumar Swaminathan iocb->ULPCONTEXT = xid; 386582527734SSukumar Swaminathan iocb->ULPIOTAG = abort_iotag; 386682527734SSukumar Swaminathan iocb->un.acxri.abortType = flag; 386782527734SSukumar Swaminathan iocb->ULPLE = 1; 386882527734SSukumar Swaminathan iocb->ULPCLASS = class; 386982527734SSukumar Swaminathan iocb->ULPCOMMAND = CMD_ABORT_XRI_CX; 387082527734SSukumar Swaminathan iocb->ULPOWNER = OWN_CHIP; 3871fcf3ce44SJohn Forte } 3872291a2b48SSukumar Swaminathan 3873fcf3ce44SJohn Forte return (iocbq); 3874fcf3ce44SJohn Forte 387582527734SSukumar Swaminathan } /* emlxs_create_abort_xri_cx() */ 3876fcf3ce44SJohn Forte 3877fcf3ce44SJohn Forte 3878fcf3ce44SJohn Forte 3879fe199829SSukumar Swaminathan /* This must be called while holding the EMLXS_FCTAB_LOCK */ 3880fcf3ce44SJohn Forte extern IOCBQ * 3881fcf3ce44SJohn Forte emlxs_create_close_xri_cn(emlxs_port_t *port, NODELIST *ndlp, 388282527734SSukumar Swaminathan uint16_t iotag, CHANNEL *cp) 3883fcf3ce44SJohn Forte { 3884fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 3885fcf3ce44SJohn Forte IOCBQ *iocbq; 3886fcf3ce44SJohn Forte IOCB *iocb; 388782527734SSukumar Swaminathan emlxs_wqe_t *wqe; 388882527734SSukumar Swaminathan emlxs_buf_t *sbp; 3889fcf3ce44SJohn Forte uint16_t abort_iotag; 3890fcf3ce44SJohn Forte 389182527734SSukumar Swaminathan if ((iocbq = (IOCBQ *)emlxs_mem_get(hba, MEM_IOCB, 0)) == NULL) { 3892fcf3ce44SJohn Forte return (NULL); 3893fcf3ce44SJohn Forte } 3894291a2b48SSukumar Swaminathan 389582527734SSukumar Swaminathan iocbq->channel = (void *)cp; 3896fcf3ce44SJohn Forte iocbq->port = (void *)port; 3897fcf3ce44SJohn Forte iocbq->node = (void *)ndlp; 3898fcf3ce44SJohn Forte iocbq->flag |= (IOCB_PRIORITY | IOCB_SPECIAL); 3899fcf3ce44SJohn Forte 3900fcf3ce44SJohn Forte /* 3901fcf3ce44SJohn Forte * set up an iotag using special Abort iotags 3902fcf3ce44SJohn Forte */ 390382527734SSukumar Swaminathan if ((hba->fc_oor_iotag >= EMLXS_MAX_ABORT_TAG)) { 390482527734SSukumar Swaminathan hba->fc_oor_iotag = hba->max_iotag; 3905fcf3ce44SJohn Forte } 390682527734SSukumar Swaminathan abort_iotag = hba->fc_oor_iotag++; 3907291a2b48SSukumar Swaminathan 390882527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 390982527734SSukumar Swaminathan wqe = &iocbq->wqe; 391082527734SSukumar Swaminathan sbp = hba->fc_table[iotag]; 3911fcf3ce44SJohn Forte 391282527734SSukumar Swaminathan /* Try to issue close by XRI if possible */ 391382527734SSukumar Swaminathan if (sbp == NULL || sbp == STALE_PACKET || sbp->xp == NULL) { 391482527734SSukumar Swaminathan wqe->un.Abort.Criteria = ABORT_REQ_TAG; 391582527734SSukumar Swaminathan wqe->AbortTag = iotag; 391682527734SSukumar Swaminathan } else { 391782527734SSukumar Swaminathan wqe->un.Abort.Criteria = ABORT_XRI_TAG; 391882527734SSukumar Swaminathan wqe->AbortTag = sbp->xp->XRI; 391982527734SSukumar Swaminathan } 392082527734SSukumar Swaminathan wqe->un.Abort.IA = 1; 392182527734SSukumar Swaminathan wqe->RequestTag = abort_iotag; 392282527734SSukumar Swaminathan wqe->Command = CMD_ABORT_XRI_CX; 392382527734SSukumar Swaminathan wqe->Class = CLASS3; 392482527734SSukumar Swaminathan wqe->CQId = 0x3ff; 392582527734SSukumar Swaminathan wqe->CmdType = WQE_TYPE_ABORT; 392682527734SSukumar Swaminathan } else { 392782527734SSukumar Swaminathan iocb = &iocbq->iocb; 392882527734SSukumar Swaminathan iocb->ULPIOTAG = abort_iotag; 392982527734SSukumar Swaminathan iocb->un.acxri.abortType = 0; 393082527734SSukumar Swaminathan iocb->un.acxri.abortContextTag = ndlp->nlp_Rpi; 393182527734SSukumar Swaminathan iocb->un.acxri.abortIoTag = iotag; 393282527734SSukumar Swaminathan iocb->ULPLE = 1; 393382527734SSukumar Swaminathan iocb->ULPCLASS = 0; 393482527734SSukumar Swaminathan iocb->ULPCOMMAND = CMD_CLOSE_XRI_CN; 393582527734SSukumar Swaminathan iocb->ULPOWNER = OWN_CHIP; 393682527734SSukumar Swaminathan } 3937fcf3ce44SJohn Forte 3938fcf3ce44SJohn Forte return (iocbq); 3939fcf3ce44SJohn Forte 394082527734SSukumar Swaminathan } /* emlxs_create_close_xri_cn() */ 3941fcf3ce44SJohn Forte 3942fcf3ce44SJohn Forte 3943fe199829SSukumar Swaminathan /* This must be called while holding the EMLXS_FCTAB_LOCK */ 3944fcf3ce44SJohn Forte extern IOCBQ * 3945291a2b48SSukumar Swaminathan emlxs_create_close_xri_cx(emlxs_port_t *port, NODELIST *ndlp, uint16_t xid, 394682527734SSukumar Swaminathan CHANNEL *cp) 3947fcf3ce44SJohn Forte { 3948fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 3949fcf3ce44SJohn Forte IOCBQ *iocbq; 3950fcf3ce44SJohn Forte IOCB *iocb; 395182527734SSukumar Swaminathan emlxs_wqe_t *wqe; 3952fcf3ce44SJohn Forte uint16_t abort_iotag; 3953fcf3ce44SJohn Forte 395482527734SSukumar Swaminathan if ((iocbq = (IOCBQ *)emlxs_mem_get(hba, MEM_IOCB, 0)) == NULL) { 3955fcf3ce44SJohn Forte return (NULL); 3956fcf3ce44SJohn Forte } 3957291a2b48SSukumar Swaminathan 395882527734SSukumar Swaminathan iocbq->channel = (void *)cp; 3959fcf3ce44SJohn Forte iocbq->port = (void *)port; 3960fcf3ce44SJohn Forte iocbq->node = (void *)ndlp; 3961fcf3ce44SJohn Forte iocbq->flag |= (IOCB_PRIORITY | IOCB_SPECIAL); 3962fcf3ce44SJohn Forte 3963fcf3ce44SJohn Forte /* 3964fcf3ce44SJohn Forte * set up an iotag using special Abort iotags 3965fcf3ce44SJohn Forte */ 396682527734SSukumar Swaminathan if ((hba->fc_oor_iotag >= EMLXS_MAX_ABORT_TAG)) { 396782527734SSukumar Swaminathan hba->fc_oor_iotag = hba->max_iotag; 396882527734SSukumar Swaminathan } 396982527734SSukumar Swaminathan abort_iotag = hba->fc_oor_iotag++; 397082527734SSukumar Swaminathan 397182527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 397282527734SSukumar Swaminathan wqe = &iocbq->wqe; 397382527734SSukumar Swaminathan wqe->un.Abort.Criteria = ABORT_XRI_TAG; 397482527734SSukumar Swaminathan wqe->un.Abort.IA = 1; 397582527734SSukumar Swaminathan wqe->RequestTag = abort_iotag; 397682527734SSukumar Swaminathan wqe->AbortTag = xid; 397782527734SSukumar Swaminathan wqe->Command = CMD_ABORT_XRI_CX; 397882527734SSukumar Swaminathan wqe->Class = CLASS3; 397982527734SSukumar Swaminathan wqe->CQId = 0x3ff; 398082527734SSukumar Swaminathan wqe->CmdType = WQE_TYPE_ABORT; 398182527734SSukumar Swaminathan } else { 398282527734SSukumar Swaminathan iocb = &iocbq->iocb; 398382527734SSukumar Swaminathan iocb->ULPCONTEXT = xid; 398482527734SSukumar Swaminathan iocb->ULPIOTAG = abort_iotag; 398582527734SSukumar Swaminathan iocb->ULPLE = 1; 398682527734SSukumar Swaminathan iocb->ULPCLASS = 0; 398782527734SSukumar Swaminathan iocb->ULPCOMMAND = CMD_CLOSE_XRI_CX; 398882527734SSukumar Swaminathan iocb->ULPOWNER = OWN_CHIP; 3989fcf3ce44SJohn Forte } 3990291a2b48SSukumar Swaminathan 3991fcf3ce44SJohn Forte return (iocbq); 3992fcf3ce44SJohn Forte 399382527734SSukumar Swaminathan } /* emlxs_create_close_xri_cx() */ 3994fcf3ce44SJohn Forte 3995fcf3ce44SJohn Forte 3996fe199829SSukumar Swaminathan #ifdef SFCT_SUPPORT 3997fe199829SSukumar Swaminathan void 3998fe199829SSukumar Swaminathan emlxs_abort_fct_exchange(emlxs_hba_t *hba, emlxs_port_t *port, uint32_t rxid) 3999fe199829SSukumar Swaminathan { 4000fe199829SSukumar Swaminathan CHANNEL *cp; 4001fe199829SSukumar Swaminathan IOCBQ *iocbq; 4002fe199829SSukumar Swaminathan IOCB *iocb; 4003fe199829SSukumar Swaminathan 4004fe199829SSukumar Swaminathan if (rxid == 0 || rxid == 0xFFFF) { 4005fe199829SSukumar Swaminathan return; 4006fe199829SSukumar Swaminathan } 4007fe199829SSukumar Swaminathan 4008fe199829SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 4009fe199829SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4010fe199829SSukumar Swaminathan "Aborting FCT exchange: xid=%x", rxid); 4011fe199829SSukumar Swaminathan 4012fe199829SSukumar Swaminathan if (emlxs_sli4_unreserve_xri(hba, rxid) == 0) { 4013fe199829SSukumar Swaminathan /* We have no way to abort unsolicited exchanges */ 4014fe199829SSukumar Swaminathan /* that we have not responded to at this time */ 4015fe199829SSukumar Swaminathan /* So we will return for now */ 4016fe199829SSukumar Swaminathan return; 4017fe199829SSukumar Swaminathan } 4018fe199829SSukumar Swaminathan } 4019fe199829SSukumar Swaminathan 4020fe199829SSukumar Swaminathan cp = &hba->chan[hba->channel_fcp]; 4021fe199829SSukumar Swaminathan 4022fe199829SSukumar Swaminathan mutex_enter(&EMLXS_FCTAB_LOCK); 4023fe199829SSukumar Swaminathan 4024fe199829SSukumar Swaminathan /* Create the abort IOCB */ 4025fe199829SSukumar Swaminathan if (hba->state >= FC_LINK_UP) { 4026fe199829SSukumar Swaminathan iocbq = emlxs_create_abort_xri_cx(port, NULL, rxid, cp, 4027fe199829SSukumar Swaminathan CLASS3, ABORT_TYPE_ABTS); 4028fe199829SSukumar Swaminathan } else { 4029fe199829SSukumar Swaminathan iocbq = emlxs_create_close_xri_cx(port, NULL, rxid, cp); 4030fe199829SSukumar Swaminathan } 4031fe199829SSukumar Swaminathan 4032fe199829SSukumar Swaminathan mutex_exit(&EMLXS_FCTAB_LOCK); 4033fe199829SSukumar Swaminathan 4034fe199829SSukumar Swaminathan if (iocbq) { 4035fe199829SSukumar Swaminathan iocb = &iocbq->iocb; 4036fe199829SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4037fe199829SSukumar Swaminathan "Aborting FCT exchange: xid=%x iotag=%x", rxid, 4038fe199829SSukumar Swaminathan iocb->ULPIOTAG); 4039fe199829SSukumar Swaminathan 4040fe199829SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq); 4041fe199829SSukumar Swaminathan } 4042fe199829SSukumar Swaminathan 4043fe199829SSukumar Swaminathan } /* emlxs_abort_fct_exchange() */ 4044fe199829SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 4045fe199829SSukumar Swaminathan 4046fe199829SSukumar Swaminathan 4047fe199829SSukumar Swaminathan void 4048fe199829SSukumar Swaminathan emlxs_abort_els_exchange(emlxs_hba_t *hba, emlxs_port_t *port, uint32_t rxid) 4049fe199829SSukumar Swaminathan { 4050fe199829SSukumar Swaminathan CHANNEL *cp; 4051fe199829SSukumar Swaminathan IOCBQ *iocbq; 4052fe199829SSukumar Swaminathan IOCB *iocb; 4053fe199829SSukumar Swaminathan 4054fe199829SSukumar Swaminathan if (rxid == 0 || rxid == 0xFFFF) { 4055fe199829SSukumar Swaminathan return; 4056fe199829SSukumar Swaminathan } 4057fe199829SSukumar Swaminathan 4058fe199829SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 4059fe199829SSukumar Swaminathan 4060fe199829SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 4061fe199829SSukumar Swaminathan "Aborting ELS exchange: xid=%x", rxid); 4062fe199829SSukumar Swaminathan 4063fe199829SSukumar Swaminathan if (emlxs_sli4_unreserve_xri(hba, rxid) == 0) { 4064fe199829SSukumar Swaminathan /* We have no way to abort unsolicited exchanges */ 4065fe199829SSukumar Swaminathan /* that we have not responded to at this time */ 4066fe199829SSukumar Swaminathan /* So we will return for now */ 4067fe199829SSukumar Swaminathan return; 4068fe199829SSukumar Swaminathan } 4069fe199829SSukumar Swaminathan } 4070fe199829SSukumar Swaminathan 4071fe199829SSukumar Swaminathan cp = &hba->chan[hba->channel_els]; 4072fe199829SSukumar Swaminathan 4073fe199829SSukumar Swaminathan mutex_enter(&EMLXS_FCTAB_LOCK); 4074fe199829SSukumar Swaminathan 4075fe199829SSukumar Swaminathan /* Create the abort IOCB */ 4076fe199829SSukumar Swaminathan if (hba->state >= FC_LINK_UP) { 4077fe199829SSukumar Swaminathan iocbq = emlxs_create_abort_xri_cx(port, NULL, rxid, cp, 4078fe199829SSukumar Swaminathan CLASS3, ABORT_TYPE_ABTS); 4079fe199829SSukumar Swaminathan } else { 4080fe199829SSukumar Swaminathan iocbq = emlxs_create_close_xri_cx(port, NULL, rxid, cp); 4081fe199829SSukumar Swaminathan } 4082fe199829SSukumar Swaminathan 4083fe199829SSukumar Swaminathan mutex_exit(&EMLXS_FCTAB_LOCK); 4084fe199829SSukumar Swaminathan 4085fe199829SSukumar Swaminathan if (iocbq) { 4086fe199829SSukumar Swaminathan iocb = &iocbq->iocb; 4087fe199829SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 4088fe199829SSukumar Swaminathan "Aborting ELS exchange: xid=%x iotag=%x", rxid, 4089fe199829SSukumar Swaminathan iocb->ULPIOTAG); 4090fe199829SSukumar Swaminathan 4091fe199829SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq); 4092fe199829SSukumar Swaminathan } 4093fe199829SSukumar Swaminathan 4094fe199829SSukumar Swaminathan } /* emlxs_abort_els_exchange() */ 4095fe199829SSukumar Swaminathan 4096fe199829SSukumar Swaminathan 4097728bdc9bSSukumar Swaminathan void 4098bb63f56eSSukumar Swaminathan emlxs_abort_ct_exchange(emlxs_hba_t *hba, emlxs_port_t *port, uint32_t rxid) 4099728bdc9bSSukumar Swaminathan { 410082527734SSukumar Swaminathan CHANNEL *cp; 4101728bdc9bSSukumar Swaminathan IOCBQ *iocbq; 4102fe199829SSukumar Swaminathan IOCB *iocb; 4103728bdc9bSSukumar Swaminathan 4104fe199829SSukumar Swaminathan if (rxid == 0 || rxid == 0xFFFF) { 4105fe199829SSukumar Swaminathan return; 4106fe199829SSukumar Swaminathan } 410782527734SSukumar Swaminathan 410882527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 4109fe199829SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_ct_msg, 4110fe199829SSukumar Swaminathan "Aborting CT exchange: xid=%x", rxid); 4111fe199829SSukumar Swaminathan 411282527734SSukumar Swaminathan if (emlxs_sli4_unreserve_xri(hba, rxid) == 0) { 411382527734SSukumar Swaminathan /* We have no way to abort unsolicited exchanges */ 411482527734SSukumar Swaminathan /* that we have not responded to at this time */ 411582527734SSukumar Swaminathan /* So we will return for now */ 411682527734SSukumar Swaminathan return; 411782527734SSukumar Swaminathan } 411882527734SSukumar Swaminathan } 411982527734SSukumar Swaminathan 412082527734SSukumar Swaminathan cp = &hba->chan[hba->channel_ct]; 4121728bdc9bSSukumar Swaminathan 4122fe199829SSukumar Swaminathan mutex_enter(&EMLXS_FCTAB_LOCK); 4123fe199829SSukumar Swaminathan 4124728bdc9bSSukumar Swaminathan /* Create the abort IOCB */ 4125728bdc9bSSukumar Swaminathan if (hba->state >= FC_LINK_UP) { 4126fe199829SSukumar Swaminathan iocbq = emlxs_create_abort_xri_cx(port, NULL, rxid, cp, 4127fe199829SSukumar Swaminathan CLASS3, ABORT_TYPE_ABTS); 4128291a2b48SSukumar Swaminathan } else { 412982527734SSukumar Swaminathan iocbq = emlxs_create_close_xri_cx(port, NULL, rxid, cp); 4130728bdc9bSSukumar Swaminathan } 413182527734SSukumar Swaminathan 4132fe199829SSukumar Swaminathan mutex_exit(&EMLXS_FCTAB_LOCK); 4133fe199829SSukumar Swaminathan 4134bb63f56eSSukumar Swaminathan if (iocbq) { 4135fe199829SSukumar Swaminathan iocb = &iocbq->iocb; 4136fe199829SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 4137fe199829SSukumar Swaminathan "Aborting CT exchange: xid=%x iotag=%x", rxid, 4138fe199829SSukumar Swaminathan iocb->ULPIOTAG); 4139fe199829SSukumar Swaminathan 414082527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq); 4141bb63f56eSSukumar Swaminathan } 414282527734SSukumar Swaminathan 414382527734SSukumar Swaminathan } /* emlxs_abort_ct_exchange() */ 4144728bdc9bSSukumar Swaminathan 4145fcf3ce44SJohn Forte 4146fe199829SSukumar Swaminathan /* This must be called while holding the EMLXS_FCTAB_LOCK */ 4147fcf3ce44SJohn Forte static void 4148fcf3ce44SJohn Forte emlxs_sbp_abort_add(emlxs_port_t *port, emlxs_buf_t *sbp, Q *abort, 4149fcf3ce44SJohn Forte uint8_t *flag, emlxs_buf_t *fpkt) 4150fcf3ce44SJohn Forte { 4151fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 4152fcf3ce44SJohn Forte IOCBQ *iocbq; 415382527734SSukumar Swaminathan CHANNEL *cp; 4154fcf3ce44SJohn Forte NODELIST *ndlp; 4155fcf3ce44SJohn Forte 415682527734SSukumar Swaminathan cp = (CHANNEL *)sbp->channel; 4157fcf3ce44SJohn Forte ndlp = sbp->node; 4158fcf3ce44SJohn Forte 4159fcf3ce44SJohn Forte /* Create the close XRI IOCB */ 416082527734SSukumar Swaminathan iocbq = emlxs_create_close_xri_cn(port, ndlp, sbp->iotag, cp); 4161fcf3ce44SJohn Forte 4162291a2b48SSukumar Swaminathan /* 4163291a2b48SSukumar Swaminathan * Add this iocb to our local abort Q 4164291a2b48SSukumar Swaminathan * This way we don't hold the CHIPQ lock too long 4165291a2b48SSukumar Swaminathan */ 4166fcf3ce44SJohn Forte if (iocbq) { 4167fcf3ce44SJohn Forte if (abort->q_first) { 4168291a2b48SSukumar Swaminathan ((IOCBQ *)abort->q_last)->next = iocbq; 4169fcf3ce44SJohn Forte abort->q_last = (uint8_t *)iocbq; 4170fcf3ce44SJohn Forte abort->q_cnt++; 4171fcf3ce44SJohn Forte } else { 4172fcf3ce44SJohn Forte abort->q_first = (uint8_t *)iocbq; 4173fcf3ce44SJohn Forte abort->q_last = (uint8_t *)iocbq; 4174fcf3ce44SJohn Forte abort->q_cnt = 1; 4175fcf3ce44SJohn Forte } 4176fcf3ce44SJohn Forte iocbq->next = NULL; 4177fcf3ce44SJohn Forte } 4178291a2b48SSukumar Swaminathan 4179fcf3ce44SJohn Forte /* set the flags */ 4180fcf3ce44SJohn Forte mutex_enter(&sbp->mtx); 4181fcf3ce44SJohn Forte 4182fcf3ce44SJohn Forte sbp->pkt_flags |= (PACKET_IN_FLUSH | PACKET_XRI_CLOSED); 418382527734SSukumar Swaminathan 4184fcf3ce44SJohn Forte sbp->ticks = hba->timer_tics + 10; 4185fcf3ce44SJohn Forte sbp->abort_attempts++; 4186fcf3ce44SJohn Forte 418782527734SSukumar Swaminathan flag[cp->channelno] = 1; 4188fcf3ce44SJohn Forte 4189fcf3ce44SJohn Forte /* 4190291a2b48SSukumar Swaminathan * If the fpkt is already set, then we will leave it alone 4191fcf3ce44SJohn Forte * This ensures that this pkt is only accounted for on one 4192fcf3ce44SJohn Forte * fpkt->flush_count 4193fcf3ce44SJohn Forte */ 4194fcf3ce44SJohn Forte if (!sbp->fpkt && fpkt) { 4195fcf3ce44SJohn Forte mutex_enter(&fpkt->mtx); 4196fcf3ce44SJohn Forte sbp->fpkt = fpkt; 4197fcf3ce44SJohn Forte fpkt->flush_count++; 4198fcf3ce44SJohn Forte mutex_exit(&fpkt->mtx); 4199fcf3ce44SJohn Forte } 4200291a2b48SSukumar Swaminathan 4201fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 4202fcf3ce44SJohn Forte 4203fcf3ce44SJohn Forte return; 4204fcf3ce44SJohn Forte 420582527734SSukumar Swaminathan } /* emlxs_sbp_abort_add() */ 4206