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 * 8*8f23e9faSHans Rosenfeld * You can obtain a copy of the license at 9*8f23e9faSHans Rosenfeld * http://www.opensource.org/licenses/cddl1.txt. 10fcf3ce44SJohn Forte * See the License for the specific language governing permissions 11fcf3ce44SJohn Forte * and limitations under the License. 12fcf3ce44SJohn Forte * 13fcf3ce44SJohn Forte * When distributing Covered Code, include this CDDL HEADER in each 14fcf3ce44SJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15fcf3ce44SJohn Forte * If applicable, add the following below this CDDL HEADER, with the 16fcf3ce44SJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying 17fcf3ce44SJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner] 18fcf3ce44SJohn Forte * 19fcf3ce44SJohn Forte * CDDL HEADER END 20fcf3ce44SJohn Forte */ 21fcf3ce44SJohn Forte 22fcf3ce44SJohn Forte /* 23*8f23e9faSHans Rosenfeld * Copyright (c) 2004-2012 Emulex. All rights reserved. 2482527734SSukumar Swaminathan * Use is subject to license terms. 25fcf3ce44SJohn Forte */ 26fcf3ce44SJohn Forte 27291a2b48SSukumar Swaminathan #include <emlxs.h> 28fcf3ce44SJohn Forte 29fcf3ce44SJohn Forte /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */ 30fcf3ce44SJohn Forte EMLXS_MSG_DEF(EMLXS_FCP_C); 31fcf3ce44SJohn Forte 32fcf3ce44SJohn Forte #define EMLXS_GET_VADDR(hba, rp, icmd) emlxs_mem_get_vaddr(hba, rp, \ 3382527734SSukumar Swaminathan PADDR(icmd->un.cont64[i].addrHigh, icmd->un.cont64[i].addrLow)); 34fcf3ce44SJohn Forte 35291a2b48SSukumar Swaminathan static void emlxs_sbp_abort_add(emlxs_port_t *port, emlxs_buf_t *sbp, 36291a2b48SSukumar Swaminathan Q *abort, uint8_t *flag, emlxs_buf_t *fpkt); 37fcf3ce44SJohn Forte 38fcf3ce44SJohn Forte #define SCSI3_PERSISTENT_RESERVE_IN 0x5e 39291a2b48SSukumar Swaminathan #define SCSI_INQUIRY 0x12 40291a2b48SSukumar Swaminathan #define SCSI_RX_DIAG 0x1C 41fcf3ce44SJohn Forte 42fcf3ce44SJohn Forte 43fcf3ce44SJohn Forte /* 44fcf3ce44SJohn Forte * emlxs_handle_fcp_event 45fcf3ce44SJohn Forte * 46fcf3ce44SJohn Forte * Description: Process an FCP Rsp Ring completion 47fcf3ce44SJohn Forte * 48fcf3ce44SJohn Forte */ 49fcf3ce44SJohn Forte /* ARGSUSED */ 50fcf3ce44SJohn Forte extern void 5182527734SSukumar Swaminathan emlxs_handle_fcp_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq) 52fcf3ce44SJohn Forte { 53fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 5482527734SSukumar Swaminathan emlxs_config_t *cfg = &CFG; 55fcf3ce44SJohn Forte IOCB *cmd; 56fcf3ce44SJohn Forte emlxs_buf_t *sbp; 57fcf3ce44SJohn Forte fc_packet_t *pkt = NULL; 58291a2b48SSukumar Swaminathan #ifdef SAN_DIAG_SUPPORT 59291a2b48SSukumar Swaminathan NODELIST *ndlp; 60291a2b48SSukumar Swaminathan #endif 61fcf3ce44SJohn Forte uint32_t iostat; 62fcf3ce44SJohn Forte uint8_t localstat; 63fcf3ce44SJohn Forte fcp_rsp_t *rsp; 64fcf3ce44SJohn Forte uint32_t rsp_data_resid; 65fcf3ce44SJohn Forte uint32_t check_underrun; 66fcf3ce44SJohn Forte uint8_t asc; 67fcf3ce44SJohn Forte uint8_t ascq; 68fcf3ce44SJohn Forte uint8_t scsi_status; 69fcf3ce44SJohn Forte uint8_t sense; 70fcf3ce44SJohn Forte uint32_t did; 71fcf3ce44SJohn Forte uint32_t fix_it; 72fcf3ce44SJohn Forte uint8_t *scsi_cmd; 73fcf3ce44SJohn Forte uint8_t scsi_opcode; 74fcf3ce44SJohn Forte uint16_t scsi_dl; 75fcf3ce44SJohn Forte uint32_t data_rx; 76*8f23e9faSHans Rosenfeld uint32_t length; 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, 99*8f23e9faSHans Rosenfeld "cmd=%x iotag=%d", cmd->ULPCOMMAND, cmd->ULPIOTAG); 100fcf3ce44SJohn Forte 101fcf3ce44SJohn Forte return; 102fcf3ce44SJohn Forte } 103291a2b48SSukumar Swaminathan 104fcf3ce44SJohn Forte HBASTATS.FcpCompleted++; 105fcf3ce44SJohn Forte 106291a2b48SSukumar Swaminathan #ifdef SAN_DIAG_SUPPORT 107291a2b48SSukumar Swaminathan emlxs_update_sd_bucket(sbp); 108291a2b48SSukumar Swaminathan #endif /* SAN_DIAG_SUPPORT */ 109291a2b48SSukumar Swaminathan 110fcf3ce44SJohn Forte pkt = PRIV2PKT(sbp); 111fcf3ce44SJohn Forte 11282527734SSukumar Swaminathan did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id); 113fcf3ce44SJohn Forte scsi_cmd = (uint8_t *)pkt->pkt_cmd; 114fcf3ce44SJohn Forte scsi_opcode = scsi_cmd[12]; 115fcf3ce44SJohn Forte data_rx = 0; 116fcf3ce44SJohn Forte 117fcf3ce44SJohn Forte /* Sync data in data buffer only on FC_PKT_FCP_READ */ 118fcf3ce44SJohn Forte if (pkt->pkt_datalen && (pkt->pkt_tran_type == FC_PKT_FCP_READ)) { 11982527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(pkt->pkt_data_dma, 0, pkt->pkt_datalen, 120fcf3ce44SJohn Forte DDI_DMA_SYNC_FORKERNEL); 121fcf3ce44SJohn Forte 122fcf3ce44SJohn Forte #ifdef TEST_SUPPORT 123fcf3ce44SJohn Forte if (hba->underrun_counter && (iostat == IOSTAT_SUCCESS) && 124fcf3ce44SJohn Forte (pkt->pkt_datalen >= 512)) { 125fcf3ce44SJohn Forte hba->underrun_counter--; 126fcf3ce44SJohn Forte iostat = IOSTAT_FCP_RSP_ERROR; 127fcf3ce44SJohn Forte 128fcf3ce44SJohn Forte /* Report 512 bytes missing by adapter */ 129fcf3ce44SJohn Forte cmd->un.fcpi.fcpi_parm = pkt->pkt_datalen - 512; 130fcf3ce44SJohn Forte 131fcf3ce44SJohn Forte /* Corrupt 512 bytes of Data buffer */ 132fcf3ce44SJohn Forte bzero((uint8_t *)pkt->pkt_data, 512); 133fcf3ce44SJohn Forte 134fcf3ce44SJohn Forte /* Set FCP response to STATUS_GOOD */ 135fcf3ce44SJohn Forte bzero((uint8_t *)pkt->pkt_resp, pkt->pkt_rsplen); 136fcf3ce44SJohn Forte } 137291a2b48SSukumar Swaminathan #endif /* TEST_SUPPORT */ 138fcf3ce44SJohn Forte } 139291a2b48SSukumar Swaminathan 140fcf3ce44SJohn Forte /* Process the pkt */ 141fcf3ce44SJohn Forte mutex_enter(&sbp->mtx); 142fcf3ce44SJohn Forte 143fcf3ce44SJohn Forte /* Check for immediate return */ 144fcf3ce44SJohn Forte if ((iostat == IOSTAT_SUCCESS) && 145fcf3ce44SJohn Forte (pkt->pkt_comp) && 146291a2b48SSukumar Swaminathan !(sbp->pkt_flags & 14782527734SSukumar Swaminathan (PACKET_ULP_OWNED | PACKET_COMPLETED | 148fcf3ce44SJohn Forte PACKET_IN_COMPLETION | PACKET_IN_TXQ | PACKET_IN_CHIPQ | 149fcf3ce44SJohn Forte PACKET_IN_DONEQ | PACKET_IN_TIMEOUT | PACKET_IN_FLUSH | 150fcf3ce44SJohn Forte PACKET_IN_ABORT | PACKET_POLLED))) { 151fcf3ce44SJohn Forte HBASTATS.FcpGood++; 152fcf3ce44SJohn Forte 153291a2b48SSukumar Swaminathan sbp->pkt_flags |= 154291a2b48SSukumar Swaminathan (PACKET_STATE_VALID | PACKET_IN_COMPLETION | 15582527734SSukumar Swaminathan PACKET_COMPLETED | PACKET_ULP_OWNED); 156fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 157fcf3ce44SJohn Forte 158fcf3ce44SJohn Forte #if (EMLXS_MODREVX == EMLXS_MODREV2X) 159fcf3ce44SJohn Forte emlxs_unswap_pkt(sbp); 160291a2b48SSukumar Swaminathan #endif /* EMLXS_MODREV2X */ 161b3660a96SSukumar Swaminathan 162b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT 163b3660a96SSukumar Swaminathan emlxs_check_dma(hba, sbp); 164b3660a96SSukumar Swaminathan #endif /* FMA_SUPPORT */ 165b3660a96SSukumar Swaminathan 16682527734SSukumar Swaminathan cp->ulpCmplCmd++; 167fcf3ce44SJohn Forte (*pkt->pkt_comp) (pkt); 168fcf3ce44SJohn Forte 169b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT 170b3660a96SSukumar Swaminathan if (hba->flag & FC_DMA_CHECK_ERROR) { 171b3660a96SSukumar Swaminathan emlxs_thread_spawn(hba, emlxs_restart_thread, 172b3660a96SSukumar Swaminathan NULL, NULL); 173b3660a96SSukumar Swaminathan } 174b3660a96SSukumar Swaminathan #endif /* FMA_SUPPORT */ 175b3660a96SSukumar Swaminathan 176fcf3ce44SJohn Forte return; 177fcf3ce44SJohn Forte } 178291a2b48SSukumar Swaminathan 179fcf3ce44SJohn Forte /* 180291a2b48SSukumar Swaminathan * A response is only placed in the resp buffer if IOSTAT_FCP_RSP_ERROR 181291a2b48SSukumar Swaminathan * is reported. 182fcf3ce44SJohn Forte */ 183fcf3ce44SJohn Forte 184*8f23e9faSHans Rosenfeld /* Check if a response buffer was not provided */ 185*8f23e9faSHans Rosenfeld if ((iostat != IOSTAT_FCP_RSP_ERROR) || (pkt->pkt_rsplen == 0)) { 186*8f23e9faSHans Rosenfeld goto done; 187*8f23e9faSHans Rosenfeld } 188*8f23e9faSHans Rosenfeld 189*8f23e9faSHans Rosenfeld EMLXS_MPDATA_SYNC(pkt->pkt_resp_dma, 0, pkt->pkt_rsplen, 190*8f23e9faSHans Rosenfeld DDI_DMA_SYNC_FORKERNEL); 191*8f23e9faSHans Rosenfeld 192*8f23e9faSHans Rosenfeld /* Get the response buffer pointer */ 193*8f23e9faSHans Rosenfeld rsp = (fcp_rsp_t *)pkt->pkt_resp; 194*8f23e9faSHans Rosenfeld 195*8f23e9faSHans Rosenfeld /* Validate the response payload */ 196*8f23e9faSHans Rosenfeld if (!rsp->fcp_u.fcp_status.resid_under && 197*8f23e9faSHans Rosenfeld !rsp->fcp_u.fcp_status.resid_over) { 198*8f23e9faSHans Rosenfeld rsp->fcp_resid = 0; 199*8f23e9faSHans Rosenfeld } 200*8f23e9faSHans Rosenfeld 201*8f23e9faSHans Rosenfeld if (!rsp->fcp_u.fcp_status.rsp_len_set) { 202*8f23e9faSHans Rosenfeld rsp->fcp_response_len = 0; 203*8f23e9faSHans Rosenfeld } 204fcf3ce44SJohn Forte 205*8f23e9faSHans Rosenfeld if (!rsp->fcp_u.fcp_status.sense_len_set) { 206*8f23e9faSHans Rosenfeld rsp->fcp_sense_len = 0; 207*8f23e9faSHans Rosenfeld } 208*8f23e9faSHans Rosenfeld 209*8f23e9faSHans Rosenfeld length = sizeof (fcp_rsp_t) + LE_SWAP32(rsp->fcp_response_len) + 210*8f23e9faSHans Rosenfeld LE_SWAP32(rsp->fcp_sense_len); 211*8f23e9faSHans Rosenfeld 212*8f23e9faSHans Rosenfeld if (length > pkt->pkt_rsplen) { 213*8f23e9faSHans Rosenfeld iostat = IOSTAT_RSP_INVALID; 214*8f23e9faSHans Rosenfeld pkt->pkt_data_resid = pkt->pkt_datalen; 215*8f23e9faSHans Rosenfeld goto done; 216*8f23e9faSHans Rosenfeld } 217fcf3ce44SJohn Forte 218*8f23e9faSHans Rosenfeld /* Set the valid response flag */ 219*8f23e9faSHans Rosenfeld sbp->pkt_flags |= PACKET_FCP_RSP_VALID; 220fcf3ce44SJohn Forte 221*8f23e9faSHans Rosenfeld scsi_status = rsp->fcp_u.fcp_status.scsi_status; 222fcf3ce44SJohn Forte 223291a2b48SSukumar Swaminathan #ifdef SAN_DIAG_SUPPORT 224*8f23e9faSHans Rosenfeld ndlp = (NODELIST *)iocbq->node; 225*8f23e9faSHans Rosenfeld if (scsi_status == SCSI_STAT_QUE_FULL) { 226*8f23e9faSHans Rosenfeld emlxs_log_sd_scsi_event(port, SD_SCSI_SUBCATEGORY_QFULL, 227*8f23e9faSHans Rosenfeld (HBA_WWN *)&ndlp->nlp_portname, sbp->lun); 228*8f23e9faSHans Rosenfeld } else if (scsi_status == SCSI_STAT_BUSY) { 229*8f23e9faSHans Rosenfeld emlxs_log_sd_scsi_event(port, 230*8f23e9faSHans Rosenfeld SD_SCSI_SUBCATEGORY_DEVBSY, 231*8f23e9faSHans Rosenfeld (HBA_WWN *)&ndlp->nlp_portname, sbp->lun); 232*8f23e9faSHans Rosenfeld } 233291a2b48SSukumar Swaminathan #endif 234291a2b48SSukumar Swaminathan 235*8f23e9faSHans Rosenfeld /* 236*8f23e9faSHans Rosenfeld * Convert a task abort to a check condition with no data 237*8f23e9faSHans Rosenfeld * transferred. We saw a data corruption when Solaris received 238*8f23e9faSHans Rosenfeld * a Task Abort from a tape. 239*8f23e9faSHans Rosenfeld */ 240a9800bebSGarrett D'Amore 241*8f23e9faSHans Rosenfeld if (scsi_status == SCSI_STAT_TASK_ABORT) { 242*8f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, 243*8f23e9faSHans Rosenfeld &emlxs_fcp_completion_error_msg, 244*8f23e9faSHans Rosenfeld "Task Abort. " 245*8f23e9faSHans Rosenfeld "Fixed. did=0x%06x sbp=%p cmd=%02x dl=%d", 246*8f23e9faSHans Rosenfeld did, sbp, scsi_opcode, pkt->pkt_datalen); 247*8f23e9faSHans Rosenfeld 248*8f23e9faSHans Rosenfeld rsp->fcp_u.fcp_status.scsi_status = 249*8f23e9faSHans Rosenfeld SCSI_STAT_CHECK_COND; 250*8f23e9faSHans Rosenfeld rsp->fcp_u.fcp_status.rsp_len_set = 0; 251*8f23e9faSHans Rosenfeld rsp->fcp_u.fcp_status.sense_len_set = 0; 252*8f23e9faSHans Rosenfeld rsp->fcp_u.fcp_status.resid_over = 0; 253*8f23e9faSHans Rosenfeld 254*8f23e9faSHans Rosenfeld if (pkt->pkt_datalen) { 255*8f23e9faSHans Rosenfeld rsp->fcp_u.fcp_status.resid_under = 1; 256*8f23e9faSHans Rosenfeld rsp->fcp_resid = 257*8f23e9faSHans Rosenfeld LE_SWAP32(pkt->pkt_datalen); 258*8f23e9faSHans Rosenfeld } else { 259*8f23e9faSHans Rosenfeld rsp->fcp_u.fcp_status.resid_under = 0; 260*8f23e9faSHans Rosenfeld rsp->fcp_resid = 0; 261*8f23e9faSHans Rosenfeld } 262fcf3ce44SJohn Forte 263*8f23e9faSHans Rosenfeld scsi_status = SCSI_STAT_CHECK_COND; 264*8f23e9faSHans Rosenfeld } 265fcf3ce44SJohn Forte 266*8f23e9faSHans Rosenfeld /* 267*8f23e9faSHans Rosenfeld * We only need to check underrun if data could 268*8f23e9faSHans Rosenfeld * have been sent 269*8f23e9faSHans Rosenfeld */ 270fcf3ce44SJohn Forte 271*8f23e9faSHans Rosenfeld /* Always check underrun if status is good */ 272*8f23e9faSHans Rosenfeld if (scsi_status == SCSI_STAT_GOOD) { 273*8f23e9faSHans Rosenfeld check_underrun = 1; 274*8f23e9faSHans Rosenfeld } 275*8f23e9faSHans Rosenfeld /* Check the sense codes if this is a check condition */ 276*8f23e9faSHans Rosenfeld else if (scsi_status == SCSI_STAT_CHECK_COND) { 277*8f23e9faSHans Rosenfeld check_underrun = 1; 278*8f23e9faSHans Rosenfeld 279*8f23e9faSHans Rosenfeld /* Check if sense data was provided */ 280*8f23e9faSHans Rosenfeld if (LE_SWAP32(rsp->fcp_sense_len) >= 14) { 281*8f23e9faSHans Rosenfeld sense = *((uint8_t *)rsp + 32 + 2); 282*8f23e9faSHans Rosenfeld asc = *((uint8_t *)rsp + 32 + 12); 283*8f23e9faSHans Rosenfeld ascq = *((uint8_t *)rsp + 32 + 13); 284fcf3ce44SJohn Forte } 285291a2b48SSukumar Swaminathan 286*8f23e9faSHans Rosenfeld #ifdef SAN_DIAG_SUPPORT 287*8f23e9faSHans Rosenfeld emlxs_log_sd_scsi_check_event(port, 288*8f23e9faSHans Rosenfeld (HBA_WWN *)&ndlp->nlp_portname, sbp->lun, 289*8f23e9faSHans Rosenfeld scsi_opcode, sense, asc, ascq); 290*8f23e9faSHans Rosenfeld #endif 291*8f23e9faSHans Rosenfeld } 292*8f23e9faSHans Rosenfeld /* Status is not good and this is not a check condition */ 293*8f23e9faSHans Rosenfeld /* No data should have been sent */ 294*8f23e9faSHans Rosenfeld else { 295*8f23e9faSHans Rosenfeld check_underrun = 0; 296*8f23e9faSHans Rosenfeld } 297*8f23e9faSHans Rosenfeld 298*8f23e9faSHans Rosenfeld /* Initialize the resids */ 299*8f23e9faSHans Rosenfeld pkt->pkt_resp_resid = 0; 300*8f23e9faSHans Rosenfeld pkt->pkt_data_resid = 0; 301*8f23e9faSHans Rosenfeld 302*8f23e9faSHans Rosenfeld /* Check if no data was to be transferred */ 303*8f23e9faSHans Rosenfeld if (pkt->pkt_datalen == 0) { 304*8f23e9faSHans Rosenfeld goto done; 305*8f23e9faSHans Rosenfeld } 306*8f23e9faSHans Rosenfeld 307*8f23e9faSHans Rosenfeld /* Get the residual underrun count reported by the SCSI reply */ 308*8f23e9faSHans Rosenfeld rsp_data_resid = (rsp->fcp_u.fcp_status.resid_under) ? 309*8f23e9faSHans Rosenfeld LE_SWAP32(rsp->fcp_resid) : 0; 310*8f23e9faSHans Rosenfeld 311*8f23e9faSHans Rosenfeld /* Set the pkt_data_resid to what the scsi response resid */ 312*8f23e9faSHans Rosenfeld pkt->pkt_data_resid = rsp_data_resid; 313*8f23e9faSHans Rosenfeld 314*8f23e9faSHans Rosenfeld /* Adjust the pkt_data_resid field if needed */ 315*8f23e9faSHans Rosenfeld if (pkt->pkt_tran_type == FC_PKT_FCP_READ) { 316fcf3ce44SJohn Forte /* 317*8f23e9faSHans Rosenfeld * Get the residual underrun count reported by 318*8f23e9faSHans Rosenfeld * our adapter 319fcf3ce44SJohn Forte */ 320*8f23e9faSHans Rosenfeld pkt->pkt_data_resid = cmd->un.fcpi.fcpi_parm; 321291a2b48SSukumar Swaminathan 322291a2b48SSukumar Swaminathan #ifdef SAN_DIAG_SUPPORT 323*8f23e9faSHans Rosenfeld if ((rsp_data_resid == 0) && (pkt->pkt_data_resid)) { 324*8f23e9faSHans Rosenfeld emlxs_log_sd_fc_rdchk_event(port, 325291a2b48SSukumar Swaminathan (HBA_WWN *)&ndlp->nlp_portname, sbp->lun, 326*8f23e9faSHans Rosenfeld scsi_opcode, pkt->pkt_data_resid); 327fcf3ce44SJohn Forte } 328*8f23e9faSHans Rosenfeld #endif 329*8f23e9faSHans Rosenfeld 330*8f23e9faSHans Rosenfeld /* Get the actual amount of data transferred */ 331*8f23e9faSHans Rosenfeld data_rx = pkt->pkt_datalen - pkt->pkt_data_resid; 332fcf3ce44SJohn Forte 333*8f23e9faSHans Rosenfeld /* 334*8f23e9faSHans Rosenfeld * If the residual being reported by the adapter is 335*8f23e9faSHans Rosenfeld * greater than the residual being reported in the 336*8f23e9faSHans Rosenfeld * reply, then we have a true underrun. 337*8f23e9faSHans Rosenfeld */ 338*8f23e9faSHans Rosenfeld if (check_underrun && (pkt->pkt_data_resid > rsp_data_resid)) { 339*8f23e9faSHans Rosenfeld switch (scsi_opcode) { 340*8f23e9faSHans Rosenfeld case SCSI_INQUIRY: 341*8f23e9faSHans Rosenfeld scsi_dl = scsi_cmd[16]; 342*8f23e9faSHans Rosenfeld break; 343*8f23e9faSHans Rosenfeld 344*8f23e9faSHans Rosenfeld case SCSI_RX_DIAG: 345*8f23e9faSHans Rosenfeld scsi_dl = 346*8f23e9faSHans Rosenfeld (scsi_cmd[15] * 0x100) + 347*8f23e9faSHans Rosenfeld scsi_cmd[16]; 348*8f23e9faSHans Rosenfeld break; 349fcf3ce44SJohn Forte 350*8f23e9faSHans Rosenfeld default: 351*8f23e9faSHans Rosenfeld scsi_dl = pkt->pkt_datalen; 352*8f23e9faSHans Rosenfeld } 353fcf3ce44SJohn Forte 354*8f23e9faSHans Rosenfeld #ifdef FCP_UNDERRUN_PATCH1 355*8f23e9faSHans Rosenfeld if (cfg[CFG_ENABLE_PATCH].current & FCP_UNDERRUN_PATCH1) { 356fcf3ce44SJohn Forte /* 357*8f23e9faSHans Rosenfeld * If status is not good and no data was 358*8f23e9faSHans Rosenfeld * actually transferred, then we must fix 359*8f23e9faSHans Rosenfeld * the issue 360fcf3ce44SJohn Forte */ 361*8f23e9faSHans Rosenfeld if ((scsi_status != SCSI_STAT_GOOD) && (data_rx == 0)) { 362*8f23e9faSHans Rosenfeld fix_it = 1; 363*8f23e9faSHans Rosenfeld 364*8f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, 365*8f23e9faSHans Rosenfeld &emlxs_fcp_completion_error_msg, 366*8f23e9faSHans Rosenfeld "Underrun(1). Fixed. " 367*8f23e9faSHans Rosenfeld "did=0x%06x sbp=%p cmd=%02x " 368*8f23e9faSHans Rosenfeld "dl=%d,%d rx=%d rsp=%d", 369*8f23e9faSHans Rosenfeld did, sbp, scsi_opcode, 370*8f23e9faSHans Rosenfeld pkt->pkt_datalen, scsi_dl, 371*8f23e9faSHans Rosenfeld (pkt->pkt_datalen - 372*8f23e9faSHans Rosenfeld pkt->pkt_data_resid), 373*8f23e9faSHans Rosenfeld rsp_data_resid); 374fcf3ce44SJohn Forte 375291a2b48SSukumar Swaminathan } 376*8f23e9faSHans Rosenfeld } 377*8f23e9faSHans Rosenfeld #endif /* FCP_UNDERRUN_PATCH1 */ 378291a2b48SSukumar Swaminathan 379fcf3ce44SJohn Forte 380*8f23e9faSHans Rosenfeld #ifdef FCP_UNDERRUN_PATCH2 381*8f23e9faSHans Rosenfeld if (cfg[CFG_ENABLE_PATCH].current & FCP_UNDERRUN_PATCH2) { 382*8f23e9faSHans Rosenfeld if (scsi_status == SCSI_STAT_GOOD) { 383*8f23e9faSHans Rosenfeld emlxs_msg_t *msg; 384fcf3ce44SJohn Forte 385*8f23e9faSHans Rosenfeld msg = &emlxs_fcp_completion_error_msg; 386*8f23e9faSHans Rosenfeld /* 387*8f23e9faSHans Rosenfeld * If status is good and this is an 388*8f23e9faSHans Rosenfeld * inquiry request and the amount of 389*8f23e9faSHans Rosenfeld * data 390*8f23e9faSHans Rosenfeld */ 391*8f23e9faSHans Rosenfeld /* 392*8f23e9faSHans Rosenfeld * requested <= data received, then we 393*8f23e9faSHans Rosenfeld * must fix the issue. 394*8f23e9faSHans Rosenfeld */ 395*8f23e9faSHans Rosenfeld 396*8f23e9faSHans Rosenfeld if ((scsi_opcode == SCSI_INQUIRY) && 397*8f23e9faSHans Rosenfeld (pkt->pkt_datalen >= data_rx) && 398*8f23e9faSHans Rosenfeld (scsi_dl <= data_rx)) { 399*8f23e9faSHans Rosenfeld fix_it = 1; 400*8f23e9faSHans Rosenfeld 401*8f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, msg, 402*8f23e9faSHans Rosenfeld "Underrun(2). Fixed. " 403*8f23e9faSHans Rosenfeld "did=0x%06x sbp=%p " 404*8f23e9faSHans Rosenfeld "cmd=%02x dl=%d,%d " 405*8f23e9faSHans Rosenfeld "rx=%d rsp=%d", 406*8f23e9faSHans Rosenfeld did, sbp, scsi_opcode, 407*8f23e9faSHans Rosenfeld pkt->pkt_datalen, scsi_dl, 408*8f23e9faSHans Rosenfeld data_rx, rsp_data_resid); 409fcf3ce44SJohn Forte 410fcf3ce44SJohn Forte } 411fcf3ce44SJohn Forte 412fcf3ce44SJohn Forte /* 413*8f23e9faSHans Rosenfeld * If status is good and this is an 414*8f23e9faSHans Rosenfeld * inquiry request and the amount of 415*8f23e9faSHans Rosenfeld * data requested >= 128 bytes, but 416*8f23e9faSHans Rosenfeld * only 128 bytes were received, 417*8f23e9faSHans Rosenfeld * then we must fix the issue. 418fcf3ce44SJohn Forte */ 419*8f23e9faSHans Rosenfeld else if ((scsi_opcode == SCSI_INQUIRY) && 420*8f23e9faSHans Rosenfeld (pkt->pkt_datalen >= 128) && 421*8f23e9faSHans Rosenfeld (scsi_dl >= 128) && (data_rx == 128)) { 422fcf3ce44SJohn Forte fix_it = 1; 423fcf3ce44SJohn Forte 424*8f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, msg, 425*8f23e9faSHans Rosenfeld "Underrun(3). Fixed. " 426*8f23e9faSHans Rosenfeld "did=0x%06x sbp=%p " 427*8f23e9faSHans Rosenfeld "cmd=%02x dl=%d,%d " 428*8f23e9faSHans Rosenfeld "rx=%d rsp=%d", 429fcf3ce44SJohn Forte did, sbp, scsi_opcode, 430fcf3ce44SJohn Forte pkt->pkt_datalen, scsi_dl, 431*8f23e9faSHans Rosenfeld data_rx, rsp_data_resid); 432fcf3ce44SJohn Forte 433fcf3ce44SJohn Forte } 434*8f23e9faSHans Rosenfeld } 43582527734SSukumar Swaminathan } 436*8f23e9faSHans Rosenfeld #endif /* FCP_UNDERRUN_PATCH2 */ 437fcf3ce44SJohn Forte 438*8f23e9faSHans Rosenfeld /* 439*8f23e9faSHans Rosenfeld * Check if SCSI response payload should be 440*8f23e9faSHans Rosenfeld * fixed or if a DATA_UNDERRUN should be 441*8f23e9faSHans Rosenfeld * reported 442*8f23e9faSHans Rosenfeld */ 443*8f23e9faSHans Rosenfeld if (fix_it) { 444*8f23e9faSHans Rosenfeld /* 445*8f23e9faSHans Rosenfeld * Fix the SCSI response payload itself 446*8f23e9faSHans Rosenfeld */ 447*8f23e9faSHans Rosenfeld rsp->fcp_u.fcp_status.resid_under = 1; 448*8f23e9faSHans Rosenfeld rsp->fcp_resid = 449*8f23e9faSHans Rosenfeld LE_SWAP32(pkt->pkt_data_resid); 450*8f23e9faSHans Rosenfeld } else { 451*8f23e9faSHans Rosenfeld /* 452*8f23e9faSHans Rosenfeld * Change the status from 453*8f23e9faSHans Rosenfeld * IOSTAT_FCP_RSP_ERROR to 454*8f23e9faSHans Rosenfeld * IOSTAT_DATA_UNDERRUN 455*8f23e9faSHans Rosenfeld */ 456*8f23e9faSHans Rosenfeld iostat = IOSTAT_DATA_UNDERRUN; 457*8f23e9faSHans Rosenfeld pkt->pkt_data_resid = 458*8f23e9faSHans Rosenfeld pkt->pkt_datalen; 459*8f23e9faSHans Rosenfeld } 460*8f23e9faSHans Rosenfeld } 461fcf3ce44SJohn Forte 462*8f23e9faSHans Rosenfeld /* 463*8f23e9faSHans Rosenfeld * If the residual being reported by the adapter is 464*8f23e9faSHans Rosenfeld * less than the residual being reported in the reply, 465*8f23e9faSHans Rosenfeld * then we have a true overrun. Since we don't know 466*8f23e9faSHans Rosenfeld * where the extra data came from or went to then we 467*8f23e9faSHans Rosenfeld * cannot trust anything we received 468*8f23e9faSHans Rosenfeld */ 469*8f23e9faSHans Rosenfeld else if (rsp_data_resid > pkt->pkt_data_resid) { 470*8f23e9faSHans Rosenfeld /* 471*8f23e9faSHans Rosenfeld * Change the status from 472*8f23e9faSHans Rosenfeld * IOSTAT_FCP_RSP_ERROR to 473*8f23e9faSHans Rosenfeld * IOSTAT_DATA_OVERRUN 474*8f23e9faSHans Rosenfeld */ 475*8f23e9faSHans Rosenfeld iostat = IOSTAT_DATA_OVERRUN; 476*8f23e9faSHans Rosenfeld pkt->pkt_data_resid = pkt->pkt_datalen; 477*8f23e9faSHans Rosenfeld } 478fcf3ce44SJohn Forte 479*8f23e9faSHans Rosenfeld } else if ((hba->sli_mode == EMLXS_HBA_SLI4_MODE) && 480*8f23e9faSHans Rosenfeld (pkt->pkt_tran_type == FC_PKT_FCP_WRITE)) { 481*8f23e9faSHans Rosenfeld /* 482*8f23e9faSHans Rosenfeld * Get the residual underrun count reported by 483*8f23e9faSHans Rosenfeld * our adapter 484*8f23e9faSHans Rosenfeld */ 485*8f23e9faSHans Rosenfeld pkt->pkt_data_resid = cmd->un.fcpi.fcpi_parm; 486fcf3ce44SJohn Forte 487*8f23e9faSHans Rosenfeld #ifdef SAN_DIAG_SUPPORT 488*8f23e9faSHans Rosenfeld if ((rsp_data_resid == 0) && (pkt->pkt_data_resid)) { 489*8f23e9faSHans Rosenfeld emlxs_log_sd_fc_rdchk_event(port, 490*8f23e9faSHans Rosenfeld (HBA_WWN *)&ndlp->nlp_portname, sbp->lun, 491*8f23e9faSHans Rosenfeld scsi_opcode, pkt->pkt_data_resid); 492*8f23e9faSHans Rosenfeld } 493*8f23e9faSHans Rosenfeld #endif /* SAN_DIAG_SUPPORT */ 494fcf3ce44SJohn Forte 495*8f23e9faSHans Rosenfeld /* Get the actual amount of data transferred */ 496*8f23e9faSHans Rosenfeld data_rx = pkt->pkt_datalen - pkt->pkt_data_resid; 497fcf3ce44SJohn Forte 498*8f23e9faSHans Rosenfeld /* 499*8f23e9faSHans Rosenfeld * If the residual being reported by the adapter is 500*8f23e9faSHans Rosenfeld * greater than the residual being reported in the 501*8f23e9faSHans Rosenfeld * reply, then we have a true underrun. 502*8f23e9faSHans Rosenfeld */ 503*8f23e9faSHans Rosenfeld if (check_underrun && (pkt->pkt_data_resid > rsp_data_resid)) { 504291a2b48SSukumar Swaminathan 505*8f23e9faSHans Rosenfeld scsi_dl = pkt->pkt_datalen; 506fcf3ce44SJohn Forte 507*8f23e9faSHans Rosenfeld #ifdef FCP_UNDERRUN_PATCH1 508*8f23e9faSHans Rosenfeld if (cfg[CFG_ENABLE_PATCH].current & FCP_UNDERRUN_PATCH1) { 509*8f23e9faSHans Rosenfeld /* 510*8f23e9faSHans Rosenfeld * If status is not good and no data was 511*8f23e9faSHans Rosenfeld * actually transferred, then we must fix 512*8f23e9faSHans Rosenfeld * the issue 513*8f23e9faSHans Rosenfeld */ 514*8f23e9faSHans Rosenfeld if ((scsi_status != SCSI_STAT_GOOD) && (data_rx == 0)) { 515*8f23e9faSHans Rosenfeld fix_it = 1; 516291a2b48SSukumar Swaminathan 517*8f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, 518*8f23e9faSHans Rosenfeld &emlxs_fcp_completion_error_msg, 519*8f23e9faSHans Rosenfeld "Underrun(1). Fixed. " 520*8f23e9faSHans Rosenfeld "did=0x%06x sbp=%p cmd=%02x " 521*8f23e9faSHans Rosenfeld "dl=%d,%d rx=%d rsp=%d", 522*8f23e9faSHans Rosenfeld did, sbp, scsi_opcode, 523*8f23e9faSHans Rosenfeld pkt->pkt_datalen, scsi_dl, 524*8f23e9faSHans Rosenfeld (pkt->pkt_datalen - 525*8f23e9faSHans Rosenfeld pkt->pkt_data_resid), 526*8f23e9faSHans Rosenfeld rsp_data_resid); 527fcf3ce44SJohn Forte 528fcf3ce44SJohn Forte } 529*8f23e9faSHans Rosenfeld } 530*8f23e9faSHans Rosenfeld #endif /* FCP_UNDERRUN_PATCH1 */ 531291a2b48SSukumar Swaminathan 532fcf3ce44SJohn Forte /* 533*8f23e9faSHans Rosenfeld * Check if SCSI response payload should be 534*8f23e9faSHans Rosenfeld * fixed or if a DATA_UNDERRUN should be 535*8f23e9faSHans Rosenfeld * reported 536fcf3ce44SJohn Forte */ 537*8f23e9faSHans Rosenfeld if (fix_it) { 538*8f23e9faSHans Rosenfeld /* 539*8f23e9faSHans Rosenfeld * Fix the SCSI response payload itself 540*8f23e9faSHans Rosenfeld */ 541*8f23e9faSHans Rosenfeld rsp->fcp_u.fcp_status.resid_under = 1; 542*8f23e9faSHans Rosenfeld rsp->fcp_resid = 543*8f23e9faSHans Rosenfeld LE_SWAP32(pkt->pkt_data_resid); 544*8f23e9faSHans Rosenfeld } else { 545fcf3ce44SJohn Forte /* 546fcf3ce44SJohn Forte * Change the status from 547fcf3ce44SJohn Forte * IOSTAT_FCP_RSP_ERROR to 548*8f23e9faSHans Rosenfeld * IOSTAT_DATA_UNDERRUN 549fcf3ce44SJohn Forte */ 550*8f23e9faSHans Rosenfeld iostat = IOSTAT_DATA_UNDERRUN; 551*8f23e9faSHans Rosenfeld pkt->pkt_data_resid = 552*8f23e9faSHans Rosenfeld pkt->pkt_datalen; 553fcf3ce44SJohn Forte } 554*8f23e9faSHans Rosenfeld } 555291a2b48SSukumar Swaminathan 556*8f23e9faSHans Rosenfeld /* 557*8f23e9faSHans Rosenfeld * If the residual being reported by the adapter is 558*8f23e9faSHans Rosenfeld * less than the residual being reported in the reply, 559*8f23e9faSHans Rosenfeld * then we have a true overrun. Since we don't know 560*8f23e9faSHans Rosenfeld * where the extra data came from or went to then we 561*8f23e9faSHans Rosenfeld * cannot trust anything we received 562*8f23e9faSHans Rosenfeld */ 563*8f23e9faSHans Rosenfeld else if (rsp_data_resid > pkt->pkt_data_resid) { 564*8f23e9faSHans Rosenfeld /* 565*8f23e9faSHans Rosenfeld * Change the status from 566*8f23e9faSHans Rosenfeld * IOSTAT_FCP_RSP_ERROR to 567*8f23e9faSHans Rosenfeld * IOSTAT_DATA_OVERRUN 568*8f23e9faSHans Rosenfeld */ 569*8f23e9faSHans Rosenfeld iostat = IOSTAT_DATA_OVERRUN; 570*8f23e9faSHans Rosenfeld pkt->pkt_data_resid = pkt->pkt_datalen; 571fcf3ce44SJohn Forte } 572fcf3ce44SJohn Forte } 573291a2b48SSukumar Swaminathan 574*8f23e9faSHans Rosenfeld done: 575*8f23e9faSHans Rosenfeld 576fcf3ce44SJohn Forte /* Print completion message */ 577fcf3ce44SJohn Forte switch (iostat) { 578fcf3ce44SJohn Forte case IOSTAT_SUCCESS: 579fcf3ce44SJohn Forte /* Build SCSI GOOD status */ 580fcf3ce44SJohn Forte if (pkt->pkt_rsplen) { 581fcf3ce44SJohn Forte bzero((uint8_t *)pkt->pkt_resp, pkt->pkt_rsplen); 582fcf3ce44SJohn Forte } 583fcf3ce44SJohn Forte break; 584fcf3ce44SJohn Forte 585fcf3ce44SJohn Forte case IOSTAT_FCP_RSP_ERROR: 586fcf3ce44SJohn Forte break; 587fcf3ce44SJohn Forte 588fcf3ce44SJohn Forte case IOSTAT_REMOTE_STOP: 589fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, 590291a2b48SSukumar Swaminathan "Remote Stop. did=0x%06x sbp=%p cmd=%02x", did, sbp, 591291a2b48SSukumar Swaminathan scsi_opcode); 592fcf3ce44SJohn Forte break; 593fcf3ce44SJohn Forte 594fcf3ce44SJohn Forte case IOSTAT_LOCAL_REJECT: 595fcf3ce44SJohn Forte localstat = cmd->un.grsp.perr.statLocalError; 596fcf3ce44SJohn Forte 597fcf3ce44SJohn Forte switch (localstat) { 598fcf3ce44SJohn Forte case IOERR_SEQUENCE_TIMEOUT: 599fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 600fcf3ce44SJohn Forte &emlxs_fcp_completion_error_msg, 601291a2b48SSukumar Swaminathan "Local reject. " 602291a2b48SSukumar Swaminathan "%s did=0x%06x sbp=%p cmd=%02x tmo=%d ", 603fcf3ce44SJohn Forte emlxs_error_xlate(localstat), did, sbp, 604fcf3ce44SJohn Forte scsi_opcode, pkt->pkt_timeout); 605fcf3ce44SJohn Forte break; 606fcf3ce44SJohn Forte 607fcf3ce44SJohn Forte default: 608fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 609fcf3ce44SJohn Forte &emlxs_fcp_completion_error_msg, 610a9800bebSGarrett D'Amore "Local reject. %s 0x%06x %p %02x (%x)(%x)", 611291a2b48SSukumar Swaminathan emlxs_error_xlate(localstat), did, sbp, 612a9800bebSGarrett D'Amore scsi_opcode, (uint16_t)cmd->ULPIOTAG, 613a9800bebSGarrett D'Amore (uint16_t)cmd->ULPCONTEXT); 614fcf3ce44SJohn Forte } 615fcf3ce44SJohn Forte 616fcf3ce44SJohn Forte break; 617fcf3ce44SJohn Forte 618fcf3ce44SJohn Forte case IOSTAT_NPORT_RJT: 619fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, 620291a2b48SSukumar Swaminathan "Nport reject. did=0x%06x sbp=%p cmd=%02x", did, sbp, 621291a2b48SSukumar Swaminathan scsi_opcode); 622fcf3ce44SJohn Forte break; 623fcf3ce44SJohn Forte 624fcf3ce44SJohn Forte case IOSTAT_FABRIC_RJT: 625fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, 626291a2b48SSukumar Swaminathan "Fabric reject. did=0x%06x sbp=%p cmd=%02x", did, sbp, 627291a2b48SSukumar Swaminathan scsi_opcode); 628fcf3ce44SJohn Forte break; 629fcf3ce44SJohn Forte 630fcf3ce44SJohn Forte case IOSTAT_NPORT_BSY: 631291a2b48SSukumar Swaminathan #ifdef SAN_DIAG_SUPPORT 632291a2b48SSukumar Swaminathan ndlp = (NODELIST *)iocbq->node; 633291a2b48SSukumar Swaminathan emlxs_log_sd_fc_bsy_event(port, (HBA_WWN *)&ndlp->nlp_portname); 634291a2b48SSukumar Swaminathan #endif 635291a2b48SSukumar Swaminathan 636fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, 637291a2b48SSukumar Swaminathan "Nport busy. did=0x%06x sbp=%p cmd=%02x", did, sbp, 638291a2b48SSukumar Swaminathan scsi_opcode); 639fcf3ce44SJohn Forte break; 640fcf3ce44SJohn Forte 641fcf3ce44SJohn Forte case IOSTAT_FABRIC_BSY: 642291a2b48SSukumar Swaminathan #ifdef SAN_DIAG_SUPPORT 643291a2b48SSukumar Swaminathan ndlp = (NODELIST *)iocbq->node; 644291a2b48SSukumar Swaminathan emlxs_log_sd_fc_bsy_event(port, NULL); 645291a2b48SSukumar Swaminathan #endif 646291a2b48SSukumar Swaminathan 647fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, 648291a2b48SSukumar Swaminathan "Fabric busy. did=0x%06x sbp=%p cmd=%02x", did, sbp, 649291a2b48SSukumar Swaminathan scsi_opcode); 650fcf3ce44SJohn Forte break; 651fcf3ce44SJohn Forte 652fcf3ce44SJohn Forte case IOSTAT_INTERMED_RSP: 653fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, 654291a2b48SSukumar Swaminathan "Intermediate response. did=0x%06x sbp=%p cmd=%02x", did, 655291a2b48SSukumar Swaminathan sbp, scsi_opcode); 656fcf3ce44SJohn Forte break; 657fcf3ce44SJohn Forte 658fcf3ce44SJohn Forte case IOSTAT_LS_RJT: 659fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, 660291a2b48SSukumar Swaminathan "LS Reject. did=0x%06x sbp=%p cmd=%02x", did, sbp, 661291a2b48SSukumar Swaminathan scsi_opcode); 662fcf3ce44SJohn Forte break; 663fcf3ce44SJohn Forte 664fcf3ce44SJohn Forte case IOSTAT_DATA_UNDERRUN: 665fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, 666291a2b48SSukumar Swaminathan "Underrun. did=0x%06x sbp=%p cmd=%02x " 667291a2b48SSukumar Swaminathan "dl=%d,%d rx=%d rsp=%d (%02x,%02x,%02x,%02x)", 668291a2b48SSukumar Swaminathan did, sbp, scsi_opcode, pkt->pkt_datalen, scsi_dl, data_rx, 669291a2b48SSukumar Swaminathan rsp_data_resid, scsi_status, sense, asc, ascq); 670fcf3ce44SJohn Forte break; 671fcf3ce44SJohn Forte 672fcf3ce44SJohn Forte case IOSTAT_DATA_OVERRUN: 673fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, 674291a2b48SSukumar Swaminathan "Overrun. did=0x%06x sbp=%p cmd=%02x " 675291a2b48SSukumar Swaminathan "dl=%d,%d rx=%d rsp=%d (%02x,%02x,%02x,%02x)", 676291a2b48SSukumar Swaminathan did, sbp, scsi_opcode, pkt->pkt_datalen, scsi_dl, data_rx, 677291a2b48SSukumar Swaminathan rsp_data_resid, scsi_status, sense, asc, ascq); 678fcf3ce44SJohn Forte break; 679fcf3ce44SJohn Forte 680*8f23e9faSHans Rosenfeld case IOSTAT_RSP_INVALID: 681*8f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, 682*8f23e9faSHans Rosenfeld "Rsp Invalid. did=0x%06x sbp=%p cmd=%02x dl=%d rl=%d" 683*8f23e9faSHans Rosenfeld "(%d, %d, %d)", 684*8f23e9faSHans Rosenfeld did, sbp, scsi_opcode, pkt->pkt_datalen, pkt->pkt_rsplen, 685*8f23e9faSHans Rosenfeld LE_SWAP32(rsp->fcp_resid), 686*8f23e9faSHans Rosenfeld LE_SWAP32(rsp->fcp_sense_len), 687*8f23e9faSHans Rosenfeld LE_SWAP32(rsp->fcp_response_len)); 688*8f23e9faSHans Rosenfeld break; 689*8f23e9faSHans Rosenfeld 690fcf3ce44SJohn Forte default: 691fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, 692fcf3ce44SJohn Forte "Unknown status=%x reason=%x did=0x%06x sbp=%p cmd=%02x", 693291a2b48SSukumar Swaminathan iostat, cmd->un.grsp.perr.statLocalError, did, sbp, 694291a2b48SSukumar Swaminathan scsi_opcode); 695fcf3ce44SJohn Forte break; 696fcf3ce44SJohn Forte } 697fcf3ce44SJohn Forte 698fcf3ce44SJohn Forte if (iostat == IOSTAT_SUCCESS) { 699fcf3ce44SJohn Forte HBASTATS.FcpGood++; 700fcf3ce44SJohn Forte } else { 701fcf3ce44SJohn Forte HBASTATS.FcpError++; 702fcf3ce44SJohn Forte } 703fcf3ce44SJohn Forte 704fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 705fcf3ce44SJohn Forte 706fcf3ce44SJohn Forte emlxs_pkt_complete(sbp, iostat, localstat, 0); 707fcf3ce44SJohn Forte 708fcf3ce44SJohn Forte return; 709fcf3ce44SJohn Forte 71082527734SSukumar Swaminathan } /* emlxs_handle_fcp_event() */ 711fcf3ce44SJohn Forte 712fcf3ce44SJohn Forte 713fcf3ce44SJohn Forte /* 714fcf3ce44SJohn Forte * emlxs_post_buffer 715fcf3ce44SJohn Forte * 716fcf3ce44SJohn Forte * This routine will post count buffers to the 717fcf3ce44SJohn Forte * ring with the QUE_RING_BUF_CN command. This 718fcf3ce44SJohn Forte * allows 2 buffers / command to be posted. 719fcf3ce44SJohn Forte * Returns the number of buffers NOT posted. 720fcf3ce44SJohn Forte */ 72182527734SSukumar Swaminathan /* SLI3 */ 722fcf3ce44SJohn Forte extern int 723fcf3ce44SJohn Forte emlxs_post_buffer(emlxs_hba_t *hba, RING *rp, int16_t cnt) 724fcf3ce44SJohn Forte { 725fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 726fcf3ce44SJohn Forte IOCB *icmd; 727fcf3ce44SJohn Forte IOCBQ *iocbq; 728fcf3ce44SJohn Forte MATCHMAP *mp; 729fcf3ce44SJohn Forte uint16_t tag; 730fcf3ce44SJohn Forte uint32_t maxqbuf; 731fcf3ce44SJohn Forte int32_t i; 732fcf3ce44SJohn Forte int32_t j; 733fcf3ce44SJohn Forte uint32_t seg; 734fcf3ce44SJohn Forte uint32_t size; 735fcf3ce44SJohn Forte 736fcf3ce44SJohn Forte mp = 0; 737fcf3ce44SJohn Forte maxqbuf = 2; 738fcf3ce44SJohn Forte tag = (uint16_t)cnt; 739fcf3ce44SJohn Forte cnt += rp->fc_missbufcnt; 740fcf3ce44SJohn Forte 74182527734SSukumar Swaminathan if (rp->ringno == hba->channel_els) { 742fcf3ce44SJohn Forte seg = MEM_BUF; 743fcf3ce44SJohn Forte size = MEM_ELSBUF_SIZE; 74482527734SSukumar Swaminathan } else if (rp->ringno == hba->channel_ip) { 745fcf3ce44SJohn Forte seg = MEM_IPBUF; 746fcf3ce44SJohn Forte size = MEM_IPBUF_SIZE; 74782527734SSukumar Swaminathan } else if (rp->ringno == hba->channel_ct) { 748fcf3ce44SJohn Forte seg = MEM_CTBUF; 749fcf3ce44SJohn Forte size = MEM_CTBUF_SIZE; 750fcf3ce44SJohn Forte } 751fcf3ce44SJohn Forte #ifdef SFCT_SUPPORT 75282527734SSukumar Swaminathan else if (rp->ringno == hba->CHANNEL_FCT) { 753fcf3ce44SJohn Forte seg = MEM_FCTBUF; 754fcf3ce44SJohn Forte size = MEM_FCTBUF_SIZE; 755fcf3ce44SJohn Forte } 756291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 757fcf3ce44SJohn Forte else { 758fcf3ce44SJohn Forte return (0); 759fcf3ce44SJohn Forte } 760fcf3ce44SJohn Forte 761fcf3ce44SJohn Forte /* 762fcf3ce44SJohn Forte * While there are buffers to post 763fcf3ce44SJohn Forte */ 764fcf3ce44SJohn Forte while (cnt) { 765*8f23e9faSHans Rosenfeld if ((iocbq = (IOCBQ *)emlxs_mem_get(hba, MEM_IOCB)) == 0) { 766fcf3ce44SJohn Forte rp->fc_missbufcnt = cnt; 767fcf3ce44SJohn Forte return (cnt); 768fcf3ce44SJohn Forte } 769291a2b48SSukumar Swaminathan 77082527734SSukumar Swaminathan iocbq->channel = (void *)&hba->chan[rp->ringno]; 771fcf3ce44SJohn Forte iocbq->port = (void *)port; 772fcf3ce44SJohn Forte iocbq->flag |= (IOCB_PRIORITY | IOCB_SPECIAL); 773fcf3ce44SJohn Forte 774fcf3ce44SJohn Forte icmd = &iocbq->iocb; 775fcf3ce44SJohn Forte 776fcf3ce44SJohn Forte /* 777fcf3ce44SJohn Forte * Max buffers can be posted per command 778fcf3ce44SJohn Forte */ 779fcf3ce44SJohn Forte for (i = 0; i < maxqbuf; i++) { 780fcf3ce44SJohn Forte if (cnt <= 0) 781fcf3ce44SJohn Forte break; 782fcf3ce44SJohn Forte 783fcf3ce44SJohn Forte /* fill in BDEs for command */ 784*8f23e9faSHans Rosenfeld if ((mp = (MATCHMAP *)emlxs_mem_get(hba, seg)) 78582527734SSukumar Swaminathan == 0) { 78682527734SSukumar Swaminathan icmd->ULPBDECOUNT = i; 787fcf3ce44SJohn Forte for (j = 0; j < i; j++) { 788291a2b48SSukumar Swaminathan mp = EMLXS_GET_VADDR(hba, rp, icmd); 789fcf3ce44SJohn Forte if (mp) { 790a9800bebSGarrett D'Amore emlxs_mem_put(hba, seg, 791a9800bebSGarrett D'Amore (void *)mp); 792fcf3ce44SJohn Forte } 793fcf3ce44SJohn Forte } 794fcf3ce44SJohn Forte 795fcf3ce44SJohn Forte rp->fc_missbufcnt = cnt + i; 796fcf3ce44SJohn Forte 797a9800bebSGarrett D'Amore emlxs_mem_put(hba, MEM_IOCB, (void *)iocbq); 798fcf3ce44SJohn Forte 799fcf3ce44SJohn Forte return (cnt + i); 800fcf3ce44SJohn Forte } 801291a2b48SSukumar Swaminathan 802fcf3ce44SJohn Forte /* 803fcf3ce44SJohn Forte * map that page and save the address pair for lookup 804fcf3ce44SJohn Forte * later 805fcf3ce44SJohn Forte */ 806291a2b48SSukumar Swaminathan emlxs_mem_map_vaddr(hba, 807291a2b48SSukumar Swaminathan rp, 808291a2b48SSukumar Swaminathan mp, 809fcf3ce44SJohn Forte (uint32_t *)&icmd->un.cont64[i].addrHigh, 810fcf3ce44SJohn Forte (uint32_t *)&icmd->un.cont64[i].addrLow); 811fcf3ce44SJohn Forte 812fcf3ce44SJohn Forte icmd->un.cont64[i].tus.f.bdeSize = size; 81382527734SSukumar Swaminathan icmd->ULPCOMMAND = CMD_QUE_RING_BUF64_CN; 814fcf3ce44SJohn Forte 815291a2b48SSukumar Swaminathan /* 816291a2b48SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 817291a2b48SSukumar Swaminathan * "UB Post: ring=%d addr=%08x%08x size=%d", 818291a2b48SSukumar Swaminathan * rp->ringno, icmd->un.cont64[i].addrHigh, 819291a2b48SSukumar Swaminathan * icmd->un.cont64[i].addrLow, size); 820291a2b48SSukumar Swaminathan */ 821fcf3ce44SJohn Forte 822fcf3ce44SJohn Forte cnt--; 823fcf3ce44SJohn Forte } 824fcf3ce44SJohn Forte 82582527734SSukumar Swaminathan icmd->ULPIOTAG = tag; 82682527734SSukumar Swaminathan icmd->ULPBDECOUNT = i; 82782527734SSukumar Swaminathan icmd->ULPLE = 1; 82882527734SSukumar Swaminathan icmd->ULPOWNER = OWN_CHIP; 829291a2b48SSukumar Swaminathan /* used for delimiter between commands */ 830a9800bebSGarrett D'Amore iocbq->bp = (void *)mp; 831fcf3ce44SJohn Forte 83282527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, &hba->chan[rp->ringno], iocbq); 833fcf3ce44SJohn Forte } 834fcf3ce44SJohn Forte 835fcf3ce44SJohn Forte rp->fc_missbufcnt = 0; 836fcf3ce44SJohn Forte 837fcf3ce44SJohn Forte return (0); 838fcf3ce44SJohn Forte 83982527734SSukumar Swaminathan } /* emlxs_post_buffer() */ 840fcf3ce44SJohn Forte 841fcf3ce44SJohn Forte 842*8f23e9faSHans Rosenfeld static void 843*8f23e9faSHans Rosenfeld emlxs_fcp_tag_nodes(emlxs_port_t *port) 844*8f23e9faSHans Rosenfeld { 845*8f23e9faSHans Rosenfeld NODELIST *nlp; 846*8f23e9faSHans Rosenfeld int i; 847*8f23e9faSHans Rosenfeld 848*8f23e9faSHans Rosenfeld /* We will process all nodes with this tag later */ 849*8f23e9faSHans Rosenfeld rw_enter(&port->node_rwlock, RW_READER); 850*8f23e9faSHans Rosenfeld for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 851*8f23e9faSHans Rosenfeld nlp = port->node_table[i]; 852*8f23e9faSHans Rosenfeld while (nlp != NULL) { 853*8f23e9faSHans Rosenfeld nlp->nlp_tag = 1; 854*8f23e9faSHans Rosenfeld nlp = nlp->nlp_list_next; 855*8f23e9faSHans Rosenfeld } 856*8f23e9faSHans Rosenfeld } 857*8f23e9faSHans Rosenfeld rw_exit(&port->node_rwlock); 858*8f23e9faSHans Rosenfeld } 859*8f23e9faSHans Rosenfeld 860*8f23e9faSHans Rosenfeld 861*8f23e9faSHans Rosenfeld static NODELIST * 862*8f23e9faSHans Rosenfeld emlxs_find_tagged_node(emlxs_port_t *port) 863*8f23e9faSHans Rosenfeld { 864*8f23e9faSHans Rosenfeld NODELIST *nlp; 865*8f23e9faSHans Rosenfeld NODELIST *tagged; 866*8f23e9faSHans Rosenfeld int i; 867*8f23e9faSHans Rosenfeld 868*8f23e9faSHans Rosenfeld /* Find first node */ 869*8f23e9faSHans Rosenfeld rw_enter(&port->node_rwlock, RW_READER); 870*8f23e9faSHans Rosenfeld tagged = 0; 871*8f23e9faSHans Rosenfeld for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 872*8f23e9faSHans Rosenfeld nlp = port->node_table[i]; 873*8f23e9faSHans Rosenfeld while (nlp != NULL) { 874*8f23e9faSHans Rosenfeld if (!nlp->nlp_tag) { 875*8f23e9faSHans Rosenfeld nlp = nlp->nlp_list_next; 876*8f23e9faSHans Rosenfeld continue; 877*8f23e9faSHans Rosenfeld } 878*8f23e9faSHans Rosenfeld nlp->nlp_tag = 0; 879*8f23e9faSHans Rosenfeld 880*8f23e9faSHans Rosenfeld if (nlp->nlp_Rpi == FABRIC_RPI) { 881*8f23e9faSHans Rosenfeld nlp = nlp->nlp_list_next; 882*8f23e9faSHans Rosenfeld continue; 883*8f23e9faSHans Rosenfeld } 884*8f23e9faSHans Rosenfeld tagged = nlp; 885*8f23e9faSHans Rosenfeld break; 886*8f23e9faSHans Rosenfeld } 887*8f23e9faSHans Rosenfeld if (tagged) { 888*8f23e9faSHans Rosenfeld break; 889*8f23e9faSHans Rosenfeld } 890*8f23e9faSHans Rosenfeld } 891*8f23e9faSHans Rosenfeld rw_exit(&port->node_rwlock); 892*8f23e9faSHans Rosenfeld return (tagged); 893*8f23e9faSHans Rosenfeld } 894*8f23e9faSHans Rosenfeld 895*8f23e9faSHans Rosenfeld 896fcf3ce44SJohn Forte extern int 897fcf3ce44SJohn Forte emlxs_port_offline(emlxs_port_t *port, uint32_t scope) 898fcf3ce44SJohn Forte { 899fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 900fcf3ce44SJohn Forte emlxs_config_t *cfg; 901fcf3ce44SJohn Forte NODELIST *nlp; 902fcf3ce44SJohn Forte fc_affected_id_t *aid; 903fcf3ce44SJohn Forte uint32_t mask; 904fcf3ce44SJohn Forte uint32_t aff_d_id; 905fcf3ce44SJohn Forte uint32_t linkdown; 906fcf3ce44SJohn Forte uint32_t vlinkdown; 907fcf3ce44SJohn Forte uint32_t action; 908fcf3ce44SJohn Forte int i; 909fcf3ce44SJohn Forte uint32_t unreg_vpi; 910fcf3ce44SJohn Forte uint32_t update; 911fcf3ce44SJohn Forte uint32_t adisc_support; 912a9800bebSGarrett D'Amore uint32_t clear_all; 9133be114edSSukumar Swaminathan uint8_t format; 914fcf3ce44SJohn Forte 915fcf3ce44SJohn Forte /* Target mode only uses this routine for linkdowns */ 916*8f23e9faSHans Rosenfeld if ((port->mode == MODE_TARGET) && (scope != 0xffffffff) && 917*8f23e9faSHans Rosenfeld (scope != 0xfeffffff) && (scope != 0xfdffffff)) { 918fcf3ce44SJohn Forte return (0); 919fcf3ce44SJohn Forte } 920291a2b48SSukumar Swaminathan 921fcf3ce44SJohn Forte cfg = &CFG; 922fcf3ce44SJohn Forte aid = (fc_affected_id_t *)&scope; 923fcf3ce44SJohn Forte linkdown = 0; 924fcf3ce44SJohn Forte vlinkdown = 0; 925fcf3ce44SJohn Forte unreg_vpi = 0; 926fcf3ce44SJohn Forte update = 0; 927a9800bebSGarrett D'Amore clear_all = 0; 928fcf3ce44SJohn Forte 929fcf3ce44SJohn Forte if (!(port->flag & EMLXS_PORT_BOUND)) { 930fcf3ce44SJohn Forte return (0); 931fcf3ce44SJohn Forte } 932291a2b48SSukumar Swaminathan 9333be114edSSukumar Swaminathan format = aid->aff_format; 9343be114edSSukumar Swaminathan 9353be114edSSukumar Swaminathan switch (format) { 936fcf3ce44SJohn Forte case 0: /* Port */ 937fcf3ce44SJohn Forte mask = 0x00ffffff; 938fcf3ce44SJohn Forte break; 939fcf3ce44SJohn Forte 940fcf3ce44SJohn Forte case 1: /* Area */ 941fcf3ce44SJohn Forte mask = 0x00ffff00; 942fcf3ce44SJohn Forte break; 943fcf3ce44SJohn Forte 944fcf3ce44SJohn Forte case 2: /* Domain */ 945fcf3ce44SJohn Forte mask = 0x00ff0000; 946fcf3ce44SJohn Forte break; 947fcf3ce44SJohn Forte 948fcf3ce44SJohn Forte case 3: /* Network */ 949fcf3ce44SJohn Forte mask = 0x00000000; 950fcf3ce44SJohn Forte break; 951fcf3ce44SJohn Forte 952fcf3ce44SJohn Forte #ifdef DHCHAP_SUPPORT 953fcf3ce44SJohn Forte case 0xfe: /* Virtual link down */ 954fcf3ce44SJohn Forte mask = 0x00000000; 955fcf3ce44SJohn Forte vlinkdown = 1; 956fcf3ce44SJohn Forte break; 957291a2b48SSukumar Swaminathan #endif /* DHCHAP_SUPPORT */ 958fcf3ce44SJohn Forte 959fcf3ce44SJohn Forte case 0xff: /* link is down */ 960fcf3ce44SJohn Forte mask = 0x00000000; 961fcf3ce44SJohn Forte linkdown = 1; 962fcf3ce44SJohn Forte break; 963fcf3ce44SJohn Forte 964*8f23e9faSHans Rosenfeld case 0xfd: /* New fabric */ 965*8f23e9faSHans Rosenfeld default: 966*8f23e9faSHans Rosenfeld mask = 0x00000000; 967*8f23e9faSHans Rosenfeld linkdown = 1; 968*8f23e9faSHans Rosenfeld clear_all = 1; 969*8f23e9faSHans Rosenfeld break; 970fcf3ce44SJohn Forte } 971fcf3ce44SJohn Forte 972fcf3ce44SJohn Forte aff_d_id = aid->aff_d_id & mask; 973fcf3ce44SJohn Forte 974fcf3ce44SJohn Forte 975fcf3ce44SJohn Forte /* 976291a2b48SSukumar Swaminathan * If link is down then this is a hard shutdown and flush 977291a2b48SSukumar Swaminathan * If link not down then this is a soft shutdown and flush 978291a2b48SSukumar Swaminathan * (e.g. RSCN) 979fcf3ce44SJohn Forte */ 980fcf3ce44SJohn Forte if (linkdown) { 981fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 982fcf3ce44SJohn Forte 983fcf3ce44SJohn Forte port->flag &= EMLXS_PORT_LINKDOWN_MASK; 984fcf3ce44SJohn Forte 985fcf3ce44SJohn Forte if (port->ulp_statec != FC_STATE_OFFLINE) { 986fcf3ce44SJohn Forte port->ulp_statec = FC_STATE_OFFLINE; 987*8f23e9faSHans Rosenfeld 988a9800bebSGarrett D'Amore port->prev_did = port->did; 989*8f23e9faSHans Rosenfeld port->did = 0; 990*8f23e9faSHans Rosenfeld port->rdid = 0; 991*8f23e9faSHans Rosenfeld 992a9800bebSGarrett D'Amore bcopy(&port->fabric_sparam, &port->prev_fabric_sparam, 993a9800bebSGarrett D'Amore sizeof (SERV_PARM)); 994*8f23e9faSHans Rosenfeld bzero(&port->fabric_sparam, sizeof (SERV_PARM)); 995*8f23e9faSHans Rosenfeld 996fcf3ce44SJohn Forte update = 1; 997fcf3ce44SJohn Forte } 998291a2b48SSukumar Swaminathan 999fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1000fcf3ce44SJohn Forte 1001*8f23e9faSHans Rosenfeld emlxs_timer_cancel_clean_address(port); 1002*8f23e9faSHans Rosenfeld 1003fcf3ce44SJohn Forte /* Tell ULP about it */ 1004fcf3ce44SJohn Forte if (update) { 1005fcf3ce44SJohn Forte if (port->flag & EMLXS_PORT_BOUND) { 1006fcf3ce44SJohn Forte if (port->vpi == 0) { 1007fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 1008291a2b48SSukumar Swaminathan &emlxs_link_down_msg, NULL); 1009fcf3ce44SJohn Forte } 1010291a2b48SSukumar Swaminathan 1011*8f23e9faSHans Rosenfeld if (port->mode == MODE_INITIATOR) { 1012*8f23e9faSHans Rosenfeld emlxs_fca_link_down(port); 10133be114edSSukumar Swaminathan } 1014291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT 1015*8f23e9faSHans Rosenfeld else if (port->mode == MODE_TARGET) { 1016fcf3ce44SJohn Forte emlxs_fct_link_down(port); 10173be114edSSukumar Swaminathan } 1018291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 1019fcf3ce44SJohn Forte 1020fcf3ce44SJohn Forte } else { 1021fcf3ce44SJohn Forte if (port->vpi == 0) { 1022fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 1023291a2b48SSukumar Swaminathan &emlxs_link_down_msg, "*"); 1024fcf3ce44SJohn Forte } 1025fcf3ce44SJohn Forte } 1026fcf3ce44SJohn Forte 1027fcf3ce44SJohn Forte 1028fcf3ce44SJohn Forte } 1029291a2b48SSukumar Swaminathan 1030fcf3ce44SJohn Forte unreg_vpi = 1; 1031fcf3ce44SJohn Forte 1032fcf3ce44SJohn Forte #ifdef DHCHAP_SUPPORT 1033fcf3ce44SJohn Forte /* Stop authentication with all nodes */ 1034fcf3ce44SJohn Forte emlxs_dhc_auth_stop(port, NULL); 1035291a2b48SSukumar Swaminathan #endif /* DHCHAP_SUPPORT */ 1036fcf3ce44SJohn Forte 1037fcf3ce44SJohn Forte /* Flush the base node */ 1038fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, &port->node_base, 0, 0, 0); 1039fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 0, &port->node_base, 0); 1040fcf3ce44SJohn Forte 1041fcf3ce44SJohn Forte /* Flush any pending ub buffers */ 1042fcf3ce44SJohn Forte emlxs_ub_flush(port); 1043fcf3ce44SJohn Forte } 1044fcf3ce44SJohn Forte #ifdef DHCHAP_SUPPORT 1045fcf3ce44SJohn Forte /* virtual link down */ 1046fcf3ce44SJohn Forte else if (vlinkdown) { 1047fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 1048fcf3ce44SJohn Forte 1049fcf3ce44SJohn Forte if (port->ulp_statec != FC_STATE_OFFLINE) { 1050fcf3ce44SJohn Forte port->ulp_statec = FC_STATE_OFFLINE; 1051fcf3ce44SJohn Forte update = 1; 1052fcf3ce44SJohn Forte } 1053291a2b48SSukumar Swaminathan 1054fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1055fcf3ce44SJohn Forte 1056*8f23e9faSHans Rosenfeld emlxs_timer_cancel_clean_address(port); 1057*8f23e9faSHans Rosenfeld 1058fcf3ce44SJohn Forte /* Tell ULP about it */ 1059fcf3ce44SJohn Forte if (update) { 1060fcf3ce44SJohn Forte if (port->flag & EMLXS_PORT_BOUND) { 1061fcf3ce44SJohn Forte if (port->vpi == 0) { 1062fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 1063fcf3ce44SJohn Forte &emlxs_link_down_msg, 1064fcf3ce44SJohn Forte "Switch authentication failed."); 1065fcf3ce44SJohn Forte } 1066291a2b48SSukumar Swaminathan 1067*8f23e9faSHans Rosenfeld if (port->mode == MODE_INITIATOR) { 1068*8f23e9faSHans Rosenfeld emlxs_fca_link_down(port); 1069*8f23e9faSHans Rosenfeld } 1070fcf3ce44SJohn Forte #ifdef SFCT_SUPPORT 1071*8f23e9faSHans Rosenfeld else if (port->mode == MODE_TARGET) { 1072fcf3ce44SJohn Forte emlxs_fct_link_down(port); 1073fcf3ce44SJohn Forte } 1074*8f23e9faSHans Rosenfeld #endif /* SFCT_SUPPORT */ 1075fcf3ce44SJohn Forte } else { 1076fcf3ce44SJohn Forte if (port->vpi == 0) { 1077fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 1078fcf3ce44SJohn Forte &emlxs_link_down_msg, 1079fcf3ce44SJohn Forte "Switch authentication failed. *"); 1080fcf3ce44SJohn Forte } 1081fcf3ce44SJohn Forte } 1082fcf3ce44SJohn Forte 1083fcf3ce44SJohn Forte 1084fcf3ce44SJohn Forte } 1085291a2b48SSukumar Swaminathan 1086fcf3ce44SJohn Forte /* Flush the base node */ 1087fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, &port->node_base, 0, 0, 0); 1088fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 0, &port->node_base, 0); 1089fcf3ce44SJohn Forte } 1090291a2b48SSukumar Swaminathan #endif /* DHCHAP_SUPPORT */ 1091*8f23e9faSHans Rosenfeld else { 1092*8f23e9faSHans Rosenfeld emlxs_timer_cancel_clean_address(port); 1093*8f23e9faSHans Rosenfeld } 1094fcf3ce44SJohn Forte 1095*8f23e9faSHans Rosenfeld if (port->mode == MODE_TARGET) { 1096*8f23e9faSHans Rosenfeld if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 1097*8f23e9faSHans Rosenfeld /* Set the node tags */ 1098*8f23e9faSHans Rosenfeld emlxs_fcp_tag_nodes(port); 1099*8f23e9faSHans Rosenfeld unreg_vpi = 0; 1100*8f23e9faSHans Rosenfeld while ((nlp = emlxs_find_tagged_node(port))) { 1101*8f23e9faSHans Rosenfeld (void) emlxs_rpi_pause_notify(port, 1102*8f23e9faSHans Rosenfeld nlp->rpip); 1103*8f23e9faSHans Rosenfeld /* 1104*8f23e9faSHans Rosenfeld * In port_online we need to resume 1105*8f23e9faSHans Rosenfeld * these RPIs before we can use them. 1106*8f23e9faSHans Rosenfeld */ 1107*8f23e9faSHans Rosenfeld } 1108*8f23e9faSHans Rosenfeld } 1109fcf3ce44SJohn Forte goto done; 1110fcf3ce44SJohn Forte } 1111291a2b48SSukumar Swaminathan 1112fcf3ce44SJohn Forte /* Set the node tags */ 1113*8f23e9faSHans Rosenfeld emlxs_fcp_tag_nodes(port); 1114fcf3ce44SJohn Forte 1115a9800bebSGarrett D'Amore if (!clear_all && (hba->flag & FC_ONLINE_MODE)) { 1116fcf3ce44SJohn Forte adisc_support = cfg[CFG_ADISC_SUPPORT].current; 1117fcf3ce44SJohn Forte } else { 1118fcf3ce44SJohn Forte adisc_support = 0; 1119fcf3ce44SJohn Forte } 1120fcf3ce44SJohn Forte 1121fcf3ce44SJohn Forte /* Check ADISC support level */ 1122fcf3ce44SJohn Forte switch (adisc_support) { 1123fcf3ce44SJohn Forte case 0: /* No support - Flush all IO to all matching nodes */ 1124fcf3ce44SJohn Forte 1125291a2b48SSukumar Swaminathan for (;;) { 1126fcf3ce44SJohn Forte /* 1127fcf3ce44SJohn Forte * We need to hold the locks this way because 1128*8f23e9faSHans Rosenfeld * EMLXS_SLI_UNREG_NODE and the flush routines enter the 1129291a2b48SSukumar Swaminathan * same locks. Also, when we release the lock the list 1130291a2b48SSukumar Swaminathan * can change out from under us. 1131fcf3ce44SJohn Forte */ 1132fcf3ce44SJohn Forte 1133fcf3ce44SJohn Forte /* Find first node */ 1134fcf3ce44SJohn Forte rw_enter(&port->node_rwlock, RW_READER); 1135fcf3ce44SJohn Forte action = 0; 1136fcf3ce44SJohn Forte for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 1137fcf3ce44SJohn Forte nlp = port->node_table[i]; 1138fcf3ce44SJohn Forte while (nlp != NULL) { 1139fcf3ce44SJohn Forte if (!nlp->nlp_tag) { 1140fcf3ce44SJohn Forte nlp = nlp->nlp_list_next; 1141fcf3ce44SJohn Forte continue; 1142fcf3ce44SJohn Forte } 1143fcf3ce44SJohn Forte nlp->nlp_tag = 0; 1144fcf3ce44SJohn Forte 1145fcf3ce44SJohn Forte /* 1146fcf3ce44SJohn Forte * Check for any device that matches 1147fcf3ce44SJohn Forte * our mask 1148fcf3ce44SJohn Forte */ 1149fcf3ce44SJohn Forte if ((nlp->nlp_DID & mask) == aff_d_id) { 1150fcf3ce44SJohn Forte if (linkdown) { 1151fcf3ce44SJohn Forte action = 1; 1152fcf3ce44SJohn Forte break; 1153291a2b48SSukumar Swaminathan } else { /* Must be an RCSN */ 1154291a2b48SSukumar Swaminathan 1155fcf3ce44SJohn Forte action = 2; 1156fcf3ce44SJohn Forte break; 1157fcf3ce44SJohn Forte } 1158fcf3ce44SJohn Forte } 1159fcf3ce44SJohn Forte nlp = nlp->nlp_list_next; 1160fcf3ce44SJohn Forte } 1161fcf3ce44SJohn Forte 1162fcf3ce44SJohn Forte if (action) { 1163fcf3ce44SJohn Forte break; 1164fcf3ce44SJohn Forte } 1165fcf3ce44SJohn Forte } 1166fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 1167fcf3ce44SJohn Forte 1168fcf3ce44SJohn Forte 1169fcf3ce44SJohn Forte /* Check if nothing was found */ 1170fcf3ce44SJohn Forte if (action == 0) { 1171fcf3ce44SJohn Forte break; 1172fcf3ce44SJohn Forte } else if (action == 1) { 1173*8f23e9faSHans Rosenfeld (void) EMLXS_SLI_UNREG_NODE(port, nlp, 1174fcf3ce44SJohn Forte NULL, NULL, NULL); 1175fcf3ce44SJohn Forte } else if (action == 2) { 1176*8f23e9faSHans Rosenfeld EMLXS_SET_DFC_STATE(nlp, NODE_LIMBO); 1177*8f23e9faSHans Rosenfeld 1178fcf3ce44SJohn Forte #ifdef DHCHAP_SUPPORT 1179fcf3ce44SJohn Forte emlxs_dhc_auth_stop(port, nlp); 1180291a2b48SSukumar Swaminathan #endif /* DHCHAP_SUPPORT */ 1181fcf3ce44SJohn Forte 1182291a2b48SSukumar Swaminathan /* 1183291a2b48SSukumar Swaminathan * Close the node for any further normal IO 1184291a2b48SSukumar Swaminathan * A PLOGI with reopen the node 1185291a2b48SSukumar Swaminathan */ 118682527734SSukumar Swaminathan emlxs_node_close(port, nlp, 118782527734SSukumar Swaminathan hba->channel_fcp, 60); 118882527734SSukumar Swaminathan emlxs_node_close(port, nlp, 118982527734SSukumar Swaminathan hba->channel_ip, 60); 1190fcf3ce44SJohn Forte 1191fcf3ce44SJohn Forte /* Flush tx queue */ 1192fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, nlp, 0, 0, 0); 1193fcf3ce44SJohn Forte 1194fcf3ce44SJohn Forte /* Flush chip queue */ 1195fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 0, nlp, 0); 1196fcf3ce44SJohn Forte } 1197291a2b48SSukumar Swaminathan 1198fcf3ce44SJohn Forte } 1199fcf3ce44SJohn Forte 1200fcf3ce44SJohn Forte break; 1201fcf3ce44SJohn Forte 1202291a2b48SSukumar Swaminathan case 1: /* Partial support - Flush IO for non-FCP2 matching nodes */ 1203fcf3ce44SJohn Forte 1204fcf3ce44SJohn Forte for (;;) { 1205fcf3ce44SJohn Forte 1206fcf3ce44SJohn Forte /* 1207fcf3ce44SJohn Forte * We need to hold the locks this way because 1208*8f23e9faSHans Rosenfeld * EMLXS_SLI_UNREG_NODE and the flush routines enter the 1209291a2b48SSukumar Swaminathan * same locks. Also, when we release the lock the list 1210291a2b48SSukumar Swaminathan * can change out from under us. 1211fcf3ce44SJohn Forte */ 1212fcf3ce44SJohn Forte rw_enter(&port->node_rwlock, RW_READER); 1213fcf3ce44SJohn Forte action = 0; 1214fcf3ce44SJohn Forte for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 1215fcf3ce44SJohn Forte nlp = port->node_table[i]; 1216fcf3ce44SJohn Forte while (nlp != NULL) { 1217fcf3ce44SJohn Forte if (!nlp->nlp_tag) { 1218fcf3ce44SJohn Forte nlp = nlp->nlp_list_next; 1219fcf3ce44SJohn Forte continue; 1220fcf3ce44SJohn Forte } 1221fcf3ce44SJohn Forte nlp->nlp_tag = 0; 1222fcf3ce44SJohn Forte 1223fcf3ce44SJohn Forte /* 1224291a2b48SSukumar Swaminathan * Check for special FCP2 target device 1225291a2b48SSukumar Swaminathan * that matches our mask 1226fcf3ce44SJohn Forte */ 1227fcf3ce44SJohn Forte if ((nlp->nlp_fcp_info & 1228fcf3ce44SJohn Forte NLP_FCP_TGT_DEVICE) && 1229291a2b48SSukumar Swaminathan (nlp-> nlp_fcp_info & 1230fcf3ce44SJohn Forte NLP_FCP_2_DEVICE) && 1231291a2b48SSukumar Swaminathan (nlp->nlp_DID & mask) == 1232291a2b48SSukumar Swaminathan aff_d_id) { 1233fcf3ce44SJohn Forte action = 3; 1234fcf3ce44SJohn Forte break; 1235fcf3ce44SJohn Forte } 1236291a2b48SSukumar Swaminathan 1237fcf3ce44SJohn Forte /* 1238fcf3ce44SJohn Forte * Check for any other device that 1239fcf3ce44SJohn Forte * matches our mask 1240fcf3ce44SJohn Forte */ 1241fcf3ce44SJohn Forte else if ((nlp->nlp_DID & mask) == 1242fcf3ce44SJohn Forte aff_d_id) { 1243fcf3ce44SJohn Forte if (linkdown) { 1244fcf3ce44SJohn Forte action = 1; 1245fcf3ce44SJohn Forte break; 1246291a2b48SSukumar Swaminathan } else { /* Must be an RSCN */ 1247291a2b48SSukumar Swaminathan 1248fcf3ce44SJohn Forte action = 2; 1249fcf3ce44SJohn Forte break; 1250fcf3ce44SJohn Forte } 1251fcf3ce44SJohn Forte } 1252291a2b48SSukumar Swaminathan 1253fcf3ce44SJohn Forte nlp = nlp->nlp_list_next; 1254fcf3ce44SJohn Forte } 1255fcf3ce44SJohn Forte 1256fcf3ce44SJohn Forte if (action) { 1257fcf3ce44SJohn Forte break; 1258fcf3ce44SJohn Forte } 1259fcf3ce44SJohn Forte } 1260fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 1261fcf3ce44SJohn Forte 1262fcf3ce44SJohn Forte /* Check if nothing was found */ 1263fcf3ce44SJohn Forte if (action == 0) { 1264fcf3ce44SJohn Forte break; 1265fcf3ce44SJohn Forte } else if (action == 1) { 1266*8f23e9faSHans Rosenfeld (void) EMLXS_SLI_UNREG_NODE(port, nlp, 1267fcf3ce44SJohn Forte NULL, NULL, NULL); 1268fcf3ce44SJohn Forte } else if (action == 2) { 1269*8f23e9faSHans Rosenfeld EMLXS_SET_DFC_STATE(nlp, NODE_LIMBO); 1270*8f23e9faSHans Rosenfeld 1271fcf3ce44SJohn Forte #ifdef DHCHAP_SUPPORT 1272fcf3ce44SJohn Forte emlxs_dhc_auth_stop(port, nlp); 1273291a2b48SSukumar Swaminathan #endif /* DHCHAP_SUPPORT */ 1274fcf3ce44SJohn Forte 1275291a2b48SSukumar Swaminathan /* 1276291a2b48SSukumar Swaminathan * Close the node for any further normal IO 1277291a2b48SSukumar Swaminathan * A PLOGI with reopen the node 1278291a2b48SSukumar Swaminathan */ 127982527734SSukumar Swaminathan emlxs_node_close(port, nlp, 128082527734SSukumar Swaminathan hba->channel_fcp, 60); 128182527734SSukumar Swaminathan emlxs_node_close(port, nlp, 128282527734SSukumar Swaminathan hba->channel_ip, 60); 1283fcf3ce44SJohn Forte 1284fcf3ce44SJohn Forte /* Flush tx queue */ 1285fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, nlp, 0, 0, 0); 1286fcf3ce44SJohn Forte 1287fcf3ce44SJohn Forte /* Flush chip queue */ 1288fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 0, nlp, 0); 1289291a2b48SSukumar Swaminathan 1290fcf3ce44SJohn Forte } else if (action == 3) { /* FCP2 devices */ 1291*8f23e9faSHans Rosenfeld EMLXS_SET_DFC_STATE(nlp, NODE_LIMBO); 1292*8f23e9faSHans Rosenfeld 1293fcf3ce44SJohn Forte unreg_vpi = 0; 1294fcf3ce44SJohn Forte 1295a9800bebSGarrett D'Amore if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 1296a9800bebSGarrett D'Amore (void) emlxs_rpi_pause_notify(port, 1297a9800bebSGarrett D'Amore nlp->rpip); 1298a9800bebSGarrett D'Amore } 1299a9800bebSGarrett D'Amore 1300fcf3ce44SJohn Forte #ifdef DHCHAP_SUPPORT 1301fcf3ce44SJohn Forte emlxs_dhc_auth_stop(port, nlp); 1302291a2b48SSukumar Swaminathan #endif /* DHCHAP_SUPPORT */ 1303fcf3ce44SJohn Forte 1304291a2b48SSukumar Swaminathan /* 1305291a2b48SSukumar Swaminathan * Close the node for any further normal IO 1306291a2b48SSukumar Swaminathan * An ADISC or a PLOGI with reopen the node 1307291a2b48SSukumar Swaminathan */ 130882527734SSukumar Swaminathan emlxs_node_close(port, nlp, 130982527734SSukumar Swaminathan hba->channel_fcp, -1); 131082527734SSukumar Swaminathan emlxs_node_close(port, nlp, hba->channel_ip, 1311fcf3ce44SJohn Forte ((linkdown) ? 0 : 60)); 1312fcf3ce44SJohn Forte 1313fcf3ce44SJohn Forte /* Flush tx queues except for FCP ring */ 1314fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, nlp, 131582527734SSukumar Swaminathan &hba->chan[hba->channel_ct], 0, 0); 1316fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, nlp, 131782527734SSukumar Swaminathan &hba->chan[hba->channel_els], 0, 0); 1318fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, nlp, 131982527734SSukumar Swaminathan &hba->chan[hba->channel_ip], 0, 0); 1320fcf3ce44SJohn Forte 1321fcf3ce44SJohn Forte /* Flush chip queues except for FCP ring */ 1322fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 132382527734SSukumar Swaminathan &hba->chan[hba->channel_ct], nlp, 0); 1324fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 132582527734SSukumar Swaminathan &hba->chan[hba->channel_els], nlp, 0); 1326fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 132782527734SSukumar Swaminathan &hba->chan[hba->channel_ip], nlp, 0); 1328fcf3ce44SJohn Forte } 1329fcf3ce44SJohn Forte } 1330fcf3ce44SJohn Forte break; 1331fcf3ce44SJohn Forte 1332fcf3ce44SJohn Forte case 2: /* Full support - Hold FCP IO to FCP target matching nodes */ 1333fcf3ce44SJohn Forte 1334fcf3ce44SJohn Forte if (!linkdown && !vlinkdown) { 1335fcf3ce44SJohn Forte break; 1336fcf3ce44SJohn Forte } 1337291a2b48SSukumar Swaminathan 1338fcf3ce44SJohn Forte for (;;) { 1339fcf3ce44SJohn Forte /* 1340fcf3ce44SJohn Forte * We need to hold the locks this way because 1341*8f23e9faSHans Rosenfeld * EMLXS_SLI_UNREG_NODE and the flush routines enter the 1342291a2b48SSukumar Swaminathan * same locks. Also, when we release the lock the list 1343291a2b48SSukumar Swaminathan * can change out from under us. 1344fcf3ce44SJohn Forte */ 1345fcf3ce44SJohn Forte rw_enter(&port->node_rwlock, RW_READER); 1346fcf3ce44SJohn Forte action = 0; 1347fcf3ce44SJohn Forte for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 1348fcf3ce44SJohn Forte nlp = port->node_table[i]; 1349fcf3ce44SJohn Forte while (nlp != NULL) { 1350fcf3ce44SJohn Forte if (!nlp->nlp_tag) { 1351fcf3ce44SJohn Forte nlp = nlp->nlp_list_next; 1352fcf3ce44SJohn Forte continue; 1353fcf3ce44SJohn Forte } 1354fcf3ce44SJohn Forte nlp->nlp_tag = 0; 1355fcf3ce44SJohn Forte 1356fcf3ce44SJohn Forte /* 1357fcf3ce44SJohn Forte * Check for FCP target device that 1358fcf3ce44SJohn Forte * matches our mask 1359fcf3ce44SJohn Forte */ 1360291a2b48SSukumar Swaminathan if ((nlp-> nlp_fcp_info & 1361fcf3ce44SJohn Forte NLP_FCP_TGT_DEVICE) && 1362291a2b48SSukumar Swaminathan (nlp->nlp_DID & mask) == 1363291a2b48SSukumar Swaminathan aff_d_id) { 1364fcf3ce44SJohn Forte action = 3; 1365fcf3ce44SJohn Forte break; 1366fcf3ce44SJohn Forte } 1367291a2b48SSukumar Swaminathan 1368fcf3ce44SJohn Forte /* 1369fcf3ce44SJohn Forte * Check for any other device that 1370fcf3ce44SJohn Forte * matches our mask 1371fcf3ce44SJohn Forte */ 1372fcf3ce44SJohn Forte else if ((nlp->nlp_DID & mask) == 1373fcf3ce44SJohn Forte aff_d_id) { 1374fcf3ce44SJohn Forte if (linkdown) { 1375fcf3ce44SJohn Forte action = 1; 1376fcf3ce44SJohn Forte break; 1377fcf3ce44SJohn Forte } else { /* Must be an RSCN */ 1378291a2b48SSukumar Swaminathan 1379fcf3ce44SJohn Forte action = 2; 1380fcf3ce44SJohn Forte break; 1381fcf3ce44SJohn Forte } 1382fcf3ce44SJohn Forte } 1383291a2b48SSukumar Swaminathan 1384fcf3ce44SJohn Forte nlp = nlp->nlp_list_next; 1385fcf3ce44SJohn Forte } 1386fcf3ce44SJohn Forte if (action) { 1387fcf3ce44SJohn Forte break; 1388fcf3ce44SJohn Forte } 1389fcf3ce44SJohn Forte } 1390fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 1391fcf3ce44SJohn Forte 1392fcf3ce44SJohn Forte /* Check if nothing was found */ 1393fcf3ce44SJohn Forte if (action == 0) { 1394fcf3ce44SJohn Forte break; 1395fcf3ce44SJohn Forte } else if (action == 1) { 1396*8f23e9faSHans Rosenfeld (void) EMLXS_SLI_UNREG_NODE(port, nlp, 1397fcf3ce44SJohn Forte NULL, NULL, NULL); 1398fcf3ce44SJohn Forte } else if (action == 2) { 1399*8f23e9faSHans Rosenfeld EMLXS_SET_DFC_STATE(nlp, NODE_LIMBO); 1400*8f23e9faSHans Rosenfeld 1401291a2b48SSukumar Swaminathan /* 1402291a2b48SSukumar Swaminathan * Close the node for any further normal IO 1403291a2b48SSukumar Swaminathan * A PLOGI with reopen the node 1404291a2b48SSukumar Swaminathan */ 140582527734SSukumar Swaminathan emlxs_node_close(port, nlp, 140682527734SSukumar Swaminathan hba->channel_fcp, 60); 140782527734SSukumar Swaminathan emlxs_node_close(port, nlp, 140882527734SSukumar Swaminathan hba->channel_ip, 60); 1409fcf3ce44SJohn Forte 1410fcf3ce44SJohn Forte /* Flush tx queue */ 1411fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, nlp, 0, 0, 0); 1412fcf3ce44SJohn Forte 1413fcf3ce44SJohn Forte /* Flush chip queue */ 1414fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 0, nlp, 0); 1415fcf3ce44SJohn Forte 1416fcf3ce44SJohn Forte } else if (action == 3) { /* FCP2 devices */ 1417*8f23e9faSHans Rosenfeld EMLXS_SET_DFC_STATE(nlp, NODE_LIMBO); 1418*8f23e9faSHans Rosenfeld 1419fcf3ce44SJohn Forte unreg_vpi = 0; 1420fcf3ce44SJohn Forte 1421a9800bebSGarrett D'Amore if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 1422a9800bebSGarrett D'Amore (void) emlxs_rpi_pause_notify(port, 1423a9800bebSGarrett D'Amore nlp->rpip); 1424a9800bebSGarrett D'Amore } 1425a9800bebSGarrett D'Amore 1426291a2b48SSukumar Swaminathan /* 1427291a2b48SSukumar Swaminathan * Close the node for any further normal IO 1428291a2b48SSukumar Swaminathan * An ADISC or a PLOGI with reopen the node 1429291a2b48SSukumar Swaminathan */ 143082527734SSukumar Swaminathan emlxs_node_close(port, nlp, 143182527734SSukumar Swaminathan hba->channel_fcp, -1); 143282527734SSukumar Swaminathan emlxs_node_close(port, nlp, hba->channel_ip, 1433fcf3ce44SJohn Forte ((linkdown) ? 0 : 60)); 1434fcf3ce44SJohn Forte 1435fcf3ce44SJohn Forte /* Flush tx queues except for FCP ring */ 1436fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, nlp, 143782527734SSukumar Swaminathan &hba->chan[hba->channel_ct], 0, 0); 1438fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, nlp, 143982527734SSukumar Swaminathan &hba->chan[hba->channel_els], 0, 0); 1440fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, nlp, 144182527734SSukumar Swaminathan &hba->chan[hba->channel_ip], 0, 0); 1442fcf3ce44SJohn Forte 1443fcf3ce44SJohn Forte /* Flush chip queues except for FCP ring */ 1444fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 144582527734SSukumar Swaminathan &hba->chan[hba->channel_ct], nlp, 0); 1446fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 144782527734SSukumar Swaminathan &hba->chan[hba->channel_els], nlp, 0); 1448fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 144982527734SSukumar Swaminathan &hba->chan[hba->channel_ip], nlp, 0); 1450fcf3ce44SJohn Forte } 1451fcf3ce44SJohn Forte } 1452fcf3ce44SJohn Forte 1453fcf3ce44SJohn Forte break; 1454fcf3ce44SJohn Forte 1455fcf3ce44SJohn Forte } /* switch() */ 1456fcf3ce44SJohn Forte 1457fcf3ce44SJohn Forte done: 1458fcf3ce44SJohn Forte 1459a9800bebSGarrett D'Amore if (unreg_vpi) { 1460a9800bebSGarrett D'Amore (void) emlxs_mb_unreg_vpi(port); 1461fcf3ce44SJohn Forte } 1462fcf3ce44SJohn Forte 1463291a2b48SSukumar Swaminathan return (0); 1464fcf3ce44SJohn Forte 146582527734SSukumar Swaminathan } /* emlxs_port_offline() */ 1466fcf3ce44SJohn Forte 1467fcf3ce44SJohn Forte 1468fcf3ce44SJohn Forte extern void 1469fcf3ce44SJohn Forte emlxs_port_online(emlxs_port_t *vport) 1470fcf3ce44SJohn Forte { 1471fcf3ce44SJohn Forte emlxs_hba_t *hba = vport->hba; 1472fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 1473*8f23e9faSHans Rosenfeld NODELIST *nlp; 1474fcf3ce44SJohn Forte uint32_t state; 1475fcf3ce44SJohn Forte uint32_t update; 1476fcf3ce44SJohn Forte uint32_t npiv_linkup; 1477fcf3ce44SJohn Forte char topology[32]; 1478fcf3ce44SJohn Forte char linkspeed[32]; 1479fcf3ce44SJohn Forte char mode[32]; 1480fcf3ce44SJohn Forte 1481fcf3ce44SJohn Forte /* 1482291a2b48SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_up_msg, 1483291a2b48SSukumar Swaminathan * "linkup_callback. vpi=%d fc_flag=%x", vport->vpi, hba->flag); 1484fcf3ce44SJohn Forte */ 1485fcf3ce44SJohn Forte 1486fcf3ce44SJohn Forte if ((vport->vpi > 0) && 1487fcf3ce44SJohn Forte (!(hba->flag & FC_NPIV_ENABLED) || 1488fcf3ce44SJohn Forte !(hba->flag & FC_NPIV_SUPPORTED))) { 1489fcf3ce44SJohn Forte return; 1490fcf3ce44SJohn Forte } 1491291a2b48SSukumar Swaminathan 1492fcf3ce44SJohn Forte if (!(vport->flag & EMLXS_PORT_BOUND) || 1493*8f23e9faSHans Rosenfeld !(vport->flag & EMLXS_PORT_ENABLED)) { 1494fcf3ce44SJohn Forte return; 1495fcf3ce44SJohn Forte } 1496291a2b48SSukumar Swaminathan 1497fcf3ce44SJohn Forte /* Check for mode */ 1498*8f23e9faSHans Rosenfeld if (port->mode == MODE_TARGET) { 1499*8f23e9faSHans Rosenfeld (void) strlcpy(mode, ", target", sizeof (mode)); 1500*8f23e9faSHans Rosenfeld 1501*8f23e9faSHans Rosenfeld if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 1502*8f23e9faSHans Rosenfeld /* Set the node tags */ 1503*8f23e9faSHans Rosenfeld emlxs_fcp_tag_nodes(vport); 1504*8f23e9faSHans Rosenfeld while ((nlp = emlxs_find_tagged_node(vport))) { 1505*8f23e9faSHans Rosenfeld /* The RPI was paused in port_offline */ 1506*8f23e9faSHans Rosenfeld (void) emlxs_rpi_resume_notify(vport, 1507*8f23e9faSHans Rosenfeld nlp->rpip, 0); 1508*8f23e9faSHans Rosenfeld } 1509*8f23e9faSHans Rosenfeld } 1510*8f23e9faSHans Rosenfeld } else if (port->mode == MODE_INITIATOR) { 1511*8f23e9faSHans Rosenfeld (void) strlcpy(mode, ", initiator", sizeof (mode)); 1512fcf3ce44SJohn Forte } else { 1513*8f23e9faSHans Rosenfeld (void) strlcpy(mode, "unknown", sizeof (mode)); 1514fcf3ce44SJohn Forte } 1515*8f23e9faSHans Rosenfeld mutex_enter(&EMLXS_PORT_LOCK); 1516fcf3ce44SJohn Forte 1517fcf3ce44SJohn Forte /* Check for loop topology */ 1518fcf3ce44SJohn Forte if (hba->topology == TOPOLOGY_LOOP) { 1519fcf3ce44SJohn Forte state = FC_STATE_LOOP; 1520*8f23e9faSHans Rosenfeld (void) strlcpy(topology, ", loop", sizeof (topology)); 1521fcf3ce44SJohn Forte } else { 1522fcf3ce44SJohn Forte state = FC_STATE_ONLINE; 1523*8f23e9faSHans Rosenfeld (void) strlcpy(topology, ", fabric", sizeof (topology)); 1524fcf3ce44SJohn Forte } 1525fcf3ce44SJohn Forte 1526fcf3ce44SJohn Forte /* Set the link speed */ 1527fcf3ce44SJohn Forte switch (hba->linkspeed) { 1528fcf3ce44SJohn Forte case 0: 1529*8f23e9faSHans Rosenfeld (void) strlcpy(linkspeed, "Gb", sizeof (linkspeed)); 1530fcf3ce44SJohn Forte state |= FC_STATE_1GBIT_SPEED; 1531fcf3ce44SJohn Forte break; 1532fcf3ce44SJohn Forte 1533fcf3ce44SJohn Forte case LA_1GHZ_LINK: 1534*8f23e9faSHans Rosenfeld (void) strlcpy(linkspeed, "1Gb", sizeof (linkspeed)); 1535fcf3ce44SJohn Forte state |= FC_STATE_1GBIT_SPEED; 1536fcf3ce44SJohn Forte break; 1537fcf3ce44SJohn Forte case LA_2GHZ_LINK: 1538*8f23e9faSHans Rosenfeld (void) strlcpy(linkspeed, "2Gb", sizeof (linkspeed)); 1539fcf3ce44SJohn Forte state |= FC_STATE_2GBIT_SPEED; 1540fcf3ce44SJohn Forte break; 1541fcf3ce44SJohn Forte case LA_4GHZ_LINK: 1542*8f23e9faSHans Rosenfeld (void) strlcpy(linkspeed, "4Gb", sizeof (linkspeed)); 1543fcf3ce44SJohn Forte state |= FC_STATE_4GBIT_SPEED; 1544fcf3ce44SJohn Forte break; 1545fcf3ce44SJohn Forte case LA_8GHZ_LINK: 1546*8f23e9faSHans Rosenfeld (void) strlcpy(linkspeed, "8Gb", sizeof (linkspeed)); 1547fcf3ce44SJohn Forte state |= FC_STATE_8GBIT_SPEED; 1548fcf3ce44SJohn Forte break; 1549fcf3ce44SJohn Forte case LA_10GHZ_LINK: 1550*8f23e9faSHans Rosenfeld (void) strlcpy(linkspeed, "10Gb", sizeof (linkspeed)); 1551fcf3ce44SJohn Forte state |= FC_STATE_10GBIT_SPEED; 1552fcf3ce44SJohn Forte break; 1553*8f23e9faSHans Rosenfeld case LA_16GHZ_LINK: 1554*8f23e9faSHans Rosenfeld (void) strlcpy(linkspeed, "16Gb", sizeof (linkspeed)); 1555*8f23e9faSHans Rosenfeld state |= FC_STATE_16GBIT_SPEED; 1556*8f23e9faSHans Rosenfeld break; 1557fcf3ce44SJohn Forte default: 1558*8f23e9faSHans Rosenfeld (void) snprintf(linkspeed, sizeof (linkspeed), "unknown(0x%x)", 1559*8f23e9faSHans Rosenfeld hba->linkspeed); 1560fcf3ce44SJohn Forte break; 1561fcf3ce44SJohn Forte } 1562fcf3ce44SJohn Forte 1563fcf3ce44SJohn Forte npiv_linkup = 0; 1564fcf3ce44SJohn Forte update = 0; 1565fcf3ce44SJohn Forte 1566fcf3ce44SJohn Forte if ((hba->state >= FC_LINK_UP) && 1567291a2b48SSukumar Swaminathan !(hba->flag & FC_LOOPBACK_MODE) && (vport->ulp_statec != state)) { 1568fcf3ce44SJohn Forte update = 1; 1569fcf3ce44SJohn Forte vport->ulp_statec = state; 1570fcf3ce44SJohn Forte 1571fcf3ce44SJohn Forte if ((vport->vpi > 0) && !(hba->flag & FC_NPIV_LINKUP)) { 1572fcf3ce44SJohn Forte hba->flag |= FC_NPIV_LINKUP; 1573fcf3ce44SJohn Forte npiv_linkup = 1; 1574fcf3ce44SJohn Forte } 1575fcf3ce44SJohn Forte } 1576291a2b48SSukumar Swaminathan 1577fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1578fcf3ce44SJohn Forte 1579fcf3ce44SJohn Forte if (update) { 1580fcf3ce44SJohn Forte if (vport->flag & EMLXS_PORT_BOUND) { 1581fcf3ce44SJohn Forte if (vport->vpi == 0) { 1582fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_up_msg, 1583291a2b48SSukumar Swaminathan "%s%s%s", linkspeed, topology, mode); 15846a573d82SSukumar Swaminathan 1585fcf3ce44SJohn Forte } else if (npiv_linkup) { 1586fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 1587291a2b48SSukumar Swaminathan &emlxs_npiv_link_up_msg, "%s%s%s", 1588fcf3ce44SJohn Forte linkspeed, topology, mode); 1589fcf3ce44SJohn Forte } 1590291a2b48SSukumar Swaminathan 1591*8f23e9faSHans Rosenfeld if (vport->mode == MODE_INITIATOR) { 1592*8f23e9faSHans Rosenfeld emlxs_fca_link_up(vport); 1593fcf3ce44SJohn Forte } 15943be114edSSukumar Swaminathan #ifdef SFCT_SUPPORT 1595*8f23e9faSHans Rosenfeld else if (vport->mode == MODE_TARGET) { 15963be114edSSukumar Swaminathan emlxs_fct_link_up(vport); 15973be114edSSukumar Swaminathan } 15983be114edSSukumar Swaminathan #endif /* SFCT_SUPPORT */ 1599fcf3ce44SJohn Forte } else { 1600fcf3ce44SJohn Forte if (vport->vpi == 0) { 1601fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_up_msg, 1602291a2b48SSukumar Swaminathan "%s%s%s *", linkspeed, topology, mode); 16036a573d82SSukumar Swaminathan 1604fcf3ce44SJohn Forte } else if (npiv_linkup) { 1605fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 1606291a2b48SSukumar Swaminathan &emlxs_npiv_link_up_msg, "%s%s%s *", 1607fcf3ce44SJohn Forte linkspeed, topology, mode); 1608fcf3ce44SJohn Forte } 1609fcf3ce44SJohn Forte } 1610fcf3ce44SJohn Forte 1611fcf3ce44SJohn Forte /* Check for waiting threads */ 1612fcf3ce44SJohn Forte if (vport->vpi == 0) { 1613fcf3ce44SJohn Forte mutex_enter(&EMLXS_LINKUP_LOCK); 1614fcf3ce44SJohn Forte if (hba->linkup_wait_flag == TRUE) { 1615fcf3ce44SJohn Forte hba->linkup_wait_flag = FALSE; 1616fcf3ce44SJohn Forte cv_broadcast(&EMLXS_LINKUP_CV); 1617fcf3ce44SJohn Forte } 1618fcf3ce44SJohn Forte mutex_exit(&EMLXS_LINKUP_LOCK); 1619fcf3ce44SJohn Forte } 1620291a2b48SSukumar Swaminathan 1621fcf3ce44SJohn Forte /* Flush any pending ub buffers */ 1622fcf3ce44SJohn Forte emlxs_ub_flush(vport); 1623fcf3ce44SJohn Forte } 1624291a2b48SSukumar Swaminathan 1625fcf3ce44SJohn Forte return; 1626fcf3ce44SJohn Forte 162782527734SSukumar Swaminathan } /* emlxs_port_online() */ 1628fcf3ce44SJohn Forte 1629fcf3ce44SJohn Forte 1630a9800bebSGarrett D'Amore /* SLI3 */ 1631fcf3ce44SJohn Forte extern void 1632fcf3ce44SJohn Forte emlxs_linkdown(emlxs_hba_t *hba) 1633fcf3ce44SJohn Forte { 1634fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 1635fcf3ce44SJohn Forte int i; 1636a9800bebSGarrett D'Amore uint32_t scope; 1637fcf3ce44SJohn Forte 1638fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 1639fcf3ce44SJohn Forte 164082527734SSukumar Swaminathan if (hba->state > FC_LINK_DOWN) { 164182527734SSukumar Swaminathan HBASTATS.LinkDown++; 164282527734SSukumar Swaminathan EMLXS_STATE_CHANGE_LOCKED(hba, FC_LINK_DOWN); 164382527734SSukumar Swaminathan } 1644fcf3ce44SJohn Forte 1645a9800bebSGarrett D'Amore /* Set scope */ 1646a9800bebSGarrett D'Amore scope = (hba->flag & FC_NEW_FABRIC)? 0xFDFFFFFF:0xFFFFFFFF; 1647a9800bebSGarrett D'Amore 1648fcf3ce44SJohn Forte /* Filter hba flags */ 1649fcf3ce44SJohn Forte hba->flag &= FC_LINKDOWN_MASK; 1650fcf3ce44SJohn Forte hba->discovery_timer = 0; 1651fcf3ce44SJohn Forte hba->linkup_timer = 0; 1652fcf3ce44SJohn Forte 1653fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1654fcf3ce44SJohn Forte 1655fcf3ce44SJohn Forte for (i = 0; i < MAX_VPORTS; i++) { 1656fcf3ce44SJohn Forte port = &VPORT(i); 1657fcf3ce44SJohn Forte 1658fcf3ce44SJohn Forte if (!(port->flag & EMLXS_PORT_BOUND)) { 1659fcf3ce44SJohn Forte continue; 1660fcf3ce44SJohn Forte } 1661291a2b48SSukumar Swaminathan 1662a9800bebSGarrett D'Amore (void) emlxs_port_offline(port, scope); 1663fcf3ce44SJohn Forte 1664fcf3ce44SJohn Forte } 1665fcf3ce44SJohn Forte 1666a9800bebSGarrett D'Amore emlxs_log_link_event(port); 1667a9800bebSGarrett D'Amore 1668fcf3ce44SJohn Forte return; 1669fcf3ce44SJohn Forte 167082527734SSukumar Swaminathan } /* emlxs_linkdown() */ 1671fcf3ce44SJohn Forte 1672fcf3ce44SJohn Forte 1673a9800bebSGarrett D'Amore /* SLI3 */ 1674fcf3ce44SJohn Forte extern void 1675fcf3ce44SJohn Forte emlxs_linkup(emlxs_hba_t *hba) 1676fcf3ce44SJohn Forte { 1677fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 1678fcf3ce44SJohn Forte emlxs_config_t *cfg = &CFG; 1679fcf3ce44SJohn Forte 1680fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 1681fcf3ce44SJohn Forte 1682*8f23e9faSHans Rosenfeld /* Check for any mode changes */ 1683*8f23e9faSHans Rosenfeld emlxs_mode_set(hba); 1684*8f23e9faSHans Rosenfeld 1685fcf3ce44SJohn Forte HBASTATS.LinkUp++; 168682527734SSukumar Swaminathan EMLXS_STATE_CHANGE_LOCKED(hba, FC_LINK_UP); 1687fcf3ce44SJohn Forte 1688fcf3ce44SJohn Forte #ifdef MENLO_SUPPORT 1689fcf3ce44SJohn Forte if (hba->flag & FC_MENLO_MODE) { 1690fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1691fcf3ce44SJohn Forte 1692fcf3ce44SJohn Forte /* 1693fcf3ce44SJohn Forte * Trigger linkup CV and don't start linkup & discovery 1694fcf3ce44SJohn Forte * timers 1695fcf3ce44SJohn Forte */ 1696fcf3ce44SJohn Forte mutex_enter(&EMLXS_LINKUP_LOCK); 1697fcf3ce44SJohn Forte cv_broadcast(&EMLXS_LINKUP_CV); 1698fcf3ce44SJohn Forte mutex_exit(&EMLXS_LINKUP_LOCK); 1699fcf3ce44SJohn Forte 1700a9800bebSGarrett D'Amore emlxs_log_link_event(port); 1701a9800bebSGarrett D'Amore 1702fcf3ce44SJohn Forte return; 1703fcf3ce44SJohn Forte } 1704291a2b48SSukumar Swaminathan #endif /* MENLO_SUPPORT */ 1705fcf3ce44SJohn Forte 1706fcf3ce44SJohn Forte /* Set the linkup & discovery timers */ 1707fcf3ce44SJohn Forte hba->linkup_timer = hba->timer_tics + cfg[CFG_LINKUP_TIMEOUT].current; 1708291a2b48SSukumar Swaminathan hba->discovery_timer = 1709291a2b48SSukumar Swaminathan hba->timer_tics + cfg[CFG_LINKUP_TIMEOUT].current + 1710291a2b48SSukumar Swaminathan cfg[CFG_DISC_TIMEOUT].current; 1711fcf3ce44SJohn Forte 1712fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1713fcf3ce44SJohn Forte 1714a9800bebSGarrett D'Amore emlxs_log_link_event(port); 1715a9800bebSGarrett D'Amore 1716fcf3ce44SJohn Forte return; 1717fcf3ce44SJohn Forte 171882527734SSukumar Swaminathan } /* emlxs_linkup() */ 1719fcf3ce44SJohn Forte 1720fcf3ce44SJohn Forte 1721fcf3ce44SJohn Forte /* 1722fcf3ce44SJohn Forte * emlxs_reset_link 1723fcf3ce44SJohn Forte * 1724fcf3ce44SJohn Forte * Description: 1725fcf3ce44SJohn Forte * Called to reset the link with an init_link 1726fcf3ce44SJohn Forte * 1727fcf3ce44SJohn Forte * Returns: 1728fcf3ce44SJohn Forte * 1729fcf3ce44SJohn Forte */ 1730fcf3ce44SJohn Forte extern int 173182527734SSukumar Swaminathan emlxs_reset_link(emlxs_hba_t *hba, uint32_t linkup, uint32_t wait) 1732fcf3ce44SJohn Forte { 1733fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 1734fcf3ce44SJohn Forte emlxs_config_t *cfg; 173582527734SSukumar Swaminathan MAILBOXQ *mbq = NULL; 173682527734SSukumar Swaminathan MAILBOX *mb = NULL; 173782527734SSukumar Swaminathan int rval = 0; 1738*8f23e9faSHans Rosenfeld int tmo; 173982527734SSukumar Swaminathan int rc; 1740fcf3ce44SJohn Forte 1741fcf3ce44SJohn Forte /* 1742fcf3ce44SJohn Forte * Get a buffer to use for the mailbox command 1743fcf3ce44SJohn Forte */ 1744*8f23e9faSHans Rosenfeld if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX)) 174582527734SSukumar Swaminathan == NULL) { 1746fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_reset_failed_msg, 1747fcf3ce44SJohn Forte "Unable to allocate mailbox buffer."); 174882527734SSukumar Swaminathan rval = 1; 174982527734SSukumar Swaminathan goto reset_link_fail; 175082527734SSukumar Swaminathan } 1751fcf3ce44SJohn Forte 1752a9800bebSGarrett D'Amore if (linkup) { 1753a9800bebSGarrett D'Amore EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_reset_msg, 1754a9800bebSGarrett D'Amore "Resetting link..."); 1755a9800bebSGarrett D'Amore } else { 1756a9800bebSGarrett D'Amore EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_reset_msg, 1757a9800bebSGarrett D'Amore "Disabling link..."); 1758a9800bebSGarrett D'Amore } 1759a9800bebSGarrett D'Amore 176082527734SSukumar Swaminathan mb = (MAILBOX *)mbq; 176182527734SSukumar Swaminathan 176282527734SSukumar Swaminathan /* Bring link down first */ 176382527734SSukumar Swaminathan emlxs_mb_down_link(hba, mbq); 176482527734SSukumar Swaminathan 176582527734SSukumar Swaminathan #define MBXERR_LINK_DOWN 0x33 176682527734SSukumar Swaminathan 176782527734SSukumar Swaminathan if (wait) { 176882527734SSukumar Swaminathan wait = MBX_WAIT; 176982527734SSukumar Swaminathan } else { 177082527734SSukumar Swaminathan wait = MBX_NOWAIT; 177182527734SSukumar Swaminathan } 177282527734SSukumar Swaminathan rc = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, wait, 0); 177382527734SSukumar Swaminathan if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS) && 177482527734SSukumar Swaminathan (rc != MBXERR_LINK_DOWN)) { 177582527734SSukumar Swaminathan rval = 1; 177682527734SSukumar Swaminathan goto reset_link_fail; 1777fcf3ce44SJohn Forte } 1778291a2b48SSukumar Swaminathan 1779*8f23e9faSHans Rosenfeld tmo = 120; 1780*8f23e9faSHans Rosenfeld do { 1781*8f23e9faSHans Rosenfeld delay(drv_usectohz(500000)); 1782*8f23e9faSHans Rosenfeld tmo--; 1783*8f23e9faSHans Rosenfeld 1784*8f23e9faSHans Rosenfeld if (!tmo) { 1785*8f23e9faSHans Rosenfeld rval = 1; 1786*8f23e9faSHans Rosenfeld 1787*8f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_reset_msg, 1788*8f23e9faSHans Rosenfeld "Linkdown timeout."); 1789*8f23e9faSHans Rosenfeld 1790*8f23e9faSHans Rosenfeld goto reset_link_fail; 1791*8f23e9faSHans Rosenfeld } 1792*8f23e9faSHans Rosenfeld } while ((hba->state >= FC_LINK_UP) && (hba->state != FC_ERROR)); 1793*8f23e9faSHans Rosenfeld 1794fcf3ce44SJohn Forte if (linkup) { 1795fcf3ce44SJohn Forte /* 1796fcf3ce44SJohn Forte * Setup and issue mailbox INITIALIZE LINK command 1797fcf3ce44SJohn Forte */ 1798fcf3ce44SJohn Forte 179982527734SSukumar Swaminathan if (wait == MBX_NOWAIT) { 1800*8f23e9faSHans Rosenfeld if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX)) 180182527734SSukumar Swaminathan == NULL) { 180282527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 180382527734SSukumar Swaminathan &emlxs_link_reset_failed_msg, 180482527734SSukumar Swaminathan "Unable to allocate mailbox buffer."); 180582527734SSukumar Swaminathan rval = 1; 180682527734SSukumar Swaminathan goto reset_link_fail; 180782527734SSukumar Swaminathan } 180882527734SSukumar Swaminathan mb = (MAILBOX *)mbq; 180982527734SSukumar Swaminathan } else { 181082527734SSukumar Swaminathan /* Reuse mbq from previous mbox */ 181182527734SSukumar Swaminathan mb = (MAILBOX *)mbq; 181282527734SSukumar Swaminathan } 181382527734SSukumar Swaminathan cfg = &CFG; 181482527734SSukumar Swaminathan 181582527734SSukumar Swaminathan emlxs_mb_init_link(hba, mbq, 1816fcf3ce44SJohn Forte cfg[CFG_TOPOLOGY].current, cfg[CFG_LINK_SPEED].current); 1817fcf3ce44SJohn Forte 1818fcf3ce44SJohn Forte mb->un.varInitLnk.lipsr_AL_PA = 0; 1819fcf3ce44SJohn Forte 1820fcf3ce44SJohn Forte /* Clear the loopback mode */ 1821fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 1822fcf3ce44SJohn Forte hba->flag &= ~FC_LOOPBACK_MODE; 1823291a2b48SSukumar Swaminathan hba->loopback_tics = 0; 1824fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1825fcf3ce44SJohn Forte 182682527734SSukumar Swaminathan rc = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, wait, 0); 182782527734SSukumar Swaminathan if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { 182882527734SSukumar Swaminathan rval = 1; 182982527734SSukumar Swaminathan goto reset_link_fail; 1830fcf3ce44SJohn Forte } 1831291a2b48SSukumar Swaminathan 1832fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_reset_msg, NULL); 183382527734SSukumar Swaminathan } 1834fcf3ce44SJohn Forte 183582527734SSukumar Swaminathan reset_link_fail: 1836291a2b48SSukumar Swaminathan 183782527734SSukumar Swaminathan if ((wait == MBX_WAIT) && mbq) { 1838a9800bebSGarrett D'Amore emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 1839fcf3ce44SJohn Forte } 1840fcf3ce44SJohn Forte 184182527734SSukumar Swaminathan return (rval); 184282527734SSukumar Swaminathan } /* emlxs_reset_link() */ 1843fcf3ce44SJohn Forte 1844fcf3ce44SJohn Forte 1845fcf3ce44SJohn Forte extern int 1846fcf3ce44SJohn Forte emlxs_online(emlxs_hba_t *hba) 1847fcf3ce44SJohn Forte { 1848fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 1849fcf3ce44SJohn Forte int32_t rval = 0; 1850fcf3ce44SJohn Forte uint32_t i = 0; 1851fcf3ce44SJohn Forte 1852fcf3ce44SJohn Forte /* Make sure adapter is offline or exit trying (30 seconds) */ 1853291a2b48SSukumar Swaminathan while (i++ < 30) { 1854fcf3ce44SJohn Forte /* Check if adapter is already going online */ 1855fcf3ce44SJohn Forte if (hba->flag & (FC_ONLINE_MODE | FC_ONLINING_MODE)) { 1856fcf3ce44SJohn Forte return (0); 1857fcf3ce44SJohn Forte } 1858291a2b48SSukumar Swaminathan 1859fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 1860fcf3ce44SJohn Forte 1861fcf3ce44SJohn Forte /* Check again */ 1862fcf3ce44SJohn Forte if (hba->flag & (FC_ONLINE_MODE | FC_ONLINING_MODE)) { 1863fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1864fcf3ce44SJohn Forte return (0); 1865fcf3ce44SJohn Forte } 1866291a2b48SSukumar Swaminathan 1867fcf3ce44SJohn Forte /* Check if adapter is offline */ 1868fcf3ce44SJohn Forte if (hba->flag & FC_OFFLINE_MODE) { 1869fcf3ce44SJohn Forte /* Mark it going online */ 1870fcf3ce44SJohn Forte hba->flag &= ~FC_OFFLINE_MODE; 1871fcf3ce44SJohn Forte hba->flag |= FC_ONLINING_MODE; 1872fcf3ce44SJohn Forte 1873fcf3ce44SJohn Forte /* Currently !FC_ONLINE_MODE and !FC_OFFLINE_MODE */ 1874fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1875fcf3ce44SJohn Forte break; 1876fcf3ce44SJohn Forte } 1877291a2b48SSukumar Swaminathan 1878fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1879fcf3ce44SJohn Forte 1880*8f23e9faSHans Rosenfeld BUSYWAIT_MS(1000); 1881fcf3ce44SJohn Forte } 1882fcf3ce44SJohn Forte 1883fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg, 1884fcf3ce44SJohn Forte "Going online..."); 1885fcf3ce44SJohn Forte 188682527734SSukumar Swaminathan if (rval = EMLXS_SLI_ONLINE(hba)) { 1887291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, "status=%x", 1888fcf3ce44SJohn Forte rval); 1889fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_offline_msg, NULL); 1890fcf3ce44SJohn Forte 1891fcf3ce44SJohn Forte /* Set FC_OFFLINE_MODE */ 1892fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 1893fcf3ce44SJohn Forte hba->flag |= FC_OFFLINE_MODE; 1894fcf3ce44SJohn Forte hba->flag &= ~FC_ONLINING_MODE; 1895fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1896fcf3ce44SJohn Forte 1897fcf3ce44SJohn Forte return (rval); 1898fcf3ce44SJohn Forte } 1899291a2b48SSukumar Swaminathan 1900fcf3ce44SJohn Forte /* Start the timer */ 1901fcf3ce44SJohn Forte emlxs_timer_start(hba); 1902fcf3ce44SJohn Forte 1903fcf3ce44SJohn Forte /* Set FC_ONLINE_MODE */ 1904fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 1905fcf3ce44SJohn Forte hba->flag |= FC_ONLINE_MODE; 1906fcf3ce44SJohn Forte hba->flag &= ~FC_ONLINING_MODE; 1907fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1908fcf3ce44SJohn Forte 1909fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_online_msg, NULL); 1910fcf3ce44SJohn Forte 1911fcf3ce44SJohn Forte #ifdef SFCT_SUPPORT 1912*8f23e9faSHans Rosenfeld if (port->flag & EMLXS_TGT_ENABLED) { 1913*8f23e9faSHans Rosenfeld (void) emlxs_fct_port_initialize(port); 1914*8f23e9faSHans Rosenfeld } 1915291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 1916fcf3ce44SJohn Forte 1917fcf3ce44SJohn Forte return (rval); 1918fcf3ce44SJohn Forte 191982527734SSukumar Swaminathan } /* emlxs_online() */ 1920fcf3ce44SJohn Forte 1921fcf3ce44SJohn Forte 1922fcf3ce44SJohn Forte extern int 1923*8f23e9faSHans Rosenfeld emlxs_offline(emlxs_hba_t *hba, uint32_t reset_requested) 1924fcf3ce44SJohn Forte { 1925fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 1926fcf3ce44SJohn Forte uint32_t i = 0; 1927fcf3ce44SJohn Forte int rval = 1; 1928fcf3ce44SJohn Forte 1929fcf3ce44SJohn Forte /* Make sure adapter is online or exit trying (30 seconds) */ 1930291a2b48SSukumar Swaminathan while (i++ < 30) { 1931fcf3ce44SJohn Forte /* Check if adapter is already going offline */ 1932fcf3ce44SJohn Forte if (hba->flag & (FC_OFFLINE_MODE | FC_OFFLINING_MODE)) { 1933fcf3ce44SJohn Forte return (0); 1934fcf3ce44SJohn Forte } 1935291a2b48SSukumar Swaminathan 1936fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 1937fcf3ce44SJohn Forte 1938fcf3ce44SJohn Forte /* Check again */ 1939fcf3ce44SJohn Forte if (hba->flag & (FC_OFFLINE_MODE | FC_OFFLINING_MODE)) { 1940fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1941fcf3ce44SJohn Forte return (0); 1942fcf3ce44SJohn Forte } 1943291a2b48SSukumar Swaminathan 1944fcf3ce44SJohn Forte /* Check if adapter is online */ 1945fcf3ce44SJohn Forte if (hba->flag & FC_ONLINE_MODE) { 1946fcf3ce44SJohn Forte /* Mark it going offline */ 1947fcf3ce44SJohn Forte hba->flag &= ~FC_ONLINE_MODE; 1948fcf3ce44SJohn Forte hba->flag |= FC_OFFLINING_MODE; 1949fcf3ce44SJohn Forte 1950fcf3ce44SJohn Forte /* Currently !FC_ONLINE_MODE and !FC_OFFLINE_MODE */ 1951fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1952fcf3ce44SJohn Forte break; 1953fcf3ce44SJohn Forte } 1954291a2b48SSukumar Swaminathan 1955fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1956fcf3ce44SJohn Forte 1957*8f23e9faSHans Rosenfeld BUSYWAIT_MS(1000); 1958fcf3ce44SJohn Forte } 1959fcf3ce44SJohn Forte 1960291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg, 1961291a2b48SSukumar Swaminathan "Going offline..."); 1962fcf3ce44SJohn Forte 1963*8f23e9faSHans Rosenfeld /* Declare link down */ 1964*8f23e9faSHans Rosenfeld if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 1965*8f23e9faSHans Rosenfeld (void) emlxs_fcf_shutdown_notify(port, 1); 1966*8f23e9faSHans Rosenfeld } else { 1967*8f23e9faSHans Rosenfeld emlxs_linkdown(hba); 1968fcf3ce44SJohn Forte } 1969*8f23e9faSHans Rosenfeld 1970fcf3ce44SJohn Forte #ifdef SFCT_SUPPORT 1971*8f23e9faSHans Rosenfeld if (port->flag & EMLXS_TGT_ENABLED) { 1972fcf3ce44SJohn Forte (void) emlxs_fct_port_shutdown(port); 1973fcf3ce44SJohn Forte } 1974291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 1975fcf3ce44SJohn Forte 1976fcf3ce44SJohn Forte /* Check if adapter was shutdown */ 1977fcf3ce44SJohn Forte if (hba->flag & FC_HARDWARE_ERROR) { 1978291a2b48SSukumar Swaminathan /* 1979291a2b48SSukumar Swaminathan * Force mailbox cleanup 1980291a2b48SSukumar Swaminathan * This will wake any sleeping or polling threads 1981291a2b48SSukumar Swaminathan */ 1982fcf3ce44SJohn Forte emlxs_mb_fini(hba, NULL, MBX_HARDWARE_ERROR); 1983fcf3ce44SJohn Forte } 1984291a2b48SSukumar Swaminathan 1985fcf3ce44SJohn Forte /* Pause here for the IO to settle */ 1986fcf3ce44SJohn Forte delay(drv_usectohz(1000000)); /* 1 sec */ 1987fcf3ce44SJohn Forte 1988fcf3ce44SJohn Forte /* Unregister all nodes */ 1989fcf3ce44SJohn Forte emlxs_ffcleanup(hba); 1990fcf3ce44SJohn Forte 1991fcf3ce44SJohn Forte if (hba->bus_type == SBUS_FC) { 199282527734SSukumar Swaminathan WRITE_SBUS_CSR_REG(hba, FC_SHS_REG(hba), 0x9A); 19934baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 199482527734SSukumar Swaminathan /* Access handle validation */ 199582527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.sbus_csr_handle); 19964baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 1997fcf3ce44SJohn Forte } 1998291a2b48SSukumar Swaminathan 1999fcf3ce44SJohn Forte /* Stop the timer */ 2000fcf3ce44SJohn Forte emlxs_timer_stop(hba); 2001fcf3ce44SJohn Forte 2002fcf3ce44SJohn Forte /* For safety flush every iotag list */ 2003fcf3ce44SJohn Forte if (emlxs_iotag_flush(hba)) { 2004fcf3ce44SJohn Forte /* Pause here for the IO to flush */ 2005728bdc9bSSukumar Swaminathan delay(drv_usectohz(1000)); 2006728bdc9bSSukumar Swaminathan } 2007728bdc9bSSukumar Swaminathan 2008728bdc9bSSukumar Swaminathan /* Wait for poll command request to settle */ 2009728bdc9bSSukumar Swaminathan while (hba->io_poll_count > 0) { 2010728bdc9bSSukumar Swaminathan delay(drv_usectohz(2000000)); /* 2 sec */ 2011fcf3ce44SJohn Forte } 2012728bdc9bSSukumar Swaminathan 201382527734SSukumar Swaminathan /* Shutdown the adapter interface */ 2014*8f23e9faSHans Rosenfeld EMLXS_SLI_OFFLINE(hba, reset_requested); 2015fcf3ce44SJohn Forte 2016fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 2017fcf3ce44SJohn Forte hba->flag |= FC_OFFLINE_MODE; 2018fcf3ce44SJohn Forte hba->flag &= ~FC_OFFLINING_MODE; 2019fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 2020fcf3ce44SJohn Forte 2021fcf3ce44SJohn Forte rval = 0; 2022fcf3ce44SJohn Forte 2023fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_offline_msg, NULL); 2024fcf3ce44SJohn Forte 2025fcf3ce44SJohn Forte done: 2026fcf3ce44SJohn Forte 2027fcf3ce44SJohn Forte return (rval); 2028fcf3ce44SJohn Forte 202982527734SSukumar Swaminathan } /* emlxs_offline() */ 2030fcf3ce44SJohn Forte 2031fcf3ce44SJohn Forte 2032fcf3ce44SJohn Forte 2033fcf3ce44SJohn Forte extern int 2034fcf3ce44SJohn Forte emlxs_power_down(emlxs_hba_t *hba) 2035fcf3ce44SJohn Forte { 20364baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 20374baa2c25SSukumar Swaminathan emlxs_port_t *port = &PPORT; 20384baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 2039fcf3ce44SJohn Forte int32_t rval = 0; 2040fcf3ce44SJohn Forte 2041*8f23e9faSHans Rosenfeld if ((rval = emlxs_offline(hba, 0))) { 2042fcf3ce44SJohn Forte return (rval); 2043fcf3ce44SJohn Forte } 204482527734SSukumar Swaminathan EMLXS_SLI_HBA_RESET(hba, 1, 1, 0); 2045291a2b48SSukumar Swaminathan 2046fcf3ce44SJohn Forte 20474baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 20484baa2c25SSukumar Swaminathan if (emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle) 20494baa2c25SSukumar Swaminathan != DDI_FM_OK) { 20504baa2c25SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 20514baa2c25SSukumar Swaminathan &emlxs_invalid_access_handle_msg, NULL); 20524baa2c25SSukumar Swaminathan return (1); 20534baa2c25SSukumar Swaminathan } 20544baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 20554baa2c25SSukumar Swaminathan 2056fcf3ce44SJohn Forte return (0); 2057fcf3ce44SJohn Forte 205882527734SSukumar Swaminathan } /* End emlxs_power_down */ 2059fcf3ce44SJohn Forte 2060fcf3ce44SJohn Forte 2061fcf3ce44SJohn Forte extern int 2062fcf3ce44SJohn Forte emlxs_power_up(emlxs_hba_t *hba) 2063fcf3ce44SJohn Forte { 20644baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 20654baa2c25SSukumar Swaminathan emlxs_port_t *port = &PPORT; 20664baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 2067fcf3ce44SJohn Forte int32_t rval = 0; 2068fcf3ce44SJohn Forte 2069fcf3ce44SJohn Forte 20704baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 20714baa2c25SSukumar Swaminathan if (emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle) 20724baa2c25SSukumar Swaminathan != DDI_FM_OK) { 20734baa2c25SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 20744baa2c25SSukumar Swaminathan &emlxs_invalid_access_handle_msg, NULL); 20754baa2c25SSukumar Swaminathan return (1); 20764baa2c25SSukumar Swaminathan } 20774baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 20784baa2c25SSukumar Swaminathan 2079fcf3ce44SJohn Forte /* Bring adapter online */ 2080fcf3ce44SJohn Forte if ((rval = emlxs_online(hba))) { 2081a9800bebSGarrett D'Amore if (hba->pci_cap_offset[PCI_CAP_ID_PM]) { 2082a9800bebSGarrett D'Amore /* Put chip in D3 state */ 2083a9800bebSGarrett D'Amore (void) ddi_put8(hba->pci_acc_handle, 2084a9800bebSGarrett D'Amore (uint8_t *)(hba->pci_addr + 2085a9800bebSGarrett D'Amore hba->pci_cap_offset[PCI_CAP_ID_PM] + 2086a9800bebSGarrett D'Amore PCI_PMCSR), 2087a9800bebSGarrett D'Amore (uint8_t)PCI_PMCSR_D3HOT); 2088a9800bebSGarrett D'Amore } 2089fcf3ce44SJohn Forte return (rval); 2090fcf3ce44SJohn Forte } 2091291a2b48SSukumar Swaminathan 2092fcf3ce44SJohn Forte return (rval); 2093fcf3ce44SJohn Forte 2094*8f23e9faSHans Rosenfeld } /* emlxs_power_up() */ 2095fcf3ce44SJohn Forte 2096fcf3ce44SJohn Forte 2097fcf3ce44SJohn Forte /* 2098291a2b48SSukumar Swaminathan * 2099fcf3ce44SJohn Forte * NAME: emlxs_ffcleanup 2100fcf3ce44SJohn Forte * 2101fcf3ce44SJohn Forte * FUNCTION: Cleanup all the Firefly resources used by configuring the adapter 2102fcf3ce44SJohn Forte * 2103fcf3ce44SJohn Forte * EXECUTION ENVIRONMENT: process only 2104fcf3ce44SJohn Forte * 2105fcf3ce44SJohn Forte * CALLED FROM: CFG_TERM 2106fcf3ce44SJohn Forte * 2107fcf3ce44SJohn Forte * INPUT: hba - pointer to the dev_ctl area. 2108fcf3ce44SJohn Forte * 2109fcf3ce44SJohn Forte * RETURNS: none 2110fcf3ce44SJohn Forte */ 2111fcf3ce44SJohn Forte extern void 2112fcf3ce44SJohn Forte emlxs_ffcleanup(emlxs_hba_t *hba) 2113fcf3ce44SJohn Forte { 2114fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 2115291a2b48SSukumar Swaminathan uint32_t i; 2116fcf3ce44SJohn Forte 2117fcf3ce44SJohn Forte /* Disable all but the mailbox interrupt */ 211882527734SSukumar Swaminathan EMLXS_SLI_DISABLE_INTR(hba, HC_MBINT_ENA); 2119fcf3ce44SJohn Forte 2120fcf3ce44SJohn Forte /* Make sure all port nodes are destroyed */ 2121291a2b48SSukumar Swaminathan for (i = 0; i < MAX_VPORTS; i++) { 2122291a2b48SSukumar Swaminathan port = &VPORT(i); 2123fcf3ce44SJohn Forte 2124fcf3ce44SJohn Forte if (port->node_count) { 2125*8f23e9faSHans Rosenfeld (void) EMLXS_SLI_UNREG_NODE(port, 0, 0, 0, 0); 2126fcf3ce44SJohn Forte } 2127fcf3ce44SJohn Forte } 2128fcf3ce44SJohn Forte 2129fcf3ce44SJohn Forte /* Clear all interrupt enable conditions */ 213082527734SSukumar Swaminathan EMLXS_SLI_DISABLE_INTR(hba, 0); 2131fcf3ce44SJohn Forte 2132fcf3ce44SJohn Forte return; 2133fcf3ce44SJohn Forte 213482527734SSukumar Swaminathan } /* emlxs_ffcleanup() */ 2135fcf3ce44SJohn Forte 2136fcf3ce44SJohn Forte 2137fcf3ce44SJohn Forte extern uint16_t 213882527734SSukumar Swaminathan emlxs_register_pkt(CHANNEL *cp, emlxs_buf_t *sbp) 2139fcf3ce44SJohn Forte { 2140fcf3ce44SJohn Forte emlxs_hba_t *hba; 2141fcf3ce44SJohn Forte emlxs_port_t *port; 2142fcf3ce44SJohn Forte uint16_t iotag; 2143fcf3ce44SJohn Forte uint32_t i; 2144fcf3ce44SJohn Forte 214582527734SSukumar Swaminathan hba = cp->hba; 2146fcf3ce44SJohn Forte 214782527734SSukumar Swaminathan mutex_enter(&EMLXS_FCTAB_LOCK); 2148fcf3ce44SJohn Forte 2149fcf3ce44SJohn Forte if (sbp->iotag != 0) { 2150fcf3ce44SJohn Forte port = &PPORT; 2151fcf3ce44SJohn Forte 2152fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 215382527734SSukumar Swaminathan "Pkt already registered! channel=%d iotag=%d sbp=%p", 215482527734SSukumar Swaminathan sbp->channel, sbp->iotag, sbp); 2155fcf3ce44SJohn Forte } 2156291a2b48SSukumar Swaminathan 2157fcf3ce44SJohn Forte iotag = 0; 215882527734SSukumar Swaminathan for (i = 0; i < hba->max_iotag; i++) { 215982527734SSukumar Swaminathan if (!hba->fc_iotag || hba->fc_iotag >= hba->max_iotag) { 216082527734SSukumar Swaminathan hba->fc_iotag = 1; 2161fcf3ce44SJohn Forte } 216282527734SSukumar Swaminathan iotag = hba->fc_iotag++; 2163fcf3ce44SJohn Forte 216482527734SSukumar Swaminathan if (hba->fc_table[iotag] == 0 || 216582527734SSukumar Swaminathan hba->fc_table[iotag] == STALE_PACKET) { 216682527734SSukumar Swaminathan hba->io_count++; 216782527734SSukumar Swaminathan hba->fc_table[iotag] = sbp; 2168fcf3ce44SJohn Forte 2169fcf3ce44SJohn Forte sbp->iotag = iotag; 217082527734SSukumar Swaminathan sbp->channel = cp; 2171fcf3ce44SJohn Forte 2172fcf3ce44SJohn Forte break; 2173fcf3ce44SJohn Forte } 2174fcf3ce44SJohn Forte iotag = 0; 2175fcf3ce44SJohn Forte } 2176fcf3ce44SJohn Forte 217782527734SSukumar Swaminathan mutex_exit(&EMLXS_FCTAB_LOCK); 2178fcf3ce44SJohn Forte 2179fcf3ce44SJohn Forte /* 2180fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 2181*8f23e9faSHans Rosenfeld * "register_pkt: channel=%d iotag=%d sbp=%p", 218282527734SSukumar Swaminathan * cp->channelno, iotag, sbp); 2183fcf3ce44SJohn Forte */ 2184fcf3ce44SJohn Forte 2185fcf3ce44SJohn Forte return (iotag); 2186fcf3ce44SJohn Forte 218782527734SSukumar Swaminathan } /* emlxs_register_pkt() */ 2188fcf3ce44SJohn Forte 2189fcf3ce44SJohn Forte 2190fcf3ce44SJohn Forte 2191fcf3ce44SJohn Forte extern emlxs_buf_t * 219282527734SSukumar Swaminathan emlxs_unregister_pkt(CHANNEL *cp, uint16_t iotag, uint32_t forced) 2193fcf3ce44SJohn Forte { 2194fcf3ce44SJohn Forte emlxs_hba_t *hba; 2195fcf3ce44SJohn Forte emlxs_buf_t *sbp; 219682527734SSukumar Swaminathan 219782527734SSukumar Swaminathan sbp = NULL; 219882527734SSukumar Swaminathan hba = cp->hba; 2199fcf3ce44SJohn Forte 2200fcf3ce44SJohn Forte /* Check the iotag range */ 220182527734SSukumar Swaminathan if ((iotag == 0) || (iotag >= hba->max_iotag)) { 2202fcf3ce44SJohn Forte return (NULL); 2203fcf3ce44SJohn Forte } 2204291a2b48SSukumar Swaminathan 2205fcf3ce44SJohn Forte /* Remove the sbp from the table */ 220682527734SSukumar Swaminathan mutex_enter(&EMLXS_FCTAB_LOCK); 220782527734SSukumar Swaminathan sbp = hba->fc_table[iotag]; 2208fcf3ce44SJohn Forte 2209fcf3ce44SJohn Forte if (!sbp || (sbp == STALE_PACKET)) { 221082527734SSukumar Swaminathan mutex_exit(&EMLXS_FCTAB_LOCK); 2211fcf3ce44SJohn Forte return (sbp); 2212fcf3ce44SJohn Forte } 2213291a2b48SSukumar Swaminathan 221482527734SSukumar Swaminathan hba->fc_table[iotag] = ((forced) ? STALE_PACKET : NULL); 221582527734SSukumar Swaminathan hba->io_count--; 2216fcf3ce44SJohn Forte sbp->iotag = 0; 2217fcf3ce44SJohn Forte 221882527734SSukumar Swaminathan mutex_exit(&EMLXS_FCTAB_LOCK); 2219fcf3ce44SJohn Forte 2220fcf3ce44SJohn Forte 2221fcf3ce44SJohn Forte /* Clean up the sbp */ 2222fcf3ce44SJohn Forte mutex_enter(&sbp->mtx); 2223fcf3ce44SJohn Forte 2224fcf3ce44SJohn Forte if (sbp->pkt_flags & PACKET_IN_TXQ) { 2225fcf3ce44SJohn Forte sbp->pkt_flags &= ~PACKET_IN_TXQ; 222682527734SSukumar Swaminathan hba->channel_tx_count--; 2227fcf3ce44SJohn Forte } 2228291a2b48SSukumar Swaminathan 2229fcf3ce44SJohn Forte if (sbp->pkt_flags & PACKET_IN_CHIPQ) { 2230fcf3ce44SJohn Forte sbp->pkt_flags &= ~PACKET_IN_CHIPQ; 2231fcf3ce44SJohn Forte } 2232291a2b48SSukumar Swaminathan 2233fcf3ce44SJohn Forte if (sbp->bmp) { 2234a9800bebSGarrett D'Amore emlxs_mem_put(hba, MEM_BPL, (void *)sbp->bmp); 2235fcf3ce44SJohn Forte sbp->bmp = 0; 2236fcf3ce44SJohn Forte } 2237fcf3ce44SJohn Forte 2238291a2b48SSukumar Swaminathan mutex_exit(&sbp->mtx); 2239fcf3ce44SJohn Forte 2240fcf3ce44SJohn Forte return (sbp); 2241fcf3ce44SJohn Forte 224282527734SSukumar Swaminathan } /* emlxs_unregister_pkt() */ 2243fcf3ce44SJohn Forte 2244fcf3ce44SJohn Forte 2245fcf3ce44SJohn Forte 224682527734SSukumar Swaminathan /* Flush all IO's to all nodes for a given IO Channel */ 2247fcf3ce44SJohn Forte extern uint32_t 224882527734SSukumar Swaminathan emlxs_tx_channel_flush(emlxs_hba_t *hba, CHANNEL *cp, emlxs_buf_t *fpkt) 2249fcf3ce44SJohn Forte { 2250fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 2251fcf3ce44SJohn Forte emlxs_buf_t *sbp; 2252fcf3ce44SJohn Forte IOCBQ *iocbq; 2253fcf3ce44SJohn Forte IOCBQ *next; 2254fcf3ce44SJohn Forte IOCB *iocb; 225582527734SSukumar Swaminathan uint32_t channelno; 2256fcf3ce44SJohn Forte Q abort; 2257fcf3ce44SJohn Forte NODELIST *ndlp; 2258fcf3ce44SJohn Forte IOCB *icmd; 2259fcf3ce44SJohn Forte MATCHMAP *mp; 2260fcf3ce44SJohn Forte uint32_t i; 226182527734SSukumar Swaminathan uint8_t flag[MAX_CHANNEL]; 2262fcf3ce44SJohn Forte 226382527734SSukumar Swaminathan channelno = cp->channelno; 2264fcf3ce44SJohn Forte bzero((void *)&abort, sizeof (Q)); 226582527734SSukumar Swaminathan bzero((void *)flag, MAX_CHANNEL * sizeof (uint8_t)); 2266fcf3ce44SJohn Forte 226782527734SSukumar Swaminathan mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 2268fcf3ce44SJohn Forte 2269fcf3ce44SJohn Forte /* While a node needs servicing */ 227082527734SSukumar Swaminathan while (cp->nodeq.q_first) { 227182527734SSukumar Swaminathan ndlp = (NODELIST *) cp->nodeq.q_first; 2272fcf3ce44SJohn Forte 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) { 227782527734SSukumar Swaminathan abort.q_first = 227882527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_first; 2279fcf3ce44SJohn Forte } else { 2280fcf3ce44SJohn Forte ((IOCBQ *)abort.q_last)->next = 228182527734SSukumar Swaminathan (IOCBQ *)ndlp->nlp_ptx[channelno].q_first; 2282fcf3ce44SJohn Forte } 228382527734SSukumar Swaminathan flag[channelno] = 1; 2284fcf3ce44SJohn Forte 228582527734SSukumar Swaminathan abort.q_last = ndlp->nlp_ptx[channelno].q_last; 228682527734SSukumar Swaminathan abort.q_cnt += ndlp->nlp_ptx[channelno].q_cnt; 2287fcf3ce44SJohn Forte } 2288291a2b48SSukumar Swaminathan 2289fcf3ce44SJohn Forte /* Check if tx queue is not empty */ 229082527734SSukumar Swaminathan if (ndlp->nlp_tx[channelno].q_first) { 2291fcf3ce44SJohn Forte /* Transfer all iocb's to local queue */ 2292fcf3ce44SJohn Forte if (abort.q_first == 0) { 229382527734SSukumar Swaminathan abort.q_first = ndlp->nlp_tx[channelno].q_first; 2294fcf3ce44SJohn Forte } else { 2295fcf3ce44SJohn Forte ((IOCBQ *)abort.q_last)->next = 229682527734SSukumar Swaminathan (IOCBQ *)ndlp->nlp_tx[channelno].q_first; 2297fcf3ce44SJohn Forte } 2298fcf3ce44SJohn Forte 229982527734SSukumar Swaminathan abort.q_last = ndlp->nlp_tx[channelno].q_last; 230082527734SSukumar Swaminathan abort.q_cnt += ndlp->nlp_tx[channelno].q_cnt; 2301fcf3ce44SJohn Forte } 2302291a2b48SSukumar Swaminathan 2303fcf3ce44SJohn Forte /* Clear the queue pointers */ 230482527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_first = NULL; 230582527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_last = NULL; 230682527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_cnt = 0; 2307fcf3ce44SJohn Forte 230882527734SSukumar Swaminathan ndlp->nlp_tx[channelno].q_first = NULL; 230982527734SSukumar Swaminathan ndlp->nlp_tx[channelno].q_last = NULL; 231082527734SSukumar Swaminathan ndlp->nlp_tx[channelno].q_cnt = 0; 2311fcf3ce44SJohn Forte 2312fcf3ce44SJohn Forte /* Remove node from service queue */ 2313fcf3ce44SJohn Forte 2314fcf3ce44SJohn Forte /* If this is the last node on list */ 231582527734SSukumar Swaminathan if (cp->nodeq.q_last == (void *)ndlp) { 231682527734SSukumar Swaminathan cp->nodeq.q_last = NULL; 231782527734SSukumar Swaminathan cp->nodeq.q_first = NULL; 231882527734SSukumar Swaminathan cp->nodeq.q_cnt = 0; 2319fcf3ce44SJohn Forte } else { 2320fcf3ce44SJohn Forte /* Remove node from head */ 232182527734SSukumar Swaminathan cp->nodeq.q_first = ndlp->nlp_next[channelno]; 232282527734SSukumar Swaminathan ((NODELIST *)cp->nodeq.q_last)->nlp_next[channelno] = 232382527734SSukumar Swaminathan cp->nodeq.q_first; 232482527734SSukumar Swaminathan cp->nodeq.q_cnt--; 2325fcf3ce44SJohn Forte } 2326fcf3ce44SJohn Forte 2327fcf3ce44SJohn Forte /* Clear node */ 232882527734SSukumar Swaminathan ndlp->nlp_next[channelno] = NULL; 2329fcf3ce44SJohn Forte } 2330fcf3ce44SJohn Forte 2331fcf3ce44SJohn Forte /* First cleanup the iocb's while still holding the lock */ 2332291a2b48SSukumar Swaminathan iocbq = (IOCBQ *) abort.q_first; 2333fcf3ce44SJohn Forte while (iocbq) { 2334fcf3ce44SJohn Forte /* Free the IoTag and the bmp */ 2335fcf3ce44SJohn Forte iocb = &iocbq->iocb; 233682527734SSukumar Swaminathan 233782527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 233882527734SSukumar Swaminathan sbp = iocbq->sbp; 233982527734SSukumar Swaminathan if (sbp) { 2340*8f23e9faSHans Rosenfeld emlxs_sli4_free_xri(port, sbp, sbp->xrip, 1); 234182527734SSukumar Swaminathan } 234282527734SSukumar Swaminathan } else { 234382527734SSukumar Swaminathan sbp = emlxs_unregister_pkt((CHANNEL *)iocbq->channel, 234482527734SSukumar Swaminathan iocb->ULPIOTAG, 0); 234582527734SSukumar Swaminathan } 2346fcf3ce44SJohn Forte 2347fcf3ce44SJohn Forte if (sbp && (sbp != STALE_PACKET)) { 2348fcf3ce44SJohn Forte mutex_enter(&sbp->mtx); 2349fcf3ce44SJohn Forte 2350fcf3ce44SJohn Forte sbp->pkt_flags |= PACKET_IN_FLUSH; 2351fcf3ce44SJohn Forte /* 2352fcf3ce44SJohn Forte * If the fpkt is already set, then we will leave it 2353291a2b48SSukumar Swaminathan * alone. This ensures that this pkt is only accounted 2354291a2b48SSukumar Swaminathan * for on one fpkt->flush_count 2355fcf3ce44SJohn Forte */ 2356fcf3ce44SJohn Forte if (!sbp->fpkt && fpkt) { 2357fcf3ce44SJohn Forte mutex_enter(&fpkt->mtx); 2358fcf3ce44SJohn Forte sbp->fpkt = fpkt; 2359fcf3ce44SJohn Forte fpkt->flush_count++; 2360fcf3ce44SJohn Forte mutex_exit(&fpkt->mtx); 2361fcf3ce44SJohn Forte } 2362291a2b48SSukumar Swaminathan 2363fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 2364fcf3ce44SJohn Forte } 2365291a2b48SSukumar Swaminathan 2366fcf3ce44SJohn Forte iocbq = (IOCBQ *)iocbq->next; 2367fcf3ce44SJohn Forte } /* end of while */ 2368fcf3ce44SJohn Forte 236982527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 2370fcf3ce44SJohn Forte 2371fcf3ce44SJohn Forte /* Now abort the iocb's */ 2372fcf3ce44SJohn Forte iocbq = (IOCBQ *)abort.q_first; 2373fcf3ce44SJohn Forte while (iocbq) { 2374fcf3ce44SJohn Forte /* Save the next iocbq for now */ 2375fcf3ce44SJohn Forte next = (IOCBQ *)iocbq->next; 2376fcf3ce44SJohn Forte 2377fcf3ce44SJohn Forte /* Unlink this iocbq */ 2378fcf3ce44SJohn Forte iocbq->next = NULL; 2379fcf3ce44SJohn Forte 2380fcf3ce44SJohn Forte /* Get the pkt */ 2381fcf3ce44SJohn Forte sbp = (emlxs_buf_t *)iocbq->sbp; 2382fcf3ce44SJohn Forte 2383fcf3ce44SJohn Forte if (sbp) { 2384fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flush_msg, 2385291a2b48SSukumar Swaminathan "tx: sbp=%p node=%p", sbp, sbp->node); 2386fcf3ce44SJohn Forte 2387fcf3ce44SJohn Forte if (hba->state >= FC_LINK_UP) { 2388fcf3ce44SJohn Forte emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 2389fcf3ce44SJohn Forte IOERR_ABORT_REQUESTED, 1); 2390fcf3ce44SJohn Forte } else { 2391fcf3ce44SJohn Forte emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 2392fcf3ce44SJohn Forte IOERR_LINK_DOWN, 1); 2393fcf3ce44SJohn Forte } 2394fcf3ce44SJohn Forte 2395fcf3ce44SJohn Forte } 2396fcf3ce44SJohn Forte /* Free the iocb and its associated buffers */ 2397fcf3ce44SJohn Forte else { 2398fcf3ce44SJohn Forte icmd = &iocbq->iocb; 239982527734SSukumar Swaminathan 240082527734SSukumar Swaminathan /* SLI3 */ 240182527734SSukumar Swaminathan if (icmd->ULPCOMMAND == CMD_QUE_RING_BUF64_CN || 240282527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_QUE_RING_BUF_CN || 240382527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_QUE_RING_LIST64_CN) { 2404fcf3ce44SJohn Forte if ((hba->flag & 2405fcf3ce44SJohn Forte (FC_ONLINE_MODE | FC_ONLINING_MODE)) == 0) { 2406fcf3ce44SJohn Forte /* HBA is detaching or offlining */ 240782527734SSukumar Swaminathan if (icmd->ULPCOMMAND != 2408fcf3ce44SJohn Forte CMD_QUE_RING_LIST64_CN) { 2409a9800bebSGarrett D'Amore void *tmp; 241082527734SSukumar Swaminathan RING *rp; 2411fcf3ce44SJohn Forte 241282527734SSukumar Swaminathan rp = &hba->sli.sli3. 241382527734SSukumar Swaminathan ring[channelno]; 2414fcf3ce44SJohn Forte for (i = 0; 241582527734SSukumar Swaminathan i < icmd->ULPBDECOUNT; 2416fcf3ce44SJohn Forte i++) { 2417fcf3ce44SJohn Forte mp = EMLXS_GET_VADDR( 2418fcf3ce44SJohn Forte hba, rp, icmd); 2419fcf3ce44SJohn Forte 2420a9800bebSGarrett D'Amore tmp = (void *)mp; 2421fcf3ce44SJohn Forte if (mp) { 2422a9800bebSGarrett D'Amore emlxs_mem_put( 2423291a2b48SSukumar Swaminathan hba, MEM_BUF, tmp); 2424fcf3ce44SJohn Forte } 2425fcf3ce44SJohn Forte } 2426fcf3ce44SJohn Forte } 2427291a2b48SSukumar Swaminathan 2428a9800bebSGarrett D'Amore emlxs_mem_put(hba, MEM_IOCB, 2429a9800bebSGarrett D'Amore (void *)iocbq); 2430fcf3ce44SJohn Forte } else { 2431fcf3ce44SJohn Forte /* repost the unsolicited buffer */ 243282527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, 2433291a2b48SSukumar Swaminathan iocbq); 2434fcf3ce44SJohn Forte } 243582527734SSukumar Swaminathan } else if (icmd->ULPCOMMAND == CMD_CLOSE_XRI_CN || 243682527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_CLOSE_XRI_CX) { 243782527734SSukumar Swaminathan 243882527734SSukumar Swaminathan emlxs_tx_put(iocbq, 1); 2439fcf3ce44SJohn Forte } 2440fcf3ce44SJohn Forte } 2441fcf3ce44SJohn Forte 2442fcf3ce44SJohn Forte iocbq = next; 2443fcf3ce44SJohn Forte 2444fcf3ce44SJohn Forte } /* end of while */ 2445fcf3ce44SJohn Forte 244682527734SSukumar Swaminathan /* Now trigger channel service */ 244782527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 244882527734SSukumar Swaminathan if (!flag[channelno]) { 244982527734SSukumar Swaminathan continue; 245082527734SSukumar Swaminathan } 245182527734SSukumar Swaminathan 245282527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, &hba->chan[channelno], 0); 245382527734SSukumar Swaminathan } 245482527734SSukumar Swaminathan 2455fcf3ce44SJohn Forte return (abort.q_cnt); 2456fcf3ce44SJohn Forte 245782527734SSukumar Swaminathan } /* emlxs_tx_channel_flush() */ 2458fcf3ce44SJohn Forte 2459fcf3ce44SJohn Forte 2460fcf3ce44SJohn Forte /* Flush all IO's on all or a given ring for a given node */ 2461fcf3ce44SJohn Forte extern uint32_t 246282527734SSukumar Swaminathan emlxs_tx_node_flush(emlxs_port_t *port, NODELIST *ndlp, CHANNEL *chan, 2463fcf3ce44SJohn Forte uint32_t shutdown, emlxs_buf_t *fpkt) 2464fcf3ce44SJohn Forte { 2465fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 2466fcf3ce44SJohn Forte emlxs_buf_t *sbp; 246782527734SSukumar Swaminathan uint32_t channelno; 246882527734SSukumar Swaminathan CHANNEL *cp; 2469fcf3ce44SJohn Forte IOCB *icmd; 2470fcf3ce44SJohn Forte IOCBQ *iocbq; 2471fcf3ce44SJohn Forte NODELIST *prev; 2472fcf3ce44SJohn Forte IOCBQ *next; 2473fcf3ce44SJohn Forte IOCB *iocb; 2474fcf3ce44SJohn Forte Q abort; 2475fcf3ce44SJohn Forte uint32_t i; 2476fcf3ce44SJohn Forte MATCHMAP *mp; 247782527734SSukumar Swaminathan uint8_t flag[MAX_CHANNEL]; 2478fcf3ce44SJohn Forte 2479fcf3ce44SJohn Forte bzero((void *)&abort, sizeof (Q)); 2480fcf3ce44SJohn Forte 2481fcf3ce44SJohn Forte /* Flush all I/O's on tx queue to this target */ 248282527734SSukumar Swaminathan mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 2483fcf3ce44SJohn Forte 2484fcf3ce44SJohn Forte if (!ndlp->nlp_base && shutdown) { 2485fcf3ce44SJohn Forte ndlp->nlp_active = 0; 2486fcf3ce44SJohn Forte } 2487291a2b48SSukumar Swaminathan 248882527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 248982527734SSukumar Swaminathan cp = &hba->chan[channelno]; 2490fcf3ce44SJohn Forte 249182527734SSukumar Swaminathan if (chan && cp != chan) { 2492fcf3ce44SJohn Forte continue; 2493fcf3ce44SJohn Forte } 2494291a2b48SSukumar Swaminathan 2495fcf3ce44SJohn Forte if (!ndlp->nlp_base || shutdown) { 2496fcf3ce44SJohn Forte /* Check if priority queue is not empty */ 249782527734SSukumar Swaminathan if (ndlp->nlp_ptx[channelno].q_first) { 2498fcf3ce44SJohn Forte /* Transfer all iocb's to local queue */ 2499fcf3ce44SJohn Forte if (abort.q_first == 0) { 2500fcf3ce44SJohn Forte abort.q_first = 250182527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_first; 2502fcf3ce44SJohn Forte } else { 250382527734SSukumar Swaminathan ((IOCBQ *)(abort.q_last))->next = 250482527734SSukumar Swaminathan (IOCBQ *)ndlp->nlp_ptx[channelno]. 2505291a2b48SSukumar Swaminathan q_first; 2506fcf3ce44SJohn Forte } 2507fcf3ce44SJohn Forte 250882527734SSukumar Swaminathan flag[channelno] = 1; 250982527734SSukumar Swaminathan 251082527734SSukumar Swaminathan abort.q_last = ndlp->nlp_ptx[channelno].q_last; 251182527734SSukumar Swaminathan abort.q_cnt += ndlp->nlp_ptx[channelno].q_cnt; 2512fcf3ce44SJohn Forte } 2513fcf3ce44SJohn Forte } 2514291a2b48SSukumar Swaminathan 2515fcf3ce44SJohn Forte /* Check if tx queue is not empty */ 251682527734SSukumar Swaminathan if (ndlp->nlp_tx[channelno].q_first) { 251782527734SSukumar Swaminathan 2518fcf3ce44SJohn Forte /* Transfer all iocb's to local queue */ 2519fcf3ce44SJohn Forte if (abort.q_first == 0) { 252082527734SSukumar Swaminathan abort.q_first = ndlp->nlp_tx[channelno].q_first; 2521fcf3ce44SJohn Forte } else { 2522fcf3ce44SJohn Forte ((IOCBQ *)abort.q_last)->next = 252382527734SSukumar Swaminathan (IOCBQ *)ndlp->nlp_tx[channelno].q_first; 2524fcf3ce44SJohn Forte } 2525fcf3ce44SJohn Forte 252682527734SSukumar Swaminathan abort.q_last = ndlp->nlp_tx[channelno].q_last; 252782527734SSukumar Swaminathan abort.q_cnt += ndlp->nlp_tx[channelno].q_cnt; 2528fcf3ce44SJohn Forte } 2529291a2b48SSukumar Swaminathan 2530fcf3ce44SJohn Forte /* Clear the queue pointers */ 253182527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_first = NULL; 253282527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_last = NULL; 253382527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_cnt = 0; 2534fcf3ce44SJohn Forte 253582527734SSukumar Swaminathan ndlp->nlp_tx[channelno].q_first = NULL; 253682527734SSukumar Swaminathan ndlp->nlp_tx[channelno].q_last = NULL; 253782527734SSukumar Swaminathan ndlp->nlp_tx[channelno].q_cnt = 0; 2538fcf3ce44SJohn Forte 253982527734SSukumar Swaminathan /* If this node was on the channel queue, remove it */ 254082527734SSukumar Swaminathan if (ndlp->nlp_next[channelno]) { 2541fcf3ce44SJohn Forte /* If this is the only node on list */ 254282527734SSukumar Swaminathan if (cp->nodeq.q_first == (void *)ndlp && 254382527734SSukumar Swaminathan cp->nodeq.q_last == (void *)ndlp) { 254482527734SSukumar Swaminathan cp->nodeq.q_last = NULL; 254582527734SSukumar Swaminathan cp->nodeq.q_first = NULL; 254682527734SSukumar Swaminathan cp->nodeq.q_cnt = 0; 254782527734SSukumar Swaminathan } else if (cp->nodeq.q_first == (void *)ndlp) { 254882527734SSukumar Swaminathan cp->nodeq.q_first = ndlp->nlp_next[channelno]; 254982527734SSukumar Swaminathan ((NODELIST *) cp->nodeq.q_last)-> 255082527734SSukumar Swaminathan nlp_next[channelno] = cp->nodeq.q_first; 255182527734SSukumar Swaminathan cp->nodeq.q_cnt--; 2552291a2b48SSukumar Swaminathan } else { 2553fcf3ce44SJohn Forte /* 2554291a2b48SSukumar Swaminathan * This is a little more difficult find the 255582527734SSukumar Swaminathan * previous node in the circular channel queue 2556fcf3ce44SJohn Forte */ 2557fcf3ce44SJohn Forte prev = ndlp; 255882527734SSukumar Swaminathan while (prev->nlp_next[channelno] != ndlp) { 255982527734SSukumar Swaminathan prev = prev->nlp_next[channelno]; 2560fcf3ce44SJohn Forte } 2561fcf3ce44SJohn Forte 256282527734SSukumar Swaminathan prev->nlp_next[channelno] = 256382527734SSukumar Swaminathan ndlp->nlp_next[channelno]; 2564fcf3ce44SJohn Forte 256582527734SSukumar Swaminathan if (cp->nodeq.q_last == (void *)ndlp) { 256682527734SSukumar Swaminathan cp->nodeq.q_last = (void *)prev; 2567fcf3ce44SJohn Forte } 256882527734SSukumar Swaminathan cp->nodeq.q_cnt--; 2569fcf3ce44SJohn Forte 2570fcf3ce44SJohn Forte } 2571fcf3ce44SJohn Forte 2572fcf3ce44SJohn Forte /* Clear node */ 257382527734SSukumar Swaminathan ndlp->nlp_next[channelno] = NULL; 2574fcf3ce44SJohn Forte } 2575291a2b48SSukumar Swaminathan 2576fcf3ce44SJohn Forte } 2577fcf3ce44SJohn Forte 2578fcf3ce44SJohn Forte /* First cleanup the iocb's while still holding the lock */ 2579291a2b48SSukumar Swaminathan iocbq = (IOCBQ *) abort.q_first; 2580fcf3ce44SJohn Forte while (iocbq) { 2581fcf3ce44SJohn Forte /* Free the IoTag and the bmp */ 2582fcf3ce44SJohn Forte iocb = &iocbq->iocb; 258382527734SSukumar Swaminathan 258482527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 258582527734SSukumar Swaminathan sbp = iocbq->sbp; 258682527734SSukumar Swaminathan if (sbp) { 2587*8f23e9faSHans Rosenfeld emlxs_sli4_free_xri(port, sbp, sbp->xrip, 1); 258882527734SSukumar Swaminathan } 258982527734SSukumar Swaminathan } else { 259082527734SSukumar Swaminathan sbp = emlxs_unregister_pkt((CHANNEL *)iocbq->channel, 259182527734SSukumar Swaminathan iocb->ULPIOTAG, 0); 259282527734SSukumar Swaminathan } 2593fcf3ce44SJohn Forte 2594fcf3ce44SJohn Forte if (sbp && (sbp != STALE_PACKET)) { 2595fcf3ce44SJohn Forte mutex_enter(&sbp->mtx); 2596fcf3ce44SJohn Forte sbp->pkt_flags |= PACKET_IN_FLUSH; 2597fcf3ce44SJohn Forte /* 2598fcf3ce44SJohn Forte * If the fpkt is already set, then we will leave it 2599291a2b48SSukumar Swaminathan * alone. This ensures that this pkt is only accounted 2600291a2b48SSukumar Swaminathan * for on one fpkt->flush_count 2601fcf3ce44SJohn Forte */ 2602fcf3ce44SJohn Forte if (!sbp->fpkt && fpkt) { 2603fcf3ce44SJohn Forte mutex_enter(&fpkt->mtx); 2604fcf3ce44SJohn Forte sbp->fpkt = fpkt; 2605fcf3ce44SJohn Forte fpkt->flush_count++; 2606fcf3ce44SJohn Forte mutex_exit(&fpkt->mtx); 2607fcf3ce44SJohn Forte } 2608291a2b48SSukumar Swaminathan 2609fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 2610fcf3ce44SJohn Forte } 2611291a2b48SSukumar Swaminathan 2612291a2b48SSukumar Swaminathan iocbq = (IOCBQ *) iocbq->next; 2613fcf3ce44SJohn Forte 2614fcf3ce44SJohn Forte } /* end of while */ 2615fcf3ce44SJohn Forte 261682527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 2617fcf3ce44SJohn Forte 2618fcf3ce44SJohn Forte /* Now abort the iocb's outside the locks */ 2619fcf3ce44SJohn Forte iocbq = (IOCBQ *)abort.q_first; 2620fcf3ce44SJohn Forte while (iocbq) { 2621fcf3ce44SJohn Forte /* Save the next iocbq for now */ 2622fcf3ce44SJohn Forte next = (IOCBQ *)iocbq->next; 2623fcf3ce44SJohn Forte 2624fcf3ce44SJohn Forte /* Unlink this iocbq */ 2625fcf3ce44SJohn Forte iocbq->next = NULL; 2626fcf3ce44SJohn Forte 2627fcf3ce44SJohn Forte /* Get the pkt */ 2628fcf3ce44SJohn Forte sbp = (emlxs_buf_t *)iocbq->sbp; 2629fcf3ce44SJohn Forte 2630fcf3ce44SJohn Forte if (sbp) { 2631fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flush_msg, 2632291a2b48SSukumar Swaminathan "tx: sbp=%p node=%p", sbp, sbp->node); 2633fcf3ce44SJohn Forte 2634fcf3ce44SJohn Forte if (hba->state >= FC_LINK_UP) { 2635fcf3ce44SJohn Forte emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 2636fcf3ce44SJohn Forte IOERR_ABORT_REQUESTED, 1); 2637fcf3ce44SJohn Forte } else { 2638fcf3ce44SJohn Forte emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 2639fcf3ce44SJohn Forte IOERR_LINK_DOWN, 1); 2640fcf3ce44SJohn Forte } 2641fcf3ce44SJohn Forte 2642fcf3ce44SJohn Forte } 2643fcf3ce44SJohn Forte /* Free the iocb and its associated buffers */ 2644fcf3ce44SJohn Forte else { 264582527734SSukumar Swaminathan /* CMD_CLOSE_XRI_CN should also free the memory */ 2646fcf3ce44SJohn Forte icmd = &iocbq->iocb; 264782527734SSukumar Swaminathan 264882527734SSukumar Swaminathan /* SLI3 */ 264982527734SSukumar Swaminathan if (icmd->ULPCOMMAND == CMD_QUE_RING_BUF64_CN || 265082527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_QUE_RING_BUF_CN || 265182527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_QUE_RING_LIST64_CN) { 2652fcf3ce44SJohn Forte if ((hba->flag & 2653fcf3ce44SJohn Forte (FC_ONLINE_MODE | FC_ONLINING_MODE)) == 0) { 2654fcf3ce44SJohn Forte /* HBA is detaching or offlining */ 265582527734SSukumar Swaminathan if (icmd->ULPCOMMAND != 2656fcf3ce44SJohn Forte CMD_QUE_RING_LIST64_CN) { 2657a9800bebSGarrett D'Amore void *tmp; 265882527734SSukumar Swaminathan RING *rp; 265982527734SSukumar Swaminathan int ch; 2660fcf3ce44SJohn Forte 266182527734SSukumar Swaminathan ch = ((CHANNEL *) 266282527734SSukumar Swaminathan iocbq->channel)->channelno; 266382527734SSukumar Swaminathan rp = &hba->sli.sli3.ring[ch]; 2664fcf3ce44SJohn Forte for (i = 0; 266582527734SSukumar Swaminathan i < icmd->ULPBDECOUNT; 2666fcf3ce44SJohn Forte i++) { 2667fcf3ce44SJohn Forte mp = EMLXS_GET_VADDR( 2668fcf3ce44SJohn Forte hba, rp, icmd); 2669fcf3ce44SJohn Forte 2670a9800bebSGarrett D'Amore tmp = (void *)mp; 2671fcf3ce44SJohn Forte if (mp) { 2672a9800bebSGarrett D'Amore emlxs_mem_put( 2673291a2b48SSukumar Swaminathan hba, MEM_BUF, tmp); 2674fcf3ce44SJohn Forte } 2675fcf3ce44SJohn Forte } 2676fcf3ce44SJohn Forte } 2677291a2b48SSukumar Swaminathan 2678a9800bebSGarrett D'Amore emlxs_mem_put(hba, MEM_IOCB, 2679a9800bebSGarrett D'Amore (void *)iocbq); 2680fcf3ce44SJohn Forte } else { 2681fcf3ce44SJohn Forte /* repost the unsolicited buffer */ 268282527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, 268382527734SSukumar Swaminathan (CHANNEL *)iocbq->channel, iocbq); 2684fcf3ce44SJohn Forte } 268582527734SSukumar Swaminathan } else if (icmd->ULPCOMMAND == CMD_CLOSE_XRI_CN || 268682527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_CLOSE_XRI_CX) { 268782527734SSukumar Swaminathan /* 268882527734SSukumar Swaminathan * Resend the abort iocbq if any 268982527734SSukumar Swaminathan */ 269082527734SSukumar Swaminathan emlxs_tx_put(iocbq, 1); 2691fcf3ce44SJohn Forte } 2692fcf3ce44SJohn Forte } 2693fcf3ce44SJohn Forte 2694fcf3ce44SJohn Forte iocbq = next; 2695fcf3ce44SJohn Forte 2696fcf3ce44SJohn Forte } /* end of while */ 2697fcf3ce44SJohn Forte 269882527734SSukumar Swaminathan /* Now trigger channel service */ 269982527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 270082527734SSukumar Swaminathan if (!flag[channelno]) { 270182527734SSukumar Swaminathan continue; 270282527734SSukumar Swaminathan } 270382527734SSukumar Swaminathan 270482527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, &hba->chan[channelno], 0); 270582527734SSukumar Swaminathan } 270682527734SSukumar Swaminathan 2707fcf3ce44SJohn Forte return (abort.q_cnt); 2708fcf3ce44SJohn Forte 270982527734SSukumar Swaminathan } /* emlxs_tx_node_flush() */ 2710fcf3ce44SJohn Forte 2711fcf3ce44SJohn Forte 2712fcf3ce44SJohn Forte /* Check for IO's on all or a given ring for a given node */ 2713fcf3ce44SJohn Forte extern uint32_t 271482527734SSukumar Swaminathan emlxs_tx_node_check(emlxs_port_t *port, NODELIST *ndlp, CHANNEL *chan) 2715fcf3ce44SJohn Forte { 2716fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 271782527734SSukumar Swaminathan uint32_t channelno; 271882527734SSukumar Swaminathan CHANNEL *cp; 2719fcf3ce44SJohn Forte uint32_t count; 2720fcf3ce44SJohn Forte 2721fcf3ce44SJohn Forte count = 0; 2722fcf3ce44SJohn Forte 2723fcf3ce44SJohn Forte /* Flush all I/O's on tx queue to this target */ 272482527734SSukumar Swaminathan mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 2725fcf3ce44SJohn Forte 272682527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 272782527734SSukumar Swaminathan cp = &hba->chan[channelno]; 2728fcf3ce44SJohn Forte 272982527734SSukumar Swaminathan if (chan && cp != chan) { 2730fcf3ce44SJohn Forte continue; 2731fcf3ce44SJohn Forte } 2732291a2b48SSukumar Swaminathan 2733fcf3ce44SJohn Forte /* Check if priority queue is not empty */ 273482527734SSukumar Swaminathan if (ndlp->nlp_ptx[channelno].q_first) { 273582527734SSukumar Swaminathan count += ndlp->nlp_ptx[channelno].q_cnt; 2736fcf3ce44SJohn Forte } 2737291a2b48SSukumar Swaminathan 2738fcf3ce44SJohn Forte /* Check if tx queue is not empty */ 273982527734SSukumar Swaminathan if (ndlp->nlp_tx[channelno].q_first) { 274082527734SSukumar Swaminathan count += ndlp->nlp_tx[channelno].q_cnt; 2741fcf3ce44SJohn Forte } 2742291a2b48SSukumar Swaminathan 2743fcf3ce44SJohn Forte } 2744fcf3ce44SJohn Forte 274582527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 2746fcf3ce44SJohn Forte 2747fcf3ce44SJohn Forte return (count); 2748fcf3ce44SJohn Forte 274982527734SSukumar Swaminathan } /* emlxs_tx_node_check() */ 2750fcf3ce44SJohn Forte 2751fcf3ce44SJohn Forte 2752fcf3ce44SJohn Forte 275382527734SSukumar Swaminathan /* Flush all IO's on the any ring for a given node's lun */ 2754fcf3ce44SJohn Forte extern uint32_t 2755291a2b48SSukumar Swaminathan emlxs_tx_lun_flush(emlxs_port_t *port, NODELIST *ndlp, uint32_t lun, 2756291a2b48SSukumar Swaminathan emlxs_buf_t *fpkt) 2757fcf3ce44SJohn Forte { 2758fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 2759fcf3ce44SJohn Forte emlxs_buf_t *sbp; 276082527734SSukumar Swaminathan uint32_t channelno; 2761fcf3ce44SJohn Forte IOCBQ *iocbq; 2762fcf3ce44SJohn Forte IOCBQ *prev; 2763fcf3ce44SJohn Forte IOCBQ *next; 2764fcf3ce44SJohn Forte IOCB *iocb; 2765fcf3ce44SJohn Forte IOCB *icmd; 2766fcf3ce44SJohn Forte Q abort; 2767fcf3ce44SJohn Forte uint32_t i; 2768fcf3ce44SJohn Forte MATCHMAP *mp; 276982527734SSukumar Swaminathan uint8_t flag[MAX_CHANNEL]; 2770fcf3ce44SJohn Forte 2771a9800bebSGarrett D'Amore if (lun == EMLXS_LUN_NONE) { 2772a9800bebSGarrett D'Amore return (0); 2773a9800bebSGarrett D'Amore } 2774a9800bebSGarrett D'Amore 2775fcf3ce44SJohn Forte bzero((void *)&abort, sizeof (Q)); 2776fcf3ce44SJohn Forte 2777fcf3ce44SJohn Forte /* Flush I/O's on txQ to this target's lun */ 277882527734SSukumar Swaminathan mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 2779fcf3ce44SJohn Forte 278082527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 2781291a2b48SSukumar Swaminathan 278282527734SSukumar Swaminathan /* Scan the priority queue first */ 278382527734SSukumar Swaminathan prev = NULL; 278482527734SSukumar Swaminathan iocbq = (IOCBQ *) ndlp->nlp_ptx[channelno].q_first; 2785fcf3ce44SJohn Forte 278682527734SSukumar Swaminathan while (iocbq) { 278782527734SSukumar Swaminathan next = (IOCBQ *)iocbq->next; 278882527734SSukumar Swaminathan iocb = &iocbq->iocb; 278982527734SSukumar Swaminathan sbp = (emlxs_buf_t *)iocbq->sbp; 279082527734SSukumar Swaminathan 279182527734SSukumar Swaminathan /* Check if this IO is for our lun */ 279282527734SSukumar Swaminathan if (sbp && (sbp->lun == lun)) { 279382527734SSukumar Swaminathan /* Remove iocb from the node's ptx queue */ 279482527734SSukumar Swaminathan if (next == 0) { 279582527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_last = 279682527734SSukumar Swaminathan (uint8_t *)prev; 279782527734SSukumar Swaminathan } 279882527734SSukumar Swaminathan 279982527734SSukumar Swaminathan if (prev == 0) { 280082527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_first = 280182527734SSukumar Swaminathan (uint8_t *)next; 280282527734SSukumar Swaminathan } else { 280382527734SSukumar Swaminathan prev->next = next; 280482527734SSukumar Swaminathan } 280582527734SSukumar Swaminathan 280682527734SSukumar Swaminathan iocbq->next = NULL; 280782527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_cnt--; 280882527734SSukumar Swaminathan 280982527734SSukumar Swaminathan /* 281082527734SSukumar Swaminathan * Add this iocb to our local abort Q 281182527734SSukumar Swaminathan */ 281282527734SSukumar Swaminathan if (abort.q_first) { 281382527734SSukumar Swaminathan ((IOCBQ *)abort.q_last)->next = iocbq; 281482527734SSukumar Swaminathan abort.q_last = (uint8_t *)iocbq; 281582527734SSukumar Swaminathan abort.q_cnt++; 281682527734SSukumar Swaminathan } else { 281782527734SSukumar Swaminathan abort.q_first = (uint8_t *)iocbq; 281882527734SSukumar Swaminathan abort.q_last = (uint8_t *)iocbq; 281982527734SSukumar Swaminathan abort.q_cnt = 1; 282082527734SSukumar Swaminathan } 282182527734SSukumar Swaminathan iocbq->next = NULL; 282282527734SSukumar Swaminathan flag[channelno] = 1; 2823fcf3ce44SJohn Forte 2824fcf3ce44SJohn Forte } else { 282582527734SSukumar Swaminathan prev = iocbq; 2826fcf3ce44SJohn Forte } 2827fcf3ce44SJohn Forte 282882527734SSukumar Swaminathan iocbq = next; 2829fcf3ce44SJohn Forte 283082527734SSukumar Swaminathan } /* while (iocbq) */ 2831fcf3ce44SJohn Forte 2832fcf3ce44SJohn Forte 283382527734SSukumar Swaminathan /* Scan the regular queue */ 283482527734SSukumar Swaminathan prev = NULL; 283582527734SSukumar Swaminathan iocbq = (IOCBQ *)ndlp->nlp_tx[channelno].q_first; 2836fcf3ce44SJohn Forte 283782527734SSukumar Swaminathan while (iocbq) { 283882527734SSukumar Swaminathan next = (IOCBQ *)iocbq->next; 283982527734SSukumar Swaminathan iocb = &iocbq->iocb; 284082527734SSukumar Swaminathan sbp = (emlxs_buf_t *)iocbq->sbp; 284182527734SSukumar Swaminathan 284282527734SSukumar Swaminathan /* Check if this IO is for our lun */ 284382527734SSukumar Swaminathan if (sbp && (sbp->lun == lun)) { 284482527734SSukumar Swaminathan /* Remove iocb from the node's tx queue */ 284582527734SSukumar Swaminathan if (next == 0) { 284682527734SSukumar Swaminathan ndlp->nlp_tx[channelno].q_last = 284782527734SSukumar Swaminathan (uint8_t *)prev; 284882527734SSukumar Swaminathan } 2849291a2b48SSukumar Swaminathan 285082527734SSukumar Swaminathan if (prev == 0) { 285182527734SSukumar Swaminathan ndlp->nlp_tx[channelno].q_first = 285282527734SSukumar Swaminathan (uint8_t *)next; 285382527734SSukumar Swaminathan } else { 285482527734SSukumar Swaminathan prev->next = next; 285582527734SSukumar Swaminathan } 2856fcf3ce44SJohn Forte 285782527734SSukumar Swaminathan iocbq->next = NULL; 285882527734SSukumar Swaminathan ndlp->nlp_tx[channelno].q_cnt--; 2859fcf3ce44SJohn Forte 286082527734SSukumar Swaminathan /* 286182527734SSukumar Swaminathan * Add this iocb to our local abort Q 286282527734SSukumar Swaminathan */ 286382527734SSukumar Swaminathan if (abort.q_first) { 286482527734SSukumar Swaminathan ((IOCBQ *) abort.q_last)->next = iocbq; 286582527734SSukumar Swaminathan abort.q_last = (uint8_t *)iocbq; 286682527734SSukumar Swaminathan abort.q_cnt++; 286782527734SSukumar Swaminathan } else { 286882527734SSukumar Swaminathan abort.q_first = (uint8_t *)iocbq; 286982527734SSukumar Swaminathan abort.q_last = (uint8_t *)iocbq; 287082527734SSukumar Swaminathan abort.q_cnt = 1; 287182527734SSukumar Swaminathan } 287282527734SSukumar Swaminathan iocbq->next = NULL; 2873fcf3ce44SJohn Forte } else { 287482527734SSukumar Swaminathan prev = iocbq; 2875fcf3ce44SJohn Forte } 2876fcf3ce44SJohn Forte 287782527734SSukumar Swaminathan iocbq = next; 2878fcf3ce44SJohn Forte 287982527734SSukumar Swaminathan } /* while (iocbq) */ 288082527734SSukumar Swaminathan } /* for loop */ 2881fcf3ce44SJohn Forte 2882fcf3ce44SJohn Forte /* First cleanup the iocb's while still holding the lock */ 2883fcf3ce44SJohn Forte iocbq = (IOCBQ *)abort.q_first; 2884fcf3ce44SJohn Forte while (iocbq) { 2885fcf3ce44SJohn Forte /* Free the IoTag and the bmp */ 2886fcf3ce44SJohn Forte iocb = &iocbq->iocb; 288782527734SSukumar Swaminathan 288882527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 288982527734SSukumar Swaminathan sbp = iocbq->sbp; 289082527734SSukumar Swaminathan if (sbp) { 2891*8f23e9faSHans Rosenfeld emlxs_sli4_free_xri(port, sbp, sbp->xrip, 1); 289282527734SSukumar Swaminathan } 289382527734SSukumar Swaminathan } else { 289482527734SSukumar Swaminathan sbp = emlxs_unregister_pkt((CHANNEL *)iocbq->channel, 289582527734SSukumar Swaminathan iocb->ULPIOTAG, 0); 289682527734SSukumar Swaminathan } 2897fcf3ce44SJohn Forte 2898fcf3ce44SJohn Forte if (sbp && (sbp != STALE_PACKET)) { 2899fcf3ce44SJohn Forte mutex_enter(&sbp->mtx); 2900fcf3ce44SJohn Forte sbp->pkt_flags |= PACKET_IN_FLUSH; 2901fcf3ce44SJohn Forte /* 2902fcf3ce44SJohn Forte * If the fpkt is already set, then we will leave it 2903291a2b48SSukumar Swaminathan * alone. This ensures that this pkt is only accounted 2904291a2b48SSukumar Swaminathan * for on one fpkt->flush_count 2905fcf3ce44SJohn Forte */ 2906fcf3ce44SJohn Forte if (!sbp->fpkt && fpkt) { 2907fcf3ce44SJohn Forte mutex_enter(&fpkt->mtx); 2908fcf3ce44SJohn Forte sbp->fpkt = fpkt; 2909fcf3ce44SJohn Forte fpkt->flush_count++; 2910fcf3ce44SJohn Forte mutex_exit(&fpkt->mtx); 2911fcf3ce44SJohn Forte } 2912291a2b48SSukumar Swaminathan 2913fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 2914fcf3ce44SJohn Forte } 2915291a2b48SSukumar Swaminathan 2916291a2b48SSukumar Swaminathan iocbq = (IOCBQ *) iocbq->next; 2917fcf3ce44SJohn Forte 2918fcf3ce44SJohn Forte } /* end of while */ 2919fcf3ce44SJohn Forte 292082527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 2921fcf3ce44SJohn Forte 2922fcf3ce44SJohn Forte /* Now abort the iocb's outside the locks */ 2923fcf3ce44SJohn Forte iocbq = (IOCBQ *)abort.q_first; 2924fcf3ce44SJohn Forte while (iocbq) { 2925fcf3ce44SJohn Forte /* Save the next iocbq for now */ 2926fcf3ce44SJohn Forte next = (IOCBQ *)iocbq->next; 2927fcf3ce44SJohn Forte 2928fcf3ce44SJohn Forte /* Unlink this iocbq */ 2929fcf3ce44SJohn Forte iocbq->next = NULL; 2930fcf3ce44SJohn Forte 2931fcf3ce44SJohn Forte /* Get the pkt */ 2932fcf3ce44SJohn Forte sbp = (emlxs_buf_t *)iocbq->sbp; 2933fcf3ce44SJohn Forte 2934fcf3ce44SJohn Forte if (sbp) { 2935fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flush_msg, 2936291a2b48SSukumar Swaminathan "tx: sbp=%p node=%p", sbp, sbp->node); 2937fcf3ce44SJohn Forte 2938fcf3ce44SJohn Forte if (hba->state >= FC_LINK_UP) { 2939fcf3ce44SJohn Forte emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 2940fcf3ce44SJohn Forte IOERR_ABORT_REQUESTED, 1); 2941fcf3ce44SJohn Forte } else { 2942fcf3ce44SJohn Forte emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 2943fcf3ce44SJohn Forte IOERR_LINK_DOWN, 1); 2944fcf3ce44SJohn Forte } 2945fcf3ce44SJohn Forte } 2946291a2b48SSukumar Swaminathan 2947fcf3ce44SJohn Forte /* Free the iocb and its associated buffers */ 2948fcf3ce44SJohn Forte else { 294982527734SSukumar Swaminathan /* Should never happen! */ 2950fcf3ce44SJohn Forte icmd = &iocbq->iocb; 2951fcf3ce44SJohn Forte 295282527734SSukumar Swaminathan /* SLI3 */ 295382527734SSukumar Swaminathan if (icmd->ULPCOMMAND == CMD_QUE_RING_BUF64_CN || 295482527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_QUE_RING_BUF_CN || 295582527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_QUE_RING_LIST64_CN) { 2956fcf3ce44SJohn Forte if ((hba->flag & 2957fcf3ce44SJohn Forte (FC_ONLINE_MODE | FC_ONLINING_MODE)) == 0) { 2958fcf3ce44SJohn Forte /* HBA is detaching or offlining */ 295982527734SSukumar Swaminathan if (icmd->ULPCOMMAND != 2960fcf3ce44SJohn Forte CMD_QUE_RING_LIST64_CN) { 2961a9800bebSGarrett D'Amore void *tmp; 296282527734SSukumar Swaminathan RING *rp; 296382527734SSukumar Swaminathan int ch; 2964fcf3ce44SJohn Forte 296582527734SSukumar Swaminathan ch = ((CHANNEL *) 296682527734SSukumar Swaminathan iocbq->channel)->channelno; 296782527734SSukumar Swaminathan rp = &hba->sli.sli3.ring[ch]; 2968fcf3ce44SJohn Forte for (i = 0; 296982527734SSukumar Swaminathan i < icmd->ULPBDECOUNT; 2970fcf3ce44SJohn Forte i++) { 2971fcf3ce44SJohn Forte mp = EMLXS_GET_VADDR( 2972fcf3ce44SJohn Forte hba, rp, icmd); 2973fcf3ce44SJohn Forte 2974a9800bebSGarrett D'Amore tmp = (void *)mp; 2975fcf3ce44SJohn Forte if (mp) { 2976a9800bebSGarrett D'Amore emlxs_mem_put( 2977291a2b48SSukumar Swaminathan hba, MEM_BUF, tmp); 2978fcf3ce44SJohn Forte } 2979fcf3ce44SJohn Forte } 2980fcf3ce44SJohn Forte } 2981291a2b48SSukumar Swaminathan 2982a9800bebSGarrett D'Amore emlxs_mem_put(hba, MEM_IOCB, 2983a9800bebSGarrett D'Amore (void *)iocbq); 2984fcf3ce44SJohn Forte } else { 2985fcf3ce44SJohn Forte /* repost the unsolicited buffer */ 298682527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, 298782527734SSukumar Swaminathan (CHANNEL *)iocbq->channel, iocbq); 2988fcf3ce44SJohn Forte } 298982527734SSukumar Swaminathan } else if (icmd->ULPCOMMAND == CMD_CLOSE_XRI_CN || 299082527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_CLOSE_XRI_CX) { 299182527734SSukumar Swaminathan /* 299282527734SSukumar Swaminathan * Resend the abort iocbq if any 299382527734SSukumar Swaminathan */ 299482527734SSukumar Swaminathan emlxs_tx_put(iocbq, 1); 2995fcf3ce44SJohn Forte } 2996fcf3ce44SJohn Forte } 2997fcf3ce44SJohn Forte 2998fcf3ce44SJohn Forte iocbq = next; 2999fcf3ce44SJohn Forte 3000fcf3ce44SJohn Forte } /* end of while */ 3001fcf3ce44SJohn Forte 300282527734SSukumar Swaminathan /* Now trigger channel service */ 300382527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 300482527734SSukumar Swaminathan if (!flag[channelno]) { 300582527734SSukumar Swaminathan continue; 300682527734SSukumar Swaminathan } 300782527734SSukumar Swaminathan 300882527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, &hba->chan[channelno], 0); 300982527734SSukumar Swaminathan } 3010fcf3ce44SJohn Forte 3011fcf3ce44SJohn Forte return (abort.q_cnt); 3012fcf3ce44SJohn Forte 301382527734SSukumar Swaminathan } /* emlxs_tx_lun_flush() */ 3014fcf3ce44SJohn Forte 3015fcf3ce44SJohn Forte 3016fcf3ce44SJohn Forte extern void 3017fcf3ce44SJohn Forte emlxs_tx_put(IOCBQ *iocbq, uint32_t lock) 3018fcf3ce44SJohn Forte { 3019fcf3ce44SJohn Forte emlxs_hba_t *hba; 3020fcf3ce44SJohn Forte emlxs_port_t *port; 302182527734SSukumar Swaminathan uint32_t channelno; 3022fcf3ce44SJohn Forte NODELIST *nlp; 302382527734SSukumar Swaminathan CHANNEL *cp; 3024fcf3ce44SJohn Forte emlxs_buf_t *sbp; 3025fcf3ce44SJohn Forte 3026fcf3ce44SJohn Forte port = (emlxs_port_t *)iocbq->port; 3027fcf3ce44SJohn Forte hba = HBA; 302882527734SSukumar Swaminathan cp = (CHANNEL *)iocbq->channel; 3029fcf3ce44SJohn Forte nlp = (NODELIST *)iocbq->node; 303082527734SSukumar Swaminathan channelno = cp->channelno; 3031fcf3ce44SJohn Forte sbp = (emlxs_buf_t *)iocbq->sbp; 3032fcf3ce44SJohn Forte 3033fcf3ce44SJohn Forte if (nlp == NULL) { 3034fcf3ce44SJohn Forte /* Set node to base node by default */ 3035fcf3ce44SJohn Forte nlp = &port->node_base; 3036fcf3ce44SJohn Forte 3037fcf3ce44SJohn Forte iocbq->node = (void *)nlp; 3038fcf3ce44SJohn Forte 3039fcf3ce44SJohn Forte if (sbp) { 3040fcf3ce44SJohn Forte sbp->node = (void *)nlp; 3041fcf3ce44SJohn Forte } 3042fcf3ce44SJohn Forte } 3043291a2b48SSukumar Swaminathan 3044fcf3ce44SJohn Forte if (lock) { 304582527734SSukumar Swaminathan mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 3046fcf3ce44SJohn Forte } 3047291a2b48SSukumar Swaminathan 3048fcf3ce44SJohn Forte if (!nlp->nlp_active || (sbp && (sbp->pkt_flags & PACKET_IN_ABORT))) { 3049fcf3ce44SJohn Forte if (sbp) { 3050fcf3ce44SJohn Forte mutex_enter(&sbp->mtx); 3051fcf3ce44SJohn Forte sbp->pkt_flags |= PACKET_IN_FLUSH; 3052fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 3053fcf3ce44SJohn Forte 305482527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 3055*8f23e9faSHans Rosenfeld emlxs_sli4_free_xri(port, sbp, sbp->xrip, 1); 305682527734SSukumar Swaminathan } else { 305782527734SSukumar Swaminathan (void) emlxs_unregister_pkt(cp, sbp->iotag, 0); 305882527734SSukumar Swaminathan } 3059fcf3ce44SJohn Forte 3060fcf3ce44SJohn Forte if (lock) { 306182527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 3062fcf3ce44SJohn Forte } 3063291a2b48SSukumar Swaminathan 3064fcf3ce44SJohn Forte if (hba->state >= FC_LINK_UP) { 3065fcf3ce44SJohn Forte emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 3066fcf3ce44SJohn Forte IOERR_ABORT_REQUESTED, 1); 3067fcf3ce44SJohn Forte } else { 3068fcf3ce44SJohn Forte emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 3069fcf3ce44SJohn Forte IOERR_LINK_DOWN, 1); 3070fcf3ce44SJohn Forte } 3071fcf3ce44SJohn Forte return; 3072fcf3ce44SJohn Forte } else { 3073fcf3ce44SJohn Forte if (lock) { 307482527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 3075fcf3ce44SJohn Forte } 3076291a2b48SSukumar Swaminathan 3077a9800bebSGarrett D'Amore emlxs_mem_put(hba, MEM_IOCB, (void *)iocbq); 3078fcf3ce44SJohn Forte } 3079fcf3ce44SJohn Forte 3080fcf3ce44SJohn Forte return; 3081fcf3ce44SJohn Forte } 3082291a2b48SSukumar Swaminathan 3083fcf3ce44SJohn Forte if (sbp) { 3084fcf3ce44SJohn Forte 3085fcf3ce44SJohn Forte mutex_enter(&sbp->mtx); 3086fcf3ce44SJohn Forte 3087291a2b48SSukumar Swaminathan if (sbp->pkt_flags & 3088291a2b48SSukumar Swaminathan (PACKET_IN_COMPLETION | PACKET_IN_CHIPQ | PACKET_IN_TXQ)) { 3089fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 3090fcf3ce44SJohn Forte if (lock) { 309182527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 3092fcf3ce44SJohn Forte } 3093fcf3ce44SJohn Forte return; 3094fcf3ce44SJohn Forte } 3095291a2b48SSukumar Swaminathan 3096fcf3ce44SJohn Forte sbp->pkt_flags |= PACKET_IN_TXQ; 309782527734SSukumar Swaminathan hba->channel_tx_count++; 3098fcf3ce44SJohn Forte 3099fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 3100fcf3ce44SJohn Forte } 3101291a2b48SSukumar Swaminathan 3102291a2b48SSukumar Swaminathan 3103fcf3ce44SJohn Forte /* Check iocbq priority */ 310482527734SSukumar Swaminathan /* Some IOCB has the high priority like reset/close xri etc */ 3105fcf3ce44SJohn Forte if (iocbq->flag & IOCB_PRIORITY) { 3106fcf3ce44SJohn Forte /* Add the iocb to the bottom of the node's ptx queue */ 310782527734SSukumar Swaminathan if (nlp->nlp_ptx[channelno].q_first) { 310882527734SSukumar Swaminathan ((IOCBQ *)nlp->nlp_ptx[channelno].q_last)->next = iocbq; 310982527734SSukumar Swaminathan nlp->nlp_ptx[channelno].q_last = (uint8_t *)iocbq; 311082527734SSukumar Swaminathan nlp->nlp_ptx[channelno].q_cnt++; 3111fcf3ce44SJohn Forte } else { 311282527734SSukumar Swaminathan nlp->nlp_ptx[channelno].q_first = (uint8_t *)iocbq; 311382527734SSukumar Swaminathan nlp->nlp_ptx[channelno].q_last = (uint8_t *)iocbq; 311482527734SSukumar Swaminathan nlp->nlp_ptx[channelno].q_cnt = 1; 3115fcf3ce44SJohn Forte } 3116fcf3ce44SJohn Forte 3117fcf3ce44SJohn Forte iocbq->next = NULL; 3118fcf3ce44SJohn Forte } else { /* Normal priority */ 3119fcf3ce44SJohn Forte 3120291a2b48SSukumar Swaminathan 3121fcf3ce44SJohn Forte /* Add the iocb to the bottom of the node's tx queue */ 312282527734SSukumar Swaminathan if (nlp->nlp_tx[channelno].q_first) { 312382527734SSukumar Swaminathan ((IOCBQ *)nlp->nlp_tx[channelno].q_last)->next = iocbq; 312482527734SSukumar Swaminathan nlp->nlp_tx[channelno].q_last = (uint8_t *)iocbq; 312582527734SSukumar Swaminathan nlp->nlp_tx[channelno].q_cnt++; 3126fcf3ce44SJohn Forte } else { 312782527734SSukumar Swaminathan nlp->nlp_tx[channelno].q_first = (uint8_t *)iocbq; 312882527734SSukumar Swaminathan nlp->nlp_tx[channelno].q_last = (uint8_t *)iocbq; 312982527734SSukumar Swaminathan nlp->nlp_tx[channelno].q_cnt = 1; 3130fcf3ce44SJohn Forte } 3131fcf3ce44SJohn Forte 3132fcf3ce44SJohn Forte iocbq->next = NULL; 3133fcf3ce44SJohn Forte } 3134fcf3ce44SJohn Forte 3135fcf3ce44SJohn Forte 3136fcf3ce44SJohn Forte /* 313782527734SSukumar Swaminathan * Check if the node is not already on channel queue and 3138291a2b48SSukumar Swaminathan * (is not closed or is a priority request) 3139fcf3ce44SJohn Forte */ 314082527734SSukumar Swaminathan if (!nlp->nlp_next[channelno] && 314182527734SSukumar Swaminathan (!(nlp->nlp_flag[channelno] & NLP_CLOSED) || 3142fcf3ce44SJohn Forte (iocbq->flag & IOCB_PRIORITY))) { 314382527734SSukumar Swaminathan /* If so, then add it to the channel queue */ 314482527734SSukumar Swaminathan if (cp->nodeq.q_first) { 314582527734SSukumar Swaminathan ((NODELIST *)cp->nodeq.q_last)->nlp_next[channelno] = 3146fcf3ce44SJohn Forte (uint8_t *)nlp; 314782527734SSukumar Swaminathan nlp->nlp_next[channelno] = cp->nodeq.q_first; 3148fcf3ce44SJohn Forte 3149fcf3ce44SJohn Forte /* 3150291a2b48SSukumar Swaminathan * If this is not the base node then add it 3151291a2b48SSukumar Swaminathan * to the tail 3152fcf3ce44SJohn Forte */ 3153fcf3ce44SJohn Forte if (!nlp->nlp_base) { 315482527734SSukumar Swaminathan cp->nodeq.q_last = (uint8_t *)nlp; 3155fcf3ce44SJohn Forte } else { /* Otherwise, add it to the head */ 3156291a2b48SSukumar Swaminathan 3157fcf3ce44SJohn Forte /* The command node always gets priority */ 315882527734SSukumar Swaminathan cp->nodeq.q_first = (uint8_t *)nlp; 3159fcf3ce44SJohn Forte } 3160fcf3ce44SJohn Forte 316182527734SSukumar Swaminathan cp->nodeq.q_cnt++; 3162fcf3ce44SJohn Forte } else { 316382527734SSukumar Swaminathan cp->nodeq.q_first = (uint8_t *)nlp; 316482527734SSukumar Swaminathan cp->nodeq.q_last = (uint8_t *)nlp; 316582527734SSukumar Swaminathan nlp->nlp_next[channelno] = nlp; 316682527734SSukumar Swaminathan cp->nodeq.q_cnt = 1; 3167fcf3ce44SJohn Forte } 3168fcf3ce44SJohn Forte } 3169291a2b48SSukumar Swaminathan 317082527734SSukumar Swaminathan HBASTATS.IocbTxPut[channelno]++; 3171fcf3ce44SJohn Forte 317282527734SSukumar Swaminathan /* Adjust the channel timeout timer */ 317382527734SSukumar Swaminathan cp->timeout = hba->timer_tics + 5; 3174fcf3ce44SJohn Forte 3175fcf3ce44SJohn Forte if (lock) { 317682527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 3177fcf3ce44SJohn Forte } 3178291a2b48SSukumar Swaminathan 3179fcf3ce44SJohn Forte return; 3180fcf3ce44SJohn Forte 318182527734SSukumar Swaminathan } /* emlxs_tx_put() */ 3182fcf3ce44SJohn Forte 3183fcf3ce44SJohn Forte 3184fcf3ce44SJohn Forte extern IOCBQ * 318582527734SSukumar Swaminathan emlxs_tx_get(CHANNEL *cp, uint32_t lock) 3186fcf3ce44SJohn Forte { 3187fcf3ce44SJohn Forte emlxs_hba_t *hba; 318882527734SSukumar Swaminathan uint32_t channelno; 3189fcf3ce44SJohn Forte IOCBQ *iocbq; 3190fcf3ce44SJohn Forte NODELIST *nlp; 3191fcf3ce44SJohn Forte emlxs_buf_t *sbp; 3192fcf3ce44SJohn Forte 319382527734SSukumar Swaminathan hba = cp->hba; 319482527734SSukumar Swaminathan channelno = cp->channelno; 3195fcf3ce44SJohn Forte 3196fcf3ce44SJohn Forte if (lock) { 319782527734SSukumar Swaminathan mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 3198fcf3ce44SJohn Forte } 3199291a2b48SSukumar Swaminathan 3200fcf3ce44SJohn Forte begin: 3201fcf3ce44SJohn Forte 3202fcf3ce44SJohn Forte iocbq = NULL; 3203fcf3ce44SJohn Forte 3204fcf3ce44SJohn Forte /* Check if a node needs servicing */ 320582527734SSukumar Swaminathan if (cp->nodeq.q_first) { 320682527734SSukumar Swaminathan nlp = (NODELIST *)cp->nodeq.q_first; 3207fcf3ce44SJohn Forte 3208fcf3ce44SJohn Forte /* Get next iocb from node's priority queue */ 3209fcf3ce44SJohn Forte 321082527734SSukumar Swaminathan if (nlp->nlp_ptx[channelno].q_first) { 321182527734SSukumar Swaminathan iocbq = (IOCBQ *)nlp->nlp_ptx[channelno].q_first; 3212fcf3ce44SJohn Forte 3213fcf3ce44SJohn Forte /* Check if this is last entry */ 321482527734SSukumar Swaminathan if (nlp->nlp_ptx[channelno].q_last == (void *)iocbq) { 321582527734SSukumar Swaminathan nlp->nlp_ptx[channelno].q_first = NULL; 321682527734SSukumar Swaminathan nlp->nlp_ptx[channelno].q_last = NULL; 321782527734SSukumar Swaminathan nlp->nlp_ptx[channelno].q_cnt = 0; 3218fcf3ce44SJohn Forte } else { 3219fcf3ce44SJohn Forte /* Remove iocb from head */ 322082527734SSukumar Swaminathan nlp->nlp_ptx[channelno].q_first = 3221fcf3ce44SJohn Forte (void *)iocbq->next; 322282527734SSukumar Swaminathan nlp->nlp_ptx[channelno].q_cnt--; 3223fcf3ce44SJohn Forte } 3224fcf3ce44SJohn Forte 3225fcf3ce44SJohn Forte iocbq->next = NULL; 3226fcf3ce44SJohn Forte } 3227291a2b48SSukumar Swaminathan 3228fcf3ce44SJohn Forte /* Get next iocb from node tx queue if node not closed */ 322982527734SSukumar Swaminathan else if (nlp->nlp_tx[channelno].q_first && 323082527734SSukumar Swaminathan !(nlp->nlp_flag[channelno] & NLP_CLOSED)) { 323182527734SSukumar Swaminathan iocbq = (IOCBQ *)nlp->nlp_tx[channelno].q_first; 3232fcf3ce44SJohn Forte 3233fcf3ce44SJohn Forte /* Check if this is last entry */ 323482527734SSukumar Swaminathan if (nlp->nlp_tx[channelno].q_last == (void *)iocbq) { 323582527734SSukumar Swaminathan nlp->nlp_tx[channelno].q_first = NULL; 323682527734SSukumar Swaminathan nlp->nlp_tx[channelno].q_last = NULL; 323782527734SSukumar Swaminathan nlp->nlp_tx[channelno].q_cnt = 0; 3238fcf3ce44SJohn Forte } else { 3239fcf3ce44SJohn Forte /* Remove iocb from head */ 324082527734SSukumar Swaminathan nlp->nlp_tx[channelno].q_first = 3241fcf3ce44SJohn Forte (void *)iocbq->next; 324282527734SSukumar Swaminathan nlp->nlp_tx[channelno].q_cnt--; 3243fcf3ce44SJohn Forte } 3244fcf3ce44SJohn Forte 3245fcf3ce44SJohn Forte iocbq->next = NULL; 3246fcf3ce44SJohn Forte } 3247291a2b48SSukumar Swaminathan 3248fcf3ce44SJohn Forte /* Now deal with node itself */ 3249fcf3ce44SJohn Forte 3250fcf3ce44SJohn Forte /* Check if node still needs servicing */ 325182527734SSukumar Swaminathan if ((nlp->nlp_ptx[channelno].q_first) || 325282527734SSukumar Swaminathan (nlp->nlp_tx[channelno].q_first && 325382527734SSukumar Swaminathan !(nlp->nlp_flag[channelno] & NLP_CLOSED))) { 3254fcf3ce44SJohn Forte 3255fcf3ce44SJohn Forte /* 3256fcf3ce44SJohn Forte * If this is the base node, then don't shift the 3257291a2b48SSukumar Swaminathan * pointers. We want to drain the base node before 3258291a2b48SSukumar Swaminathan * moving on 3259fcf3ce44SJohn Forte */ 3260fcf3ce44SJohn Forte if (!nlp->nlp_base) { 3261fcf3ce44SJohn Forte /* 326282527734SSukumar Swaminathan * Just shift channel queue pointers to next 3263fcf3ce44SJohn Forte * node 3264fcf3ce44SJohn Forte */ 326582527734SSukumar Swaminathan cp->nodeq.q_last = (void *)nlp; 326682527734SSukumar Swaminathan cp->nodeq.q_first = nlp->nlp_next[channelno]; 3267fcf3ce44SJohn Forte } 3268fcf3ce44SJohn Forte } else { 326982527734SSukumar Swaminathan /* Remove node from channel queue */ 3270fcf3ce44SJohn Forte 3271fcf3ce44SJohn Forte /* If this is the last node on list */ 327282527734SSukumar Swaminathan if (cp->nodeq.q_last == (void *)nlp) { 327382527734SSukumar Swaminathan cp->nodeq.q_last = NULL; 327482527734SSukumar Swaminathan cp->nodeq.q_first = NULL; 327582527734SSukumar Swaminathan cp->nodeq.q_cnt = 0; 3276fcf3ce44SJohn Forte } else { 3277fcf3ce44SJohn Forte /* Remove node from head */ 327882527734SSukumar Swaminathan cp->nodeq.q_first = nlp->nlp_next[channelno]; 327982527734SSukumar Swaminathan ((NODELIST *)cp->nodeq.q_last)-> 328082527734SSukumar Swaminathan nlp_next[channelno] = cp->nodeq.q_first; 328182527734SSukumar Swaminathan cp->nodeq.q_cnt--; 3282fcf3ce44SJohn Forte 3283fcf3ce44SJohn Forte } 3284fcf3ce44SJohn Forte 3285fcf3ce44SJohn Forte /* Clear node */ 328682527734SSukumar Swaminathan nlp->nlp_next[channelno] = NULL; 3287fcf3ce44SJohn Forte } 3288fcf3ce44SJohn Forte 3289fcf3ce44SJohn Forte /* 3290291a2b48SSukumar Swaminathan * If no iocbq was found on this node, then it will have 3291291a2b48SSukumar Swaminathan * been removed. So try again. 3292fcf3ce44SJohn Forte */ 3293fcf3ce44SJohn Forte if (!iocbq) { 3294fcf3ce44SJohn Forte goto begin; 3295fcf3ce44SJohn Forte } 3296291a2b48SSukumar Swaminathan 3297fcf3ce44SJohn Forte sbp = (emlxs_buf_t *)iocbq->sbp; 3298fcf3ce44SJohn Forte 3299fcf3ce44SJohn Forte if (sbp) { 3300fcf3ce44SJohn Forte /* 3301291a2b48SSukumar Swaminathan * Check flags before we enter mutex in case this 3302291a2b48SSukumar Swaminathan * has been flushed and destroyed 3303fcf3ce44SJohn Forte */ 3304fcf3ce44SJohn Forte if ((sbp->pkt_flags & 3305fcf3ce44SJohn Forte (PACKET_IN_COMPLETION | PACKET_IN_CHIPQ)) || 3306fcf3ce44SJohn Forte !(sbp->pkt_flags & PACKET_IN_TXQ)) { 3307fcf3ce44SJohn Forte goto begin; 3308fcf3ce44SJohn Forte } 3309291a2b48SSukumar Swaminathan 3310fcf3ce44SJohn Forte mutex_enter(&sbp->mtx); 3311fcf3ce44SJohn Forte 3312fcf3ce44SJohn Forte if ((sbp->pkt_flags & 3313fcf3ce44SJohn Forte (PACKET_IN_COMPLETION | PACKET_IN_CHIPQ)) || 3314fcf3ce44SJohn Forte !(sbp->pkt_flags & PACKET_IN_TXQ)) { 3315fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 3316fcf3ce44SJohn Forte goto begin; 3317fcf3ce44SJohn Forte } 3318291a2b48SSukumar Swaminathan 3319fcf3ce44SJohn Forte sbp->pkt_flags &= ~PACKET_IN_TXQ; 332082527734SSukumar Swaminathan hba->channel_tx_count--; 3321fcf3ce44SJohn Forte 3322fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 3323fcf3ce44SJohn Forte } 3324fcf3ce44SJohn Forte } 3325291a2b48SSukumar Swaminathan 3326fcf3ce44SJohn Forte if (iocbq) { 332782527734SSukumar Swaminathan HBASTATS.IocbTxGet[channelno]++; 3328fcf3ce44SJohn Forte } 3329291a2b48SSukumar Swaminathan 3330fcf3ce44SJohn Forte /* Adjust the ring timeout timer */ 333182527734SSukumar Swaminathan cp->timeout = (cp->nodeq.q_first) ? (hba->timer_tics + 5) : 0; 3332fcf3ce44SJohn Forte 3333fcf3ce44SJohn Forte if (lock) { 333482527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 3335fcf3ce44SJohn Forte } 3336291a2b48SSukumar Swaminathan 3337fcf3ce44SJohn Forte return (iocbq); 3338fcf3ce44SJohn Forte 333982527734SSukumar Swaminathan } /* emlxs_tx_get() */ 334082527734SSukumar Swaminathan 3341fcf3ce44SJohn Forte 334282527734SSukumar Swaminathan /* 334382527734SSukumar Swaminathan * Remove all cmd from from_rp's txq to to_rp's txq for ndlp. 334482527734SSukumar Swaminathan * The old IoTag has to be released, the new one has to be 334582527734SSukumar Swaminathan * allocated. Others no change 334682527734SSukumar Swaminathan * TX_CHANNEL lock is held 334782527734SSukumar Swaminathan */ 334882527734SSukumar Swaminathan extern void 334982527734SSukumar Swaminathan emlxs_tx_move(NODELIST *ndlp, CHANNEL *from_chan, CHANNEL *to_chan, 335082527734SSukumar Swaminathan uint32_t cmd, emlxs_buf_t *fpkt, uint32_t lock) 335182527734SSukumar Swaminathan { 335282527734SSukumar Swaminathan emlxs_hba_t *hba; 335382527734SSukumar Swaminathan emlxs_port_t *port; 335482527734SSukumar Swaminathan uint32_t fchanno, tchanno, i; 335582527734SSukumar Swaminathan 335682527734SSukumar Swaminathan IOCBQ *iocbq; 335782527734SSukumar Swaminathan IOCBQ *prev; 335882527734SSukumar Swaminathan IOCBQ *next; 335982527734SSukumar Swaminathan IOCB *iocb, *icmd; 336082527734SSukumar Swaminathan Q tbm; /* To Be Moved Q */ 336182527734SSukumar Swaminathan MATCHMAP *mp; 336282527734SSukumar Swaminathan 336382527734SSukumar Swaminathan NODELIST *nlp = ndlp; 336482527734SSukumar Swaminathan emlxs_buf_t *sbp; 336582527734SSukumar Swaminathan 336682527734SSukumar Swaminathan NODELIST *n_prev = NULL; 336782527734SSukumar Swaminathan NODELIST *n_next = NULL; 336882527734SSukumar Swaminathan uint16_t count = 0; 336982527734SSukumar Swaminathan 337082527734SSukumar Swaminathan hba = from_chan->hba; 337182527734SSukumar Swaminathan port = &PPORT; 337282527734SSukumar Swaminathan cmd = cmd; /* To pass lint */ 337382527734SSukumar Swaminathan 337482527734SSukumar Swaminathan fchanno = from_chan->channelno; 337582527734SSukumar Swaminathan tchanno = to_chan->channelno; 337682527734SSukumar Swaminathan 337782527734SSukumar Swaminathan if (lock) { 337882527734SSukumar Swaminathan mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 337982527734SSukumar Swaminathan } 338082527734SSukumar Swaminathan 338182527734SSukumar Swaminathan bzero((void *)&tbm, sizeof (Q)); 338282527734SSukumar Swaminathan 338382527734SSukumar Swaminathan /* Scan the ndlp's fchanno txq to get the iocb of fcp cmd */ 338482527734SSukumar Swaminathan prev = NULL; 338582527734SSukumar Swaminathan iocbq = (IOCBQ *)nlp->nlp_tx[fchanno].q_first; 338682527734SSukumar Swaminathan 338782527734SSukumar Swaminathan while (iocbq) { 338882527734SSukumar Swaminathan next = (IOCBQ *)iocbq->next; 338982527734SSukumar Swaminathan /* Check if this iocb is fcp cmd */ 339082527734SSukumar Swaminathan iocb = &iocbq->iocb; 339182527734SSukumar Swaminathan 339282527734SSukumar Swaminathan switch (iocb->ULPCOMMAND) { 339382527734SSukumar Swaminathan /* FCP commands */ 339482527734SSukumar Swaminathan case CMD_FCP_ICMND_CR: 339582527734SSukumar Swaminathan case CMD_FCP_ICMND_CX: 339682527734SSukumar Swaminathan case CMD_FCP_IREAD_CR: 339782527734SSukumar Swaminathan case CMD_FCP_IREAD_CX: 339882527734SSukumar Swaminathan case CMD_FCP_IWRITE_CR: 339982527734SSukumar Swaminathan case CMD_FCP_IWRITE_CX: 340082527734SSukumar Swaminathan case CMD_FCP_ICMND64_CR: 340182527734SSukumar Swaminathan case CMD_FCP_ICMND64_CX: 340282527734SSukumar Swaminathan case CMD_FCP_IREAD64_CR: 340382527734SSukumar Swaminathan case CMD_FCP_IREAD64_CX: 340482527734SSukumar Swaminathan case CMD_FCP_IWRITE64_CR: 340582527734SSukumar Swaminathan case CMD_FCP_IWRITE64_CX: 340682527734SSukumar Swaminathan /* We found a fcp cmd */ 340782527734SSukumar Swaminathan break; 340882527734SSukumar Swaminathan default: 340982527734SSukumar Swaminathan /* this is not fcp cmd continue */ 341082527734SSukumar Swaminathan prev = iocbq; 341182527734SSukumar Swaminathan iocbq = next; 341282527734SSukumar Swaminathan continue; 341382527734SSukumar Swaminathan } 341482527734SSukumar Swaminathan 341582527734SSukumar Swaminathan /* found a fcp cmd iocb in fchanno txq, now deque it */ 341682527734SSukumar Swaminathan if (next == NULL) { 341782527734SSukumar Swaminathan /* This is the last iocbq */ 341882527734SSukumar Swaminathan nlp->nlp_tx[fchanno].q_last = 341982527734SSukumar Swaminathan (uint8_t *)prev; 342082527734SSukumar Swaminathan } 342182527734SSukumar Swaminathan 342282527734SSukumar Swaminathan if (prev == NULL) { 342382527734SSukumar Swaminathan /* This is the first one then remove it from head */ 342482527734SSukumar Swaminathan nlp->nlp_tx[fchanno].q_first = 342582527734SSukumar Swaminathan (uint8_t *)next; 342682527734SSukumar Swaminathan } else { 342782527734SSukumar Swaminathan prev->next = next; 342882527734SSukumar Swaminathan } 342982527734SSukumar Swaminathan 343082527734SSukumar Swaminathan iocbq->next = NULL; 343182527734SSukumar Swaminathan nlp->nlp_tx[fchanno].q_cnt--; 343282527734SSukumar Swaminathan 343382527734SSukumar Swaminathan /* Add this iocb to our local toberemovedq */ 343482527734SSukumar Swaminathan /* This way we donot hold the TX_CHANNEL lock too long */ 343582527734SSukumar Swaminathan 343682527734SSukumar Swaminathan if (tbm.q_first) { 343782527734SSukumar Swaminathan ((IOCBQ *)tbm.q_last)->next = iocbq; 343882527734SSukumar Swaminathan tbm.q_last = (uint8_t *)iocbq; 343982527734SSukumar Swaminathan tbm.q_cnt++; 344082527734SSukumar Swaminathan } else { 344182527734SSukumar Swaminathan tbm.q_first = (uint8_t *)iocbq; 344282527734SSukumar Swaminathan tbm.q_last = (uint8_t *)iocbq; 344382527734SSukumar Swaminathan tbm.q_cnt = 1; 344482527734SSukumar Swaminathan } 344582527734SSukumar Swaminathan 344682527734SSukumar Swaminathan iocbq = next; 344782527734SSukumar Swaminathan 344882527734SSukumar Swaminathan } /* While (iocbq) */ 344982527734SSukumar Swaminathan 345082527734SSukumar Swaminathan if ((tchanno == hba->channel_fcp) && (tbm.q_cnt != 0)) { 345182527734SSukumar Swaminathan 345282527734SSukumar Swaminathan /* from_chan->nodeq.q_first must be non NULL */ 345382527734SSukumar Swaminathan if (from_chan->nodeq.q_first) { 345482527734SSukumar Swaminathan 345582527734SSukumar Swaminathan /* nodeq is not empty, now deal with the node itself */ 345682527734SSukumar Swaminathan if ((nlp->nlp_tx[fchanno].q_first)) { 345782527734SSukumar Swaminathan 345882527734SSukumar Swaminathan if (!nlp->nlp_base) { 345982527734SSukumar Swaminathan from_chan->nodeq.q_last = 346082527734SSukumar Swaminathan (void *)nlp; 346182527734SSukumar Swaminathan from_chan->nodeq.q_first = 346282527734SSukumar Swaminathan nlp->nlp_next[fchanno]; 346382527734SSukumar Swaminathan } 346482527734SSukumar Swaminathan 346582527734SSukumar Swaminathan } else { 346682527734SSukumar Swaminathan n_prev = (NODELIST *)from_chan->nodeq.q_first; 346782527734SSukumar Swaminathan count = from_chan->nodeq.q_cnt; 346882527734SSukumar Swaminathan 346982527734SSukumar Swaminathan if (n_prev == nlp) { 347082527734SSukumar Swaminathan 347182527734SSukumar Swaminathan /* If this is the only node on list */ 347282527734SSukumar Swaminathan if (from_chan->nodeq.q_last == 347382527734SSukumar Swaminathan (void *)nlp) { 347482527734SSukumar Swaminathan from_chan->nodeq.q_last = 347582527734SSukumar Swaminathan NULL; 347682527734SSukumar Swaminathan from_chan->nodeq.q_first = 347782527734SSukumar Swaminathan NULL; 347882527734SSukumar Swaminathan from_chan->nodeq.q_cnt = 0; 347982527734SSukumar Swaminathan } else { 348082527734SSukumar Swaminathan from_chan->nodeq.q_first = 348182527734SSukumar Swaminathan nlp->nlp_next[fchanno]; 348282527734SSukumar Swaminathan ((NODELIST *)from_chan-> 348382527734SSukumar Swaminathan nodeq.q_last)-> 348482527734SSukumar Swaminathan nlp_next[fchanno] = 348582527734SSukumar Swaminathan from_chan->nodeq.q_first; 348682527734SSukumar Swaminathan from_chan->nodeq.q_cnt--; 348782527734SSukumar Swaminathan } 348882527734SSukumar Swaminathan /* Clear node */ 348982527734SSukumar Swaminathan nlp->nlp_next[fchanno] = NULL; 349082527734SSukumar Swaminathan } else { 349182527734SSukumar Swaminathan count--; 349282527734SSukumar Swaminathan do { 349382527734SSukumar Swaminathan n_next = 349482527734SSukumar Swaminathan n_prev->nlp_next[fchanno]; 349582527734SSukumar Swaminathan if (n_next == nlp) { 349682527734SSukumar Swaminathan break; 349782527734SSukumar Swaminathan } 349882527734SSukumar Swaminathan n_prev = n_next; 349982527734SSukumar Swaminathan } while (count--); 350082527734SSukumar Swaminathan 350182527734SSukumar Swaminathan if (count != 0) { 350282527734SSukumar Swaminathan 350382527734SSukumar Swaminathan if (n_next == 350482527734SSukumar Swaminathan (NODELIST *)from_chan-> 350582527734SSukumar Swaminathan nodeq.q_last) { 350682527734SSukumar Swaminathan n_prev-> 350782527734SSukumar Swaminathan nlp_next[fchanno] 350882527734SSukumar Swaminathan = 350982527734SSukumar Swaminathan ((NODELIST *) 351082527734SSukumar Swaminathan from_chan-> 351182527734SSukumar Swaminathan nodeq.q_last)-> 351282527734SSukumar Swaminathan nlp_next 351382527734SSukumar Swaminathan [fchanno]; 351482527734SSukumar Swaminathan from_chan->nodeq.q_last 351582527734SSukumar Swaminathan = (uint8_t *)n_prev; 351682527734SSukumar Swaminathan } else { 351782527734SSukumar Swaminathan 351882527734SSukumar Swaminathan n_prev-> 351982527734SSukumar Swaminathan nlp_next[fchanno] 352082527734SSukumar Swaminathan = 352182527734SSukumar Swaminathan n_next-> nlp_next 352282527734SSukumar Swaminathan [fchanno]; 352382527734SSukumar Swaminathan } 352482527734SSukumar Swaminathan from_chan->nodeq.q_cnt--; 352582527734SSukumar Swaminathan /* Clear node */ 352682527734SSukumar Swaminathan nlp->nlp_next[fchanno] = 352782527734SSukumar Swaminathan NULL; 352882527734SSukumar Swaminathan } 352982527734SSukumar Swaminathan } 353082527734SSukumar Swaminathan } 353182527734SSukumar Swaminathan } 353282527734SSukumar Swaminathan } 353382527734SSukumar Swaminathan 353482527734SSukumar Swaminathan /* Now cleanup the iocb's */ 353582527734SSukumar Swaminathan prev = NULL; 353682527734SSukumar Swaminathan iocbq = (IOCBQ *)tbm.q_first; 353782527734SSukumar Swaminathan 353882527734SSukumar Swaminathan while (iocbq) { 353982527734SSukumar Swaminathan 354082527734SSukumar Swaminathan next = (IOCBQ *)iocbq->next; 354182527734SSukumar Swaminathan 354282527734SSukumar Swaminathan /* Free the IoTag and the bmp */ 354382527734SSukumar Swaminathan iocb = &iocbq->iocb; 354482527734SSukumar Swaminathan 354582527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 354682527734SSukumar Swaminathan sbp = iocbq->sbp; 354782527734SSukumar Swaminathan if (sbp) { 3548*8f23e9faSHans Rosenfeld emlxs_sli4_free_xri(port, sbp, sbp->xrip, 1); 354982527734SSukumar Swaminathan } 355082527734SSukumar Swaminathan } else { 355182527734SSukumar Swaminathan sbp = emlxs_unregister_pkt((CHANNEL *)iocbq->channel, 355282527734SSukumar Swaminathan iocb->ULPIOTAG, 0); 355382527734SSukumar Swaminathan } 355482527734SSukumar Swaminathan 355582527734SSukumar Swaminathan if (sbp && (sbp != STALE_PACKET)) { 355682527734SSukumar Swaminathan mutex_enter(&sbp->mtx); 355782527734SSukumar Swaminathan sbp->pkt_flags |= PACKET_IN_FLUSH; 355882527734SSukumar Swaminathan 355982527734SSukumar Swaminathan /* 356082527734SSukumar Swaminathan * If the fpkt is already set, then we will leave it 356182527734SSukumar Swaminathan * alone. This ensures that this pkt is only accounted 356282527734SSukumar Swaminathan * for on one fpkt->flush_count 356382527734SSukumar Swaminathan */ 356482527734SSukumar Swaminathan if (!sbp->fpkt && fpkt) { 356582527734SSukumar Swaminathan mutex_enter(&fpkt->mtx); 356682527734SSukumar Swaminathan sbp->fpkt = fpkt; 356782527734SSukumar Swaminathan fpkt->flush_count++; 356882527734SSukumar Swaminathan mutex_exit(&fpkt->mtx); 356982527734SSukumar Swaminathan } 357082527734SSukumar Swaminathan mutex_exit(&sbp->mtx); 357182527734SSukumar Swaminathan } 357282527734SSukumar Swaminathan iocbq = next; 357382527734SSukumar Swaminathan 357482527734SSukumar Swaminathan } /* end of while */ 357582527734SSukumar Swaminathan 357682527734SSukumar Swaminathan iocbq = (IOCBQ *)tbm.q_first; 357782527734SSukumar Swaminathan while (iocbq) { 357882527734SSukumar Swaminathan /* Save the next iocbq for now */ 357982527734SSukumar Swaminathan next = (IOCBQ *)iocbq->next; 358082527734SSukumar Swaminathan 358182527734SSukumar Swaminathan /* Unlink this iocbq */ 358282527734SSukumar Swaminathan iocbq->next = NULL; 358382527734SSukumar Swaminathan 358482527734SSukumar Swaminathan /* Get the pkt */ 358582527734SSukumar Swaminathan sbp = (emlxs_buf_t *)iocbq->sbp; 358682527734SSukumar Swaminathan 358782527734SSukumar Swaminathan if (sbp) { 358882527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flush_msg, 358982527734SSukumar Swaminathan "tx: sbp=%p node=%p", sbp, sbp->node); 359082527734SSukumar Swaminathan 359182527734SSukumar Swaminathan if (hba->state >= FC_LINK_UP) { 359282527734SSukumar Swaminathan emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 359382527734SSukumar Swaminathan IOERR_ABORT_REQUESTED, 1); 359482527734SSukumar Swaminathan } else { 359582527734SSukumar Swaminathan emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 359682527734SSukumar Swaminathan IOERR_LINK_DOWN, 1); 359782527734SSukumar Swaminathan } 359882527734SSukumar Swaminathan 359982527734SSukumar Swaminathan } 360082527734SSukumar Swaminathan /* Free the iocb and its associated buffers */ 360182527734SSukumar Swaminathan else { 360282527734SSukumar Swaminathan icmd = &iocbq->iocb; 360382527734SSukumar Swaminathan 360482527734SSukumar Swaminathan /* SLI3 */ 360582527734SSukumar Swaminathan if (icmd->ULPCOMMAND == CMD_QUE_RING_BUF64_CN || 360682527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_QUE_RING_BUF_CN || 360782527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_QUE_RING_LIST64_CN) { 360882527734SSukumar Swaminathan if ((hba->flag & 360982527734SSukumar Swaminathan (FC_ONLINE_MODE | FC_ONLINING_MODE)) == 0) { 361082527734SSukumar Swaminathan /* HBA is detaching or offlining */ 361182527734SSukumar Swaminathan if (icmd->ULPCOMMAND != 361282527734SSukumar Swaminathan CMD_QUE_RING_LIST64_CN) { 3613a9800bebSGarrett D'Amore void *tmp; 361482527734SSukumar Swaminathan RING *rp; 361582527734SSukumar Swaminathan int ch; 361682527734SSukumar Swaminathan 361782527734SSukumar Swaminathan ch = from_chan->channelno; 361882527734SSukumar Swaminathan rp = &hba->sli.sli3.ring[ch]; 361982527734SSukumar Swaminathan 362082527734SSukumar Swaminathan for (i = 0; 362182527734SSukumar Swaminathan i < icmd->ULPBDECOUNT; 362282527734SSukumar Swaminathan i++) { 362382527734SSukumar Swaminathan mp = EMLXS_GET_VADDR( 362482527734SSukumar Swaminathan hba, rp, icmd); 362582527734SSukumar Swaminathan 3626a9800bebSGarrett D'Amore tmp = (void *)mp; 362782527734SSukumar Swaminathan if (mp) { 3628a9800bebSGarrett D'Amore emlxs_mem_put( 362982527734SSukumar Swaminathan hba, 363082527734SSukumar Swaminathan MEM_BUF, 363182527734SSukumar Swaminathan tmp); 363282527734SSukumar Swaminathan } 363382527734SSukumar Swaminathan } 363482527734SSukumar Swaminathan 363582527734SSukumar Swaminathan } 363682527734SSukumar Swaminathan 3637a9800bebSGarrett D'Amore emlxs_mem_put(hba, MEM_IOCB, 3638a9800bebSGarrett D'Amore (void *)iocbq); 363982527734SSukumar Swaminathan } else { 364082527734SSukumar Swaminathan /* repost the unsolicited buffer */ 364182527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, 364282527734SSukumar Swaminathan from_chan, iocbq); 364382527734SSukumar Swaminathan } 364482527734SSukumar Swaminathan } 364582527734SSukumar Swaminathan } 364682527734SSukumar Swaminathan 364782527734SSukumar Swaminathan iocbq = next; 364882527734SSukumar Swaminathan 364982527734SSukumar Swaminathan } /* end of while */ 365082527734SSukumar Swaminathan 365182527734SSukumar Swaminathan /* Now flush the chipq if any */ 365282527734SSukumar Swaminathan if (!(nlp->nlp_flag[fchanno] & NLP_CLOSED)) { 365382527734SSukumar Swaminathan 365482527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 365582527734SSukumar Swaminathan 365682527734SSukumar Swaminathan (void) emlxs_chipq_node_flush(port, from_chan, nlp, 0); 365782527734SSukumar Swaminathan 365882527734SSukumar Swaminathan mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 365982527734SSukumar Swaminathan } 366082527734SSukumar Swaminathan 366182527734SSukumar Swaminathan if (lock) { 366282527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 366382527734SSukumar Swaminathan } 366482527734SSukumar Swaminathan 366582527734SSukumar Swaminathan return; 366682527734SSukumar Swaminathan 366782527734SSukumar Swaminathan } /* emlxs_tx_move */ 3668fcf3ce44SJohn Forte 3669fcf3ce44SJohn Forte 3670fcf3ce44SJohn Forte extern uint32_t 367182527734SSukumar Swaminathan emlxs_chipq_node_flush(emlxs_port_t *port, CHANNEL *chan, NODELIST *ndlp, 3672291a2b48SSukumar Swaminathan emlxs_buf_t *fpkt) 3673fcf3ce44SJohn Forte { 3674fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 3675fcf3ce44SJohn Forte emlxs_buf_t *sbp; 3676fcf3ce44SJohn Forte IOCBQ *iocbq; 3677fcf3ce44SJohn Forte IOCBQ *next; 3678fcf3ce44SJohn Forte Q abort; 367982527734SSukumar Swaminathan CHANNEL *cp; 368082527734SSukumar Swaminathan uint32_t channelno; 368182527734SSukumar Swaminathan uint8_t flag[MAX_CHANNEL]; 3682fcf3ce44SJohn Forte uint32_t iotag; 3683fcf3ce44SJohn Forte 3684fcf3ce44SJohn Forte bzero((void *)&abort, sizeof (Q)); 3685fcf3ce44SJohn Forte bzero((void *)flag, sizeof (flag)); 3686fcf3ce44SJohn Forte 368782527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 368882527734SSukumar Swaminathan cp = &hba->chan[channelno]; 3689fcf3ce44SJohn Forte 369082527734SSukumar Swaminathan if (chan && cp != chan) { 3691fcf3ce44SJohn Forte continue; 3692fcf3ce44SJohn Forte } 3693291a2b48SSukumar Swaminathan 369482527734SSukumar Swaminathan mutex_enter(&EMLXS_FCTAB_LOCK); 3695fcf3ce44SJohn Forte 369682527734SSukumar Swaminathan for (iotag = 1; iotag < hba->max_iotag; iotag++) { 369782527734SSukumar Swaminathan sbp = hba->fc_table[iotag]; 3698fcf3ce44SJohn Forte 3699fcf3ce44SJohn Forte if (sbp && (sbp != STALE_PACKET) && 3700fcf3ce44SJohn Forte (sbp->pkt_flags & PACKET_IN_CHIPQ) && 3701fcf3ce44SJohn Forte (sbp->node == ndlp) && 370282527734SSukumar Swaminathan (sbp->channel == cp) && 3703fcf3ce44SJohn Forte !(sbp->pkt_flags & PACKET_XRI_CLOSED)) { 3704291a2b48SSukumar Swaminathan emlxs_sbp_abort_add(port, sbp, &abort, flag, 3705291a2b48SSukumar Swaminathan fpkt); 3706fcf3ce44SJohn Forte } 3707291a2b48SSukumar Swaminathan 3708fcf3ce44SJohn Forte } 370982527734SSukumar Swaminathan mutex_exit(&EMLXS_FCTAB_LOCK); 3710fcf3ce44SJohn Forte 3711fcf3ce44SJohn Forte } /* for */ 3712fcf3ce44SJohn Forte 3713fcf3ce44SJohn Forte /* Now put the iocb's on the tx queue */ 3714fcf3ce44SJohn Forte iocbq = (IOCBQ *)abort.q_first; 3715fcf3ce44SJohn Forte while (iocbq) { 3716fcf3ce44SJohn Forte /* Save the next iocbq for now */ 3717fcf3ce44SJohn Forte next = (IOCBQ *)iocbq->next; 3718fcf3ce44SJohn Forte 3719fcf3ce44SJohn Forte /* Unlink this iocbq */ 3720fcf3ce44SJohn Forte iocbq->next = NULL; 3721fcf3ce44SJohn Forte 3722fcf3ce44SJohn Forte /* Send this iocbq */ 3723fcf3ce44SJohn Forte emlxs_tx_put(iocbq, 1); 3724fcf3ce44SJohn Forte 3725fcf3ce44SJohn Forte iocbq = next; 3726fcf3ce44SJohn Forte } 3727fcf3ce44SJohn Forte 372882527734SSukumar Swaminathan /* Now trigger channel service */ 372982527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 373082527734SSukumar Swaminathan if (!flag[channelno]) { 3731fcf3ce44SJohn Forte continue; 3732fcf3ce44SJohn Forte } 3733291a2b48SSukumar Swaminathan 373482527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, &hba->chan[channelno], 0); 3735fcf3ce44SJohn Forte } 3736fcf3ce44SJohn Forte 3737fcf3ce44SJohn Forte return (abort.q_cnt); 3738fcf3ce44SJohn Forte 373982527734SSukumar Swaminathan } /* emlxs_chipq_node_flush() */ 3740fcf3ce44SJohn Forte 3741fcf3ce44SJohn Forte 3742fcf3ce44SJohn Forte /* Flush all IO's left on all iotag lists */ 374382527734SSukumar Swaminathan extern uint32_t 3744fcf3ce44SJohn Forte emlxs_iotag_flush(emlxs_hba_t *hba) 3745fcf3ce44SJohn Forte { 3746fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 3747fcf3ce44SJohn Forte emlxs_buf_t *sbp; 3748fcf3ce44SJohn Forte IOCBQ *iocbq; 3749fcf3ce44SJohn Forte IOCB *iocb; 3750fcf3ce44SJohn Forte Q abort; 375182527734SSukumar Swaminathan CHANNEL *cp; 375282527734SSukumar Swaminathan uint32_t channelno; 3753fcf3ce44SJohn Forte uint32_t iotag; 3754fcf3ce44SJohn Forte uint32_t count; 3755fcf3ce44SJohn Forte 3756fcf3ce44SJohn Forte count = 0; 375782527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 375882527734SSukumar Swaminathan cp = &hba->chan[channelno]; 3759fcf3ce44SJohn Forte 3760fcf3ce44SJohn Forte bzero((void *)&abort, sizeof (Q)); 3761fcf3ce44SJohn Forte 376282527734SSukumar Swaminathan mutex_enter(&EMLXS_FCTAB_LOCK); 3763fcf3ce44SJohn Forte 376482527734SSukumar Swaminathan for (iotag = 1; iotag < hba->max_iotag; iotag++) { 376582527734SSukumar Swaminathan sbp = hba->fc_table[iotag]; 3766fcf3ce44SJohn Forte 376782527734SSukumar Swaminathan /* Check if the slot is empty */ 3768fcf3ce44SJohn Forte if (!sbp || (sbp == STALE_PACKET)) { 3769fcf3ce44SJohn Forte continue; 3770fcf3ce44SJohn Forte } 3771291a2b48SSukumar Swaminathan 377282527734SSukumar Swaminathan /* We are building an abort list per channel */ 377382527734SSukumar Swaminathan if (sbp->channel != cp) { 377482527734SSukumar Swaminathan continue; 377582527734SSukumar Swaminathan } 3776fcf3ce44SJohn Forte 3777a9800bebSGarrett D'Amore hba->fc_table[iotag] = STALE_PACKET; 3778a9800bebSGarrett D'Amore hba->io_count--; 3779a9800bebSGarrett D'Amore 3780a9800bebSGarrett D'Amore /* Check if IO is valid */ 3781a9800bebSGarrett D'Amore if (!(sbp->pkt_flags & PACKET_VALID) || 3782a9800bebSGarrett D'Amore (sbp->pkt_flags & (PACKET_ULP_OWNED| 3783a9800bebSGarrett D'Amore PACKET_COMPLETED|PACKET_IN_COMPLETION))) { 3784a9800bebSGarrett D'Amore EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_debug_msg, 3785*8f23e9faSHans Rosenfeld "iotag_flush: Invalid IO found. iotag=%d", 3786a9800bebSGarrett D'Amore iotag); 3787a9800bebSGarrett D'Amore 3788a9800bebSGarrett D'Amore continue; 3789a9800bebSGarrett D'Amore } 3790a9800bebSGarrett D'Amore 3791a9800bebSGarrett D'Amore sbp->iotag = 0; 3792a9800bebSGarrett D'Amore 3793fcf3ce44SJohn Forte /* Set IOCB status */ 3794fcf3ce44SJohn Forte iocbq = &sbp->iocbq; 3795fcf3ce44SJohn Forte iocb = &iocbq->iocb; 3796fcf3ce44SJohn Forte 379782527734SSukumar Swaminathan iocb->ULPSTATUS = IOSTAT_LOCAL_REJECT; 3798fcf3ce44SJohn Forte iocb->un.grsp.perr.statLocalError = IOERR_LINK_DOWN; 379982527734SSukumar Swaminathan iocb->ULPLE = 1; 3800fcf3ce44SJohn Forte iocbq->next = NULL; 3801fcf3ce44SJohn Forte 380282527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 3803a9800bebSGarrett D'Amore if (sbp->xrip) { 3804a9800bebSGarrett D'Amore EMLXS_MSGF(EMLXS_CONTEXT, 3805a9800bebSGarrett D'Amore &emlxs_sli_debug_msg, 3806*8f23e9faSHans Rosenfeld "iotag_flush: iotag=%d sbp=%p " 3807a9800bebSGarrett D'Amore "xrip=%p state=%x flag=%x", 3808a9800bebSGarrett D'Amore iotag, sbp, sbp->xrip, 3809a9800bebSGarrett D'Amore sbp->xrip->state, sbp->xrip->flag); 3810a9800bebSGarrett D'Amore } else { 3811a9800bebSGarrett D'Amore EMLXS_MSGF(EMLXS_CONTEXT, 3812a9800bebSGarrett D'Amore &emlxs_sli_debug_msg, 3813*8f23e9faSHans Rosenfeld "iotag_flush: iotag=%d sbp=%p " 3814*8f23e9faSHans Rosenfeld "xrip=NULL", iotag, sbp); 3815a9800bebSGarrett D'Amore } 3816291a2b48SSukumar Swaminathan 3817*8f23e9faSHans Rosenfeld emlxs_sli4_free_xri(port, sbp, sbp->xrip, 0); 3818a9800bebSGarrett D'Amore } else { 381982527734SSukumar Swaminathan /* Clean up the sbp */ 382082527734SSukumar Swaminathan mutex_enter(&sbp->mtx); 382182527734SSukumar Swaminathan 382282527734SSukumar Swaminathan if (sbp->pkt_flags & PACKET_IN_TXQ) { 382382527734SSukumar Swaminathan sbp->pkt_flags &= ~PACKET_IN_TXQ; 382482527734SSukumar Swaminathan hba->channel_tx_count --; 382582527734SSukumar Swaminathan } 382682527734SSukumar Swaminathan 382782527734SSukumar Swaminathan if (sbp->pkt_flags & PACKET_IN_CHIPQ) { 382882527734SSukumar Swaminathan sbp->pkt_flags &= ~PACKET_IN_CHIPQ; 382982527734SSukumar Swaminathan } 3830291a2b48SSukumar Swaminathan 383182527734SSukumar Swaminathan if (sbp->bmp) { 3832a9800bebSGarrett D'Amore emlxs_mem_put(hba, MEM_BPL, 3833a9800bebSGarrett D'Amore (void *)sbp->bmp); 383482527734SSukumar Swaminathan sbp->bmp = 0; 383582527734SSukumar Swaminathan } 383682527734SSukumar Swaminathan 383782527734SSukumar Swaminathan mutex_exit(&sbp->mtx); 3838fcf3ce44SJohn Forte } 3839291a2b48SSukumar Swaminathan 3840fcf3ce44SJohn Forte /* At this point all nodes are assumed destroyed */ 384182527734SSukumar Swaminathan mutex_enter(&sbp->mtx); 3842fcf3ce44SJohn Forte sbp->node = 0; 3843fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 3844fcf3ce44SJohn Forte 3845fcf3ce44SJohn Forte /* Add this iocb to our local abort Q */ 3846fcf3ce44SJohn Forte if (abort.q_first) { 3847291a2b48SSukumar Swaminathan ((IOCBQ *)abort.q_last)->next = iocbq; 3848fcf3ce44SJohn Forte abort.q_last = (uint8_t *)iocbq; 3849fcf3ce44SJohn Forte abort.q_cnt++; 3850fcf3ce44SJohn Forte } else { 3851fcf3ce44SJohn Forte abort.q_first = (uint8_t *)iocbq; 3852fcf3ce44SJohn Forte abort.q_last = (uint8_t *)iocbq; 3853fcf3ce44SJohn Forte abort.q_cnt = 1; 3854fcf3ce44SJohn Forte } 3855fcf3ce44SJohn Forte } 3856fcf3ce44SJohn Forte 385782527734SSukumar Swaminathan mutex_exit(&EMLXS_FCTAB_LOCK); 3858fcf3ce44SJohn Forte 3859fcf3ce44SJohn Forte /* Trigger deferred completion */ 3860fcf3ce44SJohn Forte if (abort.q_first) { 386182527734SSukumar Swaminathan mutex_enter(&cp->rsp_lock); 386282527734SSukumar Swaminathan if (cp->rsp_head == NULL) { 386382527734SSukumar Swaminathan cp->rsp_head = (IOCBQ *)abort.q_first; 386482527734SSukumar Swaminathan cp->rsp_tail = (IOCBQ *)abort.q_last; 3865fcf3ce44SJohn Forte } else { 386682527734SSukumar Swaminathan cp->rsp_tail->next = (IOCBQ *)abort.q_first; 386782527734SSukumar Swaminathan cp->rsp_tail = (IOCBQ *)abort.q_last; 3868fcf3ce44SJohn Forte } 386982527734SSukumar Swaminathan mutex_exit(&cp->rsp_lock); 3870fcf3ce44SJohn Forte 387182527734SSukumar Swaminathan emlxs_thread_trigger2(&cp->intr_thread, 387282527734SSukumar Swaminathan emlxs_proc_channel, cp); 3873fcf3ce44SJohn Forte 3874a9800bebSGarrett D'Amore EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_debug_msg, 3875a9800bebSGarrett D'Amore "iotag_flush: channel=%d count=%d", 387682527734SSukumar Swaminathan channelno, abort.q_cnt); 3877fcf3ce44SJohn Forte 3878fcf3ce44SJohn Forte count += abort.q_cnt; 3879fcf3ce44SJohn Forte } 3880fcf3ce44SJohn Forte } 3881fcf3ce44SJohn Forte 3882fcf3ce44SJohn Forte return (count); 3883fcf3ce44SJohn Forte 388482527734SSukumar Swaminathan } /* emlxs_iotag_flush() */ 3885fcf3ce44SJohn Forte 3886fcf3ce44SJohn Forte 3887fcf3ce44SJohn Forte 388882527734SSukumar Swaminathan /* Checks for IO's on all or a given channel for a given node */ 3889fcf3ce44SJohn Forte extern uint32_t 389082527734SSukumar Swaminathan emlxs_chipq_node_check(emlxs_port_t *port, CHANNEL *chan, NODELIST *ndlp) 3891fcf3ce44SJohn Forte { 3892fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 3893fcf3ce44SJohn Forte emlxs_buf_t *sbp; 389482527734SSukumar Swaminathan CHANNEL *cp; 389582527734SSukumar Swaminathan uint32_t channelno; 3896fcf3ce44SJohn Forte uint32_t count; 3897fcf3ce44SJohn Forte uint32_t iotag; 3898fcf3ce44SJohn Forte 3899fcf3ce44SJohn Forte count = 0; 3900fcf3ce44SJohn Forte 390182527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 390282527734SSukumar Swaminathan cp = &hba->chan[channelno]; 3903fcf3ce44SJohn Forte 390482527734SSukumar Swaminathan if (chan && cp != chan) { 3905fcf3ce44SJohn Forte continue; 3906fcf3ce44SJohn Forte } 3907291a2b48SSukumar Swaminathan 390882527734SSukumar Swaminathan mutex_enter(&EMLXS_FCTAB_LOCK); 3909fcf3ce44SJohn Forte 391082527734SSukumar Swaminathan for (iotag = 1; iotag < hba->max_iotag; iotag++) { 391182527734SSukumar Swaminathan sbp = hba->fc_table[iotag]; 3912fcf3ce44SJohn Forte 3913fcf3ce44SJohn Forte if (sbp && (sbp != STALE_PACKET) && 3914fcf3ce44SJohn Forte (sbp->pkt_flags & PACKET_IN_CHIPQ) && 3915fcf3ce44SJohn Forte (sbp->node == ndlp) && 391682527734SSukumar Swaminathan (sbp->channel == cp) && 3917fcf3ce44SJohn Forte !(sbp->pkt_flags & PACKET_XRI_CLOSED)) { 3918fcf3ce44SJohn Forte count++; 3919fcf3ce44SJohn Forte } 3920291a2b48SSukumar Swaminathan 3921fcf3ce44SJohn Forte } 392282527734SSukumar Swaminathan mutex_exit(&EMLXS_FCTAB_LOCK); 3923fcf3ce44SJohn Forte 3924fcf3ce44SJohn Forte } /* for */ 3925fcf3ce44SJohn Forte 3926fcf3ce44SJohn Forte return (count); 3927fcf3ce44SJohn Forte 392882527734SSukumar Swaminathan } /* emlxs_chipq_node_check() */ 3929fcf3ce44SJohn Forte 3930fcf3ce44SJohn Forte 3931fcf3ce44SJohn Forte 393282527734SSukumar Swaminathan /* Flush all IO's for a given node's lun (on any channel) */ 3933fcf3ce44SJohn Forte extern uint32_t 393482527734SSukumar Swaminathan emlxs_chipq_lun_flush(emlxs_port_t *port, NODELIST *ndlp, 393582527734SSukumar Swaminathan uint32_t lun, emlxs_buf_t *fpkt) 3936fcf3ce44SJohn Forte { 3937fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 3938fcf3ce44SJohn Forte emlxs_buf_t *sbp; 3939fcf3ce44SJohn Forte IOCBQ *iocbq; 3940fcf3ce44SJohn Forte IOCBQ *next; 3941fcf3ce44SJohn Forte Q abort; 3942fcf3ce44SJohn Forte uint32_t iotag; 394382527734SSukumar Swaminathan uint8_t flag[MAX_CHANNEL]; 394482527734SSukumar Swaminathan uint32_t channelno; 3945fcf3ce44SJohn Forte 3946a9800bebSGarrett D'Amore if (lun == EMLXS_LUN_NONE) { 3947a9800bebSGarrett D'Amore return (0); 3948a9800bebSGarrett D'Amore } 3949a9800bebSGarrett D'Amore 3950fcf3ce44SJohn Forte bzero((void *)flag, sizeof (flag)); 3951fcf3ce44SJohn Forte bzero((void *)&abort, sizeof (Q)); 3952fcf3ce44SJohn Forte 395382527734SSukumar Swaminathan mutex_enter(&EMLXS_FCTAB_LOCK); 395482527734SSukumar Swaminathan for (iotag = 1; iotag < hba->max_iotag; iotag++) { 395582527734SSukumar Swaminathan sbp = hba->fc_table[iotag]; 3956fcf3ce44SJohn Forte 3957fcf3ce44SJohn Forte if (sbp && (sbp != STALE_PACKET) && 3958fcf3ce44SJohn Forte sbp->pkt_flags & PACKET_IN_CHIPQ && 3959fcf3ce44SJohn Forte sbp->node == ndlp && 3960fcf3ce44SJohn Forte sbp->lun == lun && 3961fcf3ce44SJohn Forte !(sbp->pkt_flags & PACKET_XRI_CLOSED)) { 396282527734SSukumar Swaminathan emlxs_sbp_abort_add(port, sbp, 396382527734SSukumar Swaminathan &abort, flag, fpkt); 3964fcf3ce44SJohn Forte } 3965fcf3ce44SJohn Forte } 396682527734SSukumar Swaminathan mutex_exit(&EMLXS_FCTAB_LOCK); 3967fcf3ce44SJohn Forte 3968fcf3ce44SJohn Forte /* Now put the iocb's on the tx queue */ 3969fcf3ce44SJohn Forte iocbq = (IOCBQ *)abort.q_first; 3970fcf3ce44SJohn Forte while (iocbq) { 3971fcf3ce44SJohn Forte /* Save the next iocbq for now */ 3972fcf3ce44SJohn Forte next = (IOCBQ *)iocbq->next; 3973fcf3ce44SJohn Forte 3974fcf3ce44SJohn Forte /* Unlink this iocbq */ 3975fcf3ce44SJohn Forte iocbq->next = NULL; 3976fcf3ce44SJohn Forte 3977fcf3ce44SJohn Forte /* Send this iocbq */ 3978fcf3ce44SJohn Forte emlxs_tx_put(iocbq, 1); 3979fcf3ce44SJohn Forte 3980fcf3ce44SJohn Forte iocbq = next; 3981fcf3ce44SJohn Forte } 3982fcf3ce44SJohn Forte 398382527734SSukumar Swaminathan /* Now trigger channel service */ 398482527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 398582527734SSukumar Swaminathan if (!flag[channelno]) { 398682527734SSukumar Swaminathan continue; 398782527734SSukumar Swaminathan } 398882527734SSukumar Swaminathan 398982527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, &hba->chan[channelno], 0); 3990fcf3ce44SJohn Forte } 3991291a2b48SSukumar Swaminathan 3992fcf3ce44SJohn Forte return (abort.q_cnt); 3993fcf3ce44SJohn Forte 399482527734SSukumar Swaminathan } /* emlxs_chipq_lun_flush() */ 3995fcf3ce44SJohn Forte 3996fcf3ce44SJohn Forte 3997fcf3ce44SJohn Forte 3998fcf3ce44SJohn Forte /* 3999fcf3ce44SJohn Forte * Issue an ABORT_XRI_CN iocb command to abort an FCP command already issued. 4000fe199829SSukumar Swaminathan * This must be called while holding the EMLXS_FCTAB_LOCK 4001fcf3ce44SJohn Forte */ 4002fcf3ce44SJohn Forte extern IOCBQ * 4003291a2b48SSukumar Swaminathan emlxs_create_abort_xri_cn(emlxs_port_t *port, NODELIST *ndlp, 400482527734SSukumar Swaminathan uint16_t iotag, CHANNEL *cp, uint8_t class, int32_t flag) 4005fcf3ce44SJohn Forte { 4006fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 4007fcf3ce44SJohn Forte IOCBQ *iocbq; 4008fcf3ce44SJohn Forte IOCB *iocb; 400982527734SSukumar Swaminathan emlxs_wqe_t *wqe; 401082527734SSukumar Swaminathan emlxs_buf_t *sbp; 4011fcf3ce44SJohn Forte uint16_t abort_iotag; 4012fcf3ce44SJohn Forte 4013*8f23e9faSHans Rosenfeld if ((iocbq = (IOCBQ *)emlxs_mem_get(hba, MEM_IOCB)) == NULL) { 4014fcf3ce44SJohn Forte return (NULL); 4015fcf3ce44SJohn Forte } 4016291a2b48SSukumar Swaminathan 401782527734SSukumar Swaminathan iocbq->channel = (void *)cp; 4018fcf3ce44SJohn Forte iocbq->port = (void *)port; 4019fcf3ce44SJohn Forte iocbq->node = (void *)ndlp; 4020fcf3ce44SJohn Forte iocbq->flag |= (IOCB_PRIORITY | IOCB_SPECIAL); 4021fcf3ce44SJohn Forte 4022fcf3ce44SJohn Forte /* 4023fcf3ce44SJohn Forte * set up an iotag using special Abort iotags 4024fcf3ce44SJohn Forte */ 402582527734SSukumar Swaminathan if ((hba->fc_oor_iotag >= EMLXS_MAX_ABORT_TAG)) { 402682527734SSukumar Swaminathan hba->fc_oor_iotag = hba->max_iotag; 4027fcf3ce44SJohn Forte } 402882527734SSukumar Swaminathan abort_iotag = hba->fc_oor_iotag++; 4029291a2b48SSukumar Swaminathan 4030fcf3ce44SJohn Forte 403182527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 403282527734SSukumar Swaminathan wqe = &iocbq->wqe; 403382527734SSukumar Swaminathan sbp = hba->fc_table[iotag]; 4034fcf3ce44SJohn Forte 403582527734SSukumar Swaminathan /* Try to issue abort by XRI if possible */ 4036a9800bebSGarrett D'Amore if (sbp == NULL || sbp == STALE_PACKET || sbp->xrip == NULL) { 403782527734SSukumar Swaminathan wqe->un.Abort.Criteria = ABORT_REQ_TAG; 403882527734SSukumar Swaminathan wqe->AbortTag = iotag; 403982527734SSukumar Swaminathan } else { 404082527734SSukumar Swaminathan wqe->un.Abort.Criteria = ABORT_XRI_TAG; 4041a9800bebSGarrett D'Amore wqe->AbortTag = sbp->xrip->XRI; 404282527734SSukumar Swaminathan } 404382527734SSukumar Swaminathan wqe->un.Abort.IA = 0; 404482527734SSukumar Swaminathan wqe->RequestTag = abort_iotag; 404582527734SSukumar Swaminathan wqe->Command = CMD_ABORT_XRI_CX; 404682527734SSukumar Swaminathan wqe->Class = CLASS3; 4047*8f23e9faSHans Rosenfeld wqe->CQId = (uint16_t)0xffff; /* default CQ for response */ 404882527734SSukumar Swaminathan wqe->CmdType = WQE_TYPE_ABORT; 404982527734SSukumar Swaminathan } else { 405082527734SSukumar Swaminathan iocb = &iocbq->iocb; 405182527734SSukumar Swaminathan iocb->ULPIOTAG = abort_iotag; 405282527734SSukumar Swaminathan iocb->un.acxri.abortType = flag; 405382527734SSukumar Swaminathan iocb->un.acxri.abortContextTag = ndlp->nlp_Rpi; 405482527734SSukumar Swaminathan iocb->un.acxri.abortIoTag = iotag; 405582527734SSukumar Swaminathan iocb->ULPLE = 1; 405682527734SSukumar Swaminathan iocb->ULPCLASS = class; 405782527734SSukumar Swaminathan iocb->ULPCOMMAND = CMD_ABORT_XRI_CN; 405882527734SSukumar Swaminathan iocb->ULPOWNER = OWN_CHIP; 405982527734SSukumar Swaminathan } 4060fcf3ce44SJohn Forte 4061fcf3ce44SJohn Forte return (iocbq); 4062fcf3ce44SJohn Forte 406382527734SSukumar Swaminathan } /* emlxs_create_abort_xri_cn() */ 4064fcf3ce44SJohn Forte 4065fcf3ce44SJohn Forte 4066fe199829SSukumar Swaminathan /* This must be called while holding the EMLXS_FCTAB_LOCK */ 4067fcf3ce44SJohn Forte extern IOCBQ * 4068fcf3ce44SJohn Forte emlxs_create_abort_xri_cx(emlxs_port_t *port, NODELIST *ndlp, uint16_t xid, 406982527734SSukumar Swaminathan CHANNEL *cp, uint8_t class, int32_t flag) 4070fcf3ce44SJohn Forte { 4071fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 4072fcf3ce44SJohn Forte IOCBQ *iocbq; 4073fcf3ce44SJohn Forte IOCB *iocb; 407482527734SSukumar Swaminathan emlxs_wqe_t *wqe; 4075fcf3ce44SJohn Forte uint16_t abort_iotag; 4076fcf3ce44SJohn Forte 4077*8f23e9faSHans Rosenfeld if ((iocbq = (IOCBQ *)emlxs_mem_get(hba, MEM_IOCB)) == NULL) { 4078fcf3ce44SJohn Forte return (NULL); 4079fcf3ce44SJohn Forte } 4080291a2b48SSukumar Swaminathan 408182527734SSukumar Swaminathan iocbq->channel = (void *)cp; 4082fcf3ce44SJohn Forte iocbq->port = (void *)port; 4083fcf3ce44SJohn Forte iocbq->node = (void *)ndlp; 4084fcf3ce44SJohn Forte iocbq->flag |= (IOCB_PRIORITY | IOCB_SPECIAL); 4085fcf3ce44SJohn Forte 4086fcf3ce44SJohn Forte /* 4087fcf3ce44SJohn Forte * set up an iotag using special Abort iotags 4088fcf3ce44SJohn Forte */ 408982527734SSukumar Swaminathan if ((hba->fc_oor_iotag >= EMLXS_MAX_ABORT_TAG)) { 409082527734SSukumar Swaminathan hba->fc_oor_iotag = hba->max_iotag; 409182527734SSukumar Swaminathan } 409282527734SSukumar Swaminathan abort_iotag = hba->fc_oor_iotag++; 409382527734SSukumar Swaminathan 409482527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 409582527734SSukumar Swaminathan wqe = &iocbq->wqe; 409682527734SSukumar Swaminathan wqe->un.Abort.Criteria = ABORT_XRI_TAG; 409782527734SSukumar Swaminathan wqe->un.Abort.IA = 0; 409882527734SSukumar Swaminathan wqe->RequestTag = abort_iotag; 409982527734SSukumar Swaminathan wqe->AbortTag = xid; 410082527734SSukumar Swaminathan wqe->Command = CMD_ABORT_XRI_CX; 410182527734SSukumar Swaminathan wqe->Class = CLASS3; 4102*8f23e9faSHans Rosenfeld wqe->CQId = (uint16_t)0xffff; /* default CQ for response */ 410382527734SSukumar Swaminathan wqe->CmdType = WQE_TYPE_ABORT; 410482527734SSukumar Swaminathan } else { 410582527734SSukumar Swaminathan iocb = &iocbq->iocb; 410682527734SSukumar Swaminathan iocb->ULPCONTEXT = xid; 410782527734SSukumar Swaminathan iocb->ULPIOTAG = abort_iotag; 410882527734SSukumar Swaminathan iocb->un.acxri.abortType = flag; 410982527734SSukumar Swaminathan iocb->ULPLE = 1; 411082527734SSukumar Swaminathan iocb->ULPCLASS = class; 411182527734SSukumar Swaminathan iocb->ULPCOMMAND = CMD_ABORT_XRI_CX; 411282527734SSukumar Swaminathan iocb->ULPOWNER = OWN_CHIP; 4113fcf3ce44SJohn Forte } 4114291a2b48SSukumar Swaminathan 4115fcf3ce44SJohn Forte return (iocbq); 4116fcf3ce44SJohn Forte 411782527734SSukumar Swaminathan } /* emlxs_create_abort_xri_cx() */ 4118fcf3ce44SJohn Forte 4119fcf3ce44SJohn Forte 4120fcf3ce44SJohn Forte 4121fe199829SSukumar Swaminathan /* This must be called while holding the EMLXS_FCTAB_LOCK */ 4122fcf3ce44SJohn Forte extern IOCBQ * 4123fcf3ce44SJohn Forte emlxs_create_close_xri_cn(emlxs_port_t *port, NODELIST *ndlp, 412482527734SSukumar Swaminathan uint16_t iotag, CHANNEL *cp) 4125fcf3ce44SJohn Forte { 4126fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 4127fcf3ce44SJohn Forte IOCBQ *iocbq; 4128fcf3ce44SJohn Forte IOCB *iocb; 412982527734SSukumar Swaminathan emlxs_wqe_t *wqe; 413082527734SSukumar Swaminathan emlxs_buf_t *sbp; 4131fcf3ce44SJohn Forte uint16_t abort_iotag; 4132fcf3ce44SJohn Forte 4133*8f23e9faSHans Rosenfeld if ((iocbq = (IOCBQ *)emlxs_mem_get(hba, MEM_IOCB)) == NULL) { 4134fcf3ce44SJohn Forte return (NULL); 4135fcf3ce44SJohn Forte } 4136291a2b48SSukumar Swaminathan 413782527734SSukumar Swaminathan iocbq->channel = (void *)cp; 4138fcf3ce44SJohn Forte iocbq->port = (void *)port; 4139fcf3ce44SJohn Forte iocbq->node = (void *)ndlp; 4140fcf3ce44SJohn Forte iocbq->flag |= (IOCB_PRIORITY | IOCB_SPECIAL); 4141fcf3ce44SJohn Forte 4142fcf3ce44SJohn Forte /* 4143fcf3ce44SJohn Forte * set up an iotag using special Abort iotags 4144fcf3ce44SJohn Forte */ 414582527734SSukumar Swaminathan if ((hba->fc_oor_iotag >= EMLXS_MAX_ABORT_TAG)) { 414682527734SSukumar Swaminathan hba->fc_oor_iotag = hba->max_iotag; 4147fcf3ce44SJohn Forte } 414882527734SSukumar Swaminathan abort_iotag = hba->fc_oor_iotag++; 4149291a2b48SSukumar Swaminathan 415082527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 415182527734SSukumar Swaminathan wqe = &iocbq->wqe; 415282527734SSukumar Swaminathan sbp = hba->fc_table[iotag]; 4153fcf3ce44SJohn Forte 415482527734SSukumar Swaminathan /* Try to issue close by XRI if possible */ 4155a9800bebSGarrett D'Amore if (sbp == NULL || sbp == STALE_PACKET || sbp->xrip == NULL) { 415682527734SSukumar Swaminathan wqe->un.Abort.Criteria = ABORT_REQ_TAG; 415782527734SSukumar Swaminathan wqe->AbortTag = iotag; 415882527734SSukumar Swaminathan } else { 415982527734SSukumar Swaminathan wqe->un.Abort.Criteria = ABORT_XRI_TAG; 4160a9800bebSGarrett D'Amore wqe->AbortTag = sbp->xrip->XRI; 416182527734SSukumar Swaminathan } 416282527734SSukumar Swaminathan wqe->un.Abort.IA = 1; 416382527734SSukumar Swaminathan wqe->RequestTag = abort_iotag; 416482527734SSukumar Swaminathan wqe->Command = CMD_ABORT_XRI_CX; 416582527734SSukumar Swaminathan wqe->Class = CLASS3; 4166*8f23e9faSHans Rosenfeld wqe->CQId = (uint16_t)0xffff; /* default CQ for response */ 416782527734SSukumar Swaminathan wqe->CmdType = WQE_TYPE_ABORT; 416882527734SSukumar Swaminathan } else { 416982527734SSukumar Swaminathan iocb = &iocbq->iocb; 417082527734SSukumar Swaminathan iocb->ULPIOTAG = abort_iotag; 417182527734SSukumar Swaminathan iocb->un.acxri.abortType = 0; 417282527734SSukumar Swaminathan iocb->un.acxri.abortContextTag = ndlp->nlp_Rpi; 417382527734SSukumar Swaminathan iocb->un.acxri.abortIoTag = iotag; 417482527734SSukumar Swaminathan iocb->ULPLE = 1; 417582527734SSukumar Swaminathan iocb->ULPCLASS = 0; 417682527734SSukumar Swaminathan iocb->ULPCOMMAND = CMD_CLOSE_XRI_CN; 417782527734SSukumar Swaminathan iocb->ULPOWNER = OWN_CHIP; 417882527734SSukumar Swaminathan } 4179fcf3ce44SJohn Forte 4180fcf3ce44SJohn Forte return (iocbq); 4181fcf3ce44SJohn Forte 418282527734SSukumar Swaminathan } /* emlxs_create_close_xri_cn() */ 4183fcf3ce44SJohn Forte 4184fcf3ce44SJohn Forte 4185fe199829SSukumar Swaminathan /* This must be called while holding the EMLXS_FCTAB_LOCK */ 4186fcf3ce44SJohn Forte extern IOCBQ * 4187291a2b48SSukumar Swaminathan emlxs_create_close_xri_cx(emlxs_port_t *port, NODELIST *ndlp, uint16_t xid, 418882527734SSukumar Swaminathan CHANNEL *cp) 4189fcf3ce44SJohn Forte { 4190fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 4191fcf3ce44SJohn Forte IOCBQ *iocbq; 4192fcf3ce44SJohn Forte IOCB *iocb; 419382527734SSukumar Swaminathan emlxs_wqe_t *wqe; 4194fcf3ce44SJohn Forte uint16_t abort_iotag; 4195fcf3ce44SJohn Forte 4196*8f23e9faSHans Rosenfeld if ((iocbq = (IOCBQ *)emlxs_mem_get(hba, MEM_IOCB)) == NULL) { 4197fcf3ce44SJohn Forte return (NULL); 4198fcf3ce44SJohn Forte } 4199291a2b48SSukumar Swaminathan 420082527734SSukumar Swaminathan iocbq->channel = (void *)cp; 4201fcf3ce44SJohn Forte iocbq->port = (void *)port; 4202fcf3ce44SJohn Forte iocbq->node = (void *)ndlp; 4203fcf3ce44SJohn Forte iocbq->flag |= (IOCB_PRIORITY | IOCB_SPECIAL); 4204fcf3ce44SJohn Forte 4205fcf3ce44SJohn Forte /* 4206fcf3ce44SJohn Forte * set up an iotag using special Abort iotags 4207fcf3ce44SJohn Forte */ 420882527734SSukumar Swaminathan if ((hba->fc_oor_iotag >= EMLXS_MAX_ABORT_TAG)) { 420982527734SSukumar Swaminathan hba->fc_oor_iotag = hba->max_iotag; 421082527734SSukumar Swaminathan } 421182527734SSukumar Swaminathan abort_iotag = hba->fc_oor_iotag++; 421282527734SSukumar Swaminathan 421382527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 421482527734SSukumar Swaminathan wqe = &iocbq->wqe; 421582527734SSukumar Swaminathan wqe->un.Abort.Criteria = ABORT_XRI_TAG; 421682527734SSukumar Swaminathan wqe->un.Abort.IA = 1; 421782527734SSukumar Swaminathan wqe->RequestTag = abort_iotag; 421882527734SSukumar Swaminathan wqe->AbortTag = xid; 421982527734SSukumar Swaminathan wqe->Command = CMD_ABORT_XRI_CX; 422082527734SSukumar Swaminathan wqe->Class = CLASS3; 4221*8f23e9faSHans Rosenfeld wqe->CQId = (uint16_t)0xffff; /* default CQ for response */ 422282527734SSukumar Swaminathan wqe->CmdType = WQE_TYPE_ABORT; 422382527734SSukumar Swaminathan } else { 422482527734SSukumar Swaminathan iocb = &iocbq->iocb; 422582527734SSukumar Swaminathan iocb->ULPCONTEXT = xid; 422682527734SSukumar Swaminathan iocb->ULPIOTAG = abort_iotag; 422782527734SSukumar Swaminathan iocb->ULPLE = 1; 422882527734SSukumar Swaminathan iocb->ULPCLASS = 0; 422982527734SSukumar Swaminathan iocb->ULPCOMMAND = CMD_CLOSE_XRI_CX; 423082527734SSukumar Swaminathan iocb->ULPOWNER = OWN_CHIP; 4231fcf3ce44SJohn Forte } 4232291a2b48SSukumar Swaminathan 4233fcf3ce44SJohn Forte return (iocbq); 4234fcf3ce44SJohn Forte 423582527734SSukumar Swaminathan } /* emlxs_create_close_xri_cx() */ 4236fcf3ce44SJohn Forte 4237fcf3ce44SJohn Forte 4238a9800bebSGarrett D'Amore void 4239a9800bebSGarrett D'Amore emlxs_close_els_exchange(emlxs_hba_t *hba, emlxs_port_t *port, uint32_t rxid) 4240a9800bebSGarrett D'Amore { 4241a9800bebSGarrett D'Amore CHANNEL *cp; 4242a9800bebSGarrett D'Amore IOCBQ *iocbq; 4243a9800bebSGarrett D'Amore IOCB *iocb; 4244a9800bebSGarrett D'Amore 4245a9800bebSGarrett D'Amore if (rxid == 0 || rxid == 0xFFFF) { 4246a9800bebSGarrett D'Amore return; 4247a9800bebSGarrett D'Amore } 4248a9800bebSGarrett D'Amore 4249a9800bebSGarrett D'Amore if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 4250a9800bebSGarrett D'Amore EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 4251a9800bebSGarrett D'Amore "Closing ELS exchange: xid=%x", rxid); 4252a9800bebSGarrett D'Amore 4253*8f23e9faSHans Rosenfeld if (emlxs_sli4_unreserve_xri(port, rxid, 1) == 0) { 4254a9800bebSGarrett D'Amore return; 4255a9800bebSGarrett D'Amore } 4256a9800bebSGarrett D'Amore } 4257a9800bebSGarrett D'Amore 4258a9800bebSGarrett D'Amore cp = &hba->chan[hba->channel_els]; 4259a9800bebSGarrett D'Amore 4260a9800bebSGarrett D'Amore mutex_enter(&EMLXS_FCTAB_LOCK); 4261a9800bebSGarrett D'Amore 4262a9800bebSGarrett D'Amore /* Create the abort IOCB */ 4263a9800bebSGarrett D'Amore iocbq = emlxs_create_close_xri_cx(port, NULL, rxid, cp); 4264a9800bebSGarrett D'Amore 4265a9800bebSGarrett D'Amore mutex_exit(&EMLXS_FCTAB_LOCK); 4266a9800bebSGarrett D'Amore 4267a9800bebSGarrett D'Amore if (iocbq) { 4268a9800bebSGarrett D'Amore iocb = &iocbq->iocb; 4269a9800bebSGarrett D'Amore EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 4270*8f23e9faSHans Rosenfeld "Closing ELS exchange: xid=%x iotag=%d", rxid, 4271a9800bebSGarrett D'Amore iocb->ULPIOTAG); 4272a9800bebSGarrett D'Amore 4273a9800bebSGarrett D'Amore EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq); 4274a9800bebSGarrett D'Amore } 4275a9800bebSGarrett D'Amore 4276a9800bebSGarrett D'Amore } /* emlxs_close_els_exchange() */ 4277a9800bebSGarrett D'Amore 4278a9800bebSGarrett D'Amore 4279fe199829SSukumar Swaminathan void 4280fe199829SSukumar Swaminathan emlxs_abort_els_exchange(emlxs_hba_t *hba, emlxs_port_t *port, uint32_t rxid) 4281fe199829SSukumar Swaminathan { 4282fe199829SSukumar Swaminathan CHANNEL *cp; 4283fe199829SSukumar Swaminathan IOCBQ *iocbq; 4284fe199829SSukumar Swaminathan IOCB *iocb; 4285fe199829SSukumar Swaminathan 4286fe199829SSukumar Swaminathan if (rxid == 0 || rxid == 0xFFFF) { 4287fe199829SSukumar Swaminathan return; 4288fe199829SSukumar Swaminathan } 4289fe199829SSukumar Swaminathan 4290fe199829SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 4291fe199829SSukumar Swaminathan 4292fe199829SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 4293fe199829SSukumar Swaminathan "Aborting ELS exchange: xid=%x", rxid); 4294fe199829SSukumar Swaminathan 4295*8f23e9faSHans Rosenfeld if (emlxs_sli4_unreserve_xri(port, rxid, 1) == 0) { 4296fe199829SSukumar Swaminathan /* We have no way to abort unsolicited exchanges */ 4297fe199829SSukumar Swaminathan /* that we have not responded to at this time */ 4298fe199829SSukumar Swaminathan /* So we will return for now */ 4299fe199829SSukumar Swaminathan return; 4300fe199829SSukumar Swaminathan } 4301fe199829SSukumar Swaminathan } 4302fe199829SSukumar Swaminathan 4303fe199829SSukumar Swaminathan cp = &hba->chan[hba->channel_els]; 4304fe199829SSukumar Swaminathan 4305fe199829SSukumar Swaminathan mutex_enter(&EMLXS_FCTAB_LOCK); 4306fe199829SSukumar Swaminathan 4307fe199829SSukumar Swaminathan /* Create the abort IOCB */ 4308fe199829SSukumar Swaminathan if (hba->state >= FC_LINK_UP) { 4309fe199829SSukumar Swaminathan iocbq = emlxs_create_abort_xri_cx(port, NULL, rxid, cp, 4310fe199829SSukumar Swaminathan CLASS3, ABORT_TYPE_ABTS); 4311fe199829SSukumar Swaminathan } else { 4312fe199829SSukumar Swaminathan iocbq = emlxs_create_close_xri_cx(port, NULL, rxid, cp); 4313fe199829SSukumar Swaminathan } 4314fe199829SSukumar Swaminathan 4315fe199829SSukumar Swaminathan mutex_exit(&EMLXS_FCTAB_LOCK); 4316fe199829SSukumar Swaminathan 4317fe199829SSukumar Swaminathan if (iocbq) { 4318fe199829SSukumar Swaminathan iocb = &iocbq->iocb; 4319fe199829SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 4320*8f23e9faSHans Rosenfeld "Aborting ELS exchange: xid=%x iotag=%d", rxid, 4321fe199829SSukumar Swaminathan iocb->ULPIOTAG); 4322fe199829SSukumar Swaminathan 4323fe199829SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq); 4324fe199829SSukumar Swaminathan } 4325fe199829SSukumar Swaminathan 4326fe199829SSukumar Swaminathan } /* emlxs_abort_els_exchange() */ 4327fe199829SSukumar Swaminathan 4328fe199829SSukumar Swaminathan 4329728bdc9bSSukumar Swaminathan void 4330bb63f56eSSukumar Swaminathan emlxs_abort_ct_exchange(emlxs_hba_t *hba, emlxs_port_t *port, uint32_t rxid) 4331728bdc9bSSukumar Swaminathan { 433282527734SSukumar Swaminathan CHANNEL *cp; 4333728bdc9bSSukumar Swaminathan IOCBQ *iocbq; 4334fe199829SSukumar Swaminathan IOCB *iocb; 4335728bdc9bSSukumar Swaminathan 4336fe199829SSukumar Swaminathan if (rxid == 0 || rxid == 0xFFFF) { 4337fe199829SSukumar Swaminathan return; 4338fe199829SSukumar Swaminathan } 433982527734SSukumar Swaminathan 434082527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 4341fe199829SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_ct_msg, 4342fe199829SSukumar Swaminathan "Aborting CT exchange: xid=%x", rxid); 4343fe199829SSukumar Swaminathan 4344*8f23e9faSHans Rosenfeld if (emlxs_sli4_unreserve_xri(port, rxid, 1) == 0) { 434582527734SSukumar Swaminathan /* We have no way to abort unsolicited exchanges */ 434682527734SSukumar Swaminathan /* that we have not responded to at this time */ 434782527734SSukumar Swaminathan /* So we will return for now */ 434882527734SSukumar Swaminathan return; 434982527734SSukumar Swaminathan } 435082527734SSukumar Swaminathan } 435182527734SSukumar Swaminathan 435282527734SSukumar Swaminathan cp = &hba->chan[hba->channel_ct]; 4353728bdc9bSSukumar Swaminathan 4354fe199829SSukumar Swaminathan mutex_enter(&EMLXS_FCTAB_LOCK); 4355fe199829SSukumar Swaminathan 4356728bdc9bSSukumar Swaminathan /* Create the abort IOCB */ 4357728bdc9bSSukumar Swaminathan if (hba->state >= FC_LINK_UP) { 4358fe199829SSukumar Swaminathan iocbq = emlxs_create_abort_xri_cx(port, NULL, rxid, cp, 4359fe199829SSukumar Swaminathan CLASS3, ABORT_TYPE_ABTS); 4360291a2b48SSukumar Swaminathan } else { 436182527734SSukumar Swaminathan iocbq = emlxs_create_close_xri_cx(port, NULL, rxid, cp); 4362728bdc9bSSukumar Swaminathan } 436382527734SSukumar Swaminathan 4364fe199829SSukumar Swaminathan mutex_exit(&EMLXS_FCTAB_LOCK); 4365fe199829SSukumar Swaminathan 4366bb63f56eSSukumar Swaminathan if (iocbq) { 4367fe199829SSukumar Swaminathan iocb = &iocbq->iocb; 4368fe199829SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 4369*8f23e9faSHans Rosenfeld "Aborting CT exchange: xid=%x iotag=%d", rxid, 4370fe199829SSukumar Swaminathan iocb->ULPIOTAG); 4371fe199829SSukumar Swaminathan 437282527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq); 4373bb63f56eSSukumar Swaminathan } 437482527734SSukumar Swaminathan 437582527734SSukumar Swaminathan } /* emlxs_abort_ct_exchange() */ 4376728bdc9bSSukumar Swaminathan 4377fcf3ce44SJohn Forte 4378fe199829SSukumar Swaminathan /* This must be called while holding the EMLXS_FCTAB_LOCK */ 4379fcf3ce44SJohn Forte static void 4380fcf3ce44SJohn Forte emlxs_sbp_abort_add(emlxs_port_t *port, emlxs_buf_t *sbp, Q *abort, 4381fcf3ce44SJohn Forte uint8_t *flag, emlxs_buf_t *fpkt) 4382fcf3ce44SJohn Forte { 4383fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 4384fcf3ce44SJohn Forte IOCBQ *iocbq; 438582527734SSukumar Swaminathan CHANNEL *cp; 4386fcf3ce44SJohn Forte NODELIST *ndlp; 4387fcf3ce44SJohn Forte 438882527734SSukumar Swaminathan cp = (CHANNEL *)sbp->channel; 4389fcf3ce44SJohn Forte ndlp = sbp->node; 4390fcf3ce44SJohn Forte 4391fcf3ce44SJohn Forte /* Create the close XRI IOCB */ 4392a9800bebSGarrett D'Amore if (hba->state >= FC_LINK_UP) { 4393a9800bebSGarrett D'Amore iocbq = emlxs_create_abort_xri_cn(port, ndlp, sbp->iotag, cp, 4394a9800bebSGarrett D'Amore CLASS3, ABORT_TYPE_ABTS); 4395a9800bebSGarrett D'Amore } else { 4396a9800bebSGarrett D'Amore iocbq = emlxs_create_close_xri_cn(port, ndlp, sbp->iotag, cp); 4397a9800bebSGarrett D'Amore } 4398291a2b48SSukumar Swaminathan /* 4399291a2b48SSukumar Swaminathan * Add this iocb to our local abort Q 4400291a2b48SSukumar Swaminathan * This way we don't hold the CHIPQ lock too long 4401291a2b48SSukumar Swaminathan */ 4402fcf3ce44SJohn Forte if (iocbq) { 4403fcf3ce44SJohn Forte if (abort->q_first) { 4404291a2b48SSukumar Swaminathan ((IOCBQ *)abort->q_last)->next = iocbq; 4405fcf3ce44SJohn Forte abort->q_last = (uint8_t *)iocbq; 4406fcf3ce44SJohn Forte abort->q_cnt++; 4407fcf3ce44SJohn Forte } else { 4408fcf3ce44SJohn Forte abort->q_first = (uint8_t *)iocbq; 4409fcf3ce44SJohn Forte abort->q_last = (uint8_t *)iocbq; 4410fcf3ce44SJohn Forte abort->q_cnt = 1; 4411fcf3ce44SJohn Forte } 4412fcf3ce44SJohn Forte iocbq->next = NULL; 4413fcf3ce44SJohn Forte } 4414291a2b48SSukumar Swaminathan 4415fcf3ce44SJohn Forte /* set the flags */ 4416fcf3ce44SJohn Forte mutex_enter(&sbp->mtx); 4417fcf3ce44SJohn Forte 4418fcf3ce44SJohn Forte sbp->pkt_flags |= (PACKET_IN_FLUSH | PACKET_XRI_CLOSED); 441982527734SSukumar Swaminathan 4420fcf3ce44SJohn Forte sbp->ticks = hba->timer_tics + 10; 4421fcf3ce44SJohn Forte sbp->abort_attempts++; 4422fcf3ce44SJohn Forte 442382527734SSukumar Swaminathan flag[cp->channelno] = 1; 4424fcf3ce44SJohn Forte 4425fcf3ce44SJohn Forte /* 4426291a2b48SSukumar Swaminathan * If the fpkt is already set, then we will leave it alone 4427fcf3ce44SJohn Forte * This ensures that this pkt is only accounted for on one 4428fcf3ce44SJohn Forte * fpkt->flush_count 4429fcf3ce44SJohn Forte */ 4430fcf3ce44SJohn Forte if (!sbp->fpkt && fpkt) { 4431fcf3ce44SJohn Forte mutex_enter(&fpkt->mtx); 4432fcf3ce44SJohn Forte sbp->fpkt = fpkt; 4433fcf3ce44SJohn Forte fpkt->flush_count++; 4434fcf3ce44SJohn Forte mutex_exit(&fpkt->mtx); 4435fcf3ce44SJohn Forte } 4436291a2b48SSukumar Swaminathan 4437fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 4438fcf3ce44SJohn Forte 4439fcf3ce44SJohn Forte return; 4440fcf3ce44SJohn Forte 444182527734SSukumar Swaminathan } /* emlxs_sbp_abort_add() */ 4442