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 * 88f23e9faSHans Rosenfeld * You can obtain a copy of the license at 98f23e9faSHans 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 /* 238f23e9faSHans Rosenfeld * Copyright (c) 2004-2012 Emulex. All rights reserved. 2482527734SSukumar Swaminathan * Use is subject to license terms. 25*a3170057SPaul Winder * Copyright 2020 RackTop Systems, Inc. 26fcf3ce44SJohn Forte */ 27fcf3ce44SJohn Forte 28291a2b48SSukumar Swaminathan #include <emlxs.h> 29fcf3ce44SJohn Forte 30fcf3ce44SJohn Forte /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */ 31fcf3ce44SJohn Forte EMLXS_MSG_DEF(EMLXS_FCP_C); 32fcf3ce44SJohn Forte 33fcf3ce44SJohn Forte #define EMLXS_GET_VADDR(hba, rp, icmd) emlxs_mem_get_vaddr(hba, rp, \ 3482527734SSukumar Swaminathan PADDR(icmd->un.cont64[i].addrHigh, icmd->un.cont64[i].addrLow)); 35fcf3ce44SJohn Forte 36291a2b48SSukumar Swaminathan static void emlxs_sbp_abort_add(emlxs_port_t *port, emlxs_buf_t *sbp, 37291a2b48SSukumar Swaminathan Q *abort, uint8_t *flag, emlxs_buf_t *fpkt); 38fcf3ce44SJohn Forte 39fcf3ce44SJohn Forte #define SCSI3_PERSISTENT_RESERVE_IN 0x5e 40291a2b48SSukumar Swaminathan #define SCSI_INQUIRY 0x12 41291a2b48SSukumar Swaminathan #define SCSI_RX_DIAG 0x1C 42fcf3ce44SJohn Forte 43fcf3ce44SJohn Forte 44fcf3ce44SJohn Forte /* 45fcf3ce44SJohn Forte * emlxs_handle_fcp_event 46fcf3ce44SJohn Forte * 47fcf3ce44SJohn Forte * Description: Process an FCP Rsp Ring completion 48fcf3ce44SJohn Forte * 49fcf3ce44SJohn Forte */ 50fcf3ce44SJohn Forte /* ARGSUSED */ 51fcf3ce44SJohn Forte extern void 5282527734SSukumar Swaminathan emlxs_handle_fcp_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq) 53fcf3ce44SJohn Forte { 54fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 5582527734SSukumar Swaminathan emlxs_config_t *cfg = &CFG; 56fcf3ce44SJohn Forte IOCB *cmd; 57fcf3ce44SJohn Forte emlxs_buf_t *sbp; 58fcf3ce44SJohn Forte fc_packet_t *pkt = NULL; 59291a2b48SSukumar Swaminathan #ifdef SAN_DIAG_SUPPORT 60291a2b48SSukumar Swaminathan NODELIST *ndlp; 61291a2b48SSukumar Swaminathan #endif 62fcf3ce44SJohn Forte uint32_t iostat; 63fcf3ce44SJohn Forte uint8_t localstat; 64fcf3ce44SJohn Forte fcp_rsp_t *rsp; 65fcf3ce44SJohn Forte uint32_t rsp_data_resid; 66fcf3ce44SJohn Forte uint32_t check_underrun; 67fcf3ce44SJohn Forte uint8_t asc; 68fcf3ce44SJohn Forte uint8_t ascq; 69fcf3ce44SJohn Forte uint8_t scsi_status; 70fcf3ce44SJohn Forte uint8_t sense; 71fcf3ce44SJohn Forte uint32_t did; 72fcf3ce44SJohn Forte uint32_t fix_it; 73fcf3ce44SJohn Forte uint8_t *scsi_cmd; 74fcf3ce44SJohn Forte uint8_t scsi_opcode; 75fcf3ce44SJohn Forte uint16_t scsi_dl; 76fcf3ce44SJohn Forte uint32_t data_rx; 778f23e9faSHans Rosenfeld uint32_t length; 78fcf3ce44SJohn Forte 79fcf3ce44SJohn Forte cmd = &iocbq->iocb; 80fcf3ce44SJohn Forte 81fcf3ce44SJohn Forte /* Initialize the status */ 8282527734SSukumar Swaminathan iostat = cmd->ULPSTATUS; 83fcf3ce44SJohn Forte localstat = 0; 84fcf3ce44SJohn Forte scsi_status = 0; 85fcf3ce44SJohn Forte asc = 0; 86fcf3ce44SJohn Forte ascq = 0; 87fcf3ce44SJohn Forte sense = 0; 88fcf3ce44SJohn Forte check_underrun = 0; 89fcf3ce44SJohn Forte fix_it = 0; 90fcf3ce44SJohn Forte 91fcf3ce44SJohn Forte HBASTATS.FcpEvent++; 92fcf3ce44SJohn Forte 93fcf3ce44SJohn Forte sbp = (emlxs_buf_t *)iocbq->sbp; 94fcf3ce44SJohn Forte 95fcf3ce44SJohn Forte if (!sbp) { 96fcf3ce44SJohn Forte /* completion with missing xmit command */ 97fcf3ce44SJohn Forte HBASTATS.FcpStray++; 98fcf3ce44SJohn Forte 99fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_fcp_completion_msg, 1008f23e9faSHans Rosenfeld "cmd=%x iotag=%d", cmd->ULPCOMMAND, cmd->ULPIOTAG); 101fcf3ce44SJohn Forte 102fcf3ce44SJohn Forte return; 103fcf3ce44SJohn Forte } 104291a2b48SSukumar Swaminathan 105fcf3ce44SJohn Forte HBASTATS.FcpCompleted++; 106fcf3ce44SJohn Forte 107291a2b48SSukumar Swaminathan #ifdef SAN_DIAG_SUPPORT 108291a2b48SSukumar Swaminathan emlxs_update_sd_bucket(sbp); 109291a2b48SSukumar Swaminathan #endif /* SAN_DIAG_SUPPORT */ 110291a2b48SSukumar Swaminathan 111fcf3ce44SJohn Forte pkt = PRIV2PKT(sbp); 112fcf3ce44SJohn Forte 11382527734SSukumar Swaminathan did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id); 114fcf3ce44SJohn Forte scsi_cmd = (uint8_t *)pkt->pkt_cmd; 115fcf3ce44SJohn Forte scsi_opcode = scsi_cmd[12]; 116fcf3ce44SJohn Forte data_rx = 0; 117fcf3ce44SJohn Forte 118fcf3ce44SJohn Forte /* Sync data in data buffer only on FC_PKT_FCP_READ */ 119fcf3ce44SJohn Forte if (pkt->pkt_datalen && (pkt->pkt_tran_type == FC_PKT_FCP_READ)) { 12082527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(pkt->pkt_data_dma, 0, pkt->pkt_datalen, 121fcf3ce44SJohn Forte DDI_DMA_SYNC_FORKERNEL); 122fcf3ce44SJohn Forte 123fcf3ce44SJohn Forte #ifdef TEST_SUPPORT 124fcf3ce44SJohn Forte if (hba->underrun_counter && (iostat == IOSTAT_SUCCESS) && 125fcf3ce44SJohn Forte (pkt->pkt_datalen >= 512)) { 126fcf3ce44SJohn Forte hba->underrun_counter--; 127fcf3ce44SJohn Forte iostat = IOSTAT_FCP_RSP_ERROR; 128fcf3ce44SJohn Forte 129fcf3ce44SJohn Forte /* Report 512 bytes missing by adapter */ 130fcf3ce44SJohn Forte cmd->un.fcpi.fcpi_parm = pkt->pkt_datalen - 512; 131fcf3ce44SJohn Forte 132fcf3ce44SJohn Forte /* Corrupt 512 bytes of Data buffer */ 133fcf3ce44SJohn Forte bzero((uint8_t *)pkt->pkt_data, 512); 134fcf3ce44SJohn Forte 135fcf3ce44SJohn Forte /* Set FCP response to STATUS_GOOD */ 136fcf3ce44SJohn Forte bzero((uint8_t *)pkt->pkt_resp, pkt->pkt_rsplen); 137fcf3ce44SJohn Forte } 138291a2b48SSukumar Swaminathan #endif /* TEST_SUPPORT */ 139fcf3ce44SJohn Forte } 140291a2b48SSukumar Swaminathan 141fcf3ce44SJohn Forte /* Process the pkt */ 142fcf3ce44SJohn Forte mutex_enter(&sbp->mtx); 143fcf3ce44SJohn Forte 144fcf3ce44SJohn Forte /* Check for immediate return */ 145fcf3ce44SJohn Forte if ((iostat == IOSTAT_SUCCESS) && 146fcf3ce44SJohn Forte (pkt->pkt_comp) && 147291a2b48SSukumar Swaminathan !(sbp->pkt_flags & 14882527734SSukumar Swaminathan (PACKET_ULP_OWNED | PACKET_COMPLETED | 149fcf3ce44SJohn Forte PACKET_IN_COMPLETION | PACKET_IN_TXQ | PACKET_IN_CHIPQ | 150fcf3ce44SJohn Forte PACKET_IN_DONEQ | PACKET_IN_TIMEOUT | PACKET_IN_FLUSH | 151fcf3ce44SJohn Forte PACKET_IN_ABORT | PACKET_POLLED))) { 152fcf3ce44SJohn Forte HBASTATS.FcpGood++; 153fcf3ce44SJohn Forte 154291a2b48SSukumar Swaminathan sbp->pkt_flags |= 155291a2b48SSukumar Swaminathan (PACKET_STATE_VALID | PACKET_IN_COMPLETION | 15682527734SSukumar Swaminathan PACKET_COMPLETED | PACKET_ULP_OWNED); 157fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 158fcf3ce44SJohn Forte 159fcf3ce44SJohn Forte #if (EMLXS_MODREVX == EMLXS_MODREV2X) 160fcf3ce44SJohn Forte emlxs_unswap_pkt(sbp); 161291a2b48SSukumar Swaminathan #endif /* EMLXS_MODREV2X */ 162b3660a96SSukumar Swaminathan 163b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT 164b3660a96SSukumar Swaminathan emlxs_check_dma(hba, sbp); 165b3660a96SSukumar Swaminathan #endif /* FMA_SUPPORT */ 166b3660a96SSukumar Swaminathan 16782527734SSukumar Swaminathan cp->ulpCmplCmd++; 168fcf3ce44SJohn Forte (*pkt->pkt_comp) (pkt); 169fcf3ce44SJohn Forte 170b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT 171b3660a96SSukumar Swaminathan if (hba->flag & FC_DMA_CHECK_ERROR) { 172b3660a96SSukumar Swaminathan emlxs_thread_spawn(hba, emlxs_restart_thread, 173b3660a96SSukumar Swaminathan NULL, NULL); 174b3660a96SSukumar Swaminathan } 175b3660a96SSukumar Swaminathan #endif /* FMA_SUPPORT */ 176b3660a96SSukumar Swaminathan 177fcf3ce44SJohn Forte return; 178fcf3ce44SJohn Forte } 179291a2b48SSukumar Swaminathan 180fcf3ce44SJohn Forte /* 181291a2b48SSukumar Swaminathan * A response is only placed in the resp buffer if IOSTAT_FCP_RSP_ERROR 182291a2b48SSukumar Swaminathan * is reported. 183fcf3ce44SJohn Forte */ 184fcf3ce44SJohn Forte 1858f23e9faSHans Rosenfeld /* Check if a response buffer was not provided */ 1868f23e9faSHans Rosenfeld if ((iostat != IOSTAT_FCP_RSP_ERROR) || (pkt->pkt_rsplen == 0)) { 1878f23e9faSHans Rosenfeld goto done; 1888f23e9faSHans Rosenfeld } 1898f23e9faSHans Rosenfeld 1908f23e9faSHans Rosenfeld EMLXS_MPDATA_SYNC(pkt->pkt_resp_dma, 0, pkt->pkt_rsplen, 1918f23e9faSHans Rosenfeld DDI_DMA_SYNC_FORKERNEL); 1928f23e9faSHans Rosenfeld 1938f23e9faSHans Rosenfeld /* Get the response buffer pointer */ 1948f23e9faSHans Rosenfeld rsp = (fcp_rsp_t *)pkt->pkt_resp; 1958f23e9faSHans Rosenfeld 1968f23e9faSHans Rosenfeld /* Validate the response payload */ 1978f23e9faSHans Rosenfeld if (!rsp->fcp_u.fcp_status.resid_under && 1988f23e9faSHans Rosenfeld !rsp->fcp_u.fcp_status.resid_over) { 1998f23e9faSHans Rosenfeld rsp->fcp_resid = 0; 2008f23e9faSHans Rosenfeld } 2018f23e9faSHans Rosenfeld 2028f23e9faSHans Rosenfeld if (!rsp->fcp_u.fcp_status.rsp_len_set) { 2038f23e9faSHans Rosenfeld rsp->fcp_response_len = 0; 2048f23e9faSHans Rosenfeld } 205fcf3ce44SJohn Forte 2068f23e9faSHans Rosenfeld if (!rsp->fcp_u.fcp_status.sense_len_set) { 2078f23e9faSHans Rosenfeld rsp->fcp_sense_len = 0; 2088f23e9faSHans Rosenfeld } 2098f23e9faSHans Rosenfeld 2108f23e9faSHans Rosenfeld length = sizeof (fcp_rsp_t) + LE_SWAP32(rsp->fcp_response_len) + 2118f23e9faSHans Rosenfeld LE_SWAP32(rsp->fcp_sense_len); 2128f23e9faSHans Rosenfeld 2138f23e9faSHans Rosenfeld if (length > pkt->pkt_rsplen) { 2148f23e9faSHans Rosenfeld iostat = IOSTAT_RSP_INVALID; 2158f23e9faSHans Rosenfeld pkt->pkt_data_resid = pkt->pkt_datalen; 2168f23e9faSHans Rosenfeld goto done; 2178f23e9faSHans Rosenfeld } 218fcf3ce44SJohn Forte 2198f23e9faSHans Rosenfeld /* Set the valid response flag */ 2208f23e9faSHans Rosenfeld sbp->pkt_flags |= PACKET_FCP_RSP_VALID; 221fcf3ce44SJohn Forte 2228f23e9faSHans Rosenfeld scsi_status = rsp->fcp_u.fcp_status.scsi_status; 223fcf3ce44SJohn Forte 224291a2b48SSukumar Swaminathan #ifdef SAN_DIAG_SUPPORT 2258f23e9faSHans Rosenfeld ndlp = (NODELIST *)iocbq->node; 2268f23e9faSHans Rosenfeld if (scsi_status == SCSI_STAT_QUE_FULL) { 2278f23e9faSHans Rosenfeld emlxs_log_sd_scsi_event(port, SD_SCSI_SUBCATEGORY_QFULL, 2288f23e9faSHans Rosenfeld (HBA_WWN *)&ndlp->nlp_portname, sbp->lun); 2298f23e9faSHans Rosenfeld } else if (scsi_status == SCSI_STAT_BUSY) { 2308f23e9faSHans Rosenfeld emlxs_log_sd_scsi_event(port, 2318f23e9faSHans Rosenfeld SD_SCSI_SUBCATEGORY_DEVBSY, 2328f23e9faSHans Rosenfeld (HBA_WWN *)&ndlp->nlp_portname, sbp->lun); 2338f23e9faSHans Rosenfeld } 234291a2b48SSukumar Swaminathan #endif 235291a2b48SSukumar Swaminathan 2368f23e9faSHans Rosenfeld /* 2378f23e9faSHans Rosenfeld * Convert a task abort to a check condition with no data 2388f23e9faSHans Rosenfeld * transferred. We saw a data corruption when Solaris received 2398f23e9faSHans Rosenfeld * a Task Abort from a tape. 2408f23e9faSHans Rosenfeld */ 241a9800bebSGarrett D'Amore 2428f23e9faSHans Rosenfeld if (scsi_status == SCSI_STAT_TASK_ABORT) { 2438f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, 2448f23e9faSHans Rosenfeld &emlxs_fcp_completion_error_msg, 2458f23e9faSHans Rosenfeld "Task Abort. " 2468f23e9faSHans Rosenfeld "Fixed. did=0x%06x sbp=%p cmd=%02x dl=%d", 2478f23e9faSHans Rosenfeld did, sbp, scsi_opcode, pkt->pkt_datalen); 2488f23e9faSHans Rosenfeld 2498f23e9faSHans Rosenfeld rsp->fcp_u.fcp_status.scsi_status = 2508f23e9faSHans Rosenfeld SCSI_STAT_CHECK_COND; 2518f23e9faSHans Rosenfeld rsp->fcp_u.fcp_status.rsp_len_set = 0; 2528f23e9faSHans Rosenfeld rsp->fcp_u.fcp_status.sense_len_set = 0; 2538f23e9faSHans Rosenfeld rsp->fcp_u.fcp_status.resid_over = 0; 2548f23e9faSHans Rosenfeld 2558f23e9faSHans Rosenfeld if (pkt->pkt_datalen) { 2568f23e9faSHans Rosenfeld rsp->fcp_u.fcp_status.resid_under = 1; 2578f23e9faSHans Rosenfeld rsp->fcp_resid = 2588f23e9faSHans Rosenfeld LE_SWAP32(pkt->pkt_datalen); 2598f23e9faSHans Rosenfeld } else { 2608f23e9faSHans Rosenfeld rsp->fcp_u.fcp_status.resid_under = 0; 2618f23e9faSHans Rosenfeld rsp->fcp_resid = 0; 2628f23e9faSHans Rosenfeld } 263fcf3ce44SJohn Forte 2648f23e9faSHans Rosenfeld scsi_status = SCSI_STAT_CHECK_COND; 2658f23e9faSHans Rosenfeld } 266fcf3ce44SJohn Forte 2678f23e9faSHans Rosenfeld /* 2688f23e9faSHans Rosenfeld * We only need to check underrun if data could 2698f23e9faSHans Rosenfeld * have been sent 2708f23e9faSHans Rosenfeld */ 271fcf3ce44SJohn Forte 2728f23e9faSHans Rosenfeld /* Always check underrun if status is good */ 2738f23e9faSHans Rosenfeld if (scsi_status == SCSI_STAT_GOOD) { 2748f23e9faSHans Rosenfeld check_underrun = 1; 2758f23e9faSHans Rosenfeld } 2768f23e9faSHans Rosenfeld /* Check the sense codes if this is a check condition */ 2778f23e9faSHans Rosenfeld else if (scsi_status == SCSI_STAT_CHECK_COND) { 2788f23e9faSHans Rosenfeld check_underrun = 1; 2798f23e9faSHans Rosenfeld 2808f23e9faSHans Rosenfeld /* Check if sense data was provided */ 2818f23e9faSHans Rosenfeld if (LE_SWAP32(rsp->fcp_sense_len) >= 14) { 2828f23e9faSHans Rosenfeld sense = *((uint8_t *)rsp + 32 + 2); 2838f23e9faSHans Rosenfeld asc = *((uint8_t *)rsp + 32 + 12); 2848f23e9faSHans Rosenfeld ascq = *((uint8_t *)rsp + 32 + 13); 285fcf3ce44SJohn Forte } 286291a2b48SSukumar Swaminathan 2878f23e9faSHans Rosenfeld #ifdef SAN_DIAG_SUPPORT 2888f23e9faSHans Rosenfeld emlxs_log_sd_scsi_check_event(port, 2898f23e9faSHans Rosenfeld (HBA_WWN *)&ndlp->nlp_portname, sbp->lun, 2908f23e9faSHans Rosenfeld scsi_opcode, sense, asc, ascq); 2918f23e9faSHans Rosenfeld #endif 2928f23e9faSHans Rosenfeld } 2938f23e9faSHans Rosenfeld /* Status is not good and this is not a check condition */ 2948f23e9faSHans Rosenfeld /* No data should have been sent */ 2958f23e9faSHans Rosenfeld else { 2968f23e9faSHans Rosenfeld check_underrun = 0; 2978f23e9faSHans Rosenfeld } 2988f23e9faSHans Rosenfeld 2998f23e9faSHans Rosenfeld /* Initialize the resids */ 3008f23e9faSHans Rosenfeld pkt->pkt_resp_resid = 0; 3018f23e9faSHans Rosenfeld pkt->pkt_data_resid = 0; 3028f23e9faSHans Rosenfeld 3038f23e9faSHans Rosenfeld /* Check if no data was to be transferred */ 3048f23e9faSHans Rosenfeld if (pkt->pkt_datalen == 0) { 3058f23e9faSHans Rosenfeld goto done; 3068f23e9faSHans Rosenfeld } 3078f23e9faSHans Rosenfeld 3088f23e9faSHans Rosenfeld /* Get the residual underrun count reported by the SCSI reply */ 3098f23e9faSHans Rosenfeld rsp_data_resid = (rsp->fcp_u.fcp_status.resid_under) ? 3108f23e9faSHans Rosenfeld LE_SWAP32(rsp->fcp_resid) : 0; 3118f23e9faSHans Rosenfeld 3128f23e9faSHans Rosenfeld /* Set the pkt_data_resid to what the scsi response resid */ 3138f23e9faSHans Rosenfeld pkt->pkt_data_resid = rsp_data_resid; 3148f23e9faSHans Rosenfeld 3158f23e9faSHans Rosenfeld /* Adjust the pkt_data_resid field if needed */ 3168f23e9faSHans Rosenfeld if (pkt->pkt_tran_type == FC_PKT_FCP_READ) { 317fcf3ce44SJohn Forte /* 3188f23e9faSHans Rosenfeld * Get the residual underrun count reported by 3198f23e9faSHans Rosenfeld * our adapter 320fcf3ce44SJohn Forte */ 3218f23e9faSHans Rosenfeld pkt->pkt_data_resid = cmd->un.fcpi.fcpi_parm; 322291a2b48SSukumar Swaminathan 323291a2b48SSukumar Swaminathan #ifdef SAN_DIAG_SUPPORT 3248f23e9faSHans Rosenfeld if ((rsp_data_resid == 0) && (pkt->pkt_data_resid)) { 3258f23e9faSHans Rosenfeld emlxs_log_sd_fc_rdchk_event(port, 326291a2b48SSukumar Swaminathan (HBA_WWN *)&ndlp->nlp_portname, sbp->lun, 3278f23e9faSHans Rosenfeld scsi_opcode, pkt->pkt_data_resid); 328fcf3ce44SJohn Forte } 3298f23e9faSHans Rosenfeld #endif 3308f23e9faSHans Rosenfeld 3318f23e9faSHans Rosenfeld /* Get the actual amount of data transferred */ 3328f23e9faSHans Rosenfeld data_rx = pkt->pkt_datalen - pkt->pkt_data_resid; 333fcf3ce44SJohn Forte 3348f23e9faSHans Rosenfeld /* 3358f23e9faSHans Rosenfeld * If the residual being reported by the adapter is 3368f23e9faSHans Rosenfeld * greater than the residual being reported in the 3378f23e9faSHans Rosenfeld * reply, then we have a true underrun. 3388f23e9faSHans Rosenfeld */ 3398f23e9faSHans Rosenfeld if (check_underrun && (pkt->pkt_data_resid > rsp_data_resid)) { 3408f23e9faSHans Rosenfeld switch (scsi_opcode) { 3418f23e9faSHans Rosenfeld case SCSI_INQUIRY: 3428f23e9faSHans Rosenfeld scsi_dl = scsi_cmd[16]; 3438f23e9faSHans Rosenfeld break; 3448f23e9faSHans Rosenfeld 3458f23e9faSHans Rosenfeld case SCSI_RX_DIAG: 3468f23e9faSHans Rosenfeld scsi_dl = 3478f23e9faSHans Rosenfeld (scsi_cmd[15] * 0x100) + 3488f23e9faSHans Rosenfeld scsi_cmd[16]; 3498f23e9faSHans Rosenfeld break; 350fcf3ce44SJohn Forte 3518f23e9faSHans Rosenfeld default: 3528f23e9faSHans Rosenfeld scsi_dl = pkt->pkt_datalen; 3538f23e9faSHans Rosenfeld } 354fcf3ce44SJohn Forte 3558f23e9faSHans Rosenfeld #ifdef FCP_UNDERRUN_PATCH1 3568f23e9faSHans Rosenfeld if (cfg[CFG_ENABLE_PATCH].current & FCP_UNDERRUN_PATCH1) { 357fcf3ce44SJohn Forte /* 3588f23e9faSHans Rosenfeld * If status is not good and no data was 3598f23e9faSHans Rosenfeld * actually transferred, then we must fix 3608f23e9faSHans Rosenfeld * the issue 361fcf3ce44SJohn Forte */ 3628f23e9faSHans Rosenfeld if ((scsi_status != SCSI_STAT_GOOD) && (data_rx == 0)) { 3638f23e9faSHans Rosenfeld fix_it = 1; 3648f23e9faSHans Rosenfeld 3658f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, 3668f23e9faSHans Rosenfeld &emlxs_fcp_completion_error_msg, 3678f23e9faSHans Rosenfeld "Underrun(1). Fixed. " 3688f23e9faSHans Rosenfeld "did=0x%06x sbp=%p cmd=%02x " 3698f23e9faSHans Rosenfeld "dl=%d,%d rx=%d rsp=%d", 3708f23e9faSHans Rosenfeld did, sbp, scsi_opcode, 3718f23e9faSHans Rosenfeld pkt->pkt_datalen, scsi_dl, 3728f23e9faSHans Rosenfeld (pkt->pkt_datalen - 3738f23e9faSHans Rosenfeld pkt->pkt_data_resid), 3748f23e9faSHans Rosenfeld rsp_data_resid); 375fcf3ce44SJohn Forte 376291a2b48SSukumar Swaminathan } 3778f23e9faSHans Rosenfeld } 3788f23e9faSHans Rosenfeld #endif /* FCP_UNDERRUN_PATCH1 */ 379291a2b48SSukumar Swaminathan 380fcf3ce44SJohn Forte 3818f23e9faSHans Rosenfeld #ifdef FCP_UNDERRUN_PATCH2 3828f23e9faSHans Rosenfeld if (cfg[CFG_ENABLE_PATCH].current & FCP_UNDERRUN_PATCH2) { 3838f23e9faSHans Rosenfeld if (scsi_status == SCSI_STAT_GOOD) { 3848f23e9faSHans Rosenfeld emlxs_msg_t *msg; 385fcf3ce44SJohn Forte 3868f23e9faSHans Rosenfeld msg = &emlxs_fcp_completion_error_msg; 3878f23e9faSHans Rosenfeld /* 3888f23e9faSHans Rosenfeld * If status is good and this is an 3898f23e9faSHans Rosenfeld * inquiry request and the amount of 3908f23e9faSHans Rosenfeld * data 3918f23e9faSHans Rosenfeld */ 3928f23e9faSHans Rosenfeld /* 3938f23e9faSHans Rosenfeld * requested <= data received, then we 3948f23e9faSHans Rosenfeld * must fix the issue. 3958f23e9faSHans Rosenfeld */ 3968f23e9faSHans Rosenfeld 3978f23e9faSHans Rosenfeld if ((scsi_opcode == SCSI_INQUIRY) && 3988f23e9faSHans Rosenfeld (pkt->pkt_datalen >= data_rx) && 3998f23e9faSHans Rosenfeld (scsi_dl <= data_rx)) { 4008f23e9faSHans Rosenfeld fix_it = 1; 4018f23e9faSHans Rosenfeld 4028f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, msg, 4038f23e9faSHans Rosenfeld "Underrun(2). Fixed. " 4048f23e9faSHans Rosenfeld "did=0x%06x sbp=%p " 4058f23e9faSHans Rosenfeld "cmd=%02x dl=%d,%d " 4068f23e9faSHans Rosenfeld "rx=%d rsp=%d", 4078f23e9faSHans Rosenfeld did, sbp, scsi_opcode, 4088f23e9faSHans Rosenfeld pkt->pkt_datalen, scsi_dl, 4098f23e9faSHans Rosenfeld data_rx, rsp_data_resid); 410fcf3ce44SJohn Forte 411fcf3ce44SJohn Forte } 412fcf3ce44SJohn Forte 413fcf3ce44SJohn Forte /* 4148f23e9faSHans Rosenfeld * If status is good and this is an 4158f23e9faSHans Rosenfeld * inquiry request and the amount of 4168f23e9faSHans Rosenfeld * data requested >= 128 bytes, but 4178f23e9faSHans Rosenfeld * only 128 bytes were received, 4188f23e9faSHans Rosenfeld * then we must fix the issue. 419fcf3ce44SJohn Forte */ 4208f23e9faSHans Rosenfeld else if ((scsi_opcode == SCSI_INQUIRY) && 4218f23e9faSHans Rosenfeld (pkt->pkt_datalen >= 128) && 4228f23e9faSHans Rosenfeld (scsi_dl >= 128) && (data_rx == 128)) { 423fcf3ce44SJohn Forte fix_it = 1; 424fcf3ce44SJohn Forte 4258f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, msg, 4268f23e9faSHans Rosenfeld "Underrun(3). Fixed. " 4278f23e9faSHans Rosenfeld "did=0x%06x sbp=%p " 4288f23e9faSHans Rosenfeld "cmd=%02x dl=%d,%d " 4298f23e9faSHans Rosenfeld "rx=%d rsp=%d", 430fcf3ce44SJohn Forte did, sbp, scsi_opcode, 431fcf3ce44SJohn Forte pkt->pkt_datalen, scsi_dl, 4328f23e9faSHans Rosenfeld data_rx, rsp_data_resid); 433fcf3ce44SJohn Forte 434fcf3ce44SJohn Forte } 4358f23e9faSHans Rosenfeld } 43682527734SSukumar Swaminathan } 4378f23e9faSHans Rosenfeld #endif /* FCP_UNDERRUN_PATCH2 */ 438fcf3ce44SJohn Forte 4398f23e9faSHans Rosenfeld /* 4408f23e9faSHans Rosenfeld * Check if SCSI response payload should be 4418f23e9faSHans Rosenfeld * fixed or if a DATA_UNDERRUN should be 4428f23e9faSHans Rosenfeld * reported 4438f23e9faSHans Rosenfeld */ 4448f23e9faSHans Rosenfeld if (fix_it) { 4458f23e9faSHans Rosenfeld /* 4468f23e9faSHans Rosenfeld * Fix the SCSI response payload itself 4478f23e9faSHans Rosenfeld */ 4488f23e9faSHans Rosenfeld rsp->fcp_u.fcp_status.resid_under = 1; 4498f23e9faSHans Rosenfeld rsp->fcp_resid = 4508f23e9faSHans Rosenfeld LE_SWAP32(pkt->pkt_data_resid); 4518f23e9faSHans Rosenfeld } else { 4528f23e9faSHans Rosenfeld /* 4538f23e9faSHans Rosenfeld * Change the status from 4548f23e9faSHans Rosenfeld * IOSTAT_FCP_RSP_ERROR to 4558f23e9faSHans Rosenfeld * IOSTAT_DATA_UNDERRUN 4568f23e9faSHans Rosenfeld */ 4578f23e9faSHans Rosenfeld iostat = IOSTAT_DATA_UNDERRUN; 4588f23e9faSHans Rosenfeld pkt->pkt_data_resid = 4598f23e9faSHans Rosenfeld pkt->pkt_datalen; 4608f23e9faSHans Rosenfeld } 4618f23e9faSHans Rosenfeld } 462fcf3ce44SJohn Forte 4638f23e9faSHans Rosenfeld /* 4648f23e9faSHans Rosenfeld * If the residual being reported by the adapter is 4658f23e9faSHans Rosenfeld * less than the residual being reported in the reply, 4668f23e9faSHans Rosenfeld * then we have a true overrun. Since we don't know 4678f23e9faSHans Rosenfeld * where the extra data came from or went to then we 4688f23e9faSHans Rosenfeld * cannot trust anything we received 4698f23e9faSHans Rosenfeld */ 4708f23e9faSHans Rosenfeld else if (rsp_data_resid > pkt->pkt_data_resid) { 4718f23e9faSHans Rosenfeld /* 4728f23e9faSHans Rosenfeld * Change the status from 4738f23e9faSHans Rosenfeld * IOSTAT_FCP_RSP_ERROR to 4748f23e9faSHans Rosenfeld * IOSTAT_DATA_OVERRUN 4758f23e9faSHans Rosenfeld */ 4768f23e9faSHans Rosenfeld iostat = IOSTAT_DATA_OVERRUN; 4778f23e9faSHans Rosenfeld pkt->pkt_data_resid = pkt->pkt_datalen; 4788f23e9faSHans Rosenfeld } 479fcf3ce44SJohn Forte 4808f23e9faSHans Rosenfeld } else if ((hba->sli_mode == EMLXS_HBA_SLI4_MODE) && 4818f23e9faSHans Rosenfeld (pkt->pkt_tran_type == FC_PKT_FCP_WRITE)) { 4828f23e9faSHans Rosenfeld /* 4838f23e9faSHans Rosenfeld * Get the residual underrun count reported by 4848f23e9faSHans Rosenfeld * our adapter 4858f23e9faSHans Rosenfeld */ 4868f23e9faSHans Rosenfeld pkt->pkt_data_resid = cmd->un.fcpi.fcpi_parm; 487fcf3ce44SJohn Forte 4888f23e9faSHans Rosenfeld #ifdef SAN_DIAG_SUPPORT 4898f23e9faSHans Rosenfeld if ((rsp_data_resid == 0) && (pkt->pkt_data_resid)) { 4908f23e9faSHans Rosenfeld emlxs_log_sd_fc_rdchk_event(port, 4918f23e9faSHans Rosenfeld (HBA_WWN *)&ndlp->nlp_portname, sbp->lun, 4928f23e9faSHans Rosenfeld scsi_opcode, pkt->pkt_data_resid); 4938f23e9faSHans Rosenfeld } 4948f23e9faSHans Rosenfeld #endif /* SAN_DIAG_SUPPORT */ 495fcf3ce44SJohn Forte 4968f23e9faSHans Rosenfeld /* Get the actual amount of data transferred */ 4978f23e9faSHans Rosenfeld data_rx = pkt->pkt_datalen - pkt->pkt_data_resid; 498fcf3ce44SJohn Forte 4998f23e9faSHans Rosenfeld /* 5008f23e9faSHans Rosenfeld * If the residual being reported by the adapter is 5018f23e9faSHans Rosenfeld * greater than the residual being reported in the 5028f23e9faSHans Rosenfeld * reply, then we have a true underrun. 5038f23e9faSHans Rosenfeld */ 5048f23e9faSHans Rosenfeld if (check_underrun && (pkt->pkt_data_resid > rsp_data_resid)) { 505291a2b48SSukumar Swaminathan 5068f23e9faSHans Rosenfeld scsi_dl = pkt->pkt_datalen; 507fcf3ce44SJohn Forte 5088f23e9faSHans Rosenfeld #ifdef FCP_UNDERRUN_PATCH1 5098f23e9faSHans Rosenfeld if (cfg[CFG_ENABLE_PATCH].current & FCP_UNDERRUN_PATCH1) { 5108f23e9faSHans Rosenfeld /* 5118f23e9faSHans Rosenfeld * If status is not good and no data was 5128f23e9faSHans Rosenfeld * actually transferred, then we must fix 5138f23e9faSHans Rosenfeld * the issue 5148f23e9faSHans Rosenfeld */ 5158f23e9faSHans Rosenfeld if ((scsi_status != SCSI_STAT_GOOD) && (data_rx == 0)) { 5168f23e9faSHans Rosenfeld fix_it = 1; 517291a2b48SSukumar Swaminathan 5188f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, 5198f23e9faSHans Rosenfeld &emlxs_fcp_completion_error_msg, 5208f23e9faSHans Rosenfeld "Underrun(1). Fixed. " 5218f23e9faSHans Rosenfeld "did=0x%06x sbp=%p cmd=%02x " 5228f23e9faSHans Rosenfeld "dl=%d,%d rx=%d rsp=%d", 5238f23e9faSHans Rosenfeld did, sbp, scsi_opcode, 5248f23e9faSHans Rosenfeld pkt->pkt_datalen, scsi_dl, 5258f23e9faSHans Rosenfeld (pkt->pkt_datalen - 5268f23e9faSHans Rosenfeld pkt->pkt_data_resid), 5278f23e9faSHans Rosenfeld rsp_data_resid); 528fcf3ce44SJohn Forte 529fcf3ce44SJohn Forte } 5308f23e9faSHans Rosenfeld } 5318f23e9faSHans Rosenfeld #endif /* FCP_UNDERRUN_PATCH1 */ 532291a2b48SSukumar Swaminathan 533fcf3ce44SJohn Forte /* 5348f23e9faSHans Rosenfeld * Check if SCSI response payload should be 5358f23e9faSHans Rosenfeld * fixed or if a DATA_UNDERRUN should be 5368f23e9faSHans Rosenfeld * reported 537fcf3ce44SJohn Forte */ 5388f23e9faSHans Rosenfeld if (fix_it) { 5398f23e9faSHans Rosenfeld /* 5408f23e9faSHans Rosenfeld * Fix the SCSI response payload itself 5418f23e9faSHans Rosenfeld */ 5428f23e9faSHans Rosenfeld rsp->fcp_u.fcp_status.resid_under = 1; 5438f23e9faSHans Rosenfeld rsp->fcp_resid = 5448f23e9faSHans Rosenfeld LE_SWAP32(pkt->pkt_data_resid); 5458f23e9faSHans Rosenfeld } else { 546fcf3ce44SJohn Forte /* 547fcf3ce44SJohn Forte * Change the status from 548fcf3ce44SJohn Forte * IOSTAT_FCP_RSP_ERROR to 5498f23e9faSHans Rosenfeld * IOSTAT_DATA_UNDERRUN 550fcf3ce44SJohn Forte */ 5518f23e9faSHans Rosenfeld iostat = IOSTAT_DATA_UNDERRUN; 5528f23e9faSHans Rosenfeld pkt->pkt_data_resid = 5538f23e9faSHans Rosenfeld pkt->pkt_datalen; 554fcf3ce44SJohn Forte } 5558f23e9faSHans Rosenfeld } 556291a2b48SSukumar Swaminathan 5578f23e9faSHans Rosenfeld /* 5588f23e9faSHans Rosenfeld * If the residual being reported by the adapter is 5598f23e9faSHans Rosenfeld * less than the residual being reported in the reply, 5608f23e9faSHans Rosenfeld * then we have a true overrun. Since we don't know 5618f23e9faSHans Rosenfeld * where the extra data came from or went to then we 5628f23e9faSHans Rosenfeld * cannot trust anything we received 5638f23e9faSHans Rosenfeld */ 5648f23e9faSHans Rosenfeld else if (rsp_data_resid > pkt->pkt_data_resid) { 5658f23e9faSHans Rosenfeld /* 5668f23e9faSHans Rosenfeld * Change the status from 5678f23e9faSHans Rosenfeld * IOSTAT_FCP_RSP_ERROR to 5688f23e9faSHans Rosenfeld * IOSTAT_DATA_OVERRUN 5698f23e9faSHans Rosenfeld */ 5708f23e9faSHans Rosenfeld iostat = IOSTAT_DATA_OVERRUN; 5718f23e9faSHans Rosenfeld pkt->pkt_data_resid = pkt->pkt_datalen; 572fcf3ce44SJohn Forte } 573fcf3ce44SJohn Forte } 574291a2b48SSukumar Swaminathan 5758f23e9faSHans Rosenfeld done: 5768f23e9faSHans Rosenfeld 577fcf3ce44SJohn Forte /* Print completion message */ 578fcf3ce44SJohn Forte switch (iostat) { 579fcf3ce44SJohn Forte case IOSTAT_SUCCESS: 580fcf3ce44SJohn Forte /* Build SCSI GOOD status */ 581fcf3ce44SJohn Forte if (pkt->pkt_rsplen) { 582fcf3ce44SJohn Forte bzero((uint8_t *)pkt->pkt_resp, pkt->pkt_rsplen); 583fcf3ce44SJohn Forte } 584fcf3ce44SJohn Forte break; 585fcf3ce44SJohn Forte 586fcf3ce44SJohn Forte case IOSTAT_FCP_RSP_ERROR: 587fcf3ce44SJohn Forte break; 588fcf3ce44SJohn Forte 589fcf3ce44SJohn Forte case IOSTAT_REMOTE_STOP: 590fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, 591291a2b48SSukumar Swaminathan "Remote Stop. did=0x%06x sbp=%p cmd=%02x", did, sbp, 592291a2b48SSukumar Swaminathan scsi_opcode); 593fcf3ce44SJohn Forte break; 594fcf3ce44SJohn Forte 595fcf3ce44SJohn Forte case IOSTAT_LOCAL_REJECT: 596fcf3ce44SJohn Forte localstat = cmd->un.grsp.perr.statLocalError; 597fcf3ce44SJohn Forte 598fcf3ce44SJohn Forte switch (localstat) { 599fcf3ce44SJohn Forte case IOERR_SEQUENCE_TIMEOUT: 600fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 601fcf3ce44SJohn Forte &emlxs_fcp_completion_error_msg, 602291a2b48SSukumar Swaminathan "Local reject. " 603291a2b48SSukumar Swaminathan "%s did=0x%06x sbp=%p cmd=%02x tmo=%d ", 604fcf3ce44SJohn Forte emlxs_error_xlate(localstat), did, sbp, 605fcf3ce44SJohn Forte scsi_opcode, pkt->pkt_timeout); 606fcf3ce44SJohn Forte break; 607fcf3ce44SJohn Forte 608fcf3ce44SJohn Forte default: 609fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 610fcf3ce44SJohn Forte &emlxs_fcp_completion_error_msg, 611a9800bebSGarrett D'Amore "Local reject. %s 0x%06x %p %02x (%x)(%x)", 612291a2b48SSukumar Swaminathan emlxs_error_xlate(localstat), did, sbp, 613a9800bebSGarrett D'Amore scsi_opcode, (uint16_t)cmd->ULPIOTAG, 614a9800bebSGarrett D'Amore (uint16_t)cmd->ULPCONTEXT); 615fcf3ce44SJohn Forte } 616fcf3ce44SJohn Forte 617fcf3ce44SJohn Forte break; 618fcf3ce44SJohn Forte 619fcf3ce44SJohn Forte case IOSTAT_NPORT_RJT: 620fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, 621291a2b48SSukumar Swaminathan "Nport reject. did=0x%06x sbp=%p cmd=%02x", did, sbp, 622291a2b48SSukumar Swaminathan scsi_opcode); 623fcf3ce44SJohn Forte break; 624fcf3ce44SJohn Forte 625fcf3ce44SJohn Forte case IOSTAT_FABRIC_RJT: 626fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, 627291a2b48SSukumar Swaminathan "Fabric reject. did=0x%06x sbp=%p cmd=%02x", did, sbp, 628291a2b48SSukumar Swaminathan scsi_opcode); 629fcf3ce44SJohn Forte break; 630fcf3ce44SJohn Forte 631fcf3ce44SJohn Forte case IOSTAT_NPORT_BSY: 632291a2b48SSukumar Swaminathan #ifdef SAN_DIAG_SUPPORT 633291a2b48SSukumar Swaminathan ndlp = (NODELIST *)iocbq->node; 634291a2b48SSukumar Swaminathan emlxs_log_sd_fc_bsy_event(port, (HBA_WWN *)&ndlp->nlp_portname); 635291a2b48SSukumar Swaminathan #endif 636291a2b48SSukumar Swaminathan 637fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, 638291a2b48SSukumar Swaminathan "Nport busy. did=0x%06x sbp=%p cmd=%02x", did, sbp, 639291a2b48SSukumar Swaminathan scsi_opcode); 640fcf3ce44SJohn Forte break; 641fcf3ce44SJohn Forte 642fcf3ce44SJohn Forte case IOSTAT_FABRIC_BSY: 643291a2b48SSukumar Swaminathan #ifdef SAN_DIAG_SUPPORT 644291a2b48SSukumar Swaminathan ndlp = (NODELIST *)iocbq->node; 645291a2b48SSukumar Swaminathan emlxs_log_sd_fc_bsy_event(port, NULL); 646291a2b48SSukumar Swaminathan #endif 647291a2b48SSukumar Swaminathan 648fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, 649291a2b48SSukumar Swaminathan "Fabric busy. did=0x%06x sbp=%p cmd=%02x", did, sbp, 650291a2b48SSukumar Swaminathan scsi_opcode); 651fcf3ce44SJohn Forte break; 652fcf3ce44SJohn Forte 653fcf3ce44SJohn Forte case IOSTAT_INTERMED_RSP: 654fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, 655291a2b48SSukumar Swaminathan "Intermediate response. did=0x%06x sbp=%p cmd=%02x", did, 656291a2b48SSukumar Swaminathan sbp, scsi_opcode); 657fcf3ce44SJohn Forte break; 658fcf3ce44SJohn Forte 659fcf3ce44SJohn Forte case IOSTAT_LS_RJT: 660fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, 661291a2b48SSukumar Swaminathan "LS Reject. did=0x%06x sbp=%p cmd=%02x", did, sbp, 662291a2b48SSukumar Swaminathan scsi_opcode); 663fcf3ce44SJohn Forte break; 664fcf3ce44SJohn Forte 665fcf3ce44SJohn Forte case IOSTAT_DATA_UNDERRUN: 666fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, 667291a2b48SSukumar Swaminathan "Underrun. did=0x%06x sbp=%p cmd=%02x " 668291a2b48SSukumar Swaminathan "dl=%d,%d rx=%d rsp=%d (%02x,%02x,%02x,%02x)", 669291a2b48SSukumar Swaminathan did, sbp, scsi_opcode, pkt->pkt_datalen, scsi_dl, data_rx, 670291a2b48SSukumar Swaminathan rsp_data_resid, scsi_status, sense, asc, ascq); 671fcf3ce44SJohn Forte break; 672fcf3ce44SJohn Forte 673fcf3ce44SJohn Forte case IOSTAT_DATA_OVERRUN: 674fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, 675291a2b48SSukumar Swaminathan "Overrun. did=0x%06x sbp=%p cmd=%02x " 676291a2b48SSukumar Swaminathan "dl=%d,%d rx=%d rsp=%d (%02x,%02x,%02x,%02x)", 677291a2b48SSukumar Swaminathan did, sbp, scsi_opcode, pkt->pkt_datalen, scsi_dl, data_rx, 678291a2b48SSukumar Swaminathan rsp_data_resid, scsi_status, sense, asc, ascq); 679fcf3ce44SJohn Forte break; 680fcf3ce44SJohn Forte 6818f23e9faSHans Rosenfeld case IOSTAT_RSP_INVALID: 6828f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, 6838f23e9faSHans Rosenfeld "Rsp Invalid. did=0x%06x sbp=%p cmd=%02x dl=%d rl=%d" 6848f23e9faSHans Rosenfeld "(%d, %d, %d)", 6858f23e9faSHans Rosenfeld did, sbp, scsi_opcode, pkt->pkt_datalen, pkt->pkt_rsplen, 6868f23e9faSHans Rosenfeld LE_SWAP32(rsp->fcp_resid), 6878f23e9faSHans Rosenfeld LE_SWAP32(rsp->fcp_sense_len), 6888f23e9faSHans Rosenfeld LE_SWAP32(rsp->fcp_response_len)); 6898f23e9faSHans Rosenfeld break; 6908f23e9faSHans Rosenfeld 691fcf3ce44SJohn Forte default: 692fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, 693fcf3ce44SJohn Forte "Unknown status=%x reason=%x did=0x%06x sbp=%p cmd=%02x", 694291a2b48SSukumar Swaminathan iostat, cmd->un.grsp.perr.statLocalError, did, sbp, 695291a2b48SSukumar Swaminathan scsi_opcode); 696fcf3ce44SJohn Forte break; 697fcf3ce44SJohn Forte } 698fcf3ce44SJohn Forte 699fcf3ce44SJohn Forte if (iostat == IOSTAT_SUCCESS) { 700fcf3ce44SJohn Forte HBASTATS.FcpGood++; 701fcf3ce44SJohn Forte } else { 702fcf3ce44SJohn Forte HBASTATS.FcpError++; 703fcf3ce44SJohn Forte } 704fcf3ce44SJohn Forte 705fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 706fcf3ce44SJohn Forte 707fcf3ce44SJohn Forte emlxs_pkt_complete(sbp, iostat, localstat, 0); 708fcf3ce44SJohn Forte 709fcf3ce44SJohn Forte return; 710fcf3ce44SJohn Forte 71182527734SSukumar Swaminathan } /* emlxs_handle_fcp_event() */ 712fcf3ce44SJohn Forte 713fcf3ce44SJohn Forte 714fcf3ce44SJohn Forte /* 715fcf3ce44SJohn Forte * emlxs_post_buffer 716fcf3ce44SJohn Forte * 717fcf3ce44SJohn Forte * This routine will post count buffers to the 718fcf3ce44SJohn Forte * ring with the QUE_RING_BUF_CN command. This 719fcf3ce44SJohn Forte * allows 2 buffers / command to be posted. 720fcf3ce44SJohn Forte * Returns the number of buffers NOT posted. 721fcf3ce44SJohn Forte */ 72282527734SSukumar Swaminathan /* SLI3 */ 723fcf3ce44SJohn Forte extern int 724fcf3ce44SJohn Forte emlxs_post_buffer(emlxs_hba_t *hba, RING *rp, int16_t cnt) 725fcf3ce44SJohn Forte { 726fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 727fcf3ce44SJohn Forte IOCB *icmd; 728fcf3ce44SJohn Forte IOCBQ *iocbq; 729fcf3ce44SJohn Forte MATCHMAP *mp; 730fcf3ce44SJohn Forte uint16_t tag; 731fcf3ce44SJohn Forte uint32_t maxqbuf; 732fcf3ce44SJohn Forte int32_t i; 733fcf3ce44SJohn Forte int32_t j; 734fcf3ce44SJohn Forte uint32_t seg; 735fcf3ce44SJohn Forte uint32_t size; 736fcf3ce44SJohn Forte 737fcf3ce44SJohn Forte mp = 0; 738fcf3ce44SJohn Forte maxqbuf = 2; 739fcf3ce44SJohn Forte tag = (uint16_t)cnt; 740fcf3ce44SJohn Forte cnt += rp->fc_missbufcnt; 741fcf3ce44SJohn Forte 74282527734SSukumar Swaminathan if (rp->ringno == hba->channel_els) { 743fcf3ce44SJohn Forte seg = MEM_BUF; 744fcf3ce44SJohn Forte size = MEM_ELSBUF_SIZE; 74582527734SSukumar Swaminathan } else if (rp->ringno == hba->channel_ip) { 746fcf3ce44SJohn Forte seg = MEM_IPBUF; 747fcf3ce44SJohn Forte size = MEM_IPBUF_SIZE; 74882527734SSukumar Swaminathan } else if (rp->ringno == hba->channel_ct) { 749fcf3ce44SJohn Forte seg = MEM_CTBUF; 750fcf3ce44SJohn Forte size = MEM_CTBUF_SIZE; 751fcf3ce44SJohn Forte } 752fcf3ce44SJohn Forte #ifdef SFCT_SUPPORT 75382527734SSukumar Swaminathan else if (rp->ringno == hba->CHANNEL_FCT) { 754fcf3ce44SJohn Forte seg = MEM_FCTBUF; 755fcf3ce44SJohn Forte size = MEM_FCTBUF_SIZE; 756fcf3ce44SJohn Forte } 757291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 758fcf3ce44SJohn Forte else { 759fcf3ce44SJohn Forte return (0); 760fcf3ce44SJohn Forte } 761fcf3ce44SJohn Forte 762fcf3ce44SJohn Forte /* 763fcf3ce44SJohn Forte * While there are buffers to post 764fcf3ce44SJohn Forte */ 765fcf3ce44SJohn Forte while (cnt) { 7668f23e9faSHans Rosenfeld if ((iocbq = (IOCBQ *)emlxs_mem_get(hba, MEM_IOCB)) == 0) { 767fcf3ce44SJohn Forte rp->fc_missbufcnt = cnt; 768fcf3ce44SJohn Forte return (cnt); 769fcf3ce44SJohn Forte } 770291a2b48SSukumar Swaminathan 77182527734SSukumar Swaminathan iocbq->channel = (void *)&hba->chan[rp->ringno]; 772fcf3ce44SJohn Forte iocbq->port = (void *)port; 773fcf3ce44SJohn Forte iocbq->flag |= (IOCB_PRIORITY | IOCB_SPECIAL); 774fcf3ce44SJohn Forte 775fcf3ce44SJohn Forte icmd = &iocbq->iocb; 776fcf3ce44SJohn Forte 777fcf3ce44SJohn Forte /* 778fcf3ce44SJohn Forte * Max buffers can be posted per command 779fcf3ce44SJohn Forte */ 780fcf3ce44SJohn Forte for (i = 0; i < maxqbuf; i++) { 781fcf3ce44SJohn Forte if (cnt <= 0) 782fcf3ce44SJohn Forte break; 783fcf3ce44SJohn Forte 784fcf3ce44SJohn Forte /* fill in BDEs for command */ 7858f23e9faSHans Rosenfeld if ((mp = (MATCHMAP *)emlxs_mem_get(hba, seg)) 78682527734SSukumar Swaminathan == 0) { 78782527734SSukumar Swaminathan icmd->ULPBDECOUNT = i; 788fcf3ce44SJohn Forte for (j = 0; j < i; j++) { 789291a2b48SSukumar Swaminathan mp = EMLXS_GET_VADDR(hba, rp, icmd); 790fcf3ce44SJohn Forte if (mp) { 791a9800bebSGarrett D'Amore emlxs_mem_put(hba, seg, 792a9800bebSGarrett D'Amore (void *)mp); 793fcf3ce44SJohn Forte } 794fcf3ce44SJohn Forte } 795fcf3ce44SJohn Forte 796fcf3ce44SJohn Forte rp->fc_missbufcnt = cnt + i; 797fcf3ce44SJohn Forte 798a9800bebSGarrett D'Amore emlxs_mem_put(hba, MEM_IOCB, (void *)iocbq); 799fcf3ce44SJohn Forte 800fcf3ce44SJohn Forte return (cnt + i); 801fcf3ce44SJohn Forte } 802291a2b48SSukumar Swaminathan 803fcf3ce44SJohn Forte /* 804fcf3ce44SJohn Forte * map that page and save the address pair for lookup 805fcf3ce44SJohn Forte * later 806fcf3ce44SJohn Forte */ 807291a2b48SSukumar Swaminathan emlxs_mem_map_vaddr(hba, 808291a2b48SSukumar Swaminathan rp, 809291a2b48SSukumar Swaminathan mp, 810fcf3ce44SJohn Forte (uint32_t *)&icmd->un.cont64[i].addrHigh, 811fcf3ce44SJohn Forte (uint32_t *)&icmd->un.cont64[i].addrLow); 812fcf3ce44SJohn Forte 813fcf3ce44SJohn Forte icmd->un.cont64[i].tus.f.bdeSize = size; 81482527734SSukumar Swaminathan icmd->ULPCOMMAND = CMD_QUE_RING_BUF64_CN; 815fcf3ce44SJohn Forte 816291a2b48SSukumar Swaminathan /* 817291a2b48SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 818291a2b48SSukumar Swaminathan * "UB Post: ring=%d addr=%08x%08x size=%d", 819291a2b48SSukumar Swaminathan * rp->ringno, icmd->un.cont64[i].addrHigh, 820291a2b48SSukumar Swaminathan * icmd->un.cont64[i].addrLow, size); 821291a2b48SSukumar Swaminathan */ 822fcf3ce44SJohn Forte 823fcf3ce44SJohn Forte cnt--; 824fcf3ce44SJohn Forte } 825fcf3ce44SJohn Forte 82682527734SSukumar Swaminathan icmd->ULPIOTAG = tag; 82782527734SSukumar Swaminathan icmd->ULPBDECOUNT = i; 82882527734SSukumar Swaminathan icmd->ULPLE = 1; 82982527734SSukumar Swaminathan icmd->ULPOWNER = OWN_CHIP; 830291a2b48SSukumar Swaminathan /* used for delimiter between commands */ 831a9800bebSGarrett D'Amore iocbq->bp = (void *)mp; 832fcf3ce44SJohn Forte 83382527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, &hba->chan[rp->ringno], iocbq); 834fcf3ce44SJohn Forte } 835fcf3ce44SJohn Forte 836fcf3ce44SJohn Forte rp->fc_missbufcnt = 0; 837fcf3ce44SJohn Forte 838fcf3ce44SJohn Forte return (0); 839fcf3ce44SJohn Forte 84082527734SSukumar Swaminathan } /* emlxs_post_buffer() */ 841fcf3ce44SJohn Forte 842fcf3ce44SJohn Forte 8438f23e9faSHans Rosenfeld static void 8448f23e9faSHans Rosenfeld emlxs_fcp_tag_nodes(emlxs_port_t *port) 8458f23e9faSHans Rosenfeld { 8468f23e9faSHans Rosenfeld NODELIST *nlp; 8478f23e9faSHans Rosenfeld int i; 8488f23e9faSHans Rosenfeld 8498f23e9faSHans Rosenfeld /* We will process all nodes with this tag later */ 8508f23e9faSHans Rosenfeld rw_enter(&port->node_rwlock, RW_READER); 8518f23e9faSHans Rosenfeld for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 8528f23e9faSHans Rosenfeld nlp = port->node_table[i]; 8538f23e9faSHans Rosenfeld while (nlp != NULL) { 8548f23e9faSHans Rosenfeld nlp->nlp_tag = 1; 8558f23e9faSHans Rosenfeld nlp = nlp->nlp_list_next; 8568f23e9faSHans Rosenfeld } 8578f23e9faSHans Rosenfeld } 8588f23e9faSHans Rosenfeld rw_exit(&port->node_rwlock); 8598f23e9faSHans Rosenfeld } 8608f23e9faSHans Rosenfeld 8618f23e9faSHans Rosenfeld 8628f23e9faSHans Rosenfeld static NODELIST * 8638f23e9faSHans Rosenfeld emlxs_find_tagged_node(emlxs_port_t *port) 8648f23e9faSHans Rosenfeld { 8658f23e9faSHans Rosenfeld NODELIST *nlp; 8668f23e9faSHans Rosenfeld NODELIST *tagged; 8678f23e9faSHans Rosenfeld int i; 8688f23e9faSHans Rosenfeld 8698f23e9faSHans Rosenfeld /* Find first node */ 8708f23e9faSHans Rosenfeld rw_enter(&port->node_rwlock, RW_READER); 8718f23e9faSHans Rosenfeld tagged = 0; 8728f23e9faSHans Rosenfeld for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 8738f23e9faSHans Rosenfeld nlp = port->node_table[i]; 8748f23e9faSHans Rosenfeld while (nlp != NULL) { 8758f23e9faSHans Rosenfeld if (!nlp->nlp_tag) { 8768f23e9faSHans Rosenfeld nlp = nlp->nlp_list_next; 8778f23e9faSHans Rosenfeld continue; 8788f23e9faSHans Rosenfeld } 8798f23e9faSHans Rosenfeld nlp->nlp_tag = 0; 8808f23e9faSHans Rosenfeld 8818f23e9faSHans Rosenfeld if (nlp->nlp_Rpi == FABRIC_RPI) { 8828f23e9faSHans Rosenfeld nlp = nlp->nlp_list_next; 8838f23e9faSHans Rosenfeld continue; 8848f23e9faSHans Rosenfeld } 8858f23e9faSHans Rosenfeld tagged = nlp; 8868f23e9faSHans Rosenfeld break; 8878f23e9faSHans Rosenfeld } 8888f23e9faSHans Rosenfeld if (tagged) { 8898f23e9faSHans Rosenfeld break; 8908f23e9faSHans Rosenfeld } 8918f23e9faSHans Rosenfeld } 8928f23e9faSHans Rosenfeld rw_exit(&port->node_rwlock); 8938f23e9faSHans Rosenfeld return (tagged); 8948f23e9faSHans Rosenfeld } 8958f23e9faSHans Rosenfeld 8968f23e9faSHans Rosenfeld 897fcf3ce44SJohn Forte extern int 898fcf3ce44SJohn Forte emlxs_port_offline(emlxs_port_t *port, uint32_t scope) 899fcf3ce44SJohn Forte { 900fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 901fcf3ce44SJohn Forte emlxs_config_t *cfg; 902fcf3ce44SJohn Forte NODELIST *nlp; 903fcf3ce44SJohn Forte fc_affected_id_t *aid; 904fcf3ce44SJohn Forte uint32_t mask; 905fcf3ce44SJohn Forte uint32_t aff_d_id; 906fcf3ce44SJohn Forte uint32_t linkdown; 907fcf3ce44SJohn Forte uint32_t vlinkdown; 908fcf3ce44SJohn Forte uint32_t action; 909fcf3ce44SJohn Forte int i; 910fcf3ce44SJohn Forte uint32_t unreg_vpi; 911fcf3ce44SJohn Forte uint32_t update; 912fcf3ce44SJohn Forte uint32_t adisc_support; 913a9800bebSGarrett D'Amore uint32_t clear_all; 9143be114edSSukumar Swaminathan uint8_t format; 915fcf3ce44SJohn Forte 916fcf3ce44SJohn Forte /* Target mode only uses this routine for linkdowns */ 9178f23e9faSHans Rosenfeld if ((port->mode == MODE_TARGET) && (scope != 0xffffffff) && 9188f23e9faSHans Rosenfeld (scope != 0xfeffffff) && (scope != 0xfdffffff)) { 919fcf3ce44SJohn Forte return (0); 920fcf3ce44SJohn Forte } 921291a2b48SSukumar Swaminathan 922fcf3ce44SJohn Forte cfg = &CFG; 923fcf3ce44SJohn Forte aid = (fc_affected_id_t *)&scope; 924fcf3ce44SJohn Forte linkdown = 0; 925fcf3ce44SJohn Forte vlinkdown = 0; 926fcf3ce44SJohn Forte unreg_vpi = 0; 927fcf3ce44SJohn Forte update = 0; 928a9800bebSGarrett D'Amore clear_all = 0; 929fcf3ce44SJohn Forte 930fcf3ce44SJohn Forte if (!(port->flag & EMLXS_PORT_BOUND)) { 931fcf3ce44SJohn Forte return (0); 932fcf3ce44SJohn Forte } 933291a2b48SSukumar Swaminathan 9343be114edSSukumar Swaminathan format = aid->aff_format; 9353be114edSSukumar Swaminathan 9363be114edSSukumar Swaminathan switch (format) { 937fcf3ce44SJohn Forte case 0: /* Port */ 938fcf3ce44SJohn Forte mask = 0x00ffffff; 939fcf3ce44SJohn Forte break; 940fcf3ce44SJohn Forte 941fcf3ce44SJohn Forte case 1: /* Area */ 942fcf3ce44SJohn Forte mask = 0x00ffff00; 943fcf3ce44SJohn Forte break; 944fcf3ce44SJohn Forte 945fcf3ce44SJohn Forte case 2: /* Domain */ 946fcf3ce44SJohn Forte mask = 0x00ff0000; 947fcf3ce44SJohn Forte break; 948fcf3ce44SJohn Forte 949fcf3ce44SJohn Forte case 3: /* Network */ 950fcf3ce44SJohn Forte mask = 0x00000000; 951fcf3ce44SJohn Forte break; 952fcf3ce44SJohn Forte 953fcf3ce44SJohn Forte #ifdef DHCHAP_SUPPORT 954fcf3ce44SJohn Forte case 0xfe: /* Virtual link down */ 955fcf3ce44SJohn Forte mask = 0x00000000; 956fcf3ce44SJohn Forte vlinkdown = 1; 957fcf3ce44SJohn Forte break; 958291a2b48SSukumar Swaminathan #endif /* DHCHAP_SUPPORT */ 959fcf3ce44SJohn Forte 960fcf3ce44SJohn Forte case 0xff: /* link is down */ 961fcf3ce44SJohn Forte mask = 0x00000000; 962fcf3ce44SJohn Forte linkdown = 1; 963fcf3ce44SJohn Forte break; 964fcf3ce44SJohn Forte 9658f23e9faSHans Rosenfeld case 0xfd: /* New fabric */ 9668f23e9faSHans Rosenfeld default: 9678f23e9faSHans Rosenfeld mask = 0x00000000; 9688f23e9faSHans Rosenfeld linkdown = 1; 9698f23e9faSHans Rosenfeld clear_all = 1; 9708f23e9faSHans Rosenfeld break; 971fcf3ce44SJohn Forte } 972fcf3ce44SJohn Forte 973fcf3ce44SJohn Forte aff_d_id = aid->aff_d_id & mask; 974fcf3ce44SJohn Forte 975fcf3ce44SJohn Forte 976fcf3ce44SJohn Forte /* 977291a2b48SSukumar Swaminathan * If link is down then this is a hard shutdown and flush 978291a2b48SSukumar Swaminathan * If link not down then this is a soft shutdown and flush 979291a2b48SSukumar Swaminathan * (e.g. RSCN) 980fcf3ce44SJohn Forte */ 981fcf3ce44SJohn Forte if (linkdown) { 982fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 983fcf3ce44SJohn Forte 984fcf3ce44SJohn Forte port->flag &= EMLXS_PORT_LINKDOWN_MASK; 985fcf3ce44SJohn Forte 986fcf3ce44SJohn Forte if (port->ulp_statec != FC_STATE_OFFLINE) { 987fcf3ce44SJohn Forte port->ulp_statec = FC_STATE_OFFLINE; 9888f23e9faSHans Rosenfeld 989a9800bebSGarrett D'Amore port->prev_did = port->did; 9908f23e9faSHans Rosenfeld port->did = 0; 9918f23e9faSHans Rosenfeld port->rdid = 0; 9928f23e9faSHans Rosenfeld 993a9800bebSGarrett D'Amore bcopy(&port->fabric_sparam, &port->prev_fabric_sparam, 994a9800bebSGarrett D'Amore sizeof (SERV_PARM)); 9958f23e9faSHans Rosenfeld bzero(&port->fabric_sparam, sizeof (SERV_PARM)); 9968f23e9faSHans Rosenfeld 997fcf3ce44SJohn Forte update = 1; 998fcf3ce44SJohn Forte } 999291a2b48SSukumar Swaminathan 1000fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1001fcf3ce44SJohn Forte 10028f23e9faSHans Rosenfeld emlxs_timer_cancel_clean_address(port); 10038f23e9faSHans Rosenfeld 1004fcf3ce44SJohn Forte /* Tell ULP about it */ 1005fcf3ce44SJohn Forte if (update) { 1006fcf3ce44SJohn Forte if (port->flag & EMLXS_PORT_BOUND) { 1007fcf3ce44SJohn Forte if (port->vpi == 0) { 1008fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 1009291a2b48SSukumar Swaminathan &emlxs_link_down_msg, NULL); 1010fcf3ce44SJohn Forte } 1011291a2b48SSukumar Swaminathan 10128f23e9faSHans Rosenfeld if (port->mode == MODE_INITIATOR) { 10138f23e9faSHans Rosenfeld emlxs_fca_link_down(port); 10143be114edSSukumar Swaminathan } 1015291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT 10168f23e9faSHans Rosenfeld else if (port->mode == MODE_TARGET) { 1017fcf3ce44SJohn Forte emlxs_fct_link_down(port); 10183be114edSSukumar Swaminathan } 1019291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 1020fcf3ce44SJohn Forte 1021fcf3ce44SJohn Forte } else { 1022fcf3ce44SJohn Forte if (port->vpi == 0) { 1023fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 1024291a2b48SSukumar Swaminathan &emlxs_link_down_msg, "*"); 1025fcf3ce44SJohn Forte } 1026fcf3ce44SJohn Forte } 1027fcf3ce44SJohn Forte 1028fcf3ce44SJohn Forte 1029fcf3ce44SJohn Forte } 1030291a2b48SSukumar Swaminathan 1031fcf3ce44SJohn Forte unreg_vpi = 1; 1032fcf3ce44SJohn Forte 1033fcf3ce44SJohn Forte #ifdef DHCHAP_SUPPORT 1034fcf3ce44SJohn Forte /* Stop authentication with all nodes */ 1035fcf3ce44SJohn Forte emlxs_dhc_auth_stop(port, NULL); 1036291a2b48SSukumar Swaminathan #endif /* DHCHAP_SUPPORT */ 1037fcf3ce44SJohn Forte 1038fcf3ce44SJohn Forte /* Flush the base node */ 1039fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, &port->node_base, 0, 0, 0); 1040fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 0, &port->node_base, 0); 1041fcf3ce44SJohn Forte 1042fcf3ce44SJohn Forte /* Flush any pending ub buffers */ 1043fcf3ce44SJohn Forte emlxs_ub_flush(port); 1044fcf3ce44SJohn Forte } 1045fcf3ce44SJohn Forte #ifdef DHCHAP_SUPPORT 1046fcf3ce44SJohn Forte /* virtual link down */ 1047fcf3ce44SJohn Forte else if (vlinkdown) { 1048fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 1049fcf3ce44SJohn Forte 1050fcf3ce44SJohn Forte if (port->ulp_statec != FC_STATE_OFFLINE) { 1051fcf3ce44SJohn Forte port->ulp_statec = FC_STATE_OFFLINE; 1052fcf3ce44SJohn Forte update = 1; 1053fcf3ce44SJohn Forte } 1054291a2b48SSukumar Swaminathan 1055fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1056fcf3ce44SJohn Forte 10578f23e9faSHans Rosenfeld emlxs_timer_cancel_clean_address(port); 10588f23e9faSHans Rosenfeld 1059fcf3ce44SJohn Forte /* Tell ULP about it */ 1060fcf3ce44SJohn Forte if (update) { 1061fcf3ce44SJohn Forte if (port->flag & EMLXS_PORT_BOUND) { 1062fcf3ce44SJohn Forte if (port->vpi == 0) { 1063fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 1064fcf3ce44SJohn Forte &emlxs_link_down_msg, 1065fcf3ce44SJohn Forte "Switch authentication failed."); 1066fcf3ce44SJohn Forte } 1067291a2b48SSukumar Swaminathan 10688f23e9faSHans Rosenfeld if (port->mode == MODE_INITIATOR) { 10698f23e9faSHans Rosenfeld emlxs_fca_link_down(port); 10708f23e9faSHans Rosenfeld } 1071fcf3ce44SJohn Forte #ifdef SFCT_SUPPORT 10728f23e9faSHans Rosenfeld else if (port->mode == MODE_TARGET) { 1073fcf3ce44SJohn Forte emlxs_fct_link_down(port); 1074fcf3ce44SJohn Forte } 10758f23e9faSHans Rosenfeld #endif /* SFCT_SUPPORT */ 1076fcf3ce44SJohn Forte } else { 1077fcf3ce44SJohn Forte if (port->vpi == 0) { 1078fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 1079fcf3ce44SJohn Forte &emlxs_link_down_msg, 1080fcf3ce44SJohn Forte "Switch authentication failed. *"); 1081fcf3ce44SJohn Forte } 1082fcf3ce44SJohn Forte } 1083fcf3ce44SJohn Forte 1084fcf3ce44SJohn Forte 1085fcf3ce44SJohn Forte } 1086291a2b48SSukumar Swaminathan 1087fcf3ce44SJohn Forte /* Flush the base node */ 1088fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, &port->node_base, 0, 0, 0); 1089fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 0, &port->node_base, 0); 1090fcf3ce44SJohn Forte } 1091291a2b48SSukumar Swaminathan #endif /* DHCHAP_SUPPORT */ 10928f23e9faSHans Rosenfeld else { 10938f23e9faSHans Rosenfeld emlxs_timer_cancel_clean_address(port); 10948f23e9faSHans Rosenfeld } 1095fcf3ce44SJohn Forte 10968f23e9faSHans Rosenfeld if (port->mode == MODE_TARGET) { 10978f23e9faSHans Rosenfeld if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 10988f23e9faSHans Rosenfeld /* Set the node tags */ 10998f23e9faSHans Rosenfeld emlxs_fcp_tag_nodes(port); 11008f23e9faSHans Rosenfeld unreg_vpi = 0; 11018f23e9faSHans Rosenfeld while ((nlp = emlxs_find_tagged_node(port))) { 11028f23e9faSHans Rosenfeld (void) emlxs_rpi_pause_notify(port, 11038f23e9faSHans Rosenfeld nlp->rpip); 11048f23e9faSHans Rosenfeld /* 11058f23e9faSHans Rosenfeld * In port_online we need to resume 11068f23e9faSHans Rosenfeld * these RPIs before we can use them. 11078f23e9faSHans Rosenfeld */ 11088f23e9faSHans Rosenfeld } 11098f23e9faSHans Rosenfeld } 1110fcf3ce44SJohn Forte goto done; 1111fcf3ce44SJohn Forte } 1112291a2b48SSukumar Swaminathan 1113fcf3ce44SJohn Forte /* Set the node tags */ 11148f23e9faSHans Rosenfeld emlxs_fcp_tag_nodes(port); 1115fcf3ce44SJohn Forte 1116a9800bebSGarrett D'Amore if (!clear_all && (hba->flag & FC_ONLINE_MODE)) { 1117fcf3ce44SJohn Forte adisc_support = cfg[CFG_ADISC_SUPPORT].current; 1118fcf3ce44SJohn Forte } else { 1119fcf3ce44SJohn Forte adisc_support = 0; 1120fcf3ce44SJohn Forte } 1121fcf3ce44SJohn Forte 1122fcf3ce44SJohn Forte /* Check ADISC support level */ 1123fcf3ce44SJohn Forte switch (adisc_support) { 1124fcf3ce44SJohn Forte case 0: /* No support - Flush all IO to all matching nodes */ 1125fcf3ce44SJohn Forte 1126291a2b48SSukumar Swaminathan for (;;) { 1127fcf3ce44SJohn Forte /* 1128fcf3ce44SJohn Forte * We need to hold the locks this way because 11298f23e9faSHans Rosenfeld * EMLXS_SLI_UNREG_NODE and the flush routines enter the 1130291a2b48SSukumar Swaminathan * same locks. Also, when we release the lock the list 1131291a2b48SSukumar Swaminathan * can change out from under us. 1132fcf3ce44SJohn Forte */ 1133fcf3ce44SJohn Forte 1134fcf3ce44SJohn Forte /* Find first node */ 1135fcf3ce44SJohn Forte rw_enter(&port->node_rwlock, RW_READER); 1136fcf3ce44SJohn Forte action = 0; 1137fcf3ce44SJohn Forte for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 1138fcf3ce44SJohn Forte nlp = port->node_table[i]; 1139fcf3ce44SJohn Forte while (nlp != NULL) { 1140fcf3ce44SJohn Forte if (!nlp->nlp_tag) { 1141fcf3ce44SJohn Forte nlp = nlp->nlp_list_next; 1142fcf3ce44SJohn Forte continue; 1143fcf3ce44SJohn Forte } 1144fcf3ce44SJohn Forte nlp->nlp_tag = 0; 1145fcf3ce44SJohn Forte 1146fcf3ce44SJohn Forte /* 1147fcf3ce44SJohn Forte * Check for any device that matches 1148fcf3ce44SJohn Forte * our mask 1149fcf3ce44SJohn Forte */ 1150fcf3ce44SJohn Forte if ((nlp->nlp_DID & mask) == aff_d_id) { 1151fcf3ce44SJohn Forte if (linkdown) { 1152fcf3ce44SJohn Forte action = 1; 1153fcf3ce44SJohn Forte break; 1154291a2b48SSukumar Swaminathan } else { /* Must be an RCSN */ 1155291a2b48SSukumar Swaminathan 1156fcf3ce44SJohn Forte action = 2; 1157fcf3ce44SJohn Forte break; 1158fcf3ce44SJohn Forte } 1159fcf3ce44SJohn Forte } 1160fcf3ce44SJohn Forte nlp = nlp->nlp_list_next; 1161fcf3ce44SJohn Forte } 1162fcf3ce44SJohn Forte 1163fcf3ce44SJohn Forte if (action) { 1164fcf3ce44SJohn Forte break; 1165fcf3ce44SJohn Forte } 1166fcf3ce44SJohn Forte } 1167fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 1168fcf3ce44SJohn Forte 1169fcf3ce44SJohn Forte 1170fcf3ce44SJohn Forte /* Check if nothing was found */ 1171fcf3ce44SJohn Forte if (action == 0) { 1172fcf3ce44SJohn Forte break; 1173fcf3ce44SJohn Forte } else if (action == 1) { 11748f23e9faSHans Rosenfeld (void) EMLXS_SLI_UNREG_NODE(port, nlp, 1175fcf3ce44SJohn Forte NULL, NULL, NULL); 1176fcf3ce44SJohn Forte } else if (action == 2) { 11778f23e9faSHans Rosenfeld EMLXS_SET_DFC_STATE(nlp, NODE_LIMBO); 11788f23e9faSHans Rosenfeld 1179fcf3ce44SJohn Forte #ifdef DHCHAP_SUPPORT 1180fcf3ce44SJohn Forte emlxs_dhc_auth_stop(port, nlp); 1181291a2b48SSukumar Swaminathan #endif /* DHCHAP_SUPPORT */ 1182fcf3ce44SJohn Forte 1183291a2b48SSukumar Swaminathan /* 1184291a2b48SSukumar Swaminathan * Close the node for any further normal IO 1185291a2b48SSukumar Swaminathan * A PLOGI with reopen the node 1186291a2b48SSukumar Swaminathan */ 118782527734SSukumar Swaminathan emlxs_node_close(port, nlp, 118882527734SSukumar Swaminathan hba->channel_fcp, 60); 118982527734SSukumar Swaminathan emlxs_node_close(port, nlp, 119082527734SSukumar Swaminathan hba->channel_ip, 60); 1191fcf3ce44SJohn Forte 1192fcf3ce44SJohn Forte /* Flush tx queue */ 1193fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, nlp, 0, 0, 0); 1194fcf3ce44SJohn Forte 1195fcf3ce44SJohn Forte /* Flush chip queue */ 1196fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 0, nlp, 0); 1197fcf3ce44SJohn Forte } 1198291a2b48SSukumar Swaminathan 1199fcf3ce44SJohn Forte } 1200fcf3ce44SJohn Forte 1201fcf3ce44SJohn Forte break; 1202fcf3ce44SJohn Forte 1203291a2b48SSukumar Swaminathan case 1: /* Partial support - Flush IO for non-FCP2 matching nodes */ 1204fcf3ce44SJohn Forte 1205fcf3ce44SJohn Forte for (;;) { 1206fcf3ce44SJohn Forte 1207fcf3ce44SJohn Forte /* 1208fcf3ce44SJohn Forte * We need to hold the locks this way because 12098f23e9faSHans Rosenfeld * EMLXS_SLI_UNREG_NODE and the flush routines enter the 1210291a2b48SSukumar Swaminathan * same locks. Also, when we release the lock the list 1211291a2b48SSukumar Swaminathan * can change out from under us. 1212fcf3ce44SJohn Forte */ 1213fcf3ce44SJohn Forte rw_enter(&port->node_rwlock, RW_READER); 1214fcf3ce44SJohn Forte action = 0; 1215fcf3ce44SJohn Forte for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 1216fcf3ce44SJohn Forte nlp = port->node_table[i]; 1217fcf3ce44SJohn Forte while (nlp != NULL) { 1218fcf3ce44SJohn Forte if (!nlp->nlp_tag) { 1219fcf3ce44SJohn Forte nlp = nlp->nlp_list_next; 1220fcf3ce44SJohn Forte continue; 1221fcf3ce44SJohn Forte } 1222fcf3ce44SJohn Forte nlp->nlp_tag = 0; 1223fcf3ce44SJohn Forte 1224fcf3ce44SJohn Forte /* 1225291a2b48SSukumar Swaminathan * Check for special FCP2 target device 1226291a2b48SSukumar Swaminathan * that matches our mask 1227fcf3ce44SJohn Forte */ 1228fcf3ce44SJohn Forte if ((nlp->nlp_fcp_info & 1229fcf3ce44SJohn Forte NLP_FCP_TGT_DEVICE) && 1230291a2b48SSukumar Swaminathan (nlp-> nlp_fcp_info & 1231fcf3ce44SJohn Forte NLP_FCP_2_DEVICE) && 1232291a2b48SSukumar Swaminathan (nlp->nlp_DID & mask) == 1233291a2b48SSukumar Swaminathan aff_d_id) { 1234fcf3ce44SJohn Forte action = 3; 1235fcf3ce44SJohn Forte break; 1236fcf3ce44SJohn Forte } 1237291a2b48SSukumar Swaminathan 1238fcf3ce44SJohn Forte /* 1239fcf3ce44SJohn Forte * Check for any other device that 1240fcf3ce44SJohn Forte * matches our mask 1241fcf3ce44SJohn Forte */ 1242fcf3ce44SJohn Forte else if ((nlp->nlp_DID & mask) == 1243fcf3ce44SJohn Forte aff_d_id) { 1244fcf3ce44SJohn Forte if (linkdown) { 1245fcf3ce44SJohn Forte action = 1; 1246fcf3ce44SJohn Forte break; 1247291a2b48SSukumar Swaminathan } else { /* Must be an RSCN */ 1248291a2b48SSukumar Swaminathan 1249fcf3ce44SJohn Forte action = 2; 1250fcf3ce44SJohn Forte break; 1251fcf3ce44SJohn Forte } 1252fcf3ce44SJohn Forte } 1253291a2b48SSukumar Swaminathan 1254fcf3ce44SJohn Forte nlp = nlp->nlp_list_next; 1255fcf3ce44SJohn Forte } 1256fcf3ce44SJohn Forte 1257fcf3ce44SJohn Forte if (action) { 1258fcf3ce44SJohn Forte break; 1259fcf3ce44SJohn Forte } 1260fcf3ce44SJohn Forte } 1261fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 1262fcf3ce44SJohn Forte 1263fcf3ce44SJohn Forte /* Check if nothing was found */ 1264fcf3ce44SJohn Forte if (action == 0) { 1265fcf3ce44SJohn Forte break; 1266fcf3ce44SJohn Forte } else if (action == 1) { 12678f23e9faSHans Rosenfeld (void) EMLXS_SLI_UNREG_NODE(port, nlp, 1268fcf3ce44SJohn Forte NULL, NULL, NULL); 1269fcf3ce44SJohn Forte } else if (action == 2) { 12708f23e9faSHans Rosenfeld EMLXS_SET_DFC_STATE(nlp, NODE_LIMBO); 12718f23e9faSHans Rosenfeld 1272fcf3ce44SJohn Forte #ifdef DHCHAP_SUPPORT 1273fcf3ce44SJohn Forte emlxs_dhc_auth_stop(port, nlp); 1274291a2b48SSukumar Swaminathan #endif /* DHCHAP_SUPPORT */ 1275fcf3ce44SJohn Forte 1276291a2b48SSukumar Swaminathan /* 1277291a2b48SSukumar Swaminathan * Close the node for any further normal IO 1278291a2b48SSukumar Swaminathan * A PLOGI with reopen the node 1279291a2b48SSukumar Swaminathan */ 128082527734SSukumar Swaminathan emlxs_node_close(port, nlp, 128182527734SSukumar Swaminathan hba->channel_fcp, 60); 128282527734SSukumar Swaminathan emlxs_node_close(port, nlp, 128382527734SSukumar Swaminathan hba->channel_ip, 60); 1284fcf3ce44SJohn Forte 1285fcf3ce44SJohn Forte /* Flush tx queue */ 1286fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, nlp, 0, 0, 0); 1287fcf3ce44SJohn Forte 1288fcf3ce44SJohn Forte /* Flush chip queue */ 1289fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 0, nlp, 0); 1290291a2b48SSukumar Swaminathan 1291fcf3ce44SJohn Forte } else if (action == 3) { /* FCP2 devices */ 12928f23e9faSHans Rosenfeld EMLXS_SET_DFC_STATE(nlp, NODE_LIMBO); 12938f23e9faSHans Rosenfeld 1294fcf3ce44SJohn Forte unreg_vpi = 0; 1295fcf3ce44SJohn Forte 1296a9800bebSGarrett D'Amore if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 1297a9800bebSGarrett D'Amore (void) emlxs_rpi_pause_notify(port, 1298a9800bebSGarrett D'Amore nlp->rpip); 1299a9800bebSGarrett D'Amore } 1300a9800bebSGarrett D'Amore 1301fcf3ce44SJohn Forte #ifdef DHCHAP_SUPPORT 1302fcf3ce44SJohn Forte emlxs_dhc_auth_stop(port, nlp); 1303291a2b48SSukumar Swaminathan #endif /* DHCHAP_SUPPORT */ 1304fcf3ce44SJohn Forte 1305291a2b48SSukumar Swaminathan /* 1306291a2b48SSukumar Swaminathan * Close the node for any further normal IO 1307291a2b48SSukumar Swaminathan * An ADISC or a PLOGI with reopen the node 1308291a2b48SSukumar Swaminathan */ 130982527734SSukumar Swaminathan emlxs_node_close(port, nlp, 131082527734SSukumar Swaminathan hba->channel_fcp, -1); 131182527734SSukumar Swaminathan emlxs_node_close(port, nlp, hba->channel_ip, 1312fcf3ce44SJohn Forte ((linkdown) ? 0 : 60)); 1313fcf3ce44SJohn Forte 1314fcf3ce44SJohn Forte /* Flush tx queues except for FCP ring */ 1315fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, nlp, 131682527734SSukumar Swaminathan &hba->chan[hba->channel_ct], 0, 0); 1317fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, nlp, 131882527734SSukumar Swaminathan &hba->chan[hba->channel_els], 0, 0); 1319fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, nlp, 132082527734SSukumar Swaminathan &hba->chan[hba->channel_ip], 0, 0); 1321fcf3ce44SJohn Forte 1322fcf3ce44SJohn Forte /* Flush chip queues except for FCP ring */ 1323fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 132482527734SSukumar Swaminathan &hba->chan[hba->channel_ct], nlp, 0); 1325fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 132682527734SSukumar Swaminathan &hba->chan[hba->channel_els], nlp, 0); 1327fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 132882527734SSukumar Swaminathan &hba->chan[hba->channel_ip], nlp, 0); 1329fcf3ce44SJohn Forte } 1330fcf3ce44SJohn Forte } 1331fcf3ce44SJohn Forte break; 1332fcf3ce44SJohn Forte 1333fcf3ce44SJohn Forte case 2: /* Full support - Hold FCP IO to FCP target matching nodes */ 1334fcf3ce44SJohn Forte 1335fcf3ce44SJohn Forte if (!linkdown && !vlinkdown) { 1336fcf3ce44SJohn Forte break; 1337fcf3ce44SJohn Forte } 1338291a2b48SSukumar Swaminathan 1339fcf3ce44SJohn Forte for (;;) { 1340fcf3ce44SJohn Forte /* 1341fcf3ce44SJohn Forte * We need to hold the locks this way because 13428f23e9faSHans Rosenfeld * EMLXS_SLI_UNREG_NODE and the flush routines enter the 1343291a2b48SSukumar Swaminathan * same locks. Also, when we release the lock the list 1344291a2b48SSukumar Swaminathan * can change out from under us. 1345fcf3ce44SJohn Forte */ 1346fcf3ce44SJohn Forte rw_enter(&port->node_rwlock, RW_READER); 1347fcf3ce44SJohn Forte action = 0; 1348fcf3ce44SJohn Forte for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 1349fcf3ce44SJohn Forte nlp = port->node_table[i]; 1350fcf3ce44SJohn Forte while (nlp != NULL) { 1351fcf3ce44SJohn Forte if (!nlp->nlp_tag) { 1352fcf3ce44SJohn Forte nlp = nlp->nlp_list_next; 1353fcf3ce44SJohn Forte continue; 1354fcf3ce44SJohn Forte } 1355fcf3ce44SJohn Forte nlp->nlp_tag = 0; 1356fcf3ce44SJohn Forte 1357fcf3ce44SJohn Forte /* 1358fcf3ce44SJohn Forte * Check for FCP target device that 1359fcf3ce44SJohn Forte * matches our mask 1360fcf3ce44SJohn Forte */ 1361291a2b48SSukumar Swaminathan if ((nlp-> nlp_fcp_info & 1362fcf3ce44SJohn Forte NLP_FCP_TGT_DEVICE) && 1363291a2b48SSukumar Swaminathan (nlp->nlp_DID & mask) == 1364291a2b48SSukumar Swaminathan aff_d_id) { 1365fcf3ce44SJohn Forte action = 3; 1366fcf3ce44SJohn Forte break; 1367fcf3ce44SJohn Forte } 1368291a2b48SSukumar Swaminathan 1369fcf3ce44SJohn Forte /* 1370fcf3ce44SJohn Forte * Check for any other device that 1371fcf3ce44SJohn Forte * matches our mask 1372fcf3ce44SJohn Forte */ 1373fcf3ce44SJohn Forte else if ((nlp->nlp_DID & mask) == 1374fcf3ce44SJohn Forte aff_d_id) { 1375fcf3ce44SJohn Forte if (linkdown) { 1376fcf3ce44SJohn Forte action = 1; 1377fcf3ce44SJohn Forte break; 1378fcf3ce44SJohn Forte } else { /* Must be an RSCN */ 1379291a2b48SSukumar Swaminathan 1380fcf3ce44SJohn Forte action = 2; 1381fcf3ce44SJohn Forte break; 1382fcf3ce44SJohn Forte } 1383fcf3ce44SJohn Forte } 1384291a2b48SSukumar Swaminathan 1385fcf3ce44SJohn Forte nlp = nlp->nlp_list_next; 1386fcf3ce44SJohn Forte } 1387fcf3ce44SJohn Forte if (action) { 1388fcf3ce44SJohn Forte break; 1389fcf3ce44SJohn Forte } 1390fcf3ce44SJohn Forte } 1391fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 1392fcf3ce44SJohn Forte 1393fcf3ce44SJohn Forte /* Check if nothing was found */ 1394fcf3ce44SJohn Forte if (action == 0) { 1395fcf3ce44SJohn Forte break; 1396fcf3ce44SJohn Forte } else if (action == 1) { 13978f23e9faSHans Rosenfeld (void) EMLXS_SLI_UNREG_NODE(port, nlp, 1398fcf3ce44SJohn Forte NULL, NULL, NULL); 1399fcf3ce44SJohn Forte } else if (action == 2) { 14008f23e9faSHans Rosenfeld EMLXS_SET_DFC_STATE(nlp, NODE_LIMBO); 14018f23e9faSHans Rosenfeld 1402291a2b48SSukumar Swaminathan /* 1403291a2b48SSukumar Swaminathan * Close the node for any further normal IO 1404291a2b48SSukumar Swaminathan * A PLOGI with reopen the node 1405291a2b48SSukumar Swaminathan */ 140682527734SSukumar Swaminathan emlxs_node_close(port, nlp, 140782527734SSukumar Swaminathan hba->channel_fcp, 60); 140882527734SSukumar Swaminathan emlxs_node_close(port, nlp, 140982527734SSukumar Swaminathan hba->channel_ip, 60); 1410fcf3ce44SJohn Forte 1411fcf3ce44SJohn Forte /* Flush tx queue */ 1412fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, nlp, 0, 0, 0); 1413fcf3ce44SJohn Forte 1414fcf3ce44SJohn Forte /* Flush chip queue */ 1415fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 0, nlp, 0); 1416fcf3ce44SJohn Forte 1417fcf3ce44SJohn Forte } else if (action == 3) { /* FCP2 devices */ 14188f23e9faSHans Rosenfeld EMLXS_SET_DFC_STATE(nlp, NODE_LIMBO); 14198f23e9faSHans Rosenfeld 1420fcf3ce44SJohn Forte unreg_vpi = 0; 1421fcf3ce44SJohn Forte 1422a9800bebSGarrett D'Amore if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 1423a9800bebSGarrett D'Amore (void) emlxs_rpi_pause_notify(port, 1424a9800bebSGarrett D'Amore nlp->rpip); 1425a9800bebSGarrett D'Amore } 1426a9800bebSGarrett D'Amore 1427291a2b48SSukumar Swaminathan /* 1428291a2b48SSukumar Swaminathan * Close the node for any further normal IO 1429291a2b48SSukumar Swaminathan * An ADISC or a PLOGI with reopen the node 1430291a2b48SSukumar Swaminathan */ 143182527734SSukumar Swaminathan emlxs_node_close(port, nlp, 143282527734SSukumar Swaminathan hba->channel_fcp, -1); 143382527734SSukumar Swaminathan emlxs_node_close(port, nlp, hba->channel_ip, 1434fcf3ce44SJohn Forte ((linkdown) ? 0 : 60)); 1435fcf3ce44SJohn Forte 1436fcf3ce44SJohn Forte /* Flush tx queues except for FCP ring */ 1437fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, nlp, 143882527734SSukumar Swaminathan &hba->chan[hba->channel_ct], 0, 0); 1439fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, nlp, 144082527734SSukumar Swaminathan &hba->chan[hba->channel_els], 0, 0); 1441fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, nlp, 144282527734SSukumar Swaminathan &hba->chan[hba->channel_ip], 0, 0); 1443fcf3ce44SJohn Forte 1444fcf3ce44SJohn Forte /* Flush chip queues except for FCP ring */ 1445fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 144682527734SSukumar Swaminathan &hba->chan[hba->channel_ct], nlp, 0); 1447fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 144882527734SSukumar Swaminathan &hba->chan[hba->channel_els], nlp, 0); 1449fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 145082527734SSukumar Swaminathan &hba->chan[hba->channel_ip], nlp, 0); 1451fcf3ce44SJohn Forte } 1452fcf3ce44SJohn Forte } 1453fcf3ce44SJohn Forte 1454fcf3ce44SJohn Forte break; 1455fcf3ce44SJohn Forte 1456fcf3ce44SJohn Forte } /* switch() */ 1457fcf3ce44SJohn Forte 1458fcf3ce44SJohn Forte done: 1459fcf3ce44SJohn Forte 1460a9800bebSGarrett D'Amore if (unreg_vpi) { 1461a9800bebSGarrett D'Amore (void) emlxs_mb_unreg_vpi(port); 1462fcf3ce44SJohn Forte } 1463fcf3ce44SJohn Forte 1464291a2b48SSukumar Swaminathan return (0); 1465fcf3ce44SJohn Forte 146682527734SSukumar Swaminathan } /* emlxs_port_offline() */ 1467fcf3ce44SJohn Forte 1468fcf3ce44SJohn Forte 1469fcf3ce44SJohn Forte extern void 1470fcf3ce44SJohn Forte emlxs_port_online(emlxs_port_t *vport) 1471fcf3ce44SJohn Forte { 1472fcf3ce44SJohn Forte emlxs_hba_t *hba = vport->hba; 1473fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 14748f23e9faSHans Rosenfeld NODELIST *nlp; 1475fcf3ce44SJohn Forte uint32_t state; 1476fcf3ce44SJohn Forte uint32_t update; 1477fcf3ce44SJohn Forte uint32_t npiv_linkup; 1478fcf3ce44SJohn Forte char topology[32]; 1479fcf3ce44SJohn Forte char linkspeed[32]; 1480fcf3ce44SJohn Forte char mode[32]; 1481fcf3ce44SJohn Forte 1482fcf3ce44SJohn Forte /* 1483291a2b48SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_up_msg, 1484291a2b48SSukumar Swaminathan * "linkup_callback. vpi=%d fc_flag=%x", vport->vpi, hba->flag); 1485fcf3ce44SJohn Forte */ 1486fcf3ce44SJohn Forte 1487fcf3ce44SJohn Forte if ((vport->vpi > 0) && 1488fcf3ce44SJohn Forte (!(hba->flag & FC_NPIV_ENABLED) || 1489fcf3ce44SJohn Forte !(hba->flag & FC_NPIV_SUPPORTED))) { 1490fcf3ce44SJohn Forte return; 1491fcf3ce44SJohn Forte } 1492291a2b48SSukumar Swaminathan 1493fcf3ce44SJohn Forte if (!(vport->flag & EMLXS_PORT_BOUND) || 14948f23e9faSHans Rosenfeld !(vport->flag & EMLXS_PORT_ENABLED)) { 1495fcf3ce44SJohn Forte return; 1496fcf3ce44SJohn Forte } 1497291a2b48SSukumar Swaminathan 1498fcf3ce44SJohn Forte /* Check for mode */ 14998f23e9faSHans Rosenfeld if (port->mode == MODE_TARGET) { 15008f23e9faSHans Rosenfeld (void) strlcpy(mode, ", target", sizeof (mode)); 15018f23e9faSHans Rosenfeld 15028f23e9faSHans Rosenfeld if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 15038f23e9faSHans Rosenfeld /* Set the node tags */ 15048f23e9faSHans Rosenfeld emlxs_fcp_tag_nodes(vport); 15058f23e9faSHans Rosenfeld while ((nlp = emlxs_find_tagged_node(vport))) { 15068f23e9faSHans Rosenfeld /* The RPI was paused in port_offline */ 15078f23e9faSHans Rosenfeld (void) emlxs_rpi_resume_notify(vport, 15088f23e9faSHans Rosenfeld nlp->rpip, 0); 15098f23e9faSHans Rosenfeld } 15108f23e9faSHans Rosenfeld } 15118f23e9faSHans Rosenfeld } else if (port->mode == MODE_INITIATOR) { 15128f23e9faSHans Rosenfeld (void) strlcpy(mode, ", initiator", sizeof (mode)); 1513fcf3ce44SJohn Forte } else { 15148f23e9faSHans Rosenfeld (void) strlcpy(mode, "unknown", sizeof (mode)); 1515fcf3ce44SJohn Forte } 15168f23e9faSHans Rosenfeld mutex_enter(&EMLXS_PORT_LOCK); 1517fcf3ce44SJohn Forte 1518fcf3ce44SJohn Forte /* Check for loop topology */ 1519fcf3ce44SJohn Forte if (hba->topology == TOPOLOGY_LOOP) { 1520fcf3ce44SJohn Forte state = FC_STATE_LOOP; 15218f23e9faSHans Rosenfeld (void) strlcpy(topology, ", loop", sizeof (topology)); 1522fcf3ce44SJohn Forte } else { 1523fcf3ce44SJohn Forte state = FC_STATE_ONLINE; 15248f23e9faSHans Rosenfeld (void) strlcpy(topology, ", fabric", sizeof (topology)); 1525fcf3ce44SJohn Forte } 1526fcf3ce44SJohn Forte 1527fcf3ce44SJohn Forte /* Set the link speed */ 1528fcf3ce44SJohn Forte switch (hba->linkspeed) { 1529fcf3ce44SJohn Forte case 0: 15308f23e9faSHans Rosenfeld (void) strlcpy(linkspeed, "Gb", sizeof (linkspeed)); 1531fcf3ce44SJohn Forte state |= FC_STATE_1GBIT_SPEED; 1532fcf3ce44SJohn Forte break; 1533fcf3ce44SJohn Forte 1534fcf3ce44SJohn Forte case LA_1GHZ_LINK: 15358f23e9faSHans Rosenfeld (void) strlcpy(linkspeed, "1Gb", sizeof (linkspeed)); 1536fcf3ce44SJohn Forte state |= FC_STATE_1GBIT_SPEED; 1537fcf3ce44SJohn Forte break; 1538fcf3ce44SJohn Forte case LA_2GHZ_LINK: 15398f23e9faSHans Rosenfeld (void) strlcpy(linkspeed, "2Gb", sizeof (linkspeed)); 1540fcf3ce44SJohn Forte state |= FC_STATE_2GBIT_SPEED; 1541fcf3ce44SJohn Forte break; 1542fcf3ce44SJohn Forte case LA_4GHZ_LINK: 15438f23e9faSHans Rosenfeld (void) strlcpy(linkspeed, "4Gb", sizeof (linkspeed)); 1544fcf3ce44SJohn Forte state |= FC_STATE_4GBIT_SPEED; 1545fcf3ce44SJohn Forte break; 1546fcf3ce44SJohn Forte case LA_8GHZ_LINK: 15478f23e9faSHans Rosenfeld (void) strlcpy(linkspeed, "8Gb", sizeof (linkspeed)); 1548fcf3ce44SJohn Forte state |= FC_STATE_8GBIT_SPEED; 1549fcf3ce44SJohn Forte break; 1550fcf3ce44SJohn Forte case LA_10GHZ_LINK: 15518f23e9faSHans Rosenfeld (void) strlcpy(linkspeed, "10Gb", sizeof (linkspeed)); 1552fcf3ce44SJohn Forte state |= FC_STATE_10GBIT_SPEED; 1553fcf3ce44SJohn Forte break; 15548f23e9faSHans Rosenfeld case LA_16GHZ_LINK: 15558f23e9faSHans Rosenfeld (void) strlcpy(linkspeed, "16Gb", sizeof (linkspeed)); 15568f23e9faSHans Rosenfeld state |= FC_STATE_16GBIT_SPEED; 15578f23e9faSHans Rosenfeld break; 1558*a3170057SPaul Winder case LA_32GHZ_LINK: 1559*a3170057SPaul Winder (void) strlcpy(linkspeed, "32Gb", sizeof (linkspeed)); 1560*a3170057SPaul Winder state |= FC_STATE_32GBIT_SPEED; 1561*a3170057SPaul Winder break; 1562fcf3ce44SJohn Forte default: 15638f23e9faSHans Rosenfeld (void) snprintf(linkspeed, sizeof (linkspeed), "unknown(0x%x)", 15648f23e9faSHans Rosenfeld hba->linkspeed); 1565fcf3ce44SJohn Forte break; 1566fcf3ce44SJohn Forte } 1567fcf3ce44SJohn Forte 1568fcf3ce44SJohn Forte npiv_linkup = 0; 1569fcf3ce44SJohn Forte update = 0; 1570fcf3ce44SJohn Forte 1571fcf3ce44SJohn Forte if ((hba->state >= FC_LINK_UP) && 1572291a2b48SSukumar Swaminathan !(hba->flag & FC_LOOPBACK_MODE) && (vport->ulp_statec != state)) { 1573fcf3ce44SJohn Forte update = 1; 1574fcf3ce44SJohn Forte vport->ulp_statec = state; 1575fcf3ce44SJohn Forte 1576fcf3ce44SJohn Forte if ((vport->vpi > 0) && !(hba->flag & FC_NPIV_LINKUP)) { 1577fcf3ce44SJohn Forte hba->flag |= FC_NPIV_LINKUP; 1578fcf3ce44SJohn Forte npiv_linkup = 1; 1579fcf3ce44SJohn Forte } 1580fcf3ce44SJohn Forte } 1581291a2b48SSukumar Swaminathan 1582fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1583fcf3ce44SJohn Forte 1584fcf3ce44SJohn Forte if (update) { 1585fcf3ce44SJohn Forte if (vport->flag & EMLXS_PORT_BOUND) { 1586fcf3ce44SJohn Forte if (vport->vpi == 0) { 1587fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_up_msg, 1588291a2b48SSukumar Swaminathan "%s%s%s", linkspeed, topology, mode); 15896a573d82SSukumar Swaminathan 1590fcf3ce44SJohn Forte } else if (npiv_linkup) { 1591fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 1592291a2b48SSukumar Swaminathan &emlxs_npiv_link_up_msg, "%s%s%s", 1593fcf3ce44SJohn Forte linkspeed, topology, mode); 1594fcf3ce44SJohn Forte } 1595291a2b48SSukumar Swaminathan 15968f23e9faSHans Rosenfeld if (vport->mode == MODE_INITIATOR) { 15978f23e9faSHans Rosenfeld emlxs_fca_link_up(vport); 1598fcf3ce44SJohn Forte } 15993be114edSSukumar Swaminathan #ifdef SFCT_SUPPORT 16008f23e9faSHans Rosenfeld else if (vport->mode == MODE_TARGET) { 16013be114edSSukumar Swaminathan emlxs_fct_link_up(vport); 16023be114edSSukumar Swaminathan } 16033be114edSSukumar Swaminathan #endif /* SFCT_SUPPORT */ 1604fcf3ce44SJohn Forte } else { 1605fcf3ce44SJohn Forte if (vport->vpi == 0) { 1606fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_up_msg, 1607291a2b48SSukumar Swaminathan "%s%s%s *", linkspeed, topology, mode); 16086a573d82SSukumar Swaminathan 1609fcf3ce44SJohn Forte } else if (npiv_linkup) { 1610fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 1611291a2b48SSukumar Swaminathan &emlxs_npiv_link_up_msg, "%s%s%s *", 1612fcf3ce44SJohn Forte linkspeed, topology, mode); 1613fcf3ce44SJohn Forte } 1614fcf3ce44SJohn Forte } 1615fcf3ce44SJohn Forte 1616fcf3ce44SJohn Forte /* Check for waiting threads */ 1617fcf3ce44SJohn Forte if (vport->vpi == 0) { 1618fcf3ce44SJohn Forte mutex_enter(&EMLXS_LINKUP_LOCK); 1619fcf3ce44SJohn Forte if (hba->linkup_wait_flag == TRUE) { 1620fcf3ce44SJohn Forte hba->linkup_wait_flag = FALSE; 1621fcf3ce44SJohn Forte cv_broadcast(&EMLXS_LINKUP_CV); 1622fcf3ce44SJohn Forte } 1623fcf3ce44SJohn Forte mutex_exit(&EMLXS_LINKUP_LOCK); 1624fcf3ce44SJohn Forte } 1625291a2b48SSukumar Swaminathan 1626fcf3ce44SJohn Forte /* Flush any pending ub buffers */ 1627fcf3ce44SJohn Forte emlxs_ub_flush(vport); 1628fcf3ce44SJohn Forte } 1629291a2b48SSukumar Swaminathan 1630fcf3ce44SJohn Forte return; 1631fcf3ce44SJohn Forte 163282527734SSukumar Swaminathan } /* emlxs_port_online() */ 1633fcf3ce44SJohn Forte 1634fcf3ce44SJohn Forte 1635a9800bebSGarrett D'Amore /* SLI3 */ 1636fcf3ce44SJohn Forte extern void 1637fcf3ce44SJohn Forte emlxs_linkdown(emlxs_hba_t *hba) 1638fcf3ce44SJohn Forte { 1639fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 1640fcf3ce44SJohn Forte int i; 1641a9800bebSGarrett D'Amore uint32_t scope; 1642fcf3ce44SJohn Forte 1643fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 1644fcf3ce44SJohn Forte 164582527734SSukumar Swaminathan if (hba->state > FC_LINK_DOWN) { 164682527734SSukumar Swaminathan HBASTATS.LinkDown++; 164782527734SSukumar Swaminathan EMLXS_STATE_CHANGE_LOCKED(hba, FC_LINK_DOWN); 164882527734SSukumar Swaminathan } 1649fcf3ce44SJohn Forte 1650a9800bebSGarrett D'Amore /* Set scope */ 1651a9800bebSGarrett D'Amore scope = (hba->flag & FC_NEW_FABRIC)? 0xFDFFFFFF:0xFFFFFFFF; 1652a9800bebSGarrett D'Amore 1653fcf3ce44SJohn Forte /* Filter hba flags */ 1654fcf3ce44SJohn Forte hba->flag &= FC_LINKDOWN_MASK; 1655fcf3ce44SJohn Forte hba->discovery_timer = 0; 1656fcf3ce44SJohn Forte hba->linkup_timer = 0; 1657fcf3ce44SJohn Forte 1658fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1659fcf3ce44SJohn Forte 1660fcf3ce44SJohn Forte for (i = 0; i < MAX_VPORTS; i++) { 1661fcf3ce44SJohn Forte port = &VPORT(i); 1662fcf3ce44SJohn Forte 1663fcf3ce44SJohn Forte if (!(port->flag & EMLXS_PORT_BOUND)) { 1664fcf3ce44SJohn Forte continue; 1665fcf3ce44SJohn Forte } 1666291a2b48SSukumar Swaminathan 1667a9800bebSGarrett D'Amore (void) emlxs_port_offline(port, scope); 1668fcf3ce44SJohn Forte 1669fcf3ce44SJohn Forte } 1670fcf3ce44SJohn Forte 1671a9800bebSGarrett D'Amore emlxs_log_link_event(port); 1672a9800bebSGarrett D'Amore 1673fcf3ce44SJohn Forte return; 1674fcf3ce44SJohn Forte 167582527734SSukumar Swaminathan } /* emlxs_linkdown() */ 1676fcf3ce44SJohn Forte 1677fcf3ce44SJohn Forte 1678a9800bebSGarrett D'Amore /* SLI3 */ 1679fcf3ce44SJohn Forte extern void 1680fcf3ce44SJohn Forte emlxs_linkup(emlxs_hba_t *hba) 1681fcf3ce44SJohn Forte { 1682fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 1683fcf3ce44SJohn Forte emlxs_config_t *cfg = &CFG; 1684fcf3ce44SJohn Forte 1685fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 1686fcf3ce44SJohn Forte 16878f23e9faSHans Rosenfeld /* Check for any mode changes */ 16888f23e9faSHans Rosenfeld emlxs_mode_set(hba); 16898f23e9faSHans Rosenfeld 1690fcf3ce44SJohn Forte HBASTATS.LinkUp++; 169182527734SSukumar Swaminathan EMLXS_STATE_CHANGE_LOCKED(hba, FC_LINK_UP); 1692fcf3ce44SJohn Forte 1693fcf3ce44SJohn Forte #ifdef MENLO_SUPPORT 1694fcf3ce44SJohn Forte if (hba->flag & FC_MENLO_MODE) { 1695fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1696fcf3ce44SJohn Forte 1697fcf3ce44SJohn Forte /* 1698fcf3ce44SJohn Forte * Trigger linkup CV and don't start linkup & discovery 1699fcf3ce44SJohn Forte * timers 1700fcf3ce44SJohn Forte */ 1701fcf3ce44SJohn Forte mutex_enter(&EMLXS_LINKUP_LOCK); 1702fcf3ce44SJohn Forte cv_broadcast(&EMLXS_LINKUP_CV); 1703fcf3ce44SJohn Forte mutex_exit(&EMLXS_LINKUP_LOCK); 1704fcf3ce44SJohn Forte 1705a9800bebSGarrett D'Amore emlxs_log_link_event(port); 1706a9800bebSGarrett D'Amore 1707fcf3ce44SJohn Forte return; 1708fcf3ce44SJohn Forte } 1709291a2b48SSukumar Swaminathan #endif /* MENLO_SUPPORT */ 1710fcf3ce44SJohn Forte 1711fcf3ce44SJohn Forte /* Set the linkup & discovery timers */ 1712fcf3ce44SJohn Forte hba->linkup_timer = hba->timer_tics + cfg[CFG_LINKUP_TIMEOUT].current; 1713291a2b48SSukumar Swaminathan hba->discovery_timer = 1714291a2b48SSukumar Swaminathan hba->timer_tics + cfg[CFG_LINKUP_TIMEOUT].current + 1715291a2b48SSukumar Swaminathan cfg[CFG_DISC_TIMEOUT].current; 1716fcf3ce44SJohn Forte 1717fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1718fcf3ce44SJohn Forte 1719a9800bebSGarrett D'Amore emlxs_log_link_event(port); 1720a9800bebSGarrett D'Amore 1721fcf3ce44SJohn Forte return; 1722fcf3ce44SJohn Forte 172382527734SSukumar Swaminathan } /* emlxs_linkup() */ 1724fcf3ce44SJohn Forte 1725fcf3ce44SJohn Forte 1726fcf3ce44SJohn Forte /* 1727fcf3ce44SJohn Forte * emlxs_reset_link 1728fcf3ce44SJohn Forte * 1729fcf3ce44SJohn Forte * Description: 1730fcf3ce44SJohn Forte * Called to reset the link with an init_link 1731fcf3ce44SJohn Forte * 1732fcf3ce44SJohn Forte * Returns: 1733fcf3ce44SJohn Forte * 1734fcf3ce44SJohn Forte */ 1735fcf3ce44SJohn Forte extern int 173682527734SSukumar Swaminathan emlxs_reset_link(emlxs_hba_t *hba, uint32_t linkup, uint32_t wait) 1737fcf3ce44SJohn Forte { 1738fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 1739fcf3ce44SJohn Forte emlxs_config_t *cfg; 174082527734SSukumar Swaminathan MAILBOXQ *mbq = NULL; 174182527734SSukumar Swaminathan MAILBOX *mb = NULL; 174282527734SSukumar Swaminathan int rval = 0; 17438f23e9faSHans Rosenfeld int tmo; 174482527734SSukumar Swaminathan int rc; 1745fcf3ce44SJohn Forte 1746fcf3ce44SJohn Forte /* 1747fcf3ce44SJohn Forte * Get a buffer to use for the mailbox command 1748fcf3ce44SJohn Forte */ 17498f23e9faSHans Rosenfeld if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX)) 175082527734SSukumar Swaminathan == NULL) { 1751fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_reset_failed_msg, 1752fcf3ce44SJohn Forte "Unable to allocate mailbox buffer."); 175382527734SSukumar Swaminathan rval = 1; 175482527734SSukumar Swaminathan goto reset_link_fail; 175582527734SSukumar Swaminathan } 1756fcf3ce44SJohn Forte 1757a9800bebSGarrett D'Amore if (linkup) { 1758a9800bebSGarrett D'Amore EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_reset_msg, 1759a9800bebSGarrett D'Amore "Resetting link..."); 1760a9800bebSGarrett D'Amore } else { 1761a9800bebSGarrett D'Amore EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_reset_msg, 1762a9800bebSGarrett D'Amore "Disabling link..."); 1763a9800bebSGarrett D'Amore } 1764a9800bebSGarrett D'Amore 176582527734SSukumar Swaminathan mb = (MAILBOX *)mbq; 176682527734SSukumar Swaminathan 176782527734SSukumar Swaminathan /* Bring link down first */ 176882527734SSukumar Swaminathan emlxs_mb_down_link(hba, mbq); 176982527734SSukumar Swaminathan 177082527734SSukumar Swaminathan #define MBXERR_LINK_DOWN 0x33 177182527734SSukumar Swaminathan 177282527734SSukumar Swaminathan if (wait) { 177382527734SSukumar Swaminathan wait = MBX_WAIT; 177482527734SSukumar Swaminathan } else { 177582527734SSukumar Swaminathan wait = MBX_NOWAIT; 177682527734SSukumar Swaminathan } 177782527734SSukumar Swaminathan rc = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, wait, 0); 177882527734SSukumar Swaminathan if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS) && 177982527734SSukumar Swaminathan (rc != MBXERR_LINK_DOWN)) { 178082527734SSukumar Swaminathan rval = 1; 178182527734SSukumar Swaminathan goto reset_link_fail; 1782fcf3ce44SJohn Forte } 1783291a2b48SSukumar Swaminathan 17848f23e9faSHans Rosenfeld tmo = 120; 17858f23e9faSHans Rosenfeld do { 17868f23e9faSHans Rosenfeld delay(drv_usectohz(500000)); 17878f23e9faSHans Rosenfeld tmo--; 17888f23e9faSHans Rosenfeld 17898f23e9faSHans Rosenfeld if (!tmo) { 17908f23e9faSHans Rosenfeld rval = 1; 17918f23e9faSHans Rosenfeld 17928f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_reset_msg, 17938f23e9faSHans Rosenfeld "Linkdown timeout."); 17948f23e9faSHans Rosenfeld 17958f23e9faSHans Rosenfeld goto reset_link_fail; 17968f23e9faSHans Rosenfeld } 17978f23e9faSHans Rosenfeld } while ((hba->state >= FC_LINK_UP) && (hba->state != FC_ERROR)); 17988f23e9faSHans Rosenfeld 1799fcf3ce44SJohn Forte if (linkup) { 1800fcf3ce44SJohn Forte /* 1801fcf3ce44SJohn Forte * Setup and issue mailbox INITIALIZE LINK command 1802fcf3ce44SJohn Forte */ 1803fcf3ce44SJohn Forte 180482527734SSukumar Swaminathan if (wait == MBX_NOWAIT) { 18058f23e9faSHans Rosenfeld if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX)) 180682527734SSukumar Swaminathan == NULL) { 180782527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 180882527734SSukumar Swaminathan &emlxs_link_reset_failed_msg, 180982527734SSukumar Swaminathan "Unable to allocate mailbox buffer."); 181082527734SSukumar Swaminathan rval = 1; 181182527734SSukumar Swaminathan goto reset_link_fail; 181282527734SSukumar Swaminathan } 181382527734SSukumar Swaminathan mb = (MAILBOX *)mbq; 181482527734SSukumar Swaminathan } else { 181582527734SSukumar Swaminathan /* Reuse mbq from previous mbox */ 181682527734SSukumar Swaminathan mb = (MAILBOX *)mbq; 181782527734SSukumar Swaminathan } 181882527734SSukumar Swaminathan cfg = &CFG; 181982527734SSukumar Swaminathan 182082527734SSukumar Swaminathan emlxs_mb_init_link(hba, mbq, 1821fcf3ce44SJohn Forte cfg[CFG_TOPOLOGY].current, cfg[CFG_LINK_SPEED].current); 1822fcf3ce44SJohn Forte 1823fcf3ce44SJohn Forte mb->un.varInitLnk.lipsr_AL_PA = 0; 1824fcf3ce44SJohn Forte 1825fcf3ce44SJohn Forte /* Clear the loopback mode */ 1826fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 1827fcf3ce44SJohn Forte hba->flag &= ~FC_LOOPBACK_MODE; 1828291a2b48SSukumar Swaminathan hba->loopback_tics = 0; 1829fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1830fcf3ce44SJohn Forte 183182527734SSukumar Swaminathan rc = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, wait, 0); 183282527734SSukumar Swaminathan if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { 183382527734SSukumar Swaminathan rval = 1; 183482527734SSukumar Swaminathan goto reset_link_fail; 1835fcf3ce44SJohn Forte } 1836291a2b48SSukumar Swaminathan 1837fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_reset_msg, NULL); 183882527734SSukumar Swaminathan } 1839fcf3ce44SJohn Forte 184082527734SSukumar Swaminathan reset_link_fail: 1841291a2b48SSukumar Swaminathan 184282527734SSukumar Swaminathan if ((wait == MBX_WAIT) && mbq) { 1843a9800bebSGarrett D'Amore emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 1844fcf3ce44SJohn Forte } 1845fcf3ce44SJohn Forte 184682527734SSukumar Swaminathan return (rval); 184782527734SSukumar Swaminathan } /* emlxs_reset_link() */ 1848fcf3ce44SJohn Forte 1849fcf3ce44SJohn Forte 1850fcf3ce44SJohn Forte extern int 1851fcf3ce44SJohn Forte emlxs_online(emlxs_hba_t *hba) 1852fcf3ce44SJohn Forte { 1853fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 1854fcf3ce44SJohn Forte int32_t rval = 0; 1855fcf3ce44SJohn Forte uint32_t i = 0; 1856fcf3ce44SJohn Forte 1857fcf3ce44SJohn Forte /* Make sure adapter is offline or exit trying (30 seconds) */ 1858291a2b48SSukumar Swaminathan while (i++ < 30) { 1859fcf3ce44SJohn Forte /* Check if adapter is already going online */ 1860fcf3ce44SJohn Forte if (hba->flag & (FC_ONLINE_MODE | FC_ONLINING_MODE)) { 1861fcf3ce44SJohn Forte return (0); 1862fcf3ce44SJohn Forte } 1863291a2b48SSukumar Swaminathan 1864fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 1865fcf3ce44SJohn Forte 1866fcf3ce44SJohn Forte /* Check again */ 1867fcf3ce44SJohn Forte if (hba->flag & (FC_ONLINE_MODE | FC_ONLINING_MODE)) { 1868fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1869fcf3ce44SJohn Forte return (0); 1870fcf3ce44SJohn Forte } 1871291a2b48SSukumar Swaminathan 1872fcf3ce44SJohn Forte /* Check if adapter is offline */ 1873fcf3ce44SJohn Forte if (hba->flag & FC_OFFLINE_MODE) { 1874fcf3ce44SJohn Forte /* Mark it going online */ 1875fcf3ce44SJohn Forte hba->flag &= ~FC_OFFLINE_MODE; 1876fcf3ce44SJohn Forte hba->flag |= FC_ONLINING_MODE; 1877fcf3ce44SJohn Forte 1878fcf3ce44SJohn Forte /* Currently !FC_ONLINE_MODE and !FC_OFFLINE_MODE */ 1879fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1880fcf3ce44SJohn Forte break; 1881fcf3ce44SJohn Forte } 1882291a2b48SSukumar Swaminathan 1883fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1884fcf3ce44SJohn Forte 18858f23e9faSHans Rosenfeld BUSYWAIT_MS(1000); 1886fcf3ce44SJohn Forte } 1887fcf3ce44SJohn Forte 1888fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg, 1889fcf3ce44SJohn Forte "Going online..."); 1890fcf3ce44SJohn Forte 189182527734SSukumar Swaminathan if (rval = EMLXS_SLI_ONLINE(hba)) { 1892291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, "status=%x", 1893fcf3ce44SJohn Forte rval); 1894fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_offline_msg, NULL); 1895fcf3ce44SJohn Forte 1896fcf3ce44SJohn Forte /* Set FC_OFFLINE_MODE */ 1897fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 1898fcf3ce44SJohn Forte hba->flag |= FC_OFFLINE_MODE; 1899fcf3ce44SJohn Forte hba->flag &= ~FC_ONLINING_MODE; 1900fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1901fcf3ce44SJohn Forte 1902fcf3ce44SJohn Forte return (rval); 1903fcf3ce44SJohn Forte } 1904291a2b48SSukumar Swaminathan 1905fcf3ce44SJohn Forte /* Start the timer */ 1906fcf3ce44SJohn Forte emlxs_timer_start(hba); 1907fcf3ce44SJohn Forte 1908fcf3ce44SJohn Forte /* Set FC_ONLINE_MODE */ 1909fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 1910fcf3ce44SJohn Forte hba->flag |= FC_ONLINE_MODE; 1911fcf3ce44SJohn Forte hba->flag &= ~FC_ONLINING_MODE; 1912fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1913fcf3ce44SJohn Forte 1914fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_online_msg, NULL); 1915fcf3ce44SJohn Forte 1916fcf3ce44SJohn Forte #ifdef SFCT_SUPPORT 19178f23e9faSHans Rosenfeld if (port->flag & EMLXS_TGT_ENABLED) { 19188f23e9faSHans Rosenfeld (void) emlxs_fct_port_initialize(port); 19198f23e9faSHans Rosenfeld } 1920291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 1921fcf3ce44SJohn Forte 1922fcf3ce44SJohn Forte return (rval); 1923fcf3ce44SJohn Forte 192482527734SSukumar Swaminathan } /* emlxs_online() */ 1925fcf3ce44SJohn Forte 1926fcf3ce44SJohn Forte 1927fcf3ce44SJohn Forte extern int 19288f23e9faSHans Rosenfeld emlxs_offline(emlxs_hba_t *hba, uint32_t reset_requested) 1929fcf3ce44SJohn Forte { 1930fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 1931fcf3ce44SJohn Forte uint32_t i = 0; 1932fcf3ce44SJohn Forte int rval = 1; 1933fcf3ce44SJohn Forte 1934fcf3ce44SJohn Forte /* Make sure adapter is online or exit trying (30 seconds) */ 1935291a2b48SSukumar Swaminathan while (i++ < 30) { 1936fcf3ce44SJohn Forte /* Check if adapter is already going offline */ 1937fcf3ce44SJohn Forte if (hba->flag & (FC_OFFLINE_MODE | FC_OFFLINING_MODE)) { 1938fcf3ce44SJohn Forte return (0); 1939fcf3ce44SJohn Forte } 1940291a2b48SSukumar Swaminathan 1941fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 1942fcf3ce44SJohn Forte 1943fcf3ce44SJohn Forte /* Check again */ 1944fcf3ce44SJohn Forte if (hba->flag & (FC_OFFLINE_MODE | FC_OFFLINING_MODE)) { 1945fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1946fcf3ce44SJohn Forte return (0); 1947fcf3ce44SJohn Forte } 1948291a2b48SSukumar Swaminathan 1949fcf3ce44SJohn Forte /* Check if adapter is online */ 1950fcf3ce44SJohn Forte if (hba->flag & FC_ONLINE_MODE) { 1951fcf3ce44SJohn Forte /* Mark it going offline */ 1952fcf3ce44SJohn Forte hba->flag &= ~FC_ONLINE_MODE; 1953fcf3ce44SJohn Forte hba->flag |= FC_OFFLINING_MODE; 1954fcf3ce44SJohn Forte 1955fcf3ce44SJohn Forte /* Currently !FC_ONLINE_MODE and !FC_OFFLINE_MODE */ 1956fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1957fcf3ce44SJohn Forte break; 1958fcf3ce44SJohn Forte } 1959291a2b48SSukumar Swaminathan 1960fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 1961fcf3ce44SJohn Forte 19628f23e9faSHans Rosenfeld BUSYWAIT_MS(1000); 1963fcf3ce44SJohn Forte } 1964fcf3ce44SJohn Forte 1965291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg, 1966291a2b48SSukumar Swaminathan "Going offline..."); 1967fcf3ce44SJohn Forte 19688f23e9faSHans Rosenfeld /* Declare link down */ 19698f23e9faSHans Rosenfeld if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 19708f23e9faSHans Rosenfeld (void) emlxs_fcf_shutdown_notify(port, 1); 19718f23e9faSHans Rosenfeld } else { 19728f23e9faSHans Rosenfeld emlxs_linkdown(hba); 1973fcf3ce44SJohn Forte } 19748f23e9faSHans Rosenfeld 1975fcf3ce44SJohn Forte #ifdef SFCT_SUPPORT 19768f23e9faSHans Rosenfeld if (port->flag & EMLXS_TGT_ENABLED) { 1977fcf3ce44SJohn Forte (void) emlxs_fct_port_shutdown(port); 1978fcf3ce44SJohn Forte } 1979291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 1980fcf3ce44SJohn Forte 1981fcf3ce44SJohn Forte /* Check if adapter was shutdown */ 1982fcf3ce44SJohn Forte if (hba->flag & FC_HARDWARE_ERROR) { 1983291a2b48SSukumar Swaminathan /* 1984291a2b48SSukumar Swaminathan * Force mailbox cleanup 1985291a2b48SSukumar Swaminathan * This will wake any sleeping or polling threads 1986291a2b48SSukumar Swaminathan */ 1987fcf3ce44SJohn Forte emlxs_mb_fini(hba, NULL, MBX_HARDWARE_ERROR); 1988fcf3ce44SJohn Forte } 1989291a2b48SSukumar Swaminathan 1990fcf3ce44SJohn Forte /* Pause here for the IO to settle */ 1991fcf3ce44SJohn Forte delay(drv_usectohz(1000000)); /* 1 sec */ 1992fcf3ce44SJohn Forte 1993fcf3ce44SJohn Forte /* Unregister all nodes */ 1994fcf3ce44SJohn Forte emlxs_ffcleanup(hba); 1995fcf3ce44SJohn Forte 1996fcf3ce44SJohn Forte if (hba->bus_type == SBUS_FC) { 199782527734SSukumar Swaminathan WRITE_SBUS_CSR_REG(hba, FC_SHS_REG(hba), 0x9A); 19984baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 199982527734SSukumar Swaminathan /* Access handle validation */ 200082527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.sbus_csr_handle); 20014baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 2002fcf3ce44SJohn Forte } 2003291a2b48SSukumar Swaminathan 2004fcf3ce44SJohn Forte /* Stop the timer */ 2005fcf3ce44SJohn Forte emlxs_timer_stop(hba); 2006fcf3ce44SJohn Forte 2007fcf3ce44SJohn Forte /* For safety flush every iotag list */ 2008fcf3ce44SJohn Forte if (emlxs_iotag_flush(hba)) { 2009fcf3ce44SJohn Forte /* Pause here for the IO to flush */ 2010728bdc9bSSukumar Swaminathan delay(drv_usectohz(1000)); 2011728bdc9bSSukumar Swaminathan } 2012728bdc9bSSukumar Swaminathan 2013728bdc9bSSukumar Swaminathan /* Wait for poll command request to settle */ 2014728bdc9bSSukumar Swaminathan while (hba->io_poll_count > 0) { 2015728bdc9bSSukumar Swaminathan delay(drv_usectohz(2000000)); /* 2 sec */ 2016fcf3ce44SJohn Forte } 2017728bdc9bSSukumar Swaminathan 201882527734SSukumar Swaminathan /* Shutdown the adapter interface */ 20198f23e9faSHans Rosenfeld EMLXS_SLI_OFFLINE(hba, reset_requested); 2020fcf3ce44SJohn Forte 2021fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 2022fcf3ce44SJohn Forte hba->flag |= FC_OFFLINE_MODE; 2023fcf3ce44SJohn Forte hba->flag &= ~FC_OFFLINING_MODE; 2024fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 2025fcf3ce44SJohn Forte 2026fcf3ce44SJohn Forte rval = 0; 2027fcf3ce44SJohn Forte 2028fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_offline_msg, NULL); 2029fcf3ce44SJohn Forte 2030fcf3ce44SJohn Forte done: 2031fcf3ce44SJohn Forte 2032fcf3ce44SJohn Forte return (rval); 2033fcf3ce44SJohn Forte 203482527734SSukumar Swaminathan } /* emlxs_offline() */ 2035fcf3ce44SJohn Forte 2036fcf3ce44SJohn Forte 2037fcf3ce44SJohn Forte 2038fcf3ce44SJohn Forte extern int 2039fcf3ce44SJohn Forte emlxs_power_down(emlxs_hba_t *hba) 2040fcf3ce44SJohn Forte { 20414baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 20424baa2c25SSukumar Swaminathan emlxs_port_t *port = &PPORT; 20434baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 2044fcf3ce44SJohn Forte int32_t rval = 0; 2045fcf3ce44SJohn Forte 20468f23e9faSHans Rosenfeld if ((rval = emlxs_offline(hba, 0))) { 2047fcf3ce44SJohn Forte return (rval); 2048fcf3ce44SJohn Forte } 204982527734SSukumar Swaminathan EMLXS_SLI_HBA_RESET(hba, 1, 1, 0); 2050291a2b48SSukumar Swaminathan 2051fcf3ce44SJohn Forte 20524baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 20534baa2c25SSukumar Swaminathan if (emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle) 20544baa2c25SSukumar Swaminathan != DDI_FM_OK) { 20554baa2c25SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 20564baa2c25SSukumar Swaminathan &emlxs_invalid_access_handle_msg, NULL); 20574baa2c25SSukumar Swaminathan return (1); 20584baa2c25SSukumar Swaminathan } 20594baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 20604baa2c25SSukumar Swaminathan 2061fcf3ce44SJohn Forte return (0); 2062fcf3ce44SJohn Forte 206382527734SSukumar Swaminathan } /* End emlxs_power_down */ 2064fcf3ce44SJohn Forte 2065fcf3ce44SJohn Forte 2066fcf3ce44SJohn Forte extern int 2067fcf3ce44SJohn Forte emlxs_power_up(emlxs_hba_t *hba) 2068fcf3ce44SJohn Forte { 20694baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 20704baa2c25SSukumar Swaminathan emlxs_port_t *port = &PPORT; 20714baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 2072fcf3ce44SJohn Forte int32_t rval = 0; 2073fcf3ce44SJohn Forte 2074fcf3ce44SJohn Forte 20754baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 20764baa2c25SSukumar Swaminathan if (emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle) 20774baa2c25SSukumar Swaminathan != DDI_FM_OK) { 20784baa2c25SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 20794baa2c25SSukumar Swaminathan &emlxs_invalid_access_handle_msg, NULL); 20804baa2c25SSukumar Swaminathan return (1); 20814baa2c25SSukumar Swaminathan } 20824baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 20834baa2c25SSukumar Swaminathan 2084fcf3ce44SJohn Forte /* Bring adapter online */ 2085fcf3ce44SJohn Forte if ((rval = emlxs_online(hba))) { 2086a9800bebSGarrett D'Amore if (hba->pci_cap_offset[PCI_CAP_ID_PM]) { 2087a9800bebSGarrett D'Amore /* Put chip in D3 state */ 2088a9800bebSGarrett D'Amore (void) ddi_put8(hba->pci_acc_handle, 2089a9800bebSGarrett D'Amore (uint8_t *)(hba->pci_addr + 2090a9800bebSGarrett D'Amore hba->pci_cap_offset[PCI_CAP_ID_PM] + 2091a9800bebSGarrett D'Amore PCI_PMCSR), 2092a9800bebSGarrett D'Amore (uint8_t)PCI_PMCSR_D3HOT); 2093a9800bebSGarrett D'Amore } 2094fcf3ce44SJohn Forte return (rval); 2095fcf3ce44SJohn Forte } 2096291a2b48SSukumar Swaminathan 2097fcf3ce44SJohn Forte return (rval); 2098fcf3ce44SJohn Forte 20998f23e9faSHans Rosenfeld } /* emlxs_power_up() */ 2100fcf3ce44SJohn Forte 2101fcf3ce44SJohn Forte 2102fcf3ce44SJohn Forte /* 2103291a2b48SSukumar Swaminathan * 2104fcf3ce44SJohn Forte * NAME: emlxs_ffcleanup 2105fcf3ce44SJohn Forte * 2106fcf3ce44SJohn Forte * FUNCTION: Cleanup all the Firefly resources used by configuring the adapter 2107fcf3ce44SJohn Forte * 2108fcf3ce44SJohn Forte * EXECUTION ENVIRONMENT: process only 2109fcf3ce44SJohn Forte * 2110fcf3ce44SJohn Forte * CALLED FROM: CFG_TERM 2111fcf3ce44SJohn Forte * 2112fcf3ce44SJohn Forte * INPUT: hba - pointer to the dev_ctl area. 2113fcf3ce44SJohn Forte * 2114fcf3ce44SJohn Forte * RETURNS: none 2115fcf3ce44SJohn Forte */ 2116fcf3ce44SJohn Forte extern void 2117fcf3ce44SJohn Forte emlxs_ffcleanup(emlxs_hba_t *hba) 2118fcf3ce44SJohn Forte { 2119fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 2120291a2b48SSukumar Swaminathan uint32_t i; 2121fcf3ce44SJohn Forte 2122fcf3ce44SJohn Forte /* Disable all but the mailbox interrupt */ 212382527734SSukumar Swaminathan EMLXS_SLI_DISABLE_INTR(hba, HC_MBINT_ENA); 2124fcf3ce44SJohn Forte 2125fcf3ce44SJohn Forte /* Make sure all port nodes are destroyed */ 2126291a2b48SSukumar Swaminathan for (i = 0; i < MAX_VPORTS; i++) { 2127291a2b48SSukumar Swaminathan port = &VPORT(i); 2128fcf3ce44SJohn Forte 2129fcf3ce44SJohn Forte if (port->node_count) { 21308f23e9faSHans Rosenfeld (void) EMLXS_SLI_UNREG_NODE(port, 0, 0, 0, 0); 2131fcf3ce44SJohn Forte } 2132fcf3ce44SJohn Forte } 2133fcf3ce44SJohn Forte 2134fcf3ce44SJohn Forte /* Clear all interrupt enable conditions */ 213582527734SSukumar Swaminathan EMLXS_SLI_DISABLE_INTR(hba, 0); 2136fcf3ce44SJohn Forte 2137fcf3ce44SJohn Forte return; 2138fcf3ce44SJohn Forte 213982527734SSukumar Swaminathan } /* emlxs_ffcleanup() */ 2140fcf3ce44SJohn Forte 2141fcf3ce44SJohn Forte 2142fcf3ce44SJohn Forte extern uint16_t 214382527734SSukumar Swaminathan emlxs_register_pkt(CHANNEL *cp, emlxs_buf_t *sbp) 2144fcf3ce44SJohn Forte { 2145fcf3ce44SJohn Forte emlxs_hba_t *hba; 2146fcf3ce44SJohn Forte emlxs_port_t *port; 2147fcf3ce44SJohn Forte uint16_t iotag; 2148fcf3ce44SJohn Forte uint32_t i; 2149fcf3ce44SJohn Forte 215082527734SSukumar Swaminathan hba = cp->hba; 2151fcf3ce44SJohn Forte 215282527734SSukumar Swaminathan mutex_enter(&EMLXS_FCTAB_LOCK); 2153fcf3ce44SJohn Forte 2154fcf3ce44SJohn Forte if (sbp->iotag != 0) { 2155fcf3ce44SJohn Forte port = &PPORT; 2156fcf3ce44SJohn Forte 2157fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 215882527734SSukumar Swaminathan "Pkt already registered! channel=%d iotag=%d sbp=%p", 215982527734SSukumar Swaminathan sbp->channel, sbp->iotag, sbp); 2160fcf3ce44SJohn Forte } 2161291a2b48SSukumar Swaminathan 2162fcf3ce44SJohn Forte iotag = 0; 216382527734SSukumar Swaminathan for (i = 0; i < hba->max_iotag; i++) { 216482527734SSukumar Swaminathan if (!hba->fc_iotag || hba->fc_iotag >= hba->max_iotag) { 216582527734SSukumar Swaminathan hba->fc_iotag = 1; 2166fcf3ce44SJohn Forte } 216782527734SSukumar Swaminathan iotag = hba->fc_iotag++; 2168fcf3ce44SJohn Forte 216982527734SSukumar Swaminathan if (hba->fc_table[iotag] == 0 || 217082527734SSukumar Swaminathan hba->fc_table[iotag] == STALE_PACKET) { 217182527734SSukumar Swaminathan hba->io_count++; 217282527734SSukumar Swaminathan hba->fc_table[iotag] = sbp; 2173fcf3ce44SJohn Forte 2174fcf3ce44SJohn Forte sbp->iotag = iotag; 217582527734SSukumar Swaminathan sbp->channel = cp; 2176fcf3ce44SJohn Forte 2177fcf3ce44SJohn Forte break; 2178fcf3ce44SJohn Forte } 2179fcf3ce44SJohn Forte iotag = 0; 2180fcf3ce44SJohn Forte } 2181fcf3ce44SJohn Forte 218282527734SSukumar Swaminathan mutex_exit(&EMLXS_FCTAB_LOCK); 2183fcf3ce44SJohn Forte 2184fcf3ce44SJohn Forte /* 2185fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 21868f23e9faSHans Rosenfeld * "register_pkt: channel=%d iotag=%d sbp=%p", 218782527734SSukumar Swaminathan * cp->channelno, iotag, sbp); 2188fcf3ce44SJohn Forte */ 2189fcf3ce44SJohn Forte 2190fcf3ce44SJohn Forte return (iotag); 2191fcf3ce44SJohn Forte 219282527734SSukumar Swaminathan } /* emlxs_register_pkt() */ 2193fcf3ce44SJohn Forte 2194fcf3ce44SJohn Forte 2195fcf3ce44SJohn Forte 2196fcf3ce44SJohn Forte extern emlxs_buf_t * 219782527734SSukumar Swaminathan emlxs_unregister_pkt(CHANNEL *cp, uint16_t iotag, uint32_t forced) 2198fcf3ce44SJohn Forte { 2199fcf3ce44SJohn Forte emlxs_hba_t *hba; 2200fcf3ce44SJohn Forte emlxs_buf_t *sbp; 220182527734SSukumar Swaminathan 220282527734SSukumar Swaminathan sbp = NULL; 220382527734SSukumar Swaminathan hba = cp->hba; 2204fcf3ce44SJohn Forte 2205fcf3ce44SJohn Forte /* Check the iotag range */ 220682527734SSukumar Swaminathan if ((iotag == 0) || (iotag >= hba->max_iotag)) { 2207fcf3ce44SJohn Forte return (NULL); 2208fcf3ce44SJohn Forte } 2209291a2b48SSukumar Swaminathan 2210fcf3ce44SJohn Forte /* Remove the sbp from the table */ 221182527734SSukumar Swaminathan mutex_enter(&EMLXS_FCTAB_LOCK); 221282527734SSukumar Swaminathan sbp = hba->fc_table[iotag]; 2213fcf3ce44SJohn Forte 2214fcf3ce44SJohn Forte if (!sbp || (sbp == STALE_PACKET)) { 221582527734SSukumar Swaminathan mutex_exit(&EMLXS_FCTAB_LOCK); 2216fcf3ce44SJohn Forte return (sbp); 2217fcf3ce44SJohn Forte } 2218291a2b48SSukumar Swaminathan 221982527734SSukumar Swaminathan hba->fc_table[iotag] = ((forced) ? STALE_PACKET : NULL); 222082527734SSukumar Swaminathan hba->io_count--; 2221fcf3ce44SJohn Forte sbp->iotag = 0; 2222fcf3ce44SJohn Forte 222382527734SSukumar Swaminathan mutex_exit(&EMLXS_FCTAB_LOCK); 2224fcf3ce44SJohn Forte 2225fcf3ce44SJohn Forte 2226fcf3ce44SJohn Forte /* Clean up the sbp */ 2227fcf3ce44SJohn Forte mutex_enter(&sbp->mtx); 2228fcf3ce44SJohn Forte 2229fcf3ce44SJohn Forte if (sbp->pkt_flags & PACKET_IN_TXQ) { 2230fcf3ce44SJohn Forte sbp->pkt_flags &= ~PACKET_IN_TXQ; 223182527734SSukumar Swaminathan hba->channel_tx_count--; 2232fcf3ce44SJohn Forte } 2233291a2b48SSukumar Swaminathan 2234fcf3ce44SJohn Forte if (sbp->pkt_flags & PACKET_IN_CHIPQ) { 2235fcf3ce44SJohn Forte sbp->pkt_flags &= ~PACKET_IN_CHIPQ; 2236fcf3ce44SJohn Forte } 2237291a2b48SSukumar Swaminathan 2238fcf3ce44SJohn Forte if (sbp->bmp) { 2239a9800bebSGarrett D'Amore emlxs_mem_put(hba, MEM_BPL, (void *)sbp->bmp); 2240fcf3ce44SJohn Forte sbp->bmp = 0; 2241fcf3ce44SJohn Forte } 2242fcf3ce44SJohn Forte 2243291a2b48SSukumar Swaminathan mutex_exit(&sbp->mtx); 2244fcf3ce44SJohn Forte 2245fcf3ce44SJohn Forte return (sbp); 2246fcf3ce44SJohn Forte 224782527734SSukumar Swaminathan } /* emlxs_unregister_pkt() */ 2248fcf3ce44SJohn Forte 2249fcf3ce44SJohn Forte 2250fcf3ce44SJohn Forte 225182527734SSukumar Swaminathan /* Flush all IO's to all nodes for a given IO Channel */ 2252fcf3ce44SJohn Forte extern uint32_t 225382527734SSukumar Swaminathan emlxs_tx_channel_flush(emlxs_hba_t *hba, CHANNEL *cp, emlxs_buf_t *fpkt) 2254fcf3ce44SJohn Forte { 2255fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 2256fcf3ce44SJohn Forte emlxs_buf_t *sbp; 2257fcf3ce44SJohn Forte IOCBQ *iocbq; 2258fcf3ce44SJohn Forte IOCBQ *next; 2259fcf3ce44SJohn Forte IOCB *iocb; 226082527734SSukumar Swaminathan uint32_t channelno; 2261fcf3ce44SJohn Forte Q abort; 2262fcf3ce44SJohn Forte NODELIST *ndlp; 2263fcf3ce44SJohn Forte IOCB *icmd; 2264fcf3ce44SJohn Forte MATCHMAP *mp; 2265fcf3ce44SJohn Forte uint32_t i; 226682527734SSukumar Swaminathan uint8_t flag[MAX_CHANNEL]; 2267fcf3ce44SJohn Forte 226882527734SSukumar Swaminathan channelno = cp->channelno; 2269fcf3ce44SJohn Forte bzero((void *)&abort, sizeof (Q)); 227082527734SSukumar Swaminathan bzero((void *)flag, MAX_CHANNEL * sizeof (uint8_t)); 2271fcf3ce44SJohn Forte 227282527734SSukumar Swaminathan mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 2273fcf3ce44SJohn Forte 2274fcf3ce44SJohn Forte /* While a node needs servicing */ 227582527734SSukumar Swaminathan while (cp->nodeq.q_first) { 227682527734SSukumar Swaminathan ndlp = (NODELIST *) cp->nodeq.q_first; 2277fcf3ce44SJohn Forte 2278fcf3ce44SJohn Forte /* Check if priority queue is not empty */ 227982527734SSukumar Swaminathan if (ndlp->nlp_ptx[channelno].q_first) { 2280fcf3ce44SJohn Forte /* Transfer all iocb's to local queue */ 2281fcf3ce44SJohn Forte if (abort.q_first == 0) { 228282527734SSukumar Swaminathan abort.q_first = 228382527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_first; 2284fcf3ce44SJohn Forte } else { 2285fcf3ce44SJohn Forte ((IOCBQ *)abort.q_last)->next = 228682527734SSukumar Swaminathan (IOCBQ *)ndlp->nlp_ptx[channelno].q_first; 2287fcf3ce44SJohn Forte } 228882527734SSukumar Swaminathan flag[channelno] = 1; 2289fcf3ce44SJohn Forte 229082527734SSukumar Swaminathan abort.q_last = ndlp->nlp_ptx[channelno].q_last; 229182527734SSukumar Swaminathan abort.q_cnt += ndlp->nlp_ptx[channelno].q_cnt; 2292fcf3ce44SJohn Forte } 2293291a2b48SSukumar Swaminathan 2294fcf3ce44SJohn Forte /* Check if tx queue is not empty */ 229582527734SSukumar Swaminathan if (ndlp->nlp_tx[channelno].q_first) { 2296fcf3ce44SJohn Forte /* Transfer all iocb's to local queue */ 2297fcf3ce44SJohn Forte if (abort.q_first == 0) { 229882527734SSukumar Swaminathan abort.q_first = ndlp->nlp_tx[channelno].q_first; 2299fcf3ce44SJohn Forte } else { 2300fcf3ce44SJohn Forte ((IOCBQ *)abort.q_last)->next = 230182527734SSukumar Swaminathan (IOCBQ *)ndlp->nlp_tx[channelno].q_first; 2302fcf3ce44SJohn Forte } 2303fcf3ce44SJohn Forte 230482527734SSukumar Swaminathan abort.q_last = ndlp->nlp_tx[channelno].q_last; 230582527734SSukumar Swaminathan abort.q_cnt += ndlp->nlp_tx[channelno].q_cnt; 2306fcf3ce44SJohn Forte } 2307291a2b48SSukumar Swaminathan 2308fcf3ce44SJohn Forte /* Clear the queue pointers */ 230982527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_first = NULL; 231082527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_last = NULL; 231182527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_cnt = 0; 2312fcf3ce44SJohn Forte 231382527734SSukumar Swaminathan ndlp->nlp_tx[channelno].q_first = NULL; 231482527734SSukumar Swaminathan ndlp->nlp_tx[channelno].q_last = NULL; 231582527734SSukumar Swaminathan ndlp->nlp_tx[channelno].q_cnt = 0; 2316fcf3ce44SJohn Forte 2317fcf3ce44SJohn Forte /* Remove node from service queue */ 2318fcf3ce44SJohn Forte 2319fcf3ce44SJohn Forte /* If this is the last node on list */ 232082527734SSukumar Swaminathan if (cp->nodeq.q_last == (void *)ndlp) { 232182527734SSukumar Swaminathan cp->nodeq.q_last = NULL; 232282527734SSukumar Swaminathan cp->nodeq.q_first = NULL; 232382527734SSukumar Swaminathan cp->nodeq.q_cnt = 0; 2324fcf3ce44SJohn Forte } else { 2325fcf3ce44SJohn Forte /* Remove node from head */ 232682527734SSukumar Swaminathan cp->nodeq.q_first = ndlp->nlp_next[channelno]; 232782527734SSukumar Swaminathan ((NODELIST *)cp->nodeq.q_last)->nlp_next[channelno] = 232882527734SSukumar Swaminathan cp->nodeq.q_first; 232982527734SSukumar Swaminathan cp->nodeq.q_cnt--; 2330fcf3ce44SJohn Forte } 2331fcf3ce44SJohn Forte 2332fcf3ce44SJohn Forte /* Clear node */ 233382527734SSukumar Swaminathan ndlp->nlp_next[channelno] = NULL; 2334fcf3ce44SJohn Forte } 2335fcf3ce44SJohn Forte 2336fcf3ce44SJohn Forte /* First cleanup the iocb's while still holding the lock */ 2337291a2b48SSukumar Swaminathan iocbq = (IOCBQ *) abort.q_first; 2338fcf3ce44SJohn Forte while (iocbq) { 2339fcf3ce44SJohn Forte /* Free the IoTag and the bmp */ 2340fcf3ce44SJohn Forte iocb = &iocbq->iocb; 234182527734SSukumar Swaminathan 234282527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 234382527734SSukumar Swaminathan sbp = iocbq->sbp; 234482527734SSukumar Swaminathan if (sbp) { 23458f23e9faSHans Rosenfeld emlxs_sli4_free_xri(port, sbp, sbp->xrip, 1); 234682527734SSukumar Swaminathan } 234782527734SSukumar Swaminathan } else { 234882527734SSukumar Swaminathan sbp = emlxs_unregister_pkt((CHANNEL *)iocbq->channel, 234982527734SSukumar Swaminathan iocb->ULPIOTAG, 0); 235082527734SSukumar Swaminathan } 2351fcf3ce44SJohn Forte 2352fcf3ce44SJohn Forte if (sbp && (sbp != STALE_PACKET)) { 2353fcf3ce44SJohn Forte mutex_enter(&sbp->mtx); 2354fcf3ce44SJohn Forte 2355fcf3ce44SJohn Forte sbp->pkt_flags |= PACKET_IN_FLUSH; 2356fcf3ce44SJohn Forte /* 2357fcf3ce44SJohn Forte * If the fpkt is already set, then we will leave it 2358291a2b48SSukumar Swaminathan * alone. This ensures that this pkt is only accounted 2359291a2b48SSukumar Swaminathan * for on one fpkt->flush_count 2360fcf3ce44SJohn Forte */ 2361fcf3ce44SJohn Forte if (!sbp->fpkt && fpkt) { 2362fcf3ce44SJohn Forte mutex_enter(&fpkt->mtx); 2363fcf3ce44SJohn Forte sbp->fpkt = fpkt; 2364fcf3ce44SJohn Forte fpkt->flush_count++; 2365fcf3ce44SJohn Forte mutex_exit(&fpkt->mtx); 2366fcf3ce44SJohn Forte } 2367291a2b48SSukumar Swaminathan 2368fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 2369fcf3ce44SJohn Forte } 2370291a2b48SSukumar Swaminathan 2371fcf3ce44SJohn Forte iocbq = (IOCBQ *)iocbq->next; 2372fcf3ce44SJohn Forte } /* end of while */ 2373fcf3ce44SJohn Forte 237482527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 2375fcf3ce44SJohn Forte 2376fcf3ce44SJohn Forte /* Now abort the iocb's */ 2377fcf3ce44SJohn Forte iocbq = (IOCBQ *)abort.q_first; 2378fcf3ce44SJohn Forte while (iocbq) { 2379fcf3ce44SJohn Forte /* Save the next iocbq for now */ 2380fcf3ce44SJohn Forte next = (IOCBQ *)iocbq->next; 2381fcf3ce44SJohn Forte 2382fcf3ce44SJohn Forte /* Unlink this iocbq */ 2383fcf3ce44SJohn Forte iocbq->next = NULL; 2384fcf3ce44SJohn Forte 2385fcf3ce44SJohn Forte /* Get the pkt */ 2386fcf3ce44SJohn Forte sbp = (emlxs_buf_t *)iocbq->sbp; 2387fcf3ce44SJohn Forte 2388fcf3ce44SJohn Forte if (sbp) { 2389fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flush_msg, 2390291a2b48SSukumar Swaminathan "tx: sbp=%p node=%p", sbp, sbp->node); 2391fcf3ce44SJohn Forte 2392fcf3ce44SJohn Forte if (hba->state >= FC_LINK_UP) { 2393fcf3ce44SJohn Forte emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 2394fcf3ce44SJohn Forte IOERR_ABORT_REQUESTED, 1); 2395fcf3ce44SJohn Forte } else { 2396fcf3ce44SJohn Forte emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 2397fcf3ce44SJohn Forte IOERR_LINK_DOWN, 1); 2398fcf3ce44SJohn Forte } 2399fcf3ce44SJohn Forte 2400fcf3ce44SJohn Forte } 2401fcf3ce44SJohn Forte /* Free the iocb and its associated buffers */ 2402fcf3ce44SJohn Forte else { 2403fcf3ce44SJohn Forte icmd = &iocbq->iocb; 240482527734SSukumar Swaminathan 240582527734SSukumar Swaminathan /* SLI3 */ 240682527734SSukumar Swaminathan if (icmd->ULPCOMMAND == CMD_QUE_RING_BUF64_CN || 240782527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_QUE_RING_BUF_CN || 240882527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_QUE_RING_LIST64_CN) { 2409fcf3ce44SJohn Forte if ((hba->flag & 2410fcf3ce44SJohn Forte (FC_ONLINE_MODE | FC_ONLINING_MODE)) == 0) { 2411fcf3ce44SJohn Forte /* HBA is detaching or offlining */ 241282527734SSukumar Swaminathan if (icmd->ULPCOMMAND != 2413fcf3ce44SJohn Forte CMD_QUE_RING_LIST64_CN) { 2414a9800bebSGarrett D'Amore void *tmp; 241582527734SSukumar Swaminathan RING *rp; 2416fcf3ce44SJohn Forte 241782527734SSukumar Swaminathan rp = &hba->sli.sli3. 241882527734SSukumar Swaminathan ring[channelno]; 2419fcf3ce44SJohn Forte for (i = 0; 242082527734SSukumar Swaminathan i < icmd->ULPBDECOUNT; 2421fcf3ce44SJohn Forte i++) { 2422fcf3ce44SJohn Forte mp = EMLXS_GET_VADDR( 2423fcf3ce44SJohn Forte hba, rp, icmd); 2424fcf3ce44SJohn Forte 2425a9800bebSGarrett D'Amore tmp = (void *)mp; 2426fcf3ce44SJohn Forte if (mp) { 2427a9800bebSGarrett D'Amore emlxs_mem_put( 2428291a2b48SSukumar Swaminathan hba, MEM_BUF, tmp); 2429fcf3ce44SJohn Forte } 2430fcf3ce44SJohn Forte } 2431fcf3ce44SJohn Forte } 2432291a2b48SSukumar Swaminathan 2433a9800bebSGarrett D'Amore emlxs_mem_put(hba, MEM_IOCB, 2434a9800bebSGarrett D'Amore (void *)iocbq); 2435fcf3ce44SJohn Forte } else { 2436fcf3ce44SJohn Forte /* repost the unsolicited buffer */ 243782527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, 2438291a2b48SSukumar Swaminathan iocbq); 2439fcf3ce44SJohn Forte } 244082527734SSukumar Swaminathan } else if (icmd->ULPCOMMAND == CMD_CLOSE_XRI_CN || 244182527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_CLOSE_XRI_CX) { 244282527734SSukumar Swaminathan 244382527734SSukumar Swaminathan emlxs_tx_put(iocbq, 1); 2444fcf3ce44SJohn Forte } 2445fcf3ce44SJohn Forte } 2446fcf3ce44SJohn Forte 2447fcf3ce44SJohn Forte iocbq = next; 2448fcf3ce44SJohn Forte 2449fcf3ce44SJohn Forte } /* end of while */ 2450fcf3ce44SJohn Forte 245182527734SSukumar Swaminathan /* Now trigger channel service */ 245282527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 245382527734SSukumar Swaminathan if (!flag[channelno]) { 245482527734SSukumar Swaminathan continue; 245582527734SSukumar Swaminathan } 245682527734SSukumar Swaminathan 245782527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, &hba->chan[channelno], 0); 245882527734SSukumar Swaminathan } 245982527734SSukumar Swaminathan 2460fcf3ce44SJohn Forte return (abort.q_cnt); 2461fcf3ce44SJohn Forte 246282527734SSukumar Swaminathan } /* emlxs_tx_channel_flush() */ 2463fcf3ce44SJohn Forte 2464fcf3ce44SJohn Forte 2465fcf3ce44SJohn Forte /* Flush all IO's on all or a given ring for a given node */ 2466fcf3ce44SJohn Forte extern uint32_t 246782527734SSukumar Swaminathan emlxs_tx_node_flush(emlxs_port_t *port, NODELIST *ndlp, CHANNEL *chan, 2468fcf3ce44SJohn Forte uint32_t shutdown, emlxs_buf_t *fpkt) 2469fcf3ce44SJohn Forte { 2470fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 2471fcf3ce44SJohn Forte emlxs_buf_t *sbp; 247282527734SSukumar Swaminathan uint32_t channelno; 247382527734SSukumar Swaminathan CHANNEL *cp; 2474fcf3ce44SJohn Forte IOCB *icmd; 2475fcf3ce44SJohn Forte IOCBQ *iocbq; 2476fcf3ce44SJohn Forte NODELIST *prev; 2477fcf3ce44SJohn Forte IOCBQ *next; 2478fcf3ce44SJohn Forte IOCB *iocb; 2479fcf3ce44SJohn Forte Q abort; 2480fcf3ce44SJohn Forte uint32_t i; 2481fcf3ce44SJohn Forte MATCHMAP *mp; 248282527734SSukumar Swaminathan uint8_t flag[MAX_CHANNEL]; 2483fcf3ce44SJohn Forte 2484fcf3ce44SJohn Forte bzero((void *)&abort, sizeof (Q)); 2485fcf3ce44SJohn Forte 2486fcf3ce44SJohn Forte /* Flush all I/O's on tx queue to this target */ 248782527734SSukumar Swaminathan mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 2488fcf3ce44SJohn Forte 2489fcf3ce44SJohn Forte if (!ndlp->nlp_base && shutdown) { 2490fcf3ce44SJohn Forte ndlp->nlp_active = 0; 2491fcf3ce44SJohn Forte } 2492291a2b48SSukumar Swaminathan 249382527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 249482527734SSukumar Swaminathan cp = &hba->chan[channelno]; 2495fcf3ce44SJohn Forte 249682527734SSukumar Swaminathan if (chan && cp != chan) { 2497fcf3ce44SJohn Forte continue; 2498fcf3ce44SJohn Forte } 2499291a2b48SSukumar Swaminathan 2500fcf3ce44SJohn Forte if (!ndlp->nlp_base || shutdown) { 2501fcf3ce44SJohn Forte /* Check if priority queue is not empty */ 250282527734SSukumar Swaminathan if (ndlp->nlp_ptx[channelno].q_first) { 2503fcf3ce44SJohn Forte /* Transfer all iocb's to local queue */ 2504fcf3ce44SJohn Forte if (abort.q_first == 0) { 2505fcf3ce44SJohn Forte abort.q_first = 250682527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_first; 2507fcf3ce44SJohn Forte } else { 250882527734SSukumar Swaminathan ((IOCBQ *)(abort.q_last))->next = 250982527734SSukumar Swaminathan (IOCBQ *)ndlp->nlp_ptx[channelno]. 2510291a2b48SSukumar Swaminathan q_first; 2511fcf3ce44SJohn Forte } 2512fcf3ce44SJohn Forte 251382527734SSukumar Swaminathan flag[channelno] = 1; 251482527734SSukumar Swaminathan 251582527734SSukumar Swaminathan abort.q_last = ndlp->nlp_ptx[channelno].q_last; 251682527734SSukumar Swaminathan abort.q_cnt += ndlp->nlp_ptx[channelno].q_cnt; 2517fcf3ce44SJohn Forte } 2518fcf3ce44SJohn Forte } 2519291a2b48SSukumar Swaminathan 2520fcf3ce44SJohn Forte /* Check if tx queue is not empty */ 252182527734SSukumar Swaminathan if (ndlp->nlp_tx[channelno].q_first) { 252282527734SSukumar Swaminathan 2523fcf3ce44SJohn Forte /* Transfer all iocb's to local queue */ 2524fcf3ce44SJohn Forte if (abort.q_first == 0) { 252582527734SSukumar Swaminathan abort.q_first = ndlp->nlp_tx[channelno].q_first; 2526fcf3ce44SJohn Forte } else { 2527fcf3ce44SJohn Forte ((IOCBQ *)abort.q_last)->next = 252882527734SSukumar Swaminathan (IOCBQ *)ndlp->nlp_tx[channelno].q_first; 2529fcf3ce44SJohn Forte } 2530fcf3ce44SJohn Forte 253182527734SSukumar Swaminathan abort.q_last = ndlp->nlp_tx[channelno].q_last; 253282527734SSukumar Swaminathan abort.q_cnt += ndlp->nlp_tx[channelno].q_cnt; 2533fcf3ce44SJohn Forte } 2534291a2b48SSukumar Swaminathan 2535fcf3ce44SJohn Forte /* Clear the queue pointers */ 253682527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_first = NULL; 253782527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_last = NULL; 253882527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_cnt = 0; 2539fcf3ce44SJohn Forte 254082527734SSukumar Swaminathan ndlp->nlp_tx[channelno].q_first = NULL; 254182527734SSukumar Swaminathan ndlp->nlp_tx[channelno].q_last = NULL; 254282527734SSukumar Swaminathan ndlp->nlp_tx[channelno].q_cnt = 0; 2543fcf3ce44SJohn Forte 254482527734SSukumar Swaminathan /* If this node was on the channel queue, remove it */ 254582527734SSukumar Swaminathan if (ndlp->nlp_next[channelno]) { 2546fcf3ce44SJohn Forte /* If this is the only node on list */ 254782527734SSukumar Swaminathan if (cp->nodeq.q_first == (void *)ndlp && 254882527734SSukumar Swaminathan cp->nodeq.q_last == (void *)ndlp) { 254982527734SSukumar Swaminathan cp->nodeq.q_last = NULL; 255082527734SSukumar Swaminathan cp->nodeq.q_first = NULL; 255182527734SSukumar Swaminathan cp->nodeq.q_cnt = 0; 255282527734SSukumar Swaminathan } else if (cp->nodeq.q_first == (void *)ndlp) { 255382527734SSukumar Swaminathan cp->nodeq.q_first = ndlp->nlp_next[channelno]; 255482527734SSukumar Swaminathan ((NODELIST *) cp->nodeq.q_last)-> 255582527734SSukumar Swaminathan nlp_next[channelno] = cp->nodeq.q_first; 255682527734SSukumar Swaminathan cp->nodeq.q_cnt--; 2557291a2b48SSukumar Swaminathan } else { 2558fcf3ce44SJohn Forte /* 2559291a2b48SSukumar Swaminathan * This is a little more difficult find the 256082527734SSukumar Swaminathan * previous node in the circular channel queue 2561fcf3ce44SJohn Forte */ 2562fcf3ce44SJohn Forte prev = ndlp; 256382527734SSukumar Swaminathan while (prev->nlp_next[channelno] != ndlp) { 256482527734SSukumar Swaminathan prev = prev->nlp_next[channelno]; 2565fcf3ce44SJohn Forte } 2566fcf3ce44SJohn Forte 256782527734SSukumar Swaminathan prev->nlp_next[channelno] = 256882527734SSukumar Swaminathan ndlp->nlp_next[channelno]; 2569fcf3ce44SJohn Forte 257082527734SSukumar Swaminathan if (cp->nodeq.q_last == (void *)ndlp) { 257182527734SSukumar Swaminathan cp->nodeq.q_last = (void *)prev; 2572fcf3ce44SJohn Forte } 257382527734SSukumar Swaminathan cp->nodeq.q_cnt--; 2574fcf3ce44SJohn Forte 2575fcf3ce44SJohn Forte } 2576fcf3ce44SJohn Forte 2577fcf3ce44SJohn Forte /* Clear node */ 257882527734SSukumar Swaminathan ndlp->nlp_next[channelno] = NULL; 2579fcf3ce44SJohn Forte } 2580291a2b48SSukumar Swaminathan 2581fcf3ce44SJohn Forte } 2582fcf3ce44SJohn Forte 2583fcf3ce44SJohn Forte /* First cleanup the iocb's while still holding the lock */ 2584291a2b48SSukumar Swaminathan iocbq = (IOCBQ *) abort.q_first; 2585fcf3ce44SJohn Forte while (iocbq) { 2586fcf3ce44SJohn Forte /* Free the IoTag and the bmp */ 2587fcf3ce44SJohn Forte iocb = &iocbq->iocb; 258882527734SSukumar Swaminathan 258982527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 259082527734SSukumar Swaminathan sbp = iocbq->sbp; 259182527734SSukumar Swaminathan if (sbp) { 25928f23e9faSHans Rosenfeld emlxs_sli4_free_xri(port, sbp, sbp->xrip, 1); 259382527734SSukumar Swaminathan } 259482527734SSukumar Swaminathan } else { 259582527734SSukumar Swaminathan sbp = emlxs_unregister_pkt((CHANNEL *)iocbq->channel, 259682527734SSukumar Swaminathan iocb->ULPIOTAG, 0); 259782527734SSukumar Swaminathan } 2598fcf3ce44SJohn Forte 2599fcf3ce44SJohn Forte if (sbp && (sbp != STALE_PACKET)) { 2600fcf3ce44SJohn Forte mutex_enter(&sbp->mtx); 2601fcf3ce44SJohn Forte sbp->pkt_flags |= PACKET_IN_FLUSH; 2602fcf3ce44SJohn Forte /* 2603fcf3ce44SJohn Forte * If the fpkt is already set, then we will leave it 2604291a2b48SSukumar Swaminathan * alone. This ensures that this pkt is only accounted 2605291a2b48SSukumar Swaminathan * for on one fpkt->flush_count 2606fcf3ce44SJohn Forte */ 2607fcf3ce44SJohn Forte if (!sbp->fpkt && fpkt) { 2608fcf3ce44SJohn Forte mutex_enter(&fpkt->mtx); 2609fcf3ce44SJohn Forte sbp->fpkt = fpkt; 2610fcf3ce44SJohn Forte fpkt->flush_count++; 2611fcf3ce44SJohn Forte mutex_exit(&fpkt->mtx); 2612fcf3ce44SJohn Forte } 2613291a2b48SSukumar Swaminathan 2614fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 2615fcf3ce44SJohn Forte } 2616291a2b48SSukumar Swaminathan 2617291a2b48SSukumar Swaminathan iocbq = (IOCBQ *) iocbq->next; 2618fcf3ce44SJohn Forte 2619fcf3ce44SJohn Forte } /* end of while */ 2620fcf3ce44SJohn Forte 262182527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 2622fcf3ce44SJohn Forte 2623fcf3ce44SJohn Forte /* Now abort the iocb's outside the locks */ 2624fcf3ce44SJohn Forte iocbq = (IOCBQ *)abort.q_first; 2625fcf3ce44SJohn Forte while (iocbq) { 2626fcf3ce44SJohn Forte /* Save the next iocbq for now */ 2627fcf3ce44SJohn Forte next = (IOCBQ *)iocbq->next; 2628fcf3ce44SJohn Forte 2629fcf3ce44SJohn Forte /* Unlink this iocbq */ 2630fcf3ce44SJohn Forte iocbq->next = NULL; 2631fcf3ce44SJohn Forte 2632fcf3ce44SJohn Forte /* Get the pkt */ 2633fcf3ce44SJohn Forte sbp = (emlxs_buf_t *)iocbq->sbp; 2634fcf3ce44SJohn Forte 2635fcf3ce44SJohn Forte if (sbp) { 2636fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flush_msg, 2637291a2b48SSukumar Swaminathan "tx: sbp=%p node=%p", sbp, sbp->node); 2638fcf3ce44SJohn Forte 2639fcf3ce44SJohn Forte if (hba->state >= FC_LINK_UP) { 2640fcf3ce44SJohn Forte emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 2641fcf3ce44SJohn Forte IOERR_ABORT_REQUESTED, 1); 2642fcf3ce44SJohn Forte } else { 2643fcf3ce44SJohn Forte emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 2644fcf3ce44SJohn Forte IOERR_LINK_DOWN, 1); 2645fcf3ce44SJohn Forte } 2646fcf3ce44SJohn Forte 2647fcf3ce44SJohn Forte } 2648fcf3ce44SJohn Forte /* Free the iocb and its associated buffers */ 2649fcf3ce44SJohn Forte else { 265082527734SSukumar Swaminathan /* CMD_CLOSE_XRI_CN should also free the memory */ 2651fcf3ce44SJohn Forte icmd = &iocbq->iocb; 265282527734SSukumar Swaminathan 265382527734SSukumar Swaminathan /* SLI3 */ 265482527734SSukumar Swaminathan if (icmd->ULPCOMMAND == CMD_QUE_RING_BUF64_CN || 265582527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_QUE_RING_BUF_CN || 265682527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_QUE_RING_LIST64_CN) { 2657fcf3ce44SJohn Forte if ((hba->flag & 2658fcf3ce44SJohn Forte (FC_ONLINE_MODE | FC_ONLINING_MODE)) == 0) { 2659fcf3ce44SJohn Forte /* HBA is detaching or offlining */ 266082527734SSukumar Swaminathan if (icmd->ULPCOMMAND != 2661fcf3ce44SJohn Forte CMD_QUE_RING_LIST64_CN) { 2662a9800bebSGarrett D'Amore void *tmp; 266382527734SSukumar Swaminathan RING *rp; 266482527734SSukumar Swaminathan int ch; 2665fcf3ce44SJohn Forte 266682527734SSukumar Swaminathan ch = ((CHANNEL *) 266782527734SSukumar Swaminathan iocbq->channel)->channelno; 266882527734SSukumar Swaminathan rp = &hba->sli.sli3.ring[ch]; 2669fcf3ce44SJohn Forte for (i = 0; 267082527734SSukumar Swaminathan i < icmd->ULPBDECOUNT; 2671fcf3ce44SJohn Forte i++) { 2672fcf3ce44SJohn Forte mp = EMLXS_GET_VADDR( 2673fcf3ce44SJohn Forte hba, rp, icmd); 2674fcf3ce44SJohn Forte 2675a9800bebSGarrett D'Amore tmp = (void *)mp; 2676fcf3ce44SJohn Forte if (mp) { 2677a9800bebSGarrett D'Amore emlxs_mem_put( 2678291a2b48SSukumar Swaminathan hba, MEM_BUF, tmp); 2679fcf3ce44SJohn Forte } 2680fcf3ce44SJohn Forte } 2681fcf3ce44SJohn Forte } 2682291a2b48SSukumar Swaminathan 2683a9800bebSGarrett D'Amore emlxs_mem_put(hba, MEM_IOCB, 2684a9800bebSGarrett D'Amore (void *)iocbq); 2685fcf3ce44SJohn Forte } else { 2686fcf3ce44SJohn Forte /* repost the unsolicited buffer */ 268782527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, 268882527734SSukumar Swaminathan (CHANNEL *)iocbq->channel, iocbq); 2689fcf3ce44SJohn Forte } 269082527734SSukumar Swaminathan } else if (icmd->ULPCOMMAND == CMD_CLOSE_XRI_CN || 269182527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_CLOSE_XRI_CX) { 269282527734SSukumar Swaminathan /* 269382527734SSukumar Swaminathan * Resend the abort iocbq if any 269482527734SSukumar Swaminathan */ 269582527734SSukumar Swaminathan emlxs_tx_put(iocbq, 1); 2696fcf3ce44SJohn Forte } 2697fcf3ce44SJohn Forte } 2698fcf3ce44SJohn Forte 2699fcf3ce44SJohn Forte iocbq = next; 2700fcf3ce44SJohn Forte 2701fcf3ce44SJohn Forte } /* end of while */ 2702fcf3ce44SJohn Forte 270382527734SSukumar Swaminathan /* Now trigger channel service */ 270482527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 270582527734SSukumar Swaminathan if (!flag[channelno]) { 270682527734SSukumar Swaminathan continue; 270782527734SSukumar Swaminathan } 270882527734SSukumar Swaminathan 270982527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, &hba->chan[channelno], 0); 271082527734SSukumar Swaminathan } 271182527734SSukumar Swaminathan 2712fcf3ce44SJohn Forte return (abort.q_cnt); 2713fcf3ce44SJohn Forte 271482527734SSukumar Swaminathan } /* emlxs_tx_node_flush() */ 2715fcf3ce44SJohn Forte 2716fcf3ce44SJohn Forte 2717fcf3ce44SJohn Forte /* Check for IO's on all or a given ring for a given node */ 2718fcf3ce44SJohn Forte extern uint32_t 271982527734SSukumar Swaminathan emlxs_tx_node_check(emlxs_port_t *port, NODELIST *ndlp, CHANNEL *chan) 2720fcf3ce44SJohn Forte { 2721fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 272282527734SSukumar Swaminathan uint32_t channelno; 272382527734SSukumar Swaminathan CHANNEL *cp; 2724fcf3ce44SJohn Forte uint32_t count; 2725fcf3ce44SJohn Forte 2726fcf3ce44SJohn Forte count = 0; 2727fcf3ce44SJohn Forte 2728fcf3ce44SJohn Forte /* Flush all I/O's on tx queue to this target */ 272982527734SSukumar Swaminathan mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 2730fcf3ce44SJohn Forte 273182527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 273282527734SSukumar Swaminathan cp = &hba->chan[channelno]; 2733fcf3ce44SJohn Forte 273482527734SSukumar Swaminathan if (chan && cp != chan) { 2735fcf3ce44SJohn Forte continue; 2736fcf3ce44SJohn Forte } 2737291a2b48SSukumar Swaminathan 2738fcf3ce44SJohn Forte /* Check if priority queue is not empty */ 273982527734SSukumar Swaminathan if (ndlp->nlp_ptx[channelno].q_first) { 274082527734SSukumar Swaminathan count += ndlp->nlp_ptx[channelno].q_cnt; 2741fcf3ce44SJohn Forte } 2742291a2b48SSukumar Swaminathan 2743fcf3ce44SJohn Forte /* Check if tx queue is not empty */ 274482527734SSukumar Swaminathan if (ndlp->nlp_tx[channelno].q_first) { 274582527734SSukumar Swaminathan count += ndlp->nlp_tx[channelno].q_cnt; 2746fcf3ce44SJohn Forte } 2747291a2b48SSukumar Swaminathan 2748fcf3ce44SJohn Forte } 2749fcf3ce44SJohn Forte 275082527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 2751fcf3ce44SJohn Forte 2752fcf3ce44SJohn Forte return (count); 2753fcf3ce44SJohn Forte 275482527734SSukumar Swaminathan } /* emlxs_tx_node_check() */ 2755fcf3ce44SJohn Forte 2756fcf3ce44SJohn Forte 2757fcf3ce44SJohn Forte 275882527734SSukumar Swaminathan /* Flush all IO's on the any ring for a given node's lun */ 2759fcf3ce44SJohn Forte extern uint32_t 2760291a2b48SSukumar Swaminathan emlxs_tx_lun_flush(emlxs_port_t *port, NODELIST *ndlp, uint32_t lun, 2761291a2b48SSukumar Swaminathan emlxs_buf_t *fpkt) 2762fcf3ce44SJohn Forte { 2763fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 2764fcf3ce44SJohn Forte emlxs_buf_t *sbp; 276582527734SSukumar Swaminathan uint32_t channelno; 2766fcf3ce44SJohn Forte IOCBQ *iocbq; 2767fcf3ce44SJohn Forte IOCBQ *prev; 2768fcf3ce44SJohn Forte IOCBQ *next; 2769fcf3ce44SJohn Forte IOCB *iocb; 2770fcf3ce44SJohn Forte IOCB *icmd; 2771fcf3ce44SJohn Forte Q abort; 2772fcf3ce44SJohn Forte uint32_t i; 2773fcf3ce44SJohn Forte MATCHMAP *mp; 277482527734SSukumar Swaminathan uint8_t flag[MAX_CHANNEL]; 2775fcf3ce44SJohn Forte 2776a9800bebSGarrett D'Amore if (lun == EMLXS_LUN_NONE) { 2777a9800bebSGarrett D'Amore return (0); 2778a9800bebSGarrett D'Amore } 2779a9800bebSGarrett D'Amore 2780fcf3ce44SJohn Forte bzero((void *)&abort, sizeof (Q)); 2781fcf3ce44SJohn Forte 2782fcf3ce44SJohn Forte /* Flush I/O's on txQ to this target's lun */ 278382527734SSukumar Swaminathan mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 2784fcf3ce44SJohn Forte 278582527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 2786291a2b48SSukumar Swaminathan 278782527734SSukumar Swaminathan /* Scan the priority queue first */ 278882527734SSukumar Swaminathan prev = NULL; 278982527734SSukumar Swaminathan iocbq = (IOCBQ *) ndlp->nlp_ptx[channelno].q_first; 2790fcf3ce44SJohn Forte 279182527734SSukumar Swaminathan while (iocbq) { 279282527734SSukumar Swaminathan next = (IOCBQ *)iocbq->next; 279382527734SSukumar Swaminathan iocb = &iocbq->iocb; 279482527734SSukumar Swaminathan sbp = (emlxs_buf_t *)iocbq->sbp; 279582527734SSukumar Swaminathan 279682527734SSukumar Swaminathan /* Check if this IO is for our lun */ 279782527734SSukumar Swaminathan if (sbp && (sbp->lun == lun)) { 279882527734SSukumar Swaminathan /* Remove iocb from the node's ptx queue */ 279982527734SSukumar Swaminathan if (next == 0) { 280082527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_last = 280182527734SSukumar Swaminathan (uint8_t *)prev; 280282527734SSukumar Swaminathan } 280382527734SSukumar Swaminathan 280482527734SSukumar Swaminathan if (prev == 0) { 280582527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_first = 280682527734SSukumar Swaminathan (uint8_t *)next; 280782527734SSukumar Swaminathan } else { 280882527734SSukumar Swaminathan prev->next = next; 280982527734SSukumar Swaminathan } 281082527734SSukumar Swaminathan 281182527734SSukumar Swaminathan iocbq->next = NULL; 281282527734SSukumar Swaminathan ndlp->nlp_ptx[channelno].q_cnt--; 281382527734SSukumar Swaminathan 281482527734SSukumar Swaminathan /* 281582527734SSukumar Swaminathan * Add this iocb to our local abort Q 281682527734SSukumar Swaminathan */ 281782527734SSukumar Swaminathan if (abort.q_first) { 281882527734SSukumar Swaminathan ((IOCBQ *)abort.q_last)->next = iocbq; 281982527734SSukumar Swaminathan abort.q_last = (uint8_t *)iocbq; 282082527734SSukumar Swaminathan abort.q_cnt++; 282182527734SSukumar Swaminathan } else { 282282527734SSukumar Swaminathan abort.q_first = (uint8_t *)iocbq; 282382527734SSukumar Swaminathan abort.q_last = (uint8_t *)iocbq; 282482527734SSukumar Swaminathan abort.q_cnt = 1; 282582527734SSukumar Swaminathan } 282682527734SSukumar Swaminathan iocbq->next = NULL; 282782527734SSukumar Swaminathan flag[channelno] = 1; 2828fcf3ce44SJohn Forte 2829fcf3ce44SJohn Forte } else { 283082527734SSukumar Swaminathan prev = iocbq; 2831fcf3ce44SJohn Forte } 2832fcf3ce44SJohn Forte 283382527734SSukumar Swaminathan iocbq = next; 2834fcf3ce44SJohn Forte 283582527734SSukumar Swaminathan } /* while (iocbq) */ 2836fcf3ce44SJohn Forte 2837fcf3ce44SJohn Forte 283882527734SSukumar Swaminathan /* Scan the regular queue */ 283982527734SSukumar Swaminathan prev = NULL; 284082527734SSukumar Swaminathan iocbq = (IOCBQ *)ndlp->nlp_tx[channelno].q_first; 2841fcf3ce44SJohn Forte 284282527734SSukumar Swaminathan while (iocbq) { 284382527734SSukumar Swaminathan next = (IOCBQ *)iocbq->next; 284482527734SSukumar Swaminathan iocb = &iocbq->iocb; 284582527734SSukumar Swaminathan sbp = (emlxs_buf_t *)iocbq->sbp; 284682527734SSukumar Swaminathan 284782527734SSukumar Swaminathan /* Check if this IO is for our lun */ 284882527734SSukumar Swaminathan if (sbp && (sbp->lun == lun)) { 284982527734SSukumar Swaminathan /* Remove iocb from the node's tx queue */ 285082527734SSukumar Swaminathan if (next == 0) { 285182527734SSukumar Swaminathan ndlp->nlp_tx[channelno].q_last = 285282527734SSukumar Swaminathan (uint8_t *)prev; 285382527734SSukumar Swaminathan } 2854291a2b48SSukumar Swaminathan 285582527734SSukumar Swaminathan if (prev == 0) { 285682527734SSukumar Swaminathan ndlp->nlp_tx[channelno].q_first = 285782527734SSukumar Swaminathan (uint8_t *)next; 285882527734SSukumar Swaminathan } else { 285982527734SSukumar Swaminathan prev->next = next; 286082527734SSukumar Swaminathan } 2861fcf3ce44SJohn Forte 286282527734SSukumar Swaminathan iocbq->next = NULL; 286382527734SSukumar Swaminathan ndlp->nlp_tx[channelno].q_cnt--; 2864fcf3ce44SJohn Forte 286582527734SSukumar Swaminathan /* 286682527734SSukumar Swaminathan * Add this iocb to our local abort Q 286782527734SSukumar Swaminathan */ 286882527734SSukumar Swaminathan if (abort.q_first) { 286982527734SSukumar Swaminathan ((IOCBQ *) abort.q_last)->next = iocbq; 287082527734SSukumar Swaminathan abort.q_last = (uint8_t *)iocbq; 287182527734SSukumar Swaminathan abort.q_cnt++; 287282527734SSukumar Swaminathan } else { 287382527734SSukumar Swaminathan abort.q_first = (uint8_t *)iocbq; 287482527734SSukumar Swaminathan abort.q_last = (uint8_t *)iocbq; 287582527734SSukumar Swaminathan abort.q_cnt = 1; 287682527734SSukumar Swaminathan } 287782527734SSukumar Swaminathan iocbq->next = NULL; 2878fcf3ce44SJohn Forte } else { 287982527734SSukumar Swaminathan prev = iocbq; 2880fcf3ce44SJohn Forte } 2881fcf3ce44SJohn Forte 288282527734SSukumar Swaminathan iocbq = next; 2883fcf3ce44SJohn Forte 288482527734SSukumar Swaminathan } /* while (iocbq) */ 288582527734SSukumar Swaminathan } /* for loop */ 2886fcf3ce44SJohn Forte 2887fcf3ce44SJohn Forte /* First cleanup the iocb's while still holding the lock */ 2888fcf3ce44SJohn Forte iocbq = (IOCBQ *)abort.q_first; 2889fcf3ce44SJohn Forte while (iocbq) { 2890fcf3ce44SJohn Forte /* Free the IoTag and the bmp */ 2891fcf3ce44SJohn Forte iocb = &iocbq->iocb; 289282527734SSukumar Swaminathan 289382527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 289482527734SSukumar Swaminathan sbp = iocbq->sbp; 289582527734SSukumar Swaminathan if (sbp) { 28968f23e9faSHans Rosenfeld emlxs_sli4_free_xri(port, sbp, sbp->xrip, 1); 289782527734SSukumar Swaminathan } 289882527734SSukumar Swaminathan } else { 289982527734SSukumar Swaminathan sbp = emlxs_unregister_pkt((CHANNEL *)iocbq->channel, 290082527734SSukumar Swaminathan iocb->ULPIOTAG, 0); 290182527734SSukumar Swaminathan } 2902fcf3ce44SJohn Forte 2903fcf3ce44SJohn Forte if (sbp && (sbp != STALE_PACKET)) { 2904fcf3ce44SJohn Forte mutex_enter(&sbp->mtx); 2905fcf3ce44SJohn Forte sbp->pkt_flags |= PACKET_IN_FLUSH; 2906fcf3ce44SJohn Forte /* 2907fcf3ce44SJohn Forte * If the fpkt is already set, then we will leave it 2908291a2b48SSukumar Swaminathan * alone. This ensures that this pkt is only accounted 2909291a2b48SSukumar Swaminathan * for on one fpkt->flush_count 2910fcf3ce44SJohn Forte */ 2911fcf3ce44SJohn Forte if (!sbp->fpkt && fpkt) { 2912fcf3ce44SJohn Forte mutex_enter(&fpkt->mtx); 2913fcf3ce44SJohn Forte sbp->fpkt = fpkt; 2914fcf3ce44SJohn Forte fpkt->flush_count++; 2915fcf3ce44SJohn Forte mutex_exit(&fpkt->mtx); 2916fcf3ce44SJohn Forte } 2917291a2b48SSukumar Swaminathan 2918fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 2919fcf3ce44SJohn Forte } 2920291a2b48SSukumar Swaminathan 2921291a2b48SSukumar Swaminathan iocbq = (IOCBQ *) iocbq->next; 2922fcf3ce44SJohn Forte 2923fcf3ce44SJohn Forte } /* end of while */ 2924fcf3ce44SJohn Forte 292582527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 2926fcf3ce44SJohn Forte 2927fcf3ce44SJohn Forte /* Now abort the iocb's outside the locks */ 2928fcf3ce44SJohn Forte iocbq = (IOCBQ *)abort.q_first; 2929fcf3ce44SJohn Forte while (iocbq) { 2930fcf3ce44SJohn Forte /* Save the next iocbq for now */ 2931fcf3ce44SJohn Forte next = (IOCBQ *)iocbq->next; 2932fcf3ce44SJohn Forte 2933fcf3ce44SJohn Forte /* Unlink this iocbq */ 2934fcf3ce44SJohn Forte iocbq->next = NULL; 2935fcf3ce44SJohn Forte 2936fcf3ce44SJohn Forte /* Get the pkt */ 2937fcf3ce44SJohn Forte sbp = (emlxs_buf_t *)iocbq->sbp; 2938fcf3ce44SJohn Forte 2939fcf3ce44SJohn Forte if (sbp) { 2940fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flush_msg, 2941291a2b48SSukumar Swaminathan "tx: sbp=%p node=%p", sbp, sbp->node); 2942fcf3ce44SJohn Forte 2943fcf3ce44SJohn Forte if (hba->state >= FC_LINK_UP) { 2944fcf3ce44SJohn Forte emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 2945fcf3ce44SJohn Forte IOERR_ABORT_REQUESTED, 1); 2946fcf3ce44SJohn Forte } else { 2947fcf3ce44SJohn Forte emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 2948fcf3ce44SJohn Forte IOERR_LINK_DOWN, 1); 2949fcf3ce44SJohn Forte } 2950fcf3ce44SJohn Forte } 2951291a2b48SSukumar Swaminathan 2952fcf3ce44SJohn Forte /* Free the iocb and its associated buffers */ 2953fcf3ce44SJohn Forte else { 295482527734SSukumar Swaminathan /* Should never happen! */ 2955fcf3ce44SJohn Forte icmd = &iocbq->iocb; 2956fcf3ce44SJohn Forte 295782527734SSukumar Swaminathan /* SLI3 */ 295882527734SSukumar Swaminathan if (icmd->ULPCOMMAND == CMD_QUE_RING_BUF64_CN || 295982527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_QUE_RING_BUF_CN || 296082527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_QUE_RING_LIST64_CN) { 2961fcf3ce44SJohn Forte if ((hba->flag & 2962fcf3ce44SJohn Forte (FC_ONLINE_MODE | FC_ONLINING_MODE)) == 0) { 2963fcf3ce44SJohn Forte /* HBA is detaching or offlining */ 296482527734SSukumar Swaminathan if (icmd->ULPCOMMAND != 2965fcf3ce44SJohn Forte CMD_QUE_RING_LIST64_CN) { 2966a9800bebSGarrett D'Amore void *tmp; 296782527734SSukumar Swaminathan RING *rp; 296882527734SSukumar Swaminathan int ch; 2969fcf3ce44SJohn Forte 297082527734SSukumar Swaminathan ch = ((CHANNEL *) 297182527734SSukumar Swaminathan iocbq->channel)->channelno; 297282527734SSukumar Swaminathan rp = &hba->sli.sli3.ring[ch]; 2973fcf3ce44SJohn Forte for (i = 0; 297482527734SSukumar Swaminathan i < icmd->ULPBDECOUNT; 2975fcf3ce44SJohn Forte i++) { 2976fcf3ce44SJohn Forte mp = EMLXS_GET_VADDR( 2977fcf3ce44SJohn Forte hba, rp, icmd); 2978fcf3ce44SJohn Forte 2979a9800bebSGarrett D'Amore tmp = (void *)mp; 2980fcf3ce44SJohn Forte if (mp) { 2981a9800bebSGarrett D'Amore emlxs_mem_put( 2982291a2b48SSukumar Swaminathan hba, MEM_BUF, tmp); 2983fcf3ce44SJohn Forte } 2984fcf3ce44SJohn Forte } 2985fcf3ce44SJohn Forte } 2986291a2b48SSukumar Swaminathan 2987a9800bebSGarrett D'Amore emlxs_mem_put(hba, MEM_IOCB, 2988a9800bebSGarrett D'Amore (void *)iocbq); 2989fcf3ce44SJohn Forte } else { 2990fcf3ce44SJohn Forte /* repost the unsolicited buffer */ 299182527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, 299282527734SSukumar Swaminathan (CHANNEL *)iocbq->channel, iocbq); 2993fcf3ce44SJohn Forte } 299482527734SSukumar Swaminathan } else if (icmd->ULPCOMMAND == CMD_CLOSE_XRI_CN || 299582527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_CLOSE_XRI_CX) { 299682527734SSukumar Swaminathan /* 299782527734SSukumar Swaminathan * Resend the abort iocbq if any 299882527734SSukumar Swaminathan */ 299982527734SSukumar Swaminathan emlxs_tx_put(iocbq, 1); 3000fcf3ce44SJohn Forte } 3001fcf3ce44SJohn Forte } 3002fcf3ce44SJohn Forte 3003fcf3ce44SJohn Forte iocbq = next; 3004fcf3ce44SJohn Forte 3005fcf3ce44SJohn Forte } /* end of while */ 3006fcf3ce44SJohn Forte 300782527734SSukumar Swaminathan /* Now trigger channel service */ 300882527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 300982527734SSukumar Swaminathan if (!flag[channelno]) { 301082527734SSukumar Swaminathan continue; 301182527734SSukumar Swaminathan } 301282527734SSukumar Swaminathan 301382527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, &hba->chan[channelno], 0); 301482527734SSukumar Swaminathan } 3015fcf3ce44SJohn Forte 3016fcf3ce44SJohn Forte return (abort.q_cnt); 3017fcf3ce44SJohn Forte 301882527734SSukumar Swaminathan } /* emlxs_tx_lun_flush() */ 3019fcf3ce44SJohn Forte 3020fcf3ce44SJohn Forte 3021fcf3ce44SJohn Forte extern void 3022fcf3ce44SJohn Forte emlxs_tx_put(IOCBQ *iocbq, uint32_t lock) 3023fcf3ce44SJohn Forte { 3024fcf3ce44SJohn Forte emlxs_hba_t *hba; 3025fcf3ce44SJohn Forte emlxs_port_t *port; 302682527734SSukumar Swaminathan uint32_t channelno; 3027fcf3ce44SJohn Forte NODELIST *nlp; 302882527734SSukumar Swaminathan CHANNEL *cp; 3029fcf3ce44SJohn Forte emlxs_buf_t *sbp; 3030fcf3ce44SJohn Forte 3031fcf3ce44SJohn Forte port = (emlxs_port_t *)iocbq->port; 3032fcf3ce44SJohn Forte hba = HBA; 303382527734SSukumar Swaminathan cp = (CHANNEL *)iocbq->channel; 3034fcf3ce44SJohn Forte nlp = (NODELIST *)iocbq->node; 303582527734SSukumar Swaminathan channelno = cp->channelno; 3036fcf3ce44SJohn Forte sbp = (emlxs_buf_t *)iocbq->sbp; 3037fcf3ce44SJohn Forte 3038fcf3ce44SJohn Forte if (nlp == NULL) { 3039fcf3ce44SJohn Forte /* Set node to base node by default */ 3040fcf3ce44SJohn Forte nlp = &port->node_base; 3041fcf3ce44SJohn Forte 3042fcf3ce44SJohn Forte iocbq->node = (void *)nlp; 3043fcf3ce44SJohn Forte 3044fcf3ce44SJohn Forte if (sbp) { 3045fcf3ce44SJohn Forte sbp->node = (void *)nlp; 3046fcf3ce44SJohn Forte } 3047fcf3ce44SJohn Forte } 3048291a2b48SSukumar Swaminathan 3049fcf3ce44SJohn Forte if (lock) { 305082527734SSukumar Swaminathan mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 3051fcf3ce44SJohn Forte } 3052291a2b48SSukumar Swaminathan 3053fcf3ce44SJohn Forte if (!nlp->nlp_active || (sbp && (sbp->pkt_flags & PACKET_IN_ABORT))) { 3054fcf3ce44SJohn Forte if (sbp) { 3055fcf3ce44SJohn Forte mutex_enter(&sbp->mtx); 3056fcf3ce44SJohn Forte sbp->pkt_flags |= PACKET_IN_FLUSH; 3057fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 3058fcf3ce44SJohn Forte 305982527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 30608f23e9faSHans Rosenfeld emlxs_sli4_free_xri(port, sbp, sbp->xrip, 1); 306182527734SSukumar Swaminathan } else { 306282527734SSukumar Swaminathan (void) emlxs_unregister_pkt(cp, sbp->iotag, 0); 306382527734SSukumar Swaminathan } 3064fcf3ce44SJohn Forte 3065fcf3ce44SJohn Forte if (lock) { 306682527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 3067fcf3ce44SJohn Forte } 3068291a2b48SSukumar Swaminathan 3069fcf3ce44SJohn Forte if (hba->state >= FC_LINK_UP) { 3070fcf3ce44SJohn Forte emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 3071fcf3ce44SJohn Forte IOERR_ABORT_REQUESTED, 1); 3072fcf3ce44SJohn Forte } else { 3073fcf3ce44SJohn Forte emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 3074fcf3ce44SJohn Forte IOERR_LINK_DOWN, 1); 3075fcf3ce44SJohn Forte } 3076fcf3ce44SJohn Forte return; 3077fcf3ce44SJohn Forte } else { 3078fcf3ce44SJohn Forte if (lock) { 307982527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 3080fcf3ce44SJohn Forte } 3081291a2b48SSukumar Swaminathan 3082a9800bebSGarrett D'Amore emlxs_mem_put(hba, MEM_IOCB, (void *)iocbq); 3083fcf3ce44SJohn Forte } 3084fcf3ce44SJohn Forte 3085fcf3ce44SJohn Forte return; 3086fcf3ce44SJohn Forte } 3087291a2b48SSukumar Swaminathan 3088fcf3ce44SJohn Forte if (sbp) { 3089fcf3ce44SJohn Forte 3090fcf3ce44SJohn Forte mutex_enter(&sbp->mtx); 3091fcf3ce44SJohn Forte 3092291a2b48SSukumar Swaminathan if (sbp->pkt_flags & 3093291a2b48SSukumar Swaminathan (PACKET_IN_COMPLETION | PACKET_IN_CHIPQ | PACKET_IN_TXQ)) { 3094fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 3095fcf3ce44SJohn Forte if (lock) { 309682527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 3097fcf3ce44SJohn Forte } 3098fcf3ce44SJohn Forte return; 3099fcf3ce44SJohn Forte } 3100291a2b48SSukumar Swaminathan 3101fcf3ce44SJohn Forte sbp->pkt_flags |= PACKET_IN_TXQ; 310282527734SSukumar Swaminathan hba->channel_tx_count++; 3103fcf3ce44SJohn Forte 3104fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 3105fcf3ce44SJohn Forte } 3106291a2b48SSukumar Swaminathan 3107291a2b48SSukumar Swaminathan 3108fcf3ce44SJohn Forte /* Check iocbq priority */ 310982527734SSukumar Swaminathan /* Some IOCB has the high priority like reset/close xri etc */ 3110fcf3ce44SJohn Forte if (iocbq->flag & IOCB_PRIORITY) { 3111fcf3ce44SJohn Forte /* Add the iocb to the bottom of the node's ptx queue */ 311282527734SSukumar Swaminathan if (nlp->nlp_ptx[channelno].q_first) { 311382527734SSukumar Swaminathan ((IOCBQ *)nlp->nlp_ptx[channelno].q_last)->next = iocbq; 311482527734SSukumar Swaminathan nlp->nlp_ptx[channelno].q_last = (uint8_t *)iocbq; 311582527734SSukumar Swaminathan nlp->nlp_ptx[channelno].q_cnt++; 3116fcf3ce44SJohn Forte } else { 311782527734SSukumar Swaminathan nlp->nlp_ptx[channelno].q_first = (uint8_t *)iocbq; 311882527734SSukumar Swaminathan nlp->nlp_ptx[channelno].q_last = (uint8_t *)iocbq; 311982527734SSukumar Swaminathan nlp->nlp_ptx[channelno].q_cnt = 1; 3120fcf3ce44SJohn Forte } 3121fcf3ce44SJohn Forte 3122fcf3ce44SJohn Forte iocbq->next = NULL; 3123fcf3ce44SJohn Forte } else { /* Normal priority */ 3124fcf3ce44SJohn Forte 3125291a2b48SSukumar Swaminathan 3126fcf3ce44SJohn Forte /* Add the iocb to the bottom of the node's tx queue */ 312782527734SSukumar Swaminathan if (nlp->nlp_tx[channelno].q_first) { 312882527734SSukumar Swaminathan ((IOCBQ *)nlp->nlp_tx[channelno].q_last)->next = iocbq; 312982527734SSukumar Swaminathan nlp->nlp_tx[channelno].q_last = (uint8_t *)iocbq; 313082527734SSukumar Swaminathan nlp->nlp_tx[channelno].q_cnt++; 3131fcf3ce44SJohn Forte } else { 313282527734SSukumar Swaminathan nlp->nlp_tx[channelno].q_first = (uint8_t *)iocbq; 313382527734SSukumar Swaminathan nlp->nlp_tx[channelno].q_last = (uint8_t *)iocbq; 313482527734SSukumar Swaminathan nlp->nlp_tx[channelno].q_cnt = 1; 3135fcf3ce44SJohn Forte } 3136fcf3ce44SJohn Forte 3137fcf3ce44SJohn Forte iocbq->next = NULL; 3138fcf3ce44SJohn Forte } 3139fcf3ce44SJohn Forte 3140fcf3ce44SJohn Forte 3141fcf3ce44SJohn Forte /* 314282527734SSukumar Swaminathan * Check if the node is not already on channel queue and 3143291a2b48SSukumar Swaminathan * (is not closed or is a priority request) 3144fcf3ce44SJohn Forte */ 314582527734SSukumar Swaminathan if (!nlp->nlp_next[channelno] && 314682527734SSukumar Swaminathan (!(nlp->nlp_flag[channelno] & NLP_CLOSED) || 3147fcf3ce44SJohn Forte (iocbq->flag & IOCB_PRIORITY))) { 314882527734SSukumar Swaminathan /* If so, then add it to the channel queue */ 314982527734SSukumar Swaminathan if (cp->nodeq.q_first) { 315082527734SSukumar Swaminathan ((NODELIST *)cp->nodeq.q_last)->nlp_next[channelno] = 3151fcf3ce44SJohn Forte (uint8_t *)nlp; 315282527734SSukumar Swaminathan nlp->nlp_next[channelno] = cp->nodeq.q_first; 3153fcf3ce44SJohn Forte 3154fcf3ce44SJohn Forte /* 3155291a2b48SSukumar Swaminathan * If this is not the base node then add it 3156291a2b48SSukumar Swaminathan * to the tail 3157fcf3ce44SJohn Forte */ 3158fcf3ce44SJohn Forte if (!nlp->nlp_base) { 315982527734SSukumar Swaminathan cp->nodeq.q_last = (uint8_t *)nlp; 3160fcf3ce44SJohn Forte } else { /* Otherwise, add it to the head */ 3161291a2b48SSukumar Swaminathan 3162fcf3ce44SJohn Forte /* The command node always gets priority */ 316382527734SSukumar Swaminathan cp->nodeq.q_first = (uint8_t *)nlp; 3164fcf3ce44SJohn Forte } 3165fcf3ce44SJohn Forte 316682527734SSukumar Swaminathan cp->nodeq.q_cnt++; 3167fcf3ce44SJohn Forte } else { 316882527734SSukumar Swaminathan cp->nodeq.q_first = (uint8_t *)nlp; 316982527734SSukumar Swaminathan cp->nodeq.q_last = (uint8_t *)nlp; 317082527734SSukumar Swaminathan nlp->nlp_next[channelno] = nlp; 317182527734SSukumar Swaminathan cp->nodeq.q_cnt = 1; 3172fcf3ce44SJohn Forte } 3173fcf3ce44SJohn Forte } 3174291a2b48SSukumar Swaminathan 317582527734SSukumar Swaminathan HBASTATS.IocbTxPut[channelno]++; 3176fcf3ce44SJohn Forte 317782527734SSukumar Swaminathan /* Adjust the channel timeout timer */ 317882527734SSukumar Swaminathan cp->timeout = hba->timer_tics + 5; 3179fcf3ce44SJohn Forte 3180fcf3ce44SJohn Forte if (lock) { 318182527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 3182fcf3ce44SJohn Forte } 3183291a2b48SSukumar Swaminathan 3184fcf3ce44SJohn Forte return; 3185fcf3ce44SJohn Forte 318682527734SSukumar Swaminathan } /* emlxs_tx_put() */ 3187fcf3ce44SJohn Forte 3188fcf3ce44SJohn Forte 3189fcf3ce44SJohn Forte extern IOCBQ * 319082527734SSukumar Swaminathan emlxs_tx_get(CHANNEL *cp, uint32_t lock) 3191fcf3ce44SJohn Forte { 3192fcf3ce44SJohn Forte emlxs_hba_t *hba; 319382527734SSukumar Swaminathan uint32_t channelno; 3194fcf3ce44SJohn Forte IOCBQ *iocbq; 3195fcf3ce44SJohn Forte NODELIST *nlp; 3196fcf3ce44SJohn Forte emlxs_buf_t *sbp; 3197fcf3ce44SJohn Forte 319882527734SSukumar Swaminathan hba = cp->hba; 319982527734SSukumar Swaminathan channelno = cp->channelno; 3200fcf3ce44SJohn Forte 3201fcf3ce44SJohn Forte if (lock) { 320282527734SSukumar Swaminathan mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 3203fcf3ce44SJohn Forte } 3204291a2b48SSukumar Swaminathan 3205fcf3ce44SJohn Forte begin: 3206fcf3ce44SJohn Forte 3207fcf3ce44SJohn Forte iocbq = NULL; 3208fcf3ce44SJohn Forte 3209fcf3ce44SJohn Forte /* Check if a node needs servicing */ 321082527734SSukumar Swaminathan if (cp->nodeq.q_first) { 321182527734SSukumar Swaminathan nlp = (NODELIST *)cp->nodeq.q_first; 3212fcf3ce44SJohn Forte 3213fcf3ce44SJohn Forte /* Get next iocb from node's priority queue */ 3214fcf3ce44SJohn Forte 321582527734SSukumar Swaminathan if (nlp->nlp_ptx[channelno].q_first) { 321682527734SSukumar Swaminathan iocbq = (IOCBQ *)nlp->nlp_ptx[channelno].q_first; 3217fcf3ce44SJohn Forte 3218fcf3ce44SJohn Forte /* Check if this is last entry */ 321982527734SSukumar Swaminathan if (nlp->nlp_ptx[channelno].q_last == (void *)iocbq) { 322082527734SSukumar Swaminathan nlp->nlp_ptx[channelno].q_first = NULL; 322182527734SSukumar Swaminathan nlp->nlp_ptx[channelno].q_last = NULL; 322282527734SSukumar Swaminathan nlp->nlp_ptx[channelno].q_cnt = 0; 3223fcf3ce44SJohn Forte } else { 3224fcf3ce44SJohn Forte /* Remove iocb from head */ 322582527734SSukumar Swaminathan nlp->nlp_ptx[channelno].q_first = 3226fcf3ce44SJohn Forte (void *)iocbq->next; 322782527734SSukumar Swaminathan nlp->nlp_ptx[channelno].q_cnt--; 3228fcf3ce44SJohn Forte } 3229fcf3ce44SJohn Forte 3230fcf3ce44SJohn Forte iocbq->next = NULL; 3231fcf3ce44SJohn Forte } 3232291a2b48SSukumar Swaminathan 3233fcf3ce44SJohn Forte /* Get next iocb from node tx queue if node not closed */ 323482527734SSukumar Swaminathan else if (nlp->nlp_tx[channelno].q_first && 323582527734SSukumar Swaminathan !(nlp->nlp_flag[channelno] & NLP_CLOSED)) { 323682527734SSukumar Swaminathan iocbq = (IOCBQ *)nlp->nlp_tx[channelno].q_first; 3237fcf3ce44SJohn Forte 3238fcf3ce44SJohn Forte /* Check if this is last entry */ 323982527734SSukumar Swaminathan if (nlp->nlp_tx[channelno].q_last == (void *)iocbq) { 324082527734SSukumar Swaminathan nlp->nlp_tx[channelno].q_first = NULL; 324182527734SSukumar Swaminathan nlp->nlp_tx[channelno].q_last = NULL; 324282527734SSukumar Swaminathan nlp->nlp_tx[channelno].q_cnt = 0; 3243fcf3ce44SJohn Forte } else { 3244fcf3ce44SJohn Forte /* Remove iocb from head */ 324582527734SSukumar Swaminathan nlp->nlp_tx[channelno].q_first = 3246fcf3ce44SJohn Forte (void *)iocbq->next; 324782527734SSukumar Swaminathan nlp->nlp_tx[channelno].q_cnt--; 3248fcf3ce44SJohn Forte } 3249fcf3ce44SJohn Forte 3250fcf3ce44SJohn Forte iocbq->next = NULL; 3251fcf3ce44SJohn Forte } 3252291a2b48SSukumar Swaminathan 3253fcf3ce44SJohn Forte /* Now deal with node itself */ 3254fcf3ce44SJohn Forte 3255fcf3ce44SJohn Forte /* Check if node still needs servicing */ 325682527734SSukumar Swaminathan if ((nlp->nlp_ptx[channelno].q_first) || 325782527734SSukumar Swaminathan (nlp->nlp_tx[channelno].q_first && 325882527734SSukumar Swaminathan !(nlp->nlp_flag[channelno] & NLP_CLOSED))) { 3259fcf3ce44SJohn Forte 3260fcf3ce44SJohn Forte /* 3261fcf3ce44SJohn Forte * If this is the base node, then don't shift the 3262291a2b48SSukumar Swaminathan * pointers. We want to drain the base node before 3263291a2b48SSukumar Swaminathan * moving on 3264fcf3ce44SJohn Forte */ 3265fcf3ce44SJohn Forte if (!nlp->nlp_base) { 3266fcf3ce44SJohn Forte /* 326782527734SSukumar Swaminathan * Just shift channel queue pointers to next 3268fcf3ce44SJohn Forte * node 3269fcf3ce44SJohn Forte */ 327082527734SSukumar Swaminathan cp->nodeq.q_last = (void *)nlp; 327182527734SSukumar Swaminathan cp->nodeq.q_first = nlp->nlp_next[channelno]; 3272fcf3ce44SJohn Forte } 3273fcf3ce44SJohn Forte } else { 327482527734SSukumar Swaminathan /* Remove node from channel queue */ 3275fcf3ce44SJohn Forte 3276fcf3ce44SJohn Forte /* If this is the last node on list */ 327782527734SSukumar Swaminathan if (cp->nodeq.q_last == (void *)nlp) { 327882527734SSukumar Swaminathan cp->nodeq.q_last = NULL; 327982527734SSukumar Swaminathan cp->nodeq.q_first = NULL; 328082527734SSukumar Swaminathan cp->nodeq.q_cnt = 0; 3281fcf3ce44SJohn Forte } else { 3282fcf3ce44SJohn Forte /* Remove node from head */ 328382527734SSukumar Swaminathan cp->nodeq.q_first = nlp->nlp_next[channelno]; 328482527734SSukumar Swaminathan ((NODELIST *)cp->nodeq.q_last)-> 328582527734SSukumar Swaminathan nlp_next[channelno] = cp->nodeq.q_first; 328682527734SSukumar Swaminathan cp->nodeq.q_cnt--; 3287fcf3ce44SJohn Forte 3288fcf3ce44SJohn Forte } 3289fcf3ce44SJohn Forte 3290fcf3ce44SJohn Forte /* Clear node */ 329182527734SSukumar Swaminathan nlp->nlp_next[channelno] = NULL; 3292fcf3ce44SJohn Forte } 3293fcf3ce44SJohn Forte 3294fcf3ce44SJohn Forte /* 3295291a2b48SSukumar Swaminathan * If no iocbq was found on this node, then it will have 3296291a2b48SSukumar Swaminathan * been removed. So try again. 3297fcf3ce44SJohn Forte */ 3298fcf3ce44SJohn Forte if (!iocbq) { 3299fcf3ce44SJohn Forte goto begin; 3300fcf3ce44SJohn Forte } 3301291a2b48SSukumar Swaminathan 3302fcf3ce44SJohn Forte sbp = (emlxs_buf_t *)iocbq->sbp; 3303fcf3ce44SJohn Forte 3304fcf3ce44SJohn Forte if (sbp) { 3305fcf3ce44SJohn Forte /* 3306291a2b48SSukumar Swaminathan * Check flags before we enter mutex in case this 3307291a2b48SSukumar Swaminathan * has been flushed and destroyed 3308fcf3ce44SJohn Forte */ 3309fcf3ce44SJohn Forte if ((sbp->pkt_flags & 3310fcf3ce44SJohn Forte (PACKET_IN_COMPLETION | PACKET_IN_CHIPQ)) || 3311fcf3ce44SJohn Forte !(sbp->pkt_flags & PACKET_IN_TXQ)) { 3312fcf3ce44SJohn Forte goto begin; 3313fcf3ce44SJohn Forte } 3314291a2b48SSukumar Swaminathan 3315fcf3ce44SJohn Forte mutex_enter(&sbp->mtx); 3316fcf3ce44SJohn Forte 3317fcf3ce44SJohn Forte if ((sbp->pkt_flags & 3318fcf3ce44SJohn Forte (PACKET_IN_COMPLETION | PACKET_IN_CHIPQ)) || 3319fcf3ce44SJohn Forte !(sbp->pkt_flags & PACKET_IN_TXQ)) { 3320fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 3321fcf3ce44SJohn Forte goto begin; 3322fcf3ce44SJohn Forte } 3323291a2b48SSukumar Swaminathan 3324fcf3ce44SJohn Forte sbp->pkt_flags &= ~PACKET_IN_TXQ; 332582527734SSukumar Swaminathan hba->channel_tx_count--; 3326fcf3ce44SJohn Forte 3327fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 3328fcf3ce44SJohn Forte } 3329fcf3ce44SJohn Forte } 3330291a2b48SSukumar Swaminathan 3331fcf3ce44SJohn Forte if (iocbq) { 333282527734SSukumar Swaminathan HBASTATS.IocbTxGet[channelno]++; 3333fcf3ce44SJohn Forte } 3334291a2b48SSukumar Swaminathan 3335fcf3ce44SJohn Forte /* Adjust the ring timeout timer */ 333682527734SSukumar Swaminathan cp->timeout = (cp->nodeq.q_first) ? (hba->timer_tics + 5) : 0; 3337fcf3ce44SJohn Forte 3338fcf3ce44SJohn Forte if (lock) { 333982527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 3340fcf3ce44SJohn Forte } 3341291a2b48SSukumar Swaminathan 3342fcf3ce44SJohn Forte return (iocbq); 3343fcf3ce44SJohn Forte 334482527734SSukumar Swaminathan } /* emlxs_tx_get() */ 334582527734SSukumar Swaminathan 3346fcf3ce44SJohn Forte 334782527734SSukumar Swaminathan /* 334882527734SSukumar Swaminathan * Remove all cmd from from_rp's txq to to_rp's txq for ndlp. 334982527734SSukumar Swaminathan * The old IoTag has to be released, the new one has to be 335082527734SSukumar Swaminathan * allocated. Others no change 335182527734SSukumar Swaminathan * TX_CHANNEL lock is held 335282527734SSukumar Swaminathan */ 335382527734SSukumar Swaminathan extern void 335482527734SSukumar Swaminathan emlxs_tx_move(NODELIST *ndlp, CHANNEL *from_chan, CHANNEL *to_chan, 335582527734SSukumar Swaminathan uint32_t cmd, emlxs_buf_t *fpkt, uint32_t lock) 335682527734SSukumar Swaminathan { 335782527734SSukumar Swaminathan emlxs_hba_t *hba; 335882527734SSukumar Swaminathan emlxs_port_t *port; 335982527734SSukumar Swaminathan uint32_t fchanno, tchanno, i; 336082527734SSukumar Swaminathan 336182527734SSukumar Swaminathan IOCBQ *iocbq; 336282527734SSukumar Swaminathan IOCBQ *prev; 336382527734SSukumar Swaminathan IOCBQ *next; 336482527734SSukumar Swaminathan IOCB *iocb, *icmd; 336582527734SSukumar Swaminathan Q tbm; /* To Be Moved Q */ 336682527734SSukumar Swaminathan MATCHMAP *mp; 336782527734SSukumar Swaminathan 336882527734SSukumar Swaminathan NODELIST *nlp = ndlp; 336982527734SSukumar Swaminathan emlxs_buf_t *sbp; 337082527734SSukumar Swaminathan 337182527734SSukumar Swaminathan NODELIST *n_prev = NULL; 337282527734SSukumar Swaminathan NODELIST *n_next = NULL; 337382527734SSukumar Swaminathan uint16_t count = 0; 337482527734SSukumar Swaminathan 337582527734SSukumar Swaminathan hba = from_chan->hba; 337682527734SSukumar Swaminathan port = &PPORT; 337782527734SSukumar Swaminathan cmd = cmd; /* To pass lint */ 337882527734SSukumar Swaminathan 337982527734SSukumar Swaminathan fchanno = from_chan->channelno; 338082527734SSukumar Swaminathan tchanno = to_chan->channelno; 338182527734SSukumar Swaminathan 338282527734SSukumar Swaminathan if (lock) { 338382527734SSukumar Swaminathan mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 338482527734SSukumar Swaminathan } 338582527734SSukumar Swaminathan 338682527734SSukumar Swaminathan bzero((void *)&tbm, sizeof (Q)); 338782527734SSukumar Swaminathan 338882527734SSukumar Swaminathan /* Scan the ndlp's fchanno txq to get the iocb of fcp cmd */ 338982527734SSukumar Swaminathan prev = NULL; 339082527734SSukumar Swaminathan iocbq = (IOCBQ *)nlp->nlp_tx[fchanno].q_first; 339182527734SSukumar Swaminathan 339282527734SSukumar Swaminathan while (iocbq) { 339382527734SSukumar Swaminathan next = (IOCBQ *)iocbq->next; 339482527734SSukumar Swaminathan /* Check if this iocb is fcp cmd */ 339582527734SSukumar Swaminathan iocb = &iocbq->iocb; 339682527734SSukumar Swaminathan 339782527734SSukumar Swaminathan switch (iocb->ULPCOMMAND) { 339882527734SSukumar Swaminathan /* FCP commands */ 339982527734SSukumar Swaminathan case CMD_FCP_ICMND_CR: 340082527734SSukumar Swaminathan case CMD_FCP_ICMND_CX: 340182527734SSukumar Swaminathan case CMD_FCP_IREAD_CR: 340282527734SSukumar Swaminathan case CMD_FCP_IREAD_CX: 340382527734SSukumar Swaminathan case CMD_FCP_IWRITE_CR: 340482527734SSukumar Swaminathan case CMD_FCP_IWRITE_CX: 340582527734SSukumar Swaminathan case CMD_FCP_ICMND64_CR: 340682527734SSukumar Swaminathan case CMD_FCP_ICMND64_CX: 340782527734SSukumar Swaminathan case CMD_FCP_IREAD64_CR: 340882527734SSukumar Swaminathan case CMD_FCP_IREAD64_CX: 340982527734SSukumar Swaminathan case CMD_FCP_IWRITE64_CR: 341082527734SSukumar Swaminathan case CMD_FCP_IWRITE64_CX: 341182527734SSukumar Swaminathan /* We found a fcp cmd */ 341282527734SSukumar Swaminathan break; 341382527734SSukumar Swaminathan default: 341482527734SSukumar Swaminathan /* this is not fcp cmd continue */ 341582527734SSukumar Swaminathan prev = iocbq; 341682527734SSukumar Swaminathan iocbq = next; 341782527734SSukumar Swaminathan continue; 341882527734SSukumar Swaminathan } 341982527734SSukumar Swaminathan 342082527734SSukumar Swaminathan /* found a fcp cmd iocb in fchanno txq, now deque it */ 342182527734SSukumar Swaminathan if (next == NULL) { 342282527734SSukumar Swaminathan /* This is the last iocbq */ 342382527734SSukumar Swaminathan nlp->nlp_tx[fchanno].q_last = 342482527734SSukumar Swaminathan (uint8_t *)prev; 342582527734SSukumar Swaminathan } 342682527734SSukumar Swaminathan 342782527734SSukumar Swaminathan if (prev == NULL) { 342882527734SSukumar Swaminathan /* This is the first one then remove it from head */ 342982527734SSukumar Swaminathan nlp->nlp_tx[fchanno].q_first = 343082527734SSukumar Swaminathan (uint8_t *)next; 343182527734SSukumar Swaminathan } else { 343282527734SSukumar Swaminathan prev->next = next; 343382527734SSukumar Swaminathan } 343482527734SSukumar Swaminathan 343582527734SSukumar Swaminathan iocbq->next = NULL; 343682527734SSukumar Swaminathan nlp->nlp_tx[fchanno].q_cnt--; 343782527734SSukumar Swaminathan 343882527734SSukumar Swaminathan /* Add this iocb to our local toberemovedq */ 343982527734SSukumar Swaminathan /* This way we donot hold the TX_CHANNEL lock too long */ 344082527734SSukumar Swaminathan 344182527734SSukumar Swaminathan if (tbm.q_first) { 344282527734SSukumar Swaminathan ((IOCBQ *)tbm.q_last)->next = iocbq; 344382527734SSukumar Swaminathan tbm.q_last = (uint8_t *)iocbq; 344482527734SSukumar Swaminathan tbm.q_cnt++; 344582527734SSukumar Swaminathan } else { 344682527734SSukumar Swaminathan tbm.q_first = (uint8_t *)iocbq; 344782527734SSukumar Swaminathan tbm.q_last = (uint8_t *)iocbq; 344882527734SSukumar Swaminathan tbm.q_cnt = 1; 344982527734SSukumar Swaminathan } 345082527734SSukumar Swaminathan 345182527734SSukumar Swaminathan iocbq = next; 345282527734SSukumar Swaminathan 345382527734SSukumar Swaminathan } /* While (iocbq) */ 345482527734SSukumar Swaminathan 345582527734SSukumar Swaminathan if ((tchanno == hba->channel_fcp) && (tbm.q_cnt != 0)) { 345682527734SSukumar Swaminathan 345782527734SSukumar Swaminathan /* from_chan->nodeq.q_first must be non NULL */ 345882527734SSukumar Swaminathan if (from_chan->nodeq.q_first) { 345982527734SSukumar Swaminathan 346082527734SSukumar Swaminathan /* nodeq is not empty, now deal with the node itself */ 346182527734SSukumar Swaminathan if ((nlp->nlp_tx[fchanno].q_first)) { 346282527734SSukumar Swaminathan 346382527734SSukumar Swaminathan if (!nlp->nlp_base) { 346482527734SSukumar Swaminathan from_chan->nodeq.q_last = 346582527734SSukumar Swaminathan (void *)nlp; 346682527734SSukumar Swaminathan from_chan->nodeq.q_first = 346782527734SSukumar Swaminathan nlp->nlp_next[fchanno]; 346882527734SSukumar Swaminathan } 346982527734SSukumar Swaminathan 347082527734SSukumar Swaminathan } else { 347182527734SSukumar Swaminathan n_prev = (NODELIST *)from_chan->nodeq.q_first; 347282527734SSukumar Swaminathan count = from_chan->nodeq.q_cnt; 347382527734SSukumar Swaminathan 347482527734SSukumar Swaminathan if (n_prev == nlp) { 347582527734SSukumar Swaminathan 347682527734SSukumar Swaminathan /* If this is the only node on list */ 347782527734SSukumar Swaminathan if (from_chan->nodeq.q_last == 347882527734SSukumar Swaminathan (void *)nlp) { 347982527734SSukumar Swaminathan from_chan->nodeq.q_last = 348082527734SSukumar Swaminathan NULL; 348182527734SSukumar Swaminathan from_chan->nodeq.q_first = 348282527734SSukumar Swaminathan NULL; 348382527734SSukumar Swaminathan from_chan->nodeq.q_cnt = 0; 348482527734SSukumar Swaminathan } else { 348582527734SSukumar Swaminathan from_chan->nodeq.q_first = 348682527734SSukumar Swaminathan nlp->nlp_next[fchanno]; 348782527734SSukumar Swaminathan ((NODELIST *)from_chan-> 348882527734SSukumar Swaminathan nodeq.q_last)-> 348982527734SSukumar Swaminathan nlp_next[fchanno] = 349082527734SSukumar Swaminathan from_chan->nodeq.q_first; 349182527734SSukumar Swaminathan from_chan->nodeq.q_cnt--; 349282527734SSukumar Swaminathan } 349382527734SSukumar Swaminathan /* Clear node */ 349482527734SSukumar Swaminathan nlp->nlp_next[fchanno] = NULL; 349582527734SSukumar Swaminathan } else { 349682527734SSukumar Swaminathan count--; 349782527734SSukumar Swaminathan do { 349882527734SSukumar Swaminathan n_next = 349982527734SSukumar Swaminathan n_prev->nlp_next[fchanno]; 350082527734SSukumar Swaminathan if (n_next == nlp) { 350182527734SSukumar Swaminathan break; 350282527734SSukumar Swaminathan } 350382527734SSukumar Swaminathan n_prev = n_next; 350482527734SSukumar Swaminathan } while (count--); 350582527734SSukumar Swaminathan 350682527734SSukumar Swaminathan if (count != 0) { 350782527734SSukumar Swaminathan 350882527734SSukumar Swaminathan if (n_next == 350982527734SSukumar Swaminathan (NODELIST *)from_chan-> 351082527734SSukumar Swaminathan nodeq.q_last) { 351182527734SSukumar Swaminathan n_prev-> 351282527734SSukumar Swaminathan nlp_next[fchanno] 351382527734SSukumar Swaminathan = 351482527734SSukumar Swaminathan ((NODELIST *) 351582527734SSukumar Swaminathan from_chan-> 351682527734SSukumar Swaminathan nodeq.q_last)-> 351782527734SSukumar Swaminathan nlp_next 351882527734SSukumar Swaminathan [fchanno]; 351982527734SSukumar Swaminathan from_chan->nodeq.q_last 352082527734SSukumar Swaminathan = (uint8_t *)n_prev; 352182527734SSukumar Swaminathan } else { 352282527734SSukumar Swaminathan 352382527734SSukumar Swaminathan n_prev-> 352482527734SSukumar Swaminathan nlp_next[fchanno] 352582527734SSukumar Swaminathan = 352682527734SSukumar Swaminathan n_next-> nlp_next 352782527734SSukumar Swaminathan [fchanno]; 352882527734SSukumar Swaminathan } 352982527734SSukumar Swaminathan from_chan->nodeq.q_cnt--; 353082527734SSukumar Swaminathan /* Clear node */ 353182527734SSukumar Swaminathan nlp->nlp_next[fchanno] = 353282527734SSukumar Swaminathan NULL; 353382527734SSukumar Swaminathan } 353482527734SSukumar Swaminathan } 353582527734SSukumar Swaminathan } 353682527734SSukumar Swaminathan } 353782527734SSukumar Swaminathan } 353882527734SSukumar Swaminathan 353982527734SSukumar Swaminathan /* Now cleanup the iocb's */ 354082527734SSukumar Swaminathan prev = NULL; 354182527734SSukumar Swaminathan iocbq = (IOCBQ *)tbm.q_first; 354282527734SSukumar Swaminathan 354382527734SSukumar Swaminathan while (iocbq) { 354482527734SSukumar Swaminathan 354582527734SSukumar Swaminathan next = (IOCBQ *)iocbq->next; 354682527734SSukumar Swaminathan 354782527734SSukumar Swaminathan /* Free the IoTag and the bmp */ 354882527734SSukumar Swaminathan iocb = &iocbq->iocb; 354982527734SSukumar Swaminathan 355082527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 355182527734SSukumar Swaminathan sbp = iocbq->sbp; 355282527734SSukumar Swaminathan if (sbp) { 35538f23e9faSHans Rosenfeld emlxs_sli4_free_xri(port, sbp, sbp->xrip, 1); 355482527734SSukumar Swaminathan } 355582527734SSukumar Swaminathan } else { 355682527734SSukumar Swaminathan sbp = emlxs_unregister_pkt((CHANNEL *)iocbq->channel, 355782527734SSukumar Swaminathan iocb->ULPIOTAG, 0); 355882527734SSukumar Swaminathan } 355982527734SSukumar Swaminathan 356082527734SSukumar Swaminathan if (sbp && (sbp != STALE_PACKET)) { 356182527734SSukumar Swaminathan mutex_enter(&sbp->mtx); 356282527734SSukumar Swaminathan sbp->pkt_flags |= PACKET_IN_FLUSH; 356382527734SSukumar Swaminathan 356482527734SSukumar Swaminathan /* 356582527734SSukumar Swaminathan * If the fpkt is already set, then we will leave it 356682527734SSukumar Swaminathan * alone. This ensures that this pkt is only accounted 356782527734SSukumar Swaminathan * for on one fpkt->flush_count 356882527734SSukumar Swaminathan */ 356982527734SSukumar Swaminathan if (!sbp->fpkt && fpkt) { 357082527734SSukumar Swaminathan mutex_enter(&fpkt->mtx); 357182527734SSukumar Swaminathan sbp->fpkt = fpkt; 357282527734SSukumar Swaminathan fpkt->flush_count++; 357382527734SSukumar Swaminathan mutex_exit(&fpkt->mtx); 357482527734SSukumar Swaminathan } 357582527734SSukumar Swaminathan mutex_exit(&sbp->mtx); 357682527734SSukumar Swaminathan } 357782527734SSukumar Swaminathan iocbq = next; 357882527734SSukumar Swaminathan 357982527734SSukumar Swaminathan } /* end of while */ 358082527734SSukumar Swaminathan 358182527734SSukumar Swaminathan iocbq = (IOCBQ *)tbm.q_first; 358282527734SSukumar Swaminathan while (iocbq) { 358382527734SSukumar Swaminathan /* Save the next iocbq for now */ 358482527734SSukumar Swaminathan next = (IOCBQ *)iocbq->next; 358582527734SSukumar Swaminathan 358682527734SSukumar Swaminathan /* Unlink this iocbq */ 358782527734SSukumar Swaminathan iocbq->next = NULL; 358882527734SSukumar Swaminathan 358982527734SSukumar Swaminathan /* Get the pkt */ 359082527734SSukumar Swaminathan sbp = (emlxs_buf_t *)iocbq->sbp; 359182527734SSukumar Swaminathan 359282527734SSukumar Swaminathan if (sbp) { 359382527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flush_msg, 359482527734SSukumar Swaminathan "tx: sbp=%p node=%p", sbp, sbp->node); 359582527734SSukumar Swaminathan 359682527734SSukumar Swaminathan if (hba->state >= FC_LINK_UP) { 359782527734SSukumar Swaminathan emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 359882527734SSukumar Swaminathan IOERR_ABORT_REQUESTED, 1); 359982527734SSukumar Swaminathan } else { 360082527734SSukumar Swaminathan emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 360182527734SSukumar Swaminathan IOERR_LINK_DOWN, 1); 360282527734SSukumar Swaminathan } 360382527734SSukumar Swaminathan 360482527734SSukumar Swaminathan } 360582527734SSukumar Swaminathan /* Free the iocb and its associated buffers */ 360682527734SSukumar Swaminathan else { 360782527734SSukumar Swaminathan icmd = &iocbq->iocb; 360882527734SSukumar Swaminathan 360982527734SSukumar Swaminathan /* SLI3 */ 361082527734SSukumar Swaminathan if (icmd->ULPCOMMAND == CMD_QUE_RING_BUF64_CN || 361182527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_QUE_RING_BUF_CN || 361282527734SSukumar Swaminathan icmd->ULPCOMMAND == CMD_QUE_RING_LIST64_CN) { 361382527734SSukumar Swaminathan if ((hba->flag & 361482527734SSukumar Swaminathan (FC_ONLINE_MODE | FC_ONLINING_MODE)) == 0) { 361582527734SSukumar Swaminathan /* HBA is detaching or offlining */ 361682527734SSukumar Swaminathan if (icmd->ULPCOMMAND != 361782527734SSukumar Swaminathan CMD_QUE_RING_LIST64_CN) { 3618a9800bebSGarrett D'Amore void *tmp; 361982527734SSukumar Swaminathan RING *rp; 362082527734SSukumar Swaminathan int ch; 362182527734SSukumar Swaminathan 362282527734SSukumar Swaminathan ch = from_chan->channelno; 362382527734SSukumar Swaminathan rp = &hba->sli.sli3.ring[ch]; 362482527734SSukumar Swaminathan 362582527734SSukumar Swaminathan for (i = 0; 362682527734SSukumar Swaminathan i < icmd->ULPBDECOUNT; 362782527734SSukumar Swaminathan i++) { 362882527734SSukumar Swaminathan mp = EMLXS_GET_VADDR( 362982527734SSukumar Swaminathan hba, rp, icmd); 363082527734SSukumar Swaminathan 3631a9800bebSGarrett D'Amore tmp = (void *)mp; 363282527734SSukumar Swaminathan if (mp) { 3633a9800bebSGarrett D'Amore emlxs_mem_put( 363482527734SSukumar Swaminathan hba, 363582527734SSukumar Swaminathan MEM_BUF, 363682527734SSukumar Swaminathan tmp); 363782527734SSukumar Swaminathan } 363882527734SSukumar Swaminathan } 363982527734SSukumar Swaminathan 364082527734SSukumar Swaminathan } 364182527734SSukumar Swaminathan 3642a9800bebSGarrett D'Amore emlxs_mem_put(hba, MEM_IOCB, 3643a9800bebSGarrett D'Amore (void *)iocbq); 364482527734SSukumar Swaminathan } else { 364582527734SSukumar Swaminathan /* repost the unsolicited buffer */ 364682527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, 364782527734SSukumar Swaminathan from_chan, iocbq); 364882527734SSukumar Swaminathan } 364982527734SSukumar Swaminathan } 365082527734SSukumar Swaminathan } 365182527734SSukumar Swaminathan 365282527734SSukumar Swaminathan iocbq = next; 365382527734SSukumar Swaminathan 365482527734SSukumar Swaminathan } /* end of while */ 365582527734SSukumar Swaminathan 365682527734SSukumar Swaminathan /* Now flush the chipq if any */ 365782527734SSukumar Swaminathan if (!(nlp->nlp_flag[fchanno] & NLP_CLOSED)) { 365882527734SSukumar Swaminathan 365982527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 366082527734SSukumar Swaminathan 366182527734SSukumar Swaminathan (void) emlxs_chipq_node_flush(port, from_chan, nlp, 0); 366282527734SSukumar Swaminathan 366382527734SSukumar Swaminathan mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 366482527734SSukumar Swaminathan } 366582527734SSukumar Swaminathan 366682527734SSukumar Swaminathan if (lock) { 366782527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 366882527734SSukumar Swaminathan } 366982527734SSukumar Swaminathan 367082527734SSukumar Swaminathan return; 367182527734SSukumar Swaminathan 367282527734SSukumar Swaminathan } /* emlxs_tx_move */ 3673fcf3ce44SJohn Forte 3674fcf3ce44SJohn Forte 3675fcf3ce44SJohn Forte extern uint32_t 367682527734SSukumar Swaminathan emlxs_chipq_node_flush(emlxs_port_t *port, CHANNEL *chan, NODELIST *ndlp, 3677291a2b48SSukumar Swaminathan emlxs_buf_t *fpkt) 3678fcf3ce44SJohn Forte { 3679fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 3680fcf3ce44SJohn Forte emlxs_buf_t *sbp; 3681fcf3ce44SJohn Forte IOCBQ *iocbq; 3682fcf3ce44SJohn Forte IOCBQ *next; 3683fcf3ce44SJohn Forte Q abort; 368482527734SSukumar Swaminathan CHANNEL *cp; 368582527734SSukumar Swaminathan uint32_t channelno; 368682527734SSukumar Swaminathan uint8_t flag[MAX_CHANNEL]; 3687fcf3ce44SJohn Forte uint32_t iotag; 3688fcf3ce44SJohn Forte 3689fcf3ce44SJohn Forte bzero((void *)&abort, sizeof (Q)); 3690fcf3ce44SJohn Forte bzero((void *)flag, sizeof (flag)); 3691fcf3ce44SJohn Forte 369282527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 369382527734SSukumar Swaminathan cp = &hba->chan[channelno]; 3694fcf3ce44SJohn Forte 369582527734SSukumar Swaminathan if (chan && cp != chan) { 3696fcf3ce44SJohn Forte continue; 3697fcf3ce44SJohn Forte } 3698291a2b48SSukumar Swaminathan 369982527734SSukumar Swaminathan mutex_enter(&EMLXS_FCTAB_LOCK); 3700fcf3ce44SJohn Forte 370182527734SSukumar Swaminathan for (iotag = 1; iotag < hba->max_iotag; iotag++) { 370282527734SSukumar Swaminathan sbp = hba->fc_table[iotag]; 3703fcf3ce44SJohn Forte 3704fcf3ce44SJohn Forte if (sbp && (sbp != STALE_PACKET) && 3705fcf3ce44SJohn Forte (sbp->pkt_flags & PACKET_IN_CHIPQ) && 3706fcf3ce44SJohn Forte (sbp->node == ndlp) && 370782527734SSukumar Swaminathan (sbp->channel == cp) && 3708fcf3ce44SJohn Forte !(sbp->pkt_flags & PACKET_XRI_CLOSED)) { 3709291a2b48SSukumar Swaminathan emlxs_sbp_abort_add(port, sbp, &abort, flag, 3710291a2b48SSukumar Swaminathan fpkt); 3711fcf3ce44SJohn Forte } 3712291a2b48SSukumar Swaminathan 3713fcf3ce44SJohn Forte } 371482527734SSukumar Swaminathan mutex_exit(&EMLXS_FCTAB_LOCK); 3715fcf3ce44SJohn Forte 3716fcf3ce44SJohn Forte } /* for */ 3717fcf3ce44SJohn Forte 3718fcf3ce44SJohn Forte /* Now put the iocb's on the tx queue */ 3719fcf3ce44SJohn Forte iocbq = (IOCBQ *)abort.q_first; 3720fcf3ce44SJohn Forte while (iocbq) { 3721fcf3ce44SJohn Forte /* Save the next iocbq for now */ 3722fcf3ce44SJohn Forte next = (IOCBQ *)iocbq->next; 3723fcf3ce44SJohn Forte 3724fcf3ce44SJohn Forte /* Unlink this iocbq */ 3725fcf3ce44SJohn Forte iocbq->next = NULL; 3726fcf3ce44SJohn Forte 3727fcf3ce44SJohn Forte /* Send this iocbq */ 3728fcf3ce44SJohn Forte emlxs_tx_put(iocbq, 1); 3729fcf3ce44SJohn Forte 3730fcf3ce44SJohn Forte iocbq = next; 3731fcf3ce44SJohn Forte } 3732fcf3ce44SJohn Forte 373382527734SSukumar Swaminathan /* Now trigger channel service */ 373482527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 373582527734SSukumar Swaminathan if (!flag[channelno]) { 3736fcf3ce44SJohn Forte continue; 3737fcf3ce44SJohn Forte } 3738291a2b48SSukumar Swaminathan 373982527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, &hba->chan[channelno], 0); 3740fcf3ce44SJohn Forte } 3741fcf3ce44SJohn Forte 3742fcf3ce44SJohn Forte return (abort.q_cnt); 3743fcf3ce44SJohn Forte 374482527734SSukumar Swaminathan } /* emlxs_chipq_node_flush() */ 3745fcf3ce44SJohn Forte 3746fcf3ce44SJohn Forte 3747fcf3ce44SJohn Forte /* Flush all IO's left on all iotag lists */ 374882527734SSukumar Swaminathan extern uint32_t 3749fcf3ce44SJohn Forte emlxs_iotag_flush(emlxs_hba_t *hba) 3750fcf3ce44SJohn Forte { 3751fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 3752fcf3ce44SJohn Forte emlxs_buf_t *sbp; 3753fcf3ce44SJohn Forte IOCBQ *iocbq; 3754fcf3ce44SJohn Forte IOCB *iocb; 3755fcf3ce44SJohn Forte Q abort; 375682527734SSukumar Swaminathan CHANNEL *cp; 375782527734SSukumar Swaminathan uint32_t channelno; 3758fcf3ce44SJohn Forte uint32_t iotag; 3759fcf3ce44SJohn Forte uint32_t count; 3760fcf3ce44SJohn Forte 3761fcf3ce44SJohn Forte count = 0; 376282527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 376382527734SSukumar Swaminathan cp = &hba->chan[channelno]; 3764fcf3ce44SJohn Forte 3765fcf3ce44SJohn Forte bzero((void *)&abort, sizeof (Q)); 3766fcf3ce44SJohn Forte 376782527734SSukumar Swaminathan mutex_enter(&EMLXS_FCTAB_LOCK); 3768fcf3ce44SJohn Forte 376982527734SSukumar Swaminathan for (iotag = 1; iotag < hba->max_iotag; iotag++) { 377082527734SSukumar Swaminathan sbp = hba->fc_table[iotag]; 3771fcf3ce44SJohn Forte 377282527734SSukumar Swaminathan /* Check if the slot is empty */ 3773fcf3ce44SJohn Forte if (!sbp || (sbp == STALE_PACKET)) { 3774fcf3ce44SJohn Forte continue; 3775fcf3ce44SJohn Forte } 3776291a2b48SSukumar Swaminathan 377782527734SSukumar Swaminathan /* We are building an abort list per channel */ 377882527734SSukumar Swaminathan if (sbp->channel != cp) { 377982527734SSukumar Swaminathan continue; 378082527734SSukumar Swaminathan } 3781fcf3ce44SJohn Forte 3782a9800bebSGarrett D'Amore hba->fc_table[iotag] = STALE_PACKET; 3783a9800bebSGarrett D'Amore hba->io_count--; 3784a9800bebSGarrett D'Amore 3785a9800bebSGarrett D'Amore /* Check if IO is valid */ 3786a9800bebSGarrett D'Amore if (!(sbp->pkt_flags & PACKET_VALID) || 3787a9800bebSGarrett D'Amore (sbp->pkt_flags & (PACKET_ULP_OWNED| 3788a9800bebSGarrett D'Amore PACKET_COMPLETED|PACKET_IN_COMPLETION))) { 3789a9800bebSGarrett D'Amore EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_debug_msg, 37908f23e9faSHans Rosenfeld "iotag_flush: Invalid IO found. iotag=%d", 3791a9800bebSGarrett D'Amore iotag); 3792a9800bebSGarrett D'Amore 3793a9800bebSGarrett D'Amore continue; 3794a9800bebSGarrett D'Amore } 3795a9800bebSGarrett D'Amore 3796a9800bebSGarrett D'Amore sbp->iotag = 0; 3797a9800bebSGarrett D'Amore 3798fcf3ce44SJohn Forte /* Set IOCB status */ 3799fcf3ce44SJohn Forte iocbq = &sbp->iocbq; 3800fcf3ce44SJohn Forte iocb = &iocbq->iocb; 3801fcf3ce44SJohn Forte 380282527734SSukumar Swaminathan iocb->ULPSTATUS = IOSTAT_LOCAL_REJECT; 3803fcf3ce44SJohn Forte iocb->un.grsp.perr.statLocalError = IOERR_LINK_DOWN; 380482527734SSukumar Swaminathan iocb->ULPLE = 1; 3805fcf3ce44SJohn Forte iocbq->next = NULL; 3806fcf3ce44SJohn Forte 380782527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 3808a9800bebSGarrett D'Amore if (sbp->xrip) { 3809a9800bebSGarrett D'Amore EMLXS_MSGF(EMLXS_CONTEXT, 3810a9800bebSGarrett D'Amore &emlxs_sli_debug_msg, 38118f23e9faSHans Rosenfeld "iotag_flush: iotag=%d sbp=%p " 3812a9800bebSGarrett D'Amore "xrip=%p state=%x flag=%x", 3813a9800bebSGarrett D'Amore iotag, sbp, sbp->xrip, 3814a9800bebSGarrett D'Amore sbp->xrip->state, sbp->xrip->flag); 3815a9800bebSGarrett D'Amore } else { 3816a9800bebSGarrett D'Amore EMLXS_MSGF(EMLXS_CONTEXT, 3817a9800bebSGarrett D'Amore &emlxs_sli_debug_msg, 38188f23e9faSHans Rosenfeld "iotag_flush: iotag=%d sbp=%p " 38198f23e9faSHans Rosenfeld "xrip=NULL", iotag, sbp); 3820a9800bebSGarrett D'Amore } 3821291a2b48SSukumar Swaminathan 38228f23e9faSHans Rosenfeld emlxs_sli4_free_xri(port, sbp, sbp->xrip, 0); 3823a9800bebSGarrett D'Amore } else { 382482527734SSukumar Swaminathan /* Clean up the sbp */ 382582527734SSukumar Swaminathan mutex_enter(&sbp->mtx); 382682527734SSukumar Swaminathan 382782527734SSukumar Swaminathan if (sbp->pkt_flags & PACKET_IN_TXQ) { 382882527734SSukumar Swaminathan sbp->pkt_flags &= ~PACKET_IN_TXQ; 382982527734SSukumar Swaminathan hba->channel_tx_count --; 383082527734SSukumar Swaminathan } 383182527734SSukumar Swaminathan 383282527734SSukumar Swaminathan if (sbp->pkt_flags & PACKET_IN_CHIPQ) { 383382527734SSukumar Swaminathan sbp->pkt_flags &= ~PACKET_IN_CHIPQ; 383482527734SSukumar Swaminathan } 3835291a2b48SSukumar Swaminathan 383682527734SSukumar Swaminathan if (sbp->bmp) { 3837a9800bebSGarrett D'Amore emlxs_mem_put(hba, MEM_BPL, 3838a9800bebSGarrett D'Amore (void *)sbp->bmp); 383982527734SSukumar Swaminathan sbp->bmp = 0; 384082527734SSukumar Swaminathan } 384182527734SSukumar Swaminathan 384282527734SSukumar Swaminathan mutex_exit(&sbp->mtx); 3843fcf3ce44SJohn Forte } 3844291a2b48SSukumar Swaminathan 3845fcf3ce44SJohn Forte /* At this point all nodes are assumed destroyed */ 384682527734SSukumar Swaminathan mutex_enter(&sbp->mtx); 3847fcf3ce44SJohn Forte sbp->node = 0; 3848fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 3849fcf3ce44SJohn Forte 3850fcf3ce44SJohn Forte /* Add this iocb to our local abort Q */ 3851fcf3ce44SJohn Forte if (abort.q_first) { 3852291a2b48SSukumar Swaminathan ((IOCBQ *)abort.q_last)->next = iocbq; 3853fcf3ce44SJohn Forte abort.q_last = (uint8_t *)iocbq; 3854fcf3ce44SJohn Forte abort.q_cnt++; 3855fcf3ce44SJohn Forte } else { 3856fcf3ce44SJohn Forte abort.q_first = (uint8_t *)iocbq; 3857fcf3ce44SJohn Forte abort.q_last = (uint8_t *)iocbq; 3858fcf3ce44SJohn Forte abort.q_cnt = 1; 3859fcf3ce44SJohn Forte } 3860fcf3ce44SJohn Forte } 3861fcf3ce44SJohn Forte 386282527734SSukumar Swaminathan mutex_exit(&EMLXS_FCTAB_LOCK); 3863fcf3ce44SJohn Forte 3864fcf3ce44SJohn Forte /* Trigger deferred completion */ 3865fcf3ce44SJohn Forte if (abort.q_first) { 386682527734SSukumar Swaminathan mutex_enter(&cp->rsp_lock); 386782527734SSukumar Swaminathan if (cp->rsp_head == NULL) { 386882527734SSukumar Swaminathan cp->rsp_head = (IOCBQ *)abort.q_first; 386982527734SSukumar Swaminathan cp->rsp_tail = (IOCBQ *)abort.q_last; 3870fcf3ce44SJohn Forte } else { 387182527734SSukumar Swaminathan cp->rsp_tail->next = (IOCBQ *)abort.q_first; 387282527734SSukumar Swaminathan cp->rsp_tail = (IOCBQ *)abort.q_last; 3873fcf3ce44SJohn Forte } 387482527734SSukumar Swaminathan mutex_exit(&cp->rsp_lock); 3875fcf3ce44SJohn Forte 387682527734SSukumar Swaminathan emlxs_thread_trigger2(&cp->intr_thread, 387782527734SSukumar Swaminathan emlxs_proc_channel, cp); 3878fcf3ce44SJohn Forte 3879a9800bebSGarrett D'Amore EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_debug_msg, 3880a9800bebSGarrett D'Amore "iotag_flush: channel=%d count=%d", 388182527734SSukumar Swaminathan channelno, abort.q_cnt); 3882fcf3ce44SJohn Forte 3883fcf3ce44SJohn Forte count += abort.q_cnt; 3884fcf3ce44SJohn Forte } 3885fcf3ce44SJohn Forte } 3886fcf3ce44SJohn Forte 3887fcf3ce44SJohn Forte return (count); 3888fcf3ce44SJohn Forte 388982527734SSukumar Swaminathan } /* emlxs_iotag_flush() */ 3890fcf3ce44SJohn Forte 3891fcf3ce44SJohn Forte 3892fcf3ce44SJohn Forte 389382527734SSukumar Swaminathan /* Checks for IO's on all or a given channel for a given node */ 3894fcf3ce44SJohn Forte extern uint32_t 389582527734SSukumar Swaminathan emlxs_chipq_node_check(emlxs_port_t *port, CHANNEL *chan, NODELIST *ndlp) 3896fcf3ce44SJohn Forte { 3897fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 3898fcf3ce44SJohn Forte emlxs_buf_t *sbp; 389982527734SSukumar Swaminathan CHANNEL *cp; 390082527734SSukumar Swaminathan uint32_t channelno; 3901fcf3ce44SJohn Forte uint32_t count; 3902fcf3ce44SJohn Forte uint32_t iotag; 3903fcf3ce44SJohn Forte 3904fcf3ce44SJohn Forte count = 0; 3905fcf3ce44SJohn Forte 390682527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 390782527734SSukumar Swaminathan cp = &hba->chan[channelno]; 3908fcf3ce44SJohn Forte 390982527734SSukumar Swaminathan if (chan && cp != chan) { 3910fcf3ce44SJohn Forte continue; 3911fcf3ce44SJohn Forte } 3912291a2b48SSukumar Swaminathan 391382527734SSukumar Swaminathan mutex_enter(&EMLXS_FCTAB_LOCK); 3914fcf3ce44SJohn Forte 391582527734SSukumar Swaminathan for (iotag = 1; iotag < hba->max_iotag; iotag++) { 391682527734SSukumar Swaminathan sbp = hba->fc_table[iotag]; 3917fcf3ce44SJohn Forte 3918fcf3ce44SJohn Forte if (sbp && (sbp != STALE_PACKET) && 3919fcf3ce44SJohn Forte (sbp->pkt_flags & PACKET_IN_CHIPQ) && 3920fcf3ce44SJohn Forte (sbp->node == ndlp) && 392182527734SSukumar Swaminathan (sbp->channel == cp) && 3922fcf3ce44SJohn Forte !(sbp->pkt_flags & PACKET_XRI_CLOSED)) { 3923fcf3ce44SJohn Forte count++; 3924fcf3ce44SJohn Forte } 3925291a2b48SSukumar Swaminathan 3926fcf3ce44SJohn Forte } 392782527734SSukumar Swaminathan mutex_exit(&EMLXS_FCTAB_LOCK); 3928fcf3ce44SJohn Forte 3929fcf3ce44SJohn Forte } /* for */ 3930fcf3ce44SJohn Forte 3931fcf3ce44SJohn Forte return (count); 3932fcf3ce44SJohn Forte 393382527734SSukumar Swaminathan } /* emlxs_chipq_node_check() */ 3934fcf3ce44SJohn Forte 3935fcf3ce44SJohn Forte 3936fcf3ce44SJohn Forte 393782527734SSukumar Swaminathan /* Flush all IO's for a given node's lun (on any channel) */ 3938fcf3ce44SJohn Forte extern uint32_t 393982527734SSukumar Swaminathan emlxs_chipq_lun_flush(emlxs_port_t *port, NODELIST *ndlp, 394082527734SSukumar Swaminathan uint32_t lun, emlxs_buf_t *fpkt) 3941fcf3ce44SJohn Forte { 3942fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 3943fcf3ce44SJohn Forte emlxs_buf_t *sbp; 3944fcf3ce44SJohn Forte IOCBQ *iocbq; 3945fcf3ce44SJohn Forte IOCBQ *next; 3946fcf3ce44SJohn Forte Q abort; 3947fcf3ce44SJohn Forte uint32_t iotag; 394882527734SSukumar Swaminathan uint8_t flag[MAX_CHANNEL]; 394982527734SSukumar Swaminathan uint32_t channelno; 3950fcf3ce44SJohn Forte 3951a9800bebSGarrett D'Amore if (lun == EMLXS_LUN_NONE) { 3952a9800bebSGarrett D'Amore return (0); 3953a9800bebSGarrett D'Amore } 3954a9800bebSGarrett D'Amore 3955fcf3ce44SJohn Forte bzero((void *)flag, sizeof (flag)); 3956fcf3ce44SJohn Forte bzero((void *)&abort, sizeof (Q)); 3957fcf3ce44SJohn Forte 395882527734SSukumar Swaminathan mutex_enter(&EMLXS_FCTAB_LOCK); 395982527734SSukumar Swaminathan for (iotag = 1; iotag < hba->max_iotag; iotag++) { 396082527734SSukumar Swaminathan sbp = hba->fc_table[iotag]; 3961fcf3ce44SJohn Forte 3962fcf3ce44SJohn Forte if (sbp && (sbp != STALE_PACKET) && 3963fcf3ce44SJohn Forte sbp->pkt_flags & PACKET_IN_CHIPQ && 3964fcf3ce44SJohn Forte sbp->node == ndlp && 3965fcf3ce44SJohn Forte sbp->lun == lun && 3966fcf3ce44SJohn Forte !(sbp->pkt_flags & PACKET_XRI_CLOSED)) { 396782527734SSukumar Swaminathan emlxs_sbp_abort_add(port, sbp, 396882527734SSukumar Swaminathan &abort, flag, fpkt); 3969fcf3ce44SJohn Forte } 3970fcf3ce44SJohn Forte } 397182527734SSukumar Swaminathan mutex_exit(&EMLXS_FCTAB_LOCK); 3972fcf3ce44SJohn Forte 3973fcf3ce44SJohn Forte /* Now put the iocb's on the tx queue */ 3974fcf3ce44SJohn Forte iocbq = (IOCBQ *)abort.q_first; 3975fcf3ce44SJohn Forte while (iocbq) { 3976fcf3ce44SJohn Forte /* Save the next iocbq for now */ 3977fcf3ce44SJohn Forte next = (IOCBQ *)iocbq->next; 3978fcf3ce44SJohn Forte 3979fcf3ce44SJohn Forte /* Unlink this iocbq */ 3980fcf3ce44SJohn Forte iocbq->next = NULL; 3981fcf3ce44SJohn Forte 3982fcf3ce44SJohn Forte /* Send this iocbq */ 3983fcf3ce44SJohn Forte emlxs_tx_put(iocbq, 1); 3984fcf3ce44SJohn Forte 3985fcf3ce44SJohn Forte iocbq = next; 3986fcf3ce44SJohn Forte } 3987fcf3ce44SJohn Forte 398882527734SSukumar Swaminathan /* Now trigger channel service */ 398982527734SSukumar Swaminathan for (channelno = 0; channelno < hba->chan_count; channelno++) { 399082527734SSukumar Swaminathan if (!flag[channelno]) { 399182527734SSukumar Swaminathan continue; 399282527734SSukumar Swaminathan } 399382527734SSukumar Swaminathan 399482527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, &hba->chan[channelno], 0); 3995fcf3ce44SJohn Forte } 3996291a2b48SSukumar Swaminathan 3997fcf3ce44SJohn Forte return (abort.q_cnt); 3998fcf3ce44SJohn Forte 399982527734SSukumar Swaminathan } /* emlxs_chipq_lun_flush() */ 4000fcf3ce44SJohn Forte 4001fcf3ce44SJohn Forte 4002fcf3ce44SJohn Forte 4003fcf3ce44SJohn Forte /* 4004fcf3ce44SJohn Forte * Issue an ABORT_XRI_CN iocb command to abort an FCP command already issued. 4005fe199829SSukumar Swaminathan * This must be called while holding the EMLXS_FCTAB_LOCK 4006fcf3ce44SJohn Forte */ 4007fcf3ce44SJohn Forte extern IOCBQ * 4008291a2b48SSukumar Swaminathan emlxs_create_abort_xri_cn(emlxs_port_t *port, NODELIST *ndlp, 400982527734SSukumar Swaminathan uint16_t iotag, CHANNEL *cp, uint8_t class, int32_t flag) 4010fcf3ce44SJohn Forte { 4011fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 4012fcf3ce44SJohn Forte IOCBQ *iocbq; 4013fcf3ce44SJohn Forte IOCB *iocb; 401482527734SSukumar Swaminathan emlxs_wqe_t *wqe; 401582527734SSukumar Swaminathan emlxs_buf_t *sbp; 4016fcf3ce44SJohn Forte uint16_t abort_iotag; 4017fcf3ce44SJohn Forte 40188f23e9faSHans Rosenfeld if ((iocbq = (IOCBQ *)emlxs_mem_get(hba, MEM_IOCB)) == NULL) { 4019fcf3ce44SJohn Forte return (NULL); 4020fcf3ce44SJohn Forte } 4021291a2b48SSukumar Swaminathan 402282527734SSukumar Swaminathan iocbq->channel = (void *)cp; 4023fcf3ce44SJohn Forte iocbq->port = (void *)port; 4024fcf3ce44SJohn Forte iocbq->node = (void *)ndlp; 4025fcf3ce44SJohn Forte iocbq->flag |= (IOCB_PRIORITY | IOCB_SPECIAL); 4026fcf3ce44SJohn Forte 4027fcf3ce44SJohn Forte /* 4028fcf3ce44SJohn Forte * set up an iotag using special Abort iotags 4029fcf3ce44SJohn Forte */ 403082527734SSukumar Swaminathan if ((hba->fc_oor_iotag >= EMLXS_MAX_ABORT_TAG)) { 403182527734SSukumar Swaminathan hba->fc_oor_iotag = hba->max_iotag; 4032fcf3ce44SJohn Forte } 403382527734SSukumar Swaminathan abort_iotag = hba->fc_oor_iotag++; 4034291a2b48SSukumar Swaminathan 4035fcf3ce44SJohn Forte 403682527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 403782527734SSukumar Swaminathan wqe = &iocbq->wqe; 403882527734SSukumar Swaminathan sbp = hba->fc_table[iotag]; 4039fcf3ce44SJohn Forte 404082527734SSukumar Swaminathan /* Try to issue abort by XRI if possible */ 4041a9800bebSGarrett D'Amore if (sbp == NULL || sbp == STALE_PACKET || sbp->xrip == NULL) { 404282527734SSukumar Swaminathan wqe->un.Abort.Criteria = ABORT_REQ_TAG; 404382527734SSukumar Swaminathan wqe->AbortTag = iotag; 404482527734SSukumar Swaminathan } else { 404582527734SSukumar Swaminathan wqe->un.Abort.Criteria = ABORT_XRI_TAG; 4046a9800bebSGarrett D'Amore wqe->AbortTag = sbp->xrip->XRI; 404782527734SSukumar Swaminathan } 404882527734SSukumar Swaminathan wqe->un.Abort.IA = 0; 404982527734SSukumar Swaminathan wqe->RequestTag = abort_iotag; 405082527734SSukumar Swaminathan wqe->Command = CMD_ABORT_XRI_CX; 405182527734SSukumar Swaminathan wqe->Class = CLASS3; 40528f23e9faSHans Rosenfeld wqe->CQId = (uint16_t)0xffff; /* default CQ for response */ 405382527734SSukumar Swaminathan wqe->CmdType = WQE_TYPE_ABORT; 405482527734SSukumar Swaminathan } else { 405582527734SSukumar Swaminathan iocb = &iocbq->iocb; 405682527734SSukumar Swaminathan iocb->ULPIOTAG = abort_iotag; 405782527734SSukumar Swaminathan iocb->un.acxri.abortType = flag; 405882527734SSukumar Swaminathan iocb->un.acxri.abortContextTag = ndlp->nlp_Rpi; 405982527734SSukumar Swaminathan iocb->un.acxri.abortIoTag = iotag; 406082527734SSukumar Swaminathan iocb->ULPLE = 1; 406182527734SSukumar Swaminathan iocb->ULPCLASS = class; 406282527734SSukumar Swaminathan iocb->ULPCOMMAND = CMD_ABORT_XRI_CN; 406382527734SSukumar Swaminathan iocb->ULPOWNER = OWN_CHIP; 406482527734SSukumar Swaminathan } 4065fcf3ce44SJohn Forte 4066fcf3ce44SJohn Forte return (iocbq); 4067fcf3ce44SJohn Forte 406882527734SSukumar Swaminathan } /* emlxs_create_abort_xri_cn() */ 4069fcf3ce44SJohn Forte 4070fcf3ce44SJohn Forte 4071fe199829SSukumar Swaminathan /* This must be called while holding the EMLXS_FCTAB_LOCK */ 4072fcf3ce44SJohn Forte extern IOCBQ * 4073fcf3ce44SJohn Forte emlxs_create_abort_xri_cx(emlxs_port_t *port, NODELIST *ndlp, uint16_t xid, 407482527734SSukumar Swaminathan CHANNEL *cp, uint8_t class, int32_t flag) 4075fcf3ce44SJohn Forte { 4076fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 4077fcf3ce44SJohn Forte IOCBQ *iocbq; 4078fcf3ce44SJohn Forte IOCB *iocb; 407982527734SSukumar Swaminathan emlxs_wqe_t *wqe; 4080fcf3ce44SJohn Forte uint16_t abort_iotag; 4081fcf3ce44SJohn Forte 40828f23e9faSHans Rosenfeld if ((iocbq = (IOCBQ *)emlxs_mem_get(hba, MEM_IOCB)) == NULL) { 4083fcf3ce44SJohn Forte return (NULL); 4084fcf3ce44SJohn Forte } 4085291a2b48SSukumar Swaminathan 408682527734SSukumar Swaminathan iocbq->channel = (void *)cp; 4087fcf3ce44SJohn Forte iocbq->port = (void *)port; 4088fcf3ce44SJohn Forte iocbq->node = (void *)ndlp; 4089fcf3ce44SJohn Forte iocbq->flag |= (IOCB_PRIORITY | IOCB_SPECIAL); 4090fcf3ce44SJohn Forte 4091fcf3ce44SJohn Forte /* 4092fcf3ce44SJohn Forte * set up an iotag using special Abort iotags 4093fcf3ce44SJohn Forte */ 409482527734SSukumar Swaminathan if ((hba->fc_oor_iotag >= EMLXS_MAX_ABORT_TAG)) { 409582527734SSukumar Swaminathan hba->fc_oor_iotag = hba->max_iotag; 409682527734SSukumar Swaminathan } 409782527734SSukumar Swaminathan abort_iotag = hba->fc_oor_iotag++; 409882527734SSukumar Swaminathan 409982527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 410082527734SSukumar Swaminathan wqe = &iocbq->wqe; 410182527734SSukumar Swaminathan wqe->un.Abort.Criteria = ABORT_XRI_TAG; 410282527734SSukumar Swaminathan wqe->un.Abort.IA = 0; 410382527734SSukumar Swaminathan wqe->RequestTag = abort_iotag; 410482527734SSukumar Swaminathan wqe->AbortTag = xid; 410582527734SSukumar Swaminathan wqe->Command = CMD_ABORT_XRI_CX; 410682527734SSukumar Swaminathan wqe->Class = CLASS3; 41078f23e9faSHans Rosenfeld wqe->CQId = (uint16_t)0xffff; /* default CQ for response */ 410882527734SSukumar Swaminathan wqe->CmdType = WQE_TYPE_ABORT; 410982527734SSukumar Swaminathan } else { 411082527734SSukumar Swaminathan iocb = &iocbq->iocb; 411182527734SSukumar Swaminathan iocb->ULPCONTEXT = xid; 411282527734SSukumar Swaminathan iocb->ULPIOTAG = abort_iotag; 411382527734SSukumar Swaminathan iocb->un.acxri.abortType = flag; 411482527734SSukumar Swaminathan iocb->ULPLE = 1; 411582527734SSukumar Swaminathan iocb->ULPCLASS = class; 411682527734SSukumar Swaminathan iocb->ULPCOMMAND = CMD_ABORT_XRI_CX; 411782527734SSukumar Swaminathan iocb->ULPOWNER = OWN_CHIP; 4118fcf3ce44SJohn Forte } 4119291a2b48SSukumar Swaminathan 4120fcf3ce44SJohn Forte return (iocbq); 4121fcf3ce44SJohn Forte 412282527734SSukumar Swaminathan } /* emlxs_create_abort_xri_cx() */ 4123fcf3ce44SJohn Forte 4124fcf3ce44SJohn Forte 4125fcf3ce44SJohn Forte 4126fe199829SSukumar Swaminathan /* This must be called while holding the EMLXS_FCTAB_LOCK */ 4127fcf3ce44SJohn Forte extern IOCBQ * 4128fcf3ce44SJohn Forte emlxs_create_close_xri_cn(emlxs_port_t *port, NODELIST *ndlp, 412982527734SSukumar Swaminathan uint16_t iotag, CHANNEL *cp) 4130fcf3ce44SJohn Forte { 4131fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 4132fcf3ce44SJohn Forte IOCBQ *iocbq; 4133fcf3ce44SJohn Forte IOCB *iocb; 413482527734SSukumar Swaminathan emlxs_wqe_t *wqe; 413582527734SSukumar Swaminathan emlxs_buf_t *sbp; 4136fcf3ce44SJohn Forte uint16_t abort_iotag; 4137fcf3ce44SJohn Forte 41388f23e9faSHans Rosenfeld if ((iocbq = (IOCBQ *)emlxs_mem_get(hba, MEM_IOCB)) == NULL) { 4139fcf3ce44SJohn Forte return (NULL); 4140fcf3ce44SJohn Forte } 4141291a2b48SSukumar Swaminathan 414282527734SSukumar Swaminathan iocbq->channel = (void *)cp; 4143fcf3ce44SJohn Forte iocbq->port = (void *)port; 4144fcf3ce44SJohn Forte iocbq->node = (void *)ndlp; 4145fcf3ce44SJohn Forte iocbq->flag |= (IOCB_PRIORITY | IOCB_SPECIAL); 4146fcf3ce44SJohn Forte 4147fcf3ce44SJohn Forte /* 4148fcf3ce44SJohn Forte * set up an iotag using special Abort iotags 4149fcf3ce44SJohn Forte */ 415082527734SSukumar Swaminathan if ((hba->fc_oor_iotag >= EMLXS_MAX_ABORT_TAG)) { 415182527734SSukumar Swaminathan hba->fc_oor_iotag = hba->max_iotag; 4152fcf3ce44SJohn Forte } 415382527734SSukumar Swaminathan abort_iotag = hba->fc_oor_iotag++; 4154291a2b48SSukumar Swaminathan 415582527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 415682527734SSukumar Swaminathan wqe = &iocbq->wqe; 415782527734SSukumar Swaminathan sbp = hba->fc_table[iotag]; 4158fcf3ce44SJohn Forte 415982527734SSukumar Swaminathan /* Try to issue close by XRI if possible */ 4160a9800bebSGarrett D'Amore if (sbp == NULL || sbp == STALE_PACKET || sbp->xrip == NULL) { 416182527734SSukumar Swaminathan wqe->un.Abort.Criteria = ABORT_REQ_TAG; 416282527734SSukumar Swaminathan wqe->AbortTag = iotag; 416382527734SSukumar Swaminathan } else { 416482527734SSukumar Swaminathan wqe->un.Abort.Criteria = ABORT_XRI_TAG; 4165a9800bebSGarrett D'Amore wqe->AbortTag = sbp->xrip->XRI; 416682527734SSukumar Swaminathan } 416782527734SSukumar Swaminathan wqe->un.Abort.IA = 1; 416882527734SSukumar Swaminathan wqe->RequestTag = abort_iotag; 416982527734SSukumar Swaminathan wqe->Command = CMD_ABORT_XRI_CX; 417082527734SSukumar Swaminathan wqe->Class = CLASS3; 41718f23e9faSHans Rosenfeld wqe->CQId = (uint16_t)0xffff; /* default CQ for response */ 417282527734SSukumar Swaminathan wqe->CmdType = WQE_TYPE_ABORT; 417382527734SSukumar Swaminathan } else { 417482527734SSukumar Swaminathan iocb = &iocbq->iocb; 417582527734SSukumar Swaminathan iocb->ULPIOTAG = abort_iotag; 417682527734SSukumar Swaminathan iocb->un.acxri.abortType = 0; 417782527734SSukumar Swaminathan iocb->un.acxri.abortContextTag = ndlp->nlp_Rpi; 417882527734SSukumar Swaminathan iocb->un.acxri.abortIoTag = iotag; 417982527734SSukumar Swaminathan iocb->ULPLE = 1; 418082527734SSukumar Swaminathan iocb->ULPCLASS = 0; 418182527734SSukumar Swaminathan iocb->ULPCOMMAND = CMD_CLOSE_XRI_CN; 418282527734SSukumar Swaminathan iocb->ULPOWNER = OWN_CHIP; 418382527734SSukumar Swaminathan } 4184fcf3ce44SJohn Forte 4185fcf3ce44SJohn Forte return (iocbq); 4186fcf3ce44SJohn Forte 418782527734SSukumar Swaminathan } /* emlxs_create_close_xri_cn() */ 4188fcf3ce44SJohn Forte 4189fcf3ce44SJohn Forte 4190fe199829SSukumar Swaminathan /* This must be called while holding the EMLXS_FCTAB_LOCK */ 4191fcf3ce44SJohn Forte extern IOCBQ * 4192291a2b48SSukumar Swaminathan emlxs_create_close_xri_cx(emlxs_port_t *port, NODELIST *ndlp, uint16_t xid, 419382527734SSukumar Swaminathan CHANNEL *cp) 4194fcf3ce44SJohn Forte { 4195fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 4196fcf3ce44SJohn Forte IOCBQ *iocbq; 4197fcf3ce44SJohn Forte IOCB *iocb; 419882527734SSukumar Swaminathan emlxs_wqe_t *wqe; 4199fcf3ce44SJohn Forte uint16_t abort_iotag; 4200fcf3ce44SJohn Forte 42018f23e9faSHans Rosenfeld if ((iocbq = (IOCBQ *)emlxs_mem_get(hba, MEM_IOCB)) == NULL) { 4202fcf3ce44SJohn Forte return (NULL); 4203fcf3ce44SJohn Forte } 4204291a2b48SSukumar Swaminathan 420582527734SSukumar Swaminathan iocbq->channel = (void *)cp; 4206fcf3ce44SJohn Forte iocbq->port = (void *)port; 4207fcf3ce44SJohn Forte iocbq->node = (void *)ndlp; 4208fcf3ce44SJohn Forte iocbq->flag |= (IOCB_PRIORITY | IOCB_SPECIAL); 4209fcf3ce44SJohn Forte 4210fcf3ce44SJohn Forte /* 4211fcf3ce44SJohn Forte * set up an iotag using special Abort iotags 4212fcf3ce44SJohn Forte */ 421382527734SSukumar Swaminathan if ((hba->fc_oor_iotag >= EMLXS_MAX_ABORT_TAG)) { 421482527734SSukumar Swaminathan hba->fc_oor_iotag = hba->max_iotag; 421582527734SSukumar Swaminathan } 421682527734SSukumar Swaminathan abort_iotag = hba->fc_oor_iotag++; 421782527734SSukumar Swaminathan 421882527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 421982527734SSukumar Swaminathan wqe = &iocbq->wqe; 422082527734SSukumar Swaminathan wqe->un.Abort.Criteria = ABORT_XRI_TAG; 422182527734SSukumar Swaminathan wqe->un.Abort.IA = 1; 422282527734SSukumar Swaminathan wqe->RequestTag = abort_iotag; 422382527734SSukumar Swaminathan wqe->AbortTag = xid; 422482527734SSukumar Swaminathan wqe->Command = CMD_ABORT_XRI_CX; 422582527734SSukumar Swaminathan wqe->Class = CLASS3; 42268f23e9faSHans Rosenfeld wqe->CQId = (uint16_t)0xffff; /* default CQ for response */ 422782527734SSukumar Swaminathan wqe->CmdType = WQE_TYPE_ABORT; 422882527734SSukumar Swaminathan } else { 422982527734SSukumar Swaminathan iocb = &iocbq->iocb; 423082527734SSukumar Swaminathan iocb->ULPCONTEXT = xid; 423182527734SSukumar Swaminathan iocb->ULPIOTAG = abort_iotag; 423282527734SSukumar Swaminathan iocb->ULPLE = 1; 423382527734SSukumar Swaminathan iocb->ULPCLASS = 0; 423482527734SSukumar Swaminathan iocb->ULPCOMMAND = CMD_CLOSE_XRI_CX; 423582527734SSukumar Swaminathan iocb->ULPOWNER = OWN_CHIP; 4236fcf3ce44SJohn Forte } 4237291a2b48SSukumar Swaminathan 4238fcf3ce44SJohn Forte return (iocbq); 4239fcf3ce44SJohn Forte 424082527734SSukumar Swaminathan } /* emlxs_create_close_xri_cx() */ 4241fcf3ce44SJohn Forte 4242fcf3ce44SJohn Forte 4243a9800bebSGarrett D'Amore void 4244a9800bebSGarrett D'Amore emlxs_close_els_exchange(emlxs_hba_t *hba, emlxs_port_t *port, uint32_t rxid) 4245a9800bebSGarrett D'Amore { 4246a9800bebSGarrett D'Amore CHANNEL *cp; 4247a9800bebSGarrett D'Amore IOCBQ *iocbq; 4248a9800bebSGarrett D'Amore IOCB *iocb; 4249a9800bebSGarrett D'Amore 4250a9800bebSGarrett D'Amore if (rxid == 0 || rxid == 0xFFFF) { 4251a9800bebSGarrett D'Amore return; 4252a9800bebSGarrett D'Amore } 4253a9800bebSGarrett D'Amore 4254a9800bebSGarrett D'Amore if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 4255a9800bebSGarrett D'Amore EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 4256a9800bebSGarrett D'Amore "Closing ELS exchange: xid=%x", rxid); 4257a9800bebSGarrett D'Amore 42588f23e9faSHans Rosenfeld if (emlxs_sli4_unreserve_xri(port, rxid, 1) == 0) { 4259a9800bebSGarrett D'Amore return; 4260a9800bebSGarrett D'Amore } 4261a9800bebSGarrett D'Amore } 4262a9800bebSGarrett D'Amore 4263a9800bebSGarrett D'Amore cp = &hba->chan[hba->channel_els]; 4264a9800bebSGarrett D'Amore 4265a9800bebSGarrett D'Amore mutex_enter(&EMLXS_FCTAB_LOCK); 4266a9800bebSGarrett D'Amore 4267a9800bebSGarrett D'Amore /* Create the abort IOCB */ 4268a9800bebSGarrett D'Amore iocbq = emlxs_create_close_xri_cx(port, NULL, rxid, cp); 4269a9800bebSGarrett D'Amore 4270a9800bebSGarrett D'Amore mutex_exit(&EMLXS_FCTAB_LOCK); 4271a9800bebSGarrett D'Amore 4272a9800bebSGarrett D'Amore if (iocbq) { 4273a9800bebSGarrett D'Amore iocb = &iocbq->iocb; 4274a9800bebSGarrett D'Amore EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 42758f23e9faSHans Rosenfeld "Closing ELS exchange: xid=%x iotag=%d", rxid, 4276a9800bebSGarrett D'Amore iocb->ULPIOTAG); 4277a9800bebSGarrett D'Amore 4278a9800bebSGarrett D'Amore EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq); 4279a9800bebSGarrett D'Amore } 4280a9800bebSGarrett D'Amore 4281a9800bebSGarrett D'Amore } /* emlxs_close_els_exchange() */ 4282a9800bebSGarrett D'Amore 4283a9800bebSGarrett D'Amore 4284fe199829SSukumar Swaminathan void 4285fe199829SSukumar Swaminathan emlxs_abort_els_exchange(emlxs_hba_t *hba, emlxs_port_t *port, uint32_t rxid) 4286fe199829SSukumar Swaminathan { 4287fe199829SSukumar Swaminathan CHANNEL *cp; 4288fe199829SSukumar Swaminathan IOCBQ *iocbq; 4289fe199829SSukumar Swaminathan IOCB *iocb; 4290fe199829SSukumar Swaminathan 4291fe199829SSukumar Swaminathan if (rxid == 0 || rxid == 0xFFFF) { 4292fe199829SSukumar Swaminathan return; 4293fe199829SSukumar Swaminathan } 4294fe199829SSukumar Swaminathan 4295fe199829SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 4296fe199829SSukumar Swaminathan 4297fe199829SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 4298fe199829SSukumar Swaminathan "Aborting ELS exchange: xid=%x", rxid); 4299fe199829SSukumar Swaminathan 43008f23e9faSHans Rosenfeld if (emlxs_sli4_unreserve_xri(port, rxid, 1) == 0) { 4301fe199829SSukumar Swaminathan /* We have no way to abort unsolicited exchanges */ 4302fe199829SSukumar Swaminathan /* that we have not responded to at this time */ 4303fe199829SSukumar Swaminathan /* So we will return for now */ 4304fe199829SSukumar Swaminathan return; 4305fe199829SSukumar Swaminathan } 4306fe199829SSukumar Swaminathan } 4307fe199829SSukumar Swaminathan 4308fe199829SSukumar Swaminathan cp = &hba->chan[hba->channel_els]; 4309fe199829SSukumar Swaminathan 4310fe199829SSukumar Swaminathan mutex_enter(&EMLXS_FCTAB_LOCK); 4311fe199829SSukumar Swaminathan 4312fe199829SSukumar Swaminathan /* Create the abort IOCB */ 4313fe199829SSukumar Swaminathan if (hba->state >= FC_LINK_UP) { 4314fe199829SSukumar Swaminathan iocbq = emlxs_create_abort_xri_cx(port, NULL, rxid, cp, 4315fe199829SSukumar Swaminathan CLASS3, ABORT_TYPE_ABTS); 4316fe199829SSukumar Swaminathan } else { 4317fe199829SSukumar Swaminathan iocbq = emlxs_create_close_xri_cx(port, NULL, rxid, cp); 4318fe199829SSukumar Swaminathan } 4319fe199829SSukumar Swaminathan 4320fe199829SSukumar Swaminathan mutex_exit(&EMLXS_FCTAB_LOCK); 4321fe199829SSukumar Swaminathan 4322fe199829SSukumar Swaminathan if (iocbq) { 4323fe199829SSukumar Swaminathan iocb = &iocbq->iocb; 4324fe199829SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 43258f23e9faSHans Rosenfeld "Aborting ELS exchange: xid=%x iotag=%d", rxid, 4326fe199829SSukumar Swaminathan iocb->ULPIOTAG); 4327fe199829SSukumar Swaminathan 4328fe199829SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq); 4329fe199829SSukumar Swaminathan } 4330fe199829SSukumar Swaminathan 4331fe199829SSukumar Swaminathan } /* emlxs_abort_els_exchange() */ 4332fe199829SSukumar Swaminathan 4333fe199829SSukumar Swaminathan 4334728bdc9bSSukumar Swaminathan void 4335bb63f56eSSukumar Swaminathan emlxs_abort_ct_exchange(emlxs_hba_t *hba, emlxs_port_t *port, uint32_t rxid) 4336728bdc9bSSukumar Swaminathan { 433782527734SSukumar Swaminathan CHANNEL *cp; 4338728bdc9bSSukumar Swaminathan IOCBQ *iocbq; 4339fe199829SSukumar Swaminathan IOCB *iocb; 4340728bdc9bSSukumar Swaminathan 4341fe199829SSukumar Swaminathan if (rxid == 0 || rxid == 0xFFFF) { 4342fe199829SSukumar Swaminathan return; 4343fe199829SSukumar Swaminathan } 434482527734SSukumar Swaminathan 434582527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 4346fe199829SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_ct_msg, 4347fe199829SSukumar Swaminathan "Aborting CT exchange: xid=%x", rxid); 4348fe199829SSukumar Swaminathan 43498f23e9faSHans Rosenfeld if (emlxs_sli4_unreserve_xri(port, rxid, 1) == 0) { 435082527734SSukumar Swaminathan /* We have no way to abort unsolicited exchanges */ 435182527734SSukumar Swaminathan /* that we have not responded to at this time */ 435282527734SSukumar Swaminathan /* So we will return for now */ 435382527734SSukumar Swaminathan return; 435482527734SSukumar Swaminathan } 435582527734SSukumar Swaminathan } 435682527734SSukumar Swaminathan 435782527734SSukumar Swaminathan cp = &hba->chan[hba->channel_ct]; 4358728bdc9bSSukumar Swaminathan 4359fe199829SSukumar Swaminathan mutex_enter(&EMLXS_FCTAB_LOCK); 4360fe199829SSukumar Swaminathan 4361728bdc9bSSukumar Swaminathan /* Create the abort IOCB */ 4362728bdc9bSSukumar Swaminathan if (hba->state >= FC_LINK_UP) { 4363fe199829SSukumar Swaminathan iocbq = emlxs_create_abort_xri_cx(port, NULL, rxid, cp, 4364fe199829SSukumar Swaminathan CLASS3, ABORT_TYPE_ABTS); 4365291a2b48SSukumar Swaminathan } else { 436682527734SSukumar Swaminathan iocbq = emlxs_create_close_xri_cx(port, NULL, rxid, cp); 4367728bdc9bSSukumar Swaminathan } 436882527734SSukumar Swaminathan 4369fe199829SSukumar Swaminathan mutex_exit(&EMLXS_FCTAB_LOCK); 4370fe199829SSukumar Swaminathan 4371bb63f56eSSukumar Swaminathan if (iocbq) { 4372fe199829SSukumar Swaminathan iocb = &iocbq->iocb; 4373fe199829SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 43748f23e9faSHans Rosenfeld "Aborting CT exchange: xid=%x iotag=%d", rxid, 4375fe199829SSukumar Swaminathan iocb->ULPIOTAG); 4376fe199829SSukumar Swaminathan 437782527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq); 4378bb63f56eSSukumar Swaminathan } 437982527734SSukumar Swaminathan 438082527734SSukumar Swaminathan } /* emlxs_abort_ct_exchange() */ 4381728bdc9bSSukumar Swaminathan 4382fcf3ce44SJohn Forte 4383fe199829SSukumar Swaminathan /* This must be called while holding the EMLXS_FCTAB_LOCK */ 4384fcf3ce44SJohn Forte static void 4385fcf3ce44SJohn Forte emlxs_sbp_abort_add(emlxs_port_t *port, emlxs_buf_t *sbp, Q *abort, 4386fcf3ce44SJohn Forte uint8_t *flag, emlxs_buf_t *fpkt) 4387fcf3ce44SJohn Forte { 4388fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 4389fcf3ce44SJohn Forte IOCBQ *iocbq; 439082527734SSukumar Swaminathan CHANNEL *cp; 4391fcf3ce44SJohn Forte NODELIST *ndlp; 4392fcf3ce44SJohn Forte 439382527734SSukumar Swaminathan cp = (CHANNEL *)sbp->channel; 4394fcf3ce44SJohn Forte ndlp = sbp->node; 4395fcf3ce44SJohn Forte 4396fcf3ce44SJohn Forte /* Create the close XRI IOCB */ 4397a9800bebSGarrett D'Amore if (hba->state >= FC_LINK_UP) { 4398a9800bebSGarrett D'Amore iocbq = emlxs_create_abort_xri_cn(port, ndlp, sbp->iotag, cp, 4399a9800bebSGarrett D'Amore CLASS3, ABORT_TYPE_ABTS); 4400a9800bebSGarrett D'Amore } else { 4401a9800bebSGarrett D'Amore iocbq = emlxs_create_close_xri_cn(port, ndlp, sbp->iotag, cp); 4402a9800bebSGarrett D'Amore } 4403291a2b48SSukumar Swaminathan /* 4404291a2b48SSukumar Swaminathan * Add this iocb to our local abort Q 4405291a2b48SSukumar Swaminathan * This way we don't hold the CHIPQ lock too long 4406291a2b48SSukumar Swaminathan */ 4407fcf3ce44SJohn Forte if (iocbq) { 4408fcf3ce44SJohn Forte if (abort->q_first) { 4409291a2b48SSukumar Swaminathan ((IOCBQ *)abort->q_last)->next = iocbq; 4410fcf3ce44SJohn Forte abort->q_last = (uint8_t *)iocbq; 4411fcf3ce44SJohn Forte abort->q_cnt++; 4412fcf3ce44SJohn Forte } else { 4413fcf3ce44SJohn Forte abort->q_first = (uint8_t *)iocbq; 4414fcf3ce44SJohn Forte abort->q_last = (uint8_t *)iocbq; 4415fcf3ce44SJohn Forte abort->q_cnt = 1; 4416fcf3ce44SJohn Forte } 4417fcf3ce44SJohn Forte iocbq->next = NULL; 4418fcf3ce44SJohn Forte } 4419291a2b48SSukumar Swaminathan 4420fcf3ce44SJohn Forte /* set the flags */ 4421fcf3ce44SJohn Forte mutex_enter(&sbp->mtx); 4422fcf3ce44SJohn Forte 4423fcf3ce44SJohn Forte sbp->pkt_flags |= (PACKET_IN_FLUSH | PACKET_XRI_CLOSED); 442482527734SSukumar Swaminathan 4425fcf3ce44SJohn Forte sbp->ticks = hba->timer_tics + 10; 4426fcf3ce44SJohn Forte sbp->abort_attempts++; 4427fcf3ce44SJohn Forte 442882527734SSukumar Swaminathan flag[cp->channelno] = 1; 4429fcf3ce44SJohn Forte 4430fcf3ce44SJohn Forte /* 4431291a2b48SSukumar Swaminathan * If the fpkt is already set, then we will leave it alone 4432fcf3ce44SJohn Forte * This ensures that this pkt is only accounted for on one 4433fcf3ce44SJohn Forte * fpkt->flush_count 4434fcf3ce44SJohn Forte */ 4435fcf3ce44SJohn Forte if (!sbp->fpkt && fpkt) { 4436fcf3ce44SJohn Forte mutex_enter(&fpkt->mtx); 4437fcf3ce44SJohn Forte sbp->fpkt = fpkt; 4438fcf3ce44SJohn Forte fpkt->flush_count++; 4439fcf3ce44SJohn Forte mutex_exit(&fpkt->mtx); 4440fcf3ce44SJohn Forte } 4441291a2b48SSukumar Swaminathan 4442fcf3ce44SJohn Forte mutex_exit(&sbp->mtx); 4443fcf3ce44SJohn Forte 4444fcf3ce44SJohn Forte return; 4445fcf3ce44SJohn Forte 444682527734SSukumar Swaminathan } /* emlxs_sbp_abort_add() */ 4447