1fcf3ce44SJohn Forte /* 2fcf3ce44SJohn Forte * CDDL HEADER START 3fcf3ce44SJohn Forte * 4fcf3ce44SJohn Forte * The contents of this file are subject to the terms of the 5fcf3ce44SJohn Forte * Common Development and Distribution License (the "License"). 6fcf3ce44SJohn Forte * You may not use this file except in compliance with the License. 7fcf3ce44SJohn Forte * 8fcf3ce44SJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9fcf3ce44SJohn Forte * or http://www.opensolaris.org/os/licensing. 10fcf3ce44SJohn Forte * See the License for the specific language governing permissions 11fcf3ce44SJohn Forte * and limitations under the License. 12fcf3ce44SJohn Forte * 13fcf3ce44SJohn Forte * When distributing Covered Code, include this CDDL HEADER in each 14fcf3ce44SJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15fcf3ce44SJohn Forte * If applicable, add the following below this CDDL HEADER, with the 16fcf3ce44SJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying 17fcf3ce44SJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner] 18fcf3ce44SJohn Forte * 19fcf3ce44SJohn Forte * CDDL HEADER END 20fcf3ce44SJohn Forte */ 21fcf3ce44SJohn Forte 22c1fad183SDaniel Beauregard /* Copyright 2010 QLogic Corporation */ 23fcf3ce44SJohn Forte 24fcf3ce44SJohn Forte /* 25*f885d00fSDaniel Beauregard * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 26fcf3ce44SJohn Forte */ 27fcf3ce44SJohn Forte 28c1fad183SDaniel Beauregard #pragma ident "Copyright 2010 QLogic Corporation; ql_isr.c" 29fcf3ce44SJohn Forte 30fcf3ce44SJohn Forte /* 31fcf3ce44SJohn Forte * ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file. 32fcf3ce44SJohn Forte * 33fcf3ce44SJohn Forte * *********************************************************************** 34fcf3ce44SJohn Forte * * ** 35fcf3ce44SJohn Forte * * NOTICE ** 36c1fad183SDaniel Beauregard * * COPYRIGHT (C) 1996-2010 QLOGIC CORPORATION ** 37fcf3ce44SJohn Forte * * ALL RIGHTS RESERVED ** 38fcf3ce44SJohn Forte * * ** 39fcf3ce44SJohn Forte * *********************************************************************** 40fcf3ce44SJohn Forte * 41fcf3ce44SJohn Forte */ 42fcf3ce44SJohn Forte 43fcf3ce44SJohn Forte #include <ql_apps.h> 44fcf3ce44SJohn Forte #include <ql_api.h> 45fcf3ce44SJohn Forte #include <ql_debug.h> 46fcf3ce44SJohn Forte #include <ql_iocb.h> 47fcf3ce44SJohn Forte #include <ql_isr.h> 48fcf3ce44SJohn Forte #include <ql_init.h> 49fcf3ce44SJohn Forte #include <ql_mbx.h> 50eb82ff87SDaniel Beauregard #include <ql_nx.h> 51fcf3ce44SJohn Forte #include <ql_xioctl.h> 52fcf3ce44SJohn Forte 53fcf3ce44SJohn Forte /* 54fcf3ce44SJohn Forte * Local Function Prototypes. 55fcf3ce44SJohn Forte */ 5616dd44c2SDaniel Beauregard static void ql_handle_uncommon_risc_intr(ql_adapter_state_t *, uint32_t, 5716dd44c2SDaniel Beauregard uint32_t *); 58fcf3ce44SJohn Forte static void ql_spurious_intr(ql_adapter_state_t *, int); 59fcf3ce44SJohn Forte static void ql_mbx_completion(ql_adapter_state_t *, uint16_t, uint32_t *, 60fcf3ce44SJohn Forte uint32_t *, int); 61fcf3ce44SJohn Forte static void ql_async_event(ql_adapter_state_t *, uint32_t, ql_head_t *, 62fcf3ce44SJohn Forte uint32_t *, uint32_t *, int); 63fcf3ce44SJohn Forte static void ql_fast_fcp_post(ql_srb_t *); 64fcf3ce44SJohn Forte static void ql_response_pkt(ql_adapter_state_t *, ql_head_t *, uint32_t *, 65fcf3ce44SJohn Forte uint32_t *, int); 66fcf3ce44SJohn Forte static void ql_error_entry(ql_adapter_state_t *, response_t *, ql_head_t *, 67fcf3ce44SJohn Forte uint32_t *, uint32_t *); 68fcf3ce44SJohn Forte static int ql_status_entry(ql_adapter_state_t *, sts_entry_t *, ql_head_t *, 69fcf3ce44SJohn Forte uint32_t *, uint32_t *); 70fcf3ce44SJohn Forte static int ql_24xx_status_entry(ql_adapter_state_t *, sts_24xx_entry_t *, 71fcf3ce44SJohn Forte ql_head_t *, uint32_t *, uint32_t *); 72fcf3ce44SJohn Forte static int ql_status_error(ql_adapter_state_t *, ql_srb_t *, sts_entry_t *, 73fcf3ce44SJohn Forte ql_head_t *, uint32_t *, uint32_t *); 74fcf3ce44SJohn Forte static void ql_status_cont_entry(ql_adapter_state_t *, sts_cont_entry_t *, 75fcf3ce44SJohn Forte ql_head_t *, uint32_t *, uint32_t *); 76fcf3ce44SJohn Forte static void ql_ip_entry(ql_adapter_state_t *, ip_entry_t *, ql_head_t *, 77fcf3ce44SJohn Forte uint32_t *, uint32_t *); 78fcf3ce44SJohn Forte static void ql_ip_rcv_entry(ql_adapter_state_t *, ip_rcv_entry_t *, 79fcf3ce44SJohn Forte ql_head_t *, uint32_t *, uint32_t *); 80fcf3ce44SJohn Forte static void ql_ip_rcv_cont_entry(ql_adapter_state_t *, 81fcf3ce44SJohn Forte ip_rcv_cont_entry_t *, ql_head_t *, uint32_t *, uint32_t *); 82fcf3ce44SJohn Forte static void ql_ip_24xx_rcv_entry(ql_adapter_state_t *, ip_rcv_24xx_entry_t *, 83fcf3ce44SJohn Forte ql_head_t *, uint32_t *, uint32_t *); 84fcf3ce44SJohn Forte static void ql_ms_entry(ql_adapter_state_t *, ms_entry_t *, ql_head_t *, 85fcf3ce44SJohn Forte uint32_t *, uint32_t *); 86fcf3ce44SJohn Forte static void ql_report_id_entry(ql_adapter_state_t *, report_id_1_t *, 87fcf3ce44SJohn Forte ql_head_t *, uint32_t *, uint32_t *); 885dfd244aSDaniel Beauregard static void ql_els_passthru_entry(ql_adapter_state_t *, 895dfd244aSDaniel Beauregard els_passthru_entry_rsp_t *, ql_head_t *, uint32_t *, uint32_t *); 90a2b3ff35SDaniel Beauregard static ql_srb_t *ql_verify_preprocessed_cmd(ql_adapter_state_t *, uint32_t *, 91a2b3ff35SDaniel Beauregard uint32_t *, uint32_t *); 92a2b3ff35SDaniel Beauregard static void ql_signal_abort(ql_adapter_state_t *ha, uint32_t *set_flags); 93fcf3ce44SJohn Forte 94*f885d00fSDaniel Beauregard /* 95*f885d00fSDaniel Beauregard * Spurious interrupt counter 96*f885d00fSDaniel Beauregard */ 97*f885d00fSDaniel Beauregard uint32_t ql_spurious_cnt = 4; 98*f885d00fSDaniel Beauregard uint32_t ql_max_intr_loop = 16; 99*f885d00fSDaniel Beauregard 100fcf3ce44SJohn Forte /* 101fcf3ce44SJohn Forte * ql_isr 102fcf3ce44SJohn Forte * Process all INTX intr types. 103fcf3ce44SJohn Forte * 104fcf3ce44SJohn Forte * Input: 105fcf3ce44SJohn Forte * arg1: adapter state pointer. 106fcf3ce44SJohn Forte * 107fcf3ce44SJohn Forte * Returns: 108fcf3ce44SJohn Forte * DDI_INTR_CLAIMED or DDI_INTR_UNCLAIMED 109fcf3ce44SJohn Forte * 110fcf3ce44SJohn Forte * Context: 111fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 112fcf3ce44SJohn Forte */ 113fcf3ce44SJohn Forte /* ARGSUSED */ 114fcf3ce44SJohn Forte uint_t 115fcf3ce44SJohn Forte ql_isr(caddr_t arg1) 116fcf3ce44SJohn Forte { 117fcf3ce44SJohn Forte return (ql_isr_aif(arg1, 0)); 118fcf3ce44SJohn Forte } 119fcf3ce44SJohn Forte 120fcf3ce44SJohn Forte /* 121fcf3ce44SJohn Forte * ql_isr_default 122fcf3ce44SJohn Forte * Process unknown/unvectored intr types 123fcf3ce44SJohn Forte * 124fcf3ce44SJohn Forte * Input: 125fcf3ce44SJohn Forte * arg1: adapter state pointer. 126fcf3ce44SJohn Forte * arg2: interrupt vector. 127fcf3ce44SJohn Forte * 128fcf3ce44SJohn Forte * Returns: 129fcf3ce44SJohn Forte * DDI_INTR_CLAIMED or DDI_INTR_UNCLAIMED 130fcf3ce44SJohn Forte * 131fcf3ce44SJohn Forte * Context: 132fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 133fcf3ce44SJohn Forte */ 134fcf3ce44SJohn Forte /* ARGSUSED */ 135fcf3ce44SJohn Forte uint_t 136fcf3ce44SJohn Forte ql_isr_default(caddr_t arg1, caddr_t arg2) 137fcf3ce44SJohn Forte { 138fcf3ce44SJohn Forte ql_adapter_state_t *ha = (void *)arg1; 139fcf3ce44SJohn Forte 140fcf3ce44SJohn Forte EL(ha, "isr_default called: idx=%x\n", arg2); 141fcf3ce44SJohn Forte return (ql_isr_aif(arg1, arg2)); 142fcf3ce44SJohn Forte } 143fcf3ce44SJohn Forte 144fcf3ce44SJohn Forte /* 145fcf3ce44SJohn Forte * ql_isr_aif 146fcf3ce44SJohn Forte * Process mailbox and I/O command completions. 147fcf3ce44SJohn Forte * 148fcf3ce44SJohn Forte * Input: 149fcf3ce44SJohn Forte * arg: adapter state pointer. 150fcf3ce44SJohn Forte * intvec: interrupt vector. 151fcf3ce44SJohn Forte * 152fcf3ce44SJohn Forte * Returns: 153fcf3ce44SJohn Forte * DDI_INTR_CLAIMED or DDI_INTR_UNCLAIMED 154fcf3ce44SJohn Forte * 155fcf3ce44SJohn Forte * Context: 156fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 157fcf3ce44SJohn Forte */ 158fcf3ce44SJohn Forte /* ARGSUSED */ 159fcf3ce44SJohn Forte uint_t 160fcf3ce44SJohn Forte ql_isr_aif(caddr_t arg, caddr_t intvec) 161fcf3ce44SJohn Forte { 162fcf3ce44SJohn Forte uint16_t mbx; 163fcf3ce44SJohn Forte uint32_t stat; 164fcf3ce44SJohn Forte ql_adapter_state_t *ha = (void *)arg; 165fcf3ce44SJohn Forte uint32_t set_flags = 0; 166fcf3ce44SJohn Forte uint32_t reset_flags = 0; 167fcf3ce44SJohn Forte ql_head_t isr_done_q = {NULL, NULL}; 168fcf3ce44SJohn Forte uint_t rval = DDI_INTR_UNCLAIMED; 169fcf3ce44SJohn Forte int spurious_intr = 0; 170fcf3ce44SJohn Forte boolean_t intr = B_FALSE, daemon = B_FALSE; 171fcf3ce44SJohn Forte int intr_loop = 4; 172*f885d00fSDaniel Beauregard boolean_t clear_spurious = B_TRUE; 173fcf3ce44SJohn Forte 174fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 175fcf3ce44SJohn Forte 176fcf3ce44SJohn Forte QL_PM_LOCK(ha); 177fcf3ce44SJohn Forte if (ha->power_level != PM_LEVEL_D0) { 178fcf3ce44SJohn Forte /* 179fcf3ce44SJohn Forte * Looks like we are about to go down soon, exit early. 180fcf3ce44SJohn Forte */ 181fcf3ce44SJohn Forte QL_PM_UNLOCK(ha); 182fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): power down exit\n", ha->instance); 183fcf3ce44SJohn Forte return (DDI_INTR_UNCLAIMED); 184fcf3ce44SJohn Forte } 185fcf3ce44SJohn Forte ha->busy++; 186fcf3ce44SJohn Forte QL_PM_UNLOCK(ha); 187fcf3ce44SJohn Forte 188fcf3ce44SJohn Forte /* Acquire interrupt lock. */ 189fcf3ce44SJohn Forte INTR_LOCK(ha); 190fcf3ce44SJohn Forte 191fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_CTRL_2200)) { 192fcf3ce44SJohn Forte while (RD16_IO_REG(ha, istatus) & RISC_INT) { 193fcf3ce44SJohn Forte /* Reset idle timer. */ 194fcf3ce44SJohn Forte ha->idle_timer = 0; 195fcf3ce44SJohn Forte rval = DDI_INTR_CLAIMED; 196fcf3ce44SJohn Forte if (intr_loop) { 197fcf3ce44SJohn Forte intr_loop--; 198fcf3ce44SJohn Forte } 199fcf3ce44SJohn Forte 200fcf3ce44SJohn Forte /* Special Fast Post 2200. */ 201fcf3ce44SJohn Forte stat = 0; 202fcf3ce44SJohn Forte if (ha->task_daemon_flags & FIRMWARE_LOADED && 203fcf3ce44SJohn Forte ha->flags & ONLINE) { 204fcf3ce44SJohn Forte ql_srb_t *sp; 205fcf3ce44SJohn Forte 206eb82ff87SDaniel Beauregard mbx = RD16_IO_REG(ha, mailbox_out[23]); 207fcf3ce44SJohn Forte 208fcf3ce44SJohn Forte if ((mbx & 3) == MBX23_SCSI_COMPLETION) { 209fcf3ce44SJohn Forte /* Release mailbox registers. */ 210fcf3ce44SJohn Forte WRT16_IO_REG(ha, semaphore, 0); 211fcf3ce44SJohn Forte 212fcf3ce44SJohn Forte if (intr_loop) { 213fcf3ce44SJohn Forte WRT16_IO_REG(ha, hccr, 214fcf3ce44SJohn Forte HC_CLR_RISC_INT); 215fcf3ce44SJohn Forte } 216fcf3ce44SJohn Forte 217fcf3ce44SJohn Forte /* Get handle. */ 218fcf3ce44SJohn Forte mbx >>= 4; 219fcf3ce44SJohn Forte stat = mbx & OSC_INDEX_MASK; 220fcf3ce44SJohn Forte 221fcf3ce44SJohn Forte /* Validate handle. */ 222fcf3ce44SJohn Forte sp = stat < MAX_OUTSTANDING_COMMANDS ? 223fcf3ce44SJohn Forte ha->outstanding_cmds[stat] : NULL; 224fcf3ce44SJohn Forte 225fcf3ce44SJohn Forte if (sp != NULL && (sp->handle & 0xfff) 226fcf3ce44SJohn Forte == mbx) { 227fcf3ce44SJohn Forte ha->outstanding_cmds[stat] = 228fcf3ce44SJohn Forte NULL; 229fcf3ce44SJohn Forte sp->handle = 0; 230fcf3ce44SJohn Forte sp->flags &= 231fcf3ce44SJohn Forte ~SRB_IN_TOKEN_ARRAY; 232fcf3ce44SJohn Forte 233fcf3ce44SJohn Forte /* Set completed status. */ 234fcf3ce44SJohn Forte sp->flags |= SRB_ISP_COMPLETED; 235fcf3ce44SJohn Forte 236fcf3ce44SJohn Forte /* Set completion status */ 237fcf3ce44SJohn Forte sp->pkt->pkt_reason = 238fcf3ce44SJohn Forte CS_COMPLETE; 239fcf3ce44SJohn Forte 240fcf3ce44SJohn Forte ql_fast_fcp_post(sp); 241fcf3ce44SJohn Forte } else if (mbx != 242fcf3ce44SJohn Forte (QL_FCA_BRAND & 0xfff)) { 243fcf3ce44SJohn Forte if (sp == NULL) { 244fcf3ce44SJohn Forte EL(ha, "unknown IOCB" 245fcf3ce44SJohn Forte " handle=%xh\n", 246fcf3ce44SJohn Forte mbx); 247fcf3ce44SJohn Forte } else { 248fcf3ce44SJohn Forte EL(ha, "mismatch IOCB" 249fcf3ce44SJohn Forte " handle pkt=%xh, " 250fcf3ce44SJohn Forte "sp=%xh\n", mbx, 251fcf3ce44SJohn Forte sp->handle & 0xfff); 252fcf3ce44SJohn Forte } 253fcf3ce44SJohn Forte 254fcf3ce44SJohn Forte (void) ql_binary_fw_dump(ha, 255fcf3ce44SJohn Forte FALSE); 256fcf3ce44SJohn Forte 257fcf3ce44SJohn Forte if (!(ha->task_daemon_flags & 258fcf3ce44SJohn Forte (ISP_ABORT_NEEDED | 259fcf3ce44SJohn Forte ABORT_ISP_ACTIVE))) { 260fcf3ce44SJohn Forte EL(ha, "ISP Invalid " 261fcf3ce44SJohn Forte "handle, " 262fcf3ce44SJohn Forte "isp_abort_needed" 263fcf3ce44SJohn Forte "\n"); 264fcf3ce44SJohn Forte set_flags |= 265fcf3ce44SJohn Forte ISP_ABORT_NEEDED; 266fcf3ce44SJohn Forte } 267fcf3ce44SJohn Forte } 268fcf3ce44SJohn Forte } 269fcf3ce44SJohn Forte } 270fcf3ce44SJohn Forte 271fcf3ce44SJohn Forte if (stat == 0) { 272fcf3ce44SJohn Forte /* Check for mailbox interrupt. */ 273fcf3ce44SJohn Forte mbx = RD16_IO_REG(ha, semaphore); 274fcf3ce44SJohn Forte if (mbx & BIT_0) { 275fcf3ce44SJohn Forte /* Release mailbox registers. */ 276fcf3ce44SJohn Forte WRT16_IO_REG(ha, semaphore, 0); 277fcf3ce44SJohn Forte 278fcf3ce44SJohn Forte /* Get mailbox data. */ 279eb82ff87SDaniel Beauregard mbx = RD16_IO_REG(ha, mailbox_out[0]); 280fcf3ce44SJohn Forte if (mbx > 0x3fff && mbx < 0x8000) { 281fcf3ce44SJohn Forte ql_mbx_completion(ha, mbx, 282fcf3ce44SJohn Forte &set_flags, &reset_flags, 283fcf3ce44SJohn Forte intr_loop); 284fcf3ce44SJohn Forte } else if (mbx > 0x7fff && 285fcf3ce44SJohn Forte mbx < 0xc000) { 286fcf3ce44SJohn Forte ql_async_event(ha, mbx, 287fcf3ce44SJohn Forte &isr_done_q, &set_flags, 288fcf3ce44SJohn Forte &reset_flags, intr_loop); 289fcf3ce44SJohn Forte } else { 290fcf3ce44SJohn Forte EL(ha, "UNKNOWN interrupt " 291fcf3ce44SJohn Forte "type\n"); 292fcf3ce44SJohn Forte intr = B_TRUE; 293fcf3ce44SJohn Forte } 294fcf3ce44SJohn Forte } else { 295fcf3ce44SJohn Forte ha->isp_rsp_index = RD16_IO_REG(ha, 296fcf3ce44SJohn Forte resp_in); 297fcf3ce44SJohn Forte 298fcf3ce44SJohn Forte if (ha->isp_rsp_index != 299fcf3ce44SJohn Forte ha->rsp_ring_index) { 300fcf3ce44SJohn Forte ql_response_pkt(ha, 301fcf3ce44SJohn Forte &isr_done_q, &set_flags, 302fcf3ce44SJohn Forte &reset_flags, intr_loop); 303fcf3ce44SJohn Forte } else if (++spurious_intr == 304fcf3ce44SJohn Forte MAX_SPURIOUS_INTR) { 305fcf3ce44SJohn Forte /* 306fcf3ce44SJohn Forte * Process excessive 307fcf3ce44SJohn Forte * spurious intrrupts 308fcf3ce44SJohn Forte */ 309fcf3ce44SJohn Forte ql_spurious_intr(ha, 310fcf3ce44SJohn Forte intr_loop); 311fcf3ce44SJohn Forte EL(ha, "excessive spurious " 312fcf3ce44SJohn Forte "interrupts, " 313fcf3ce44SJohn Forte "isp_abort_needed\n"); 314fcf3ce44SJohn Forte set_flags |= ISP_ABORT_NEEDED; 315fcf3ce44SJohn Forte } else { 316fcf3ce44SJohn Forte intr = B_TRUE; 317fcf3ce44SJohn Forte } 318fcf3ce44SJohn Forte } 319fcf3ce44SJohn Forte } 320fcf3ce44SJohn Forte 321fcf3ce44SJohn Forte /* Clear RISC interrupt */ 322fcf3ce44SJohn Forte if (intr || intr_loop == 0) { 323fcf3ce44SJohn Forte intr = B_FALSE; 324fcf3ce44SJohn Forte WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT); 325fcf3ce44SJohn Forte } 326fcf3ce44SJohn Forte 327fcf3ce44SJohn Forte if (set_flags != 0 || reset_flags != 0) { 328fcf3ce44SJohn Forte TASK_DAEMON_LOCK(ha); 329fcf3ce44SJohn Forte ha->task_daemon_flags |= set_flags; 330fcf3ce44SJohn Forte ha->task_daemon_flags &= ~reset_flags; 331fcf3ce44SJohn Forte TASK_DAEMON_UNLOCK(ha); 332fcf3ce44SJohn Forte set_flags = 0; 333fcf3ce44SJohn Forte reset_flags = 0; 334fcf3ce44SJohn Forte daemon = B_TRUE; 335fcf3ce44SJohn Forte } 336fcf3ce44SJohn Forte } 337fcf3ce44SJohn Forte } else { 338*f885d00fSDaniel Beauregard uint32_t ql_max_intr_loop_cnt = 0; 339*f885d00fSDaniel Beauregard 340eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_8021)) { 341eb82ff87SDaniel Beauregard ql_8021_clr_hw_intr(ha); 342*f885d00fSDaniel Beauregard intr_loop = 1; 343eb82ff87SDaniel Beauregard } 344*f885d00fSDaniel Beauregard while (((stat = RD32_IO_REG(ha, risc2host)) & RH_RISC_INT) && 345*f885d00fSDaniel Beauregard (++ql_max_intr_loop_cnt < ql_max_intr_loop)) { 346*f885d00fSDaniel Beauregard 347*f885d00fSDaniel Beauregard clear_spurious = B_TRUE; /* assume ok */ 348*f885d00fSDaniel Beauregard 34916dd44c2SDaniel Beauregard /* Capture FW defined interrupt info */ 350fcf3ce44SJohn Forte mbx = MSW(stat); 351fcf3ce44SJohn Forte 352fcf3ce44SJohn Forte /* Reset idle timer. */ 353fcf3ce44SJohn Forte ha->idle_timer = 0; 354fcf3ce44SJohn Forte rval = DDI_INTR_CLAIMED; 355eb82ff87SDaniel Beauregard 356eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_8021) && 357*f885d00fSDaniel Beauregard (RD32_IO_REG(ha, nx_risc_int) == 0 || 358*f885d00fSDaniel Beauregard intr_loop == 0)) { 359eb82ff87SDaniel Beauregard break; 360eb82ff87SDaniel Beauregard } 361eb82ff87SDaniel Beauregard 362fcf3ce44SJohn Forte if (intr_loop) { 363fcf3ce44SJohn Forte intr_loop--; 364fcf3ce44SJohn Forte } 365fcf3ce44SJohn Forte 366fcf3ce44SJohn Forte switch (stat & 0x1ff) { 367fcf3ce44SJohn Forte case ROM_MBX_SUCCESS: 368fcf3ce44SJohn Forte case ROM_MBX_ERR: 369fcf3ce44SJohn Forte ql_mbx_completion(ha, mbx, &set_flags, 370fcf3ce44SJohn Forte &reset_flags, intr_loop); 371fcf3ce44SJohn Forte 372fcf3ce44SJohn Forte /* Release mailbox registers. */ 373eb82ff87SDaniel Beauregard if ((CFG_IST(ha, CFG_CTRL_24258081)) == 0) { 374fcf3ce44SJohn Forte WRT16_IO_REG(ha, semaphore, 0); 375fcf3ce44SJohn Forte } 376fcf3ce44SJohn Forte break; 377fcf3ce44SJohn Forte 378fcf3ce44SJohn Forte case MBX_SUCCESS: 379fcf3ce44SJohn Forte case MBX_ERR: 380fcf3ce44SJohn Forte /* Sun FW, Release mailbox registers. */ 381eb82ff87SDaniel Beauregard if ((CFG_IST(ha, CFG_CTRL_24258081)) == 0) { 382fcf3ce44SJohn Forte WRT16_IO_REG(ha, semaphore, 0); 383fcf3ce44SJohn Forte } 384fcf3ce44SJohn Forte ql_mbx_completion(ha, mbx, &set_flags, 385fcf3ce44SJohn Forte &reset_flags, intr_loop); 386fcf3ce44SJohn Forte break; 387fcf3ce44SJohn Forte 388fcf3ce44SJohn Forte case ASYNC_EVENT: 389fcf3ce44SJohn Forte /* Sun FW, Release mailbox registers. */ 390eb82ff87SDaniel Beauregard if ((CFG_IST(ha, CFG_CTRL_24258081)) == 0) { 391fcf3ce44SJohn Forte WRT16_IO_REG(ha, semaphore, 0); 392fcf3ce44SJohn Forte } 393fcf3ce44SJohn Forte ql_async_event(ha, (uint32_t)mbx, &isr_done_q, 394fcf3ce44SJohn Forte &set_flags, &reset_flags, intr_loop); 395fcf3ce44SJohn Forte break; 396fcf3ce44SJohn Forte 397fcf3ce44SJohn Forte case RESP_UPDATE: 398fcf3ce44SJohn Forte if (mbx != ha->rsp_ring_index) { 399fcf3ce44SJohn Forte ha->isp_rsp_index = mbx; 400fcf3ce44SJohn Forte ql_response_pkt(ha, &isr_done_q, 401fcf3ce44SJohn Forte &set_flags, &reset_flags, 402fcf3ce44SJohn Forte intr_loop); 403fcf3ce44SJohn Forte } else if (++spurious_intr == 404*f885d00fSDaniel Beauregard ql_spurious_cnt) { 405fcf3ce44SJohn Forte /* Process excessive spurious intr. */ 406fcf3ce44SJohn Forte ql_spurious_intr(ha, intr_loop); 407fcf3ce44SJohn Forte EL(ha, "excessive spurious " 408fcf3ce44SJohn Forte "interrupts, isp_abort_needed\n"); 409fcf3ce44SJohn Forte set_flags |= ISP_ABORT_NEEDED; 410*f885d00fSDaniel Beauregard clear_spurious = B_FALSE; 411fcf3ce44SJohn Forte } else { 412*f885d00fSDaniel Beauregard QL_PRINT_10(CE_CONT, "(%d): response " 413*f885d00fSDaniel Beauregard "ring index same as before\n", 414*f885d00fSDaniel Beauregard ha->instance); 415fcf3ce44SJohn Forte intr = B_TRUE; 416*f885d00fSDaniel Beauregard clear_spurious = B_FALSE; 417fcf3ce44SJohn Forte } 418fcf3ce44SJohn Forte break; 419fcf3ce44SJohn Forte 420fcf3ce44SJohn Forte case SCSI_FAST_POST_16: 421fcf3ce44SJohn Forte stat = (stat & 0xffff0000) | MBA_CMPLT_1_16BIT; 422fcf3ce44SJohn Forte ql_async_event(ha, stat, &isr_done_q, 423fcf3ce44SJohn Forte &set_flags, &reset_flags, intr_loop); 424fcf3ce44SJohn Forte break; 425fcf3ce44SJohn Forte 426fcf3ce44SJohn Forte case SCSI_FAST_POST_32: 427fcf3ce44SJohn Forte stat = (stat & 0xffff0000) | MBA_CMPLT_1_32BIT; 428fcf3ce44SJohn Forte ql_async_event(ha, stat, &isr_done_q, 429fcf3ce44SJohn Forte &set_flags, &reset_flags, intr_loop); 430fcf3ce44SJohn Forte break; 431fcf3ce44SJohn Forte 432fcf3ce44SJohn Forte case CTIO_FAST_POST: 433fcf3ce44SJohn Forte stat = (stat & 0xffff0000) | 434fcf3ce44SJohn Forte MBA_CTIO_COMPLETION; 435fcf3ce44SJohn Forte ql_async_event(ha, stat, &isr_done_q, 436fcf3ce44SJohn Forte &set_flags, &reset_flags, intr_loop); 437fcf3ce44SJohn Forte break; 438fcf3ce44SJohn Forte 439fcf3ce44SJohn Forte case IP_FAST_POST_XMT: 440fcf3ce44SJohn Forte stat = (stat & 0xffff0000) | MBA_IP_COMPLETION; 441fcf3ce44SJohn Forte ql_async_event(ha, stat, &isr_done_q, 442fcf3ce44SJohn Forte &set_flags, &reset_flags, intr_loop); 443fcf3ce44SJohn Forte break; 444fcf3ce44SJohn Forte 445fcf3ce44SJohn Forte case IP_FAST_POST_RCV: 446fcf3ce44SJohn Forte stat = (stat & 0xffff0000) | MBA_IP_RECEIVE; 447fcf3ce44SJohn Forte ql_async_event(ha, stat, &isr_done_q, 448fcf3ce44SJohn Forte &set_flags, &reset_flags, intr_loop); 449fcf3ce44SJohn Forte break; 450fcf3ce44SJohn Forte 451fcf3ce44SJohn Forte case IP_FAST_POST_BRD: 452fcf3ce44SJohn Forte stat = (stat & 0xffff0000) | MBA_IP_BROADCAST; 453fcf3ce44SJohn Forte ql_async_event(ha, stat, &isr_done_q, 454fcf3ce44SJohn Forte &set_flags, &reset_flags, intr_loop); 455fcf3ce44SJohn Forte break; 456fcf3ce44SJohn Forte 457fcf3ce44SJohn Forte case IP_FAST_POST_RCV_ALN: 458fcf3ce44SJohn Forte stat = (stat & 0xffff0000) | 459fcf3ce44SJohn Forte MBA_IP_HDR_DATA_SPLIT; 460fcf3ce44SJohn Forte ql_async_event(ha, stat, &isr_done_q, 461fcf3ce44SJohn Forte &set_flags, &reset_flags, intr_loop); 462fcf3ce44SJohn Forte break; 463fcf3ce44SJohn Forte 464fcf3ce44SJohn Forte case ATIO_UPDATE: 465fcf3ce44SJohn Forte EL(ha, "unsupported ATIO queue update" 466fcf3ce44SJohn Forte " interrupt, status=%xh\n", stat); 467fcf3ce44SJohn Forte intr = B_TRUE; 468fcf3ce44SJohn Forte break; 469fcf3ce44SJohn Forte 470fcf3ce44SJohn Forte case ATIO_RESP_UPDATE: 471fcf3ce44SJohn Forte EL(ha, "unsupported ATIO response queue " 472fcf3ce44SJohn Forte "update interrupt, status=%xh\n", stat); 473fcf3ce44SJohn Forte intr = B_TRUE; 474fcf3ce44SJohn Forte break; 475fcf3ce44SJohn Forte 476fcf3ce44SJohn Forte default: 47716dd44c2SDaniel Beauregard ql_handle_uncommon_risc_intr(ha, stat, 47816dd44c2SDaniel Beauregard &set_flags); 479fcf3ce44SJohn Forte intr = B_TRUE; 480fcf3ce44SJohn Forte break; 481fcf3ce44SJohn Forte } 482fcf3ce44SJohn Forte 483fcf3ce44SJohn Forte /* Clear RISC interrupt */ 484fcf3ce44SJohn Forte if (intr || intr_loop == 0) { 485fcf3ce44SJohn Forte intr = B_FALSE; 486eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_8021)) { 487eb82ff87SDaniel Beauregard ql_8021_clr_fw_intr(ha); 488eb82ff87SDaniel Beauregard } else if (CFG_IST(ha, CFG_CTRL_242581)) { 489eb82ff87SDaniel Beauregard WRT32_IO_REG(ha, hccr, 490eb82ff87SDaniel Beauregard HC24_CLR_RISC_INT); 491eb82ff87SDaniel Beauregard } else { 492eb82ff87SDaniel Beauregard WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT); 493eb82ff87SDaniel Beauregard } 494fcf3ce44SJohn Forte } 495fcf3ce44SJohn Forte 496fcf3ce44SJohn Forte if (set_flags != 0 || reset_flags != 0) { 497fcf3ce44SJohn Forte TASK_DAEMON_LOCK(ha); 498fcf3ce44SJohn Forte ha->task_daemon_flags |= set_flags; 499fcf3ce44SJohn Forte ha->task_daemon_flags &= ~reset_flags; 500fcf3ce44SJohn Forte TASK_DAEMON_UNLOCK(ha); 501fcf3ce44SJohn Forte set_flags = 0; 502fcf3ce44SJohn Forte reset_flags = 0; 503fcf3ce44SJohn Forte daemon = B_TRUE; 504fcf3ce44SJohn Forte } 505fcf3ce44SJohn Forte 506fcf3ce44SJohn Forte if (ha->flags & PARITY_ERROR) { 507fcf3ce44SJohn Forte EL(ha, "parity/pause exit\n"); 508fcf3ce44SJohn Forte mbx = RD16_IO_REG(ha, hccr); /* PCI posting */ 509fcf3ce44SJohn Forte break; 510fcf3ce44SJohn Forte } 511*f885d00fSDaniel Beauregard 512*f885d00fSDaniel Beauregard if (clear_spurious) { 513*f885d00fSDaniel Beauregard spurious_intr = 0; 514*f885d00fSDaniel Beauregard } 515fcf3ce44SJohn Forte } 516fcf3ce44SJohn Forte } 517fcf3ce44SJohn Forte 518fcf3ce44SJohn Forte /* Process claimed interrupts during polls. */ 519fcf3ce44SJohn Forte if (rval == DDI_INTR_UNCLAIMED && ha->intr_claimed == B_TRUE) { 520fcf3ce44SJohn Forte ha->intr_claimed = B_FALSE; 521fcf3ce44SJohn Forte rval = DDI_INTR_CLAIMED; 522fcf3ce44SJohn Forte } 523fcf3ce44SJohn Forte 524fcf3ce44SJohn Forte /* Release interrupt lock. */ 525fcf3ce44SJohn Forte INTR_UNLOCK(ha); 526fcf3ce44SJohn Forte 527fcf3ce44SJohn Forte if (daemon) { 528fcf3ce44SJohn Forte ql_awaken_task_daemon(ha, NULL, 0, 0); 529fcf3ce44SJohn Forte } 530fcf3ce44SJohn Forte 531fcf3ce44SJohn Forte if (isr_done_q.first != NULL) { 532fcf3ce44SJohn Forte ql_done(isr_done_q.first); 533fcf3ce44SJohn Forte } 534fcf3ce44SJohn Forte 535fcf3ce44SJohn Forte if (rval == DDI_INTR_CLAIMED) { 536fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 537fcf3ce44SJohn Forte ha->xioctl->TotalInterrupts++; 538fcf3ce44SJohn Forte } else { 539fcf3ce44SJohn Forte /*EMPTY*/ 540fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): interrupt not claimed\n", 541fcf3ce44SJohn Forte ha->instance); 542fcf3ce44SJohn Forte } 543fcf3ce44SJohn Forte 544fcf3ce44SJohn Forte QL_PM_LOCK(ha); 545fcf3ce44SJohn Forte ha->busy--; 546fcf3ce44SJohn Forte QL_PM_UNLOCK(ha); 547fcf3ce44SJohn Forte 548fcf3ce44SJohn Forte return (rval); 549fcf3ce44SJohn Forte } 550fcf3ce44SJohn Forte 55116dd44c2SDaniel Beauregard /* 55216dd44c2SDaniel Beauregard * ql_handle_uncommon_risc_intr 55316dd44c2SDaniel Beauregard * Handle an uncommon RISC interrupt. 55416dd44c2SDaniel Beauregard * 55516dd44c2SDaniel Beauregard * Input: 55616dd44c2SDaniel Beauregard * ha: adapter state pointer. 55716dd44c2SDaniel Beauregard * stat: interrupt status 55816dd44c2SDaniel Beauregard * 55916dd44c2SDaniel Beauregard * Context: 56016dd44c2SDaniel Beauregard * Interrupt or Kernel context, no mailbox commands allowed. 56116dd44c2SDaniel Beauregard */ 56216dd44c2SDaniel Beauregard static void 56316dd44c2SDaniel Beauregard ql_handle_uncommon_risc_intr(ql_adapter_state_t *ha, uint32_t stat, 56416dd44c2SDaniel Beauregard uint32_t *set_flags) 56516dd44c2SDaniel Beauregard { 56616dd44c2SDaniel Beauregard uint16_t hccr_reg; 56716dd44c2SDaniel Beauregard 56816dd44c2SDaniel Beauregard hccr_reg = RD16_IO_REG(ha, hccr); 56916dd44c2SDaniel Beauregard 57016dd44c2SDaniel Beauregard if (stat & RH_RISC_PAUSED || 57116dd44c2SDaniel Beauregard (hccr_reg & (BIT_15 | BIT_13 | BIT_11 | BIT_8))) { 57216dd44c2SDaniel Beauregard 57316dd44c2SDaniel Beauregard ADAPTER_STATE_LOCK(ha); 57416dd44c2SDaniel Beauregard ha->flags |= PARITY_ERROR; 57516dd44c2SDaniel Beauregard ADAPTER_STATE_UNLOCK(ha); 57616dd44c2SDaniel Beauregard 57716dd44c2SDaniel Beauregard if (ha->parity_pause_errors == 0 || 57816dd44c2SDaniel Beauregard ha->parity_hccr_err != hccr_reg || 57916dd44c2SDaniel Beauregard ha->parity_stat_err != stat) { 58016dd44c2SDaniel Beauregard cmn_err(CE_WARN, "qlc(%d): isr, Internal Parity/" 58116dd44c2SDaniel Beauregard "Pause Error - hccr=%xh, stat=%xh, count=%d", 58216dd44c2SDaniel Beauregard ha->instance, hccr_reg, stat, 58316dd44c2SDaniel Beauregard ha->parity_pause_errors); 58416dd44c2SDaniel Beauregard ha->parity_hccr_err = hccr_reg; 58516dd44c2SDaniel Beauregard ha->parity_stat_err = stat; 58616dd44c2SDaniel Beauregard } 58716dd44c2SDaniel Beauregard 58816dd44c2SDaniel Beauregard EL(ha, "parity/pause error, isp_abort_needed\n"); 58916dd44c2SDaniel Beauregard 59016dd44c2SDaniel Beauregard if (ql_binary_fw_dump(ha, FALSE) != QL_SUCCESS) { 59116dd44c2SDaniel Beauregard ql_reset_chip(ha); 59216dd44c2SDaniel Beauregard } 59316dd44c2SDaniel Beauregard 59416dd44c2SDaniel Beauregard if (ha->parity_pause_errors == 0) { 595eb82ff87SDaniel Beauregard ha->log_parity_pause = B_TRUE; 59616dd44c2SDaniel Beauregard } 59716dd44c2SDaniel Beauregard 59816dd44c2SDaniel Beauregard if (ha->parity_pause_errors < 0xffffffff) { 59916dd44c2SDaniel Beauregard ha->parity_pause_errors++; 60016dd44c2SDaniel Beauregard } 60116dd44c2SDaniel Beauregard 60216dd44c2SDaniel Beauregard *set_flags |= ISP_ABORT_NEEDED; 60316dd44c2SDaniel Beauregard 60416dd44c2SDaniel Beauregard /* Disable ISP interrupts. */ 605eb82ff87SDaniel Beauregard CFG_IST(ha, CFG_CTRL_8021) ? ql_8021_disable_intrs(ha) : 606eb82ff87SDaniel Beauregard WRT16_IO_REG(ha, ictrl, 0); 60716dd44c2SDaniel Beauregard ADAPTER_STATE_LOCK(ha); 60816dd44c2SDaniel Beauregard ha->flags &= ~INTERRUPTS_ENABLED; 60916dd44c2SDaniel Beauregard ADAPTER_STATE_UNLOCK(ha); 61016dd44c2SDaniel Beauregard } else { 61116dd44c2SDaniel Beauregard EL(ha, "UNKNOWN interrupt status=%xh, hccr=%xh\n", 61216dd44c2SDaniel Beauregard stat, hccr_reg); 61316dd44c2SDaniel Beauregard } 61416dd44c2SDaniel Beauregard } 61516dd44c2SDaniel Beauregard 616fcf3ce44SJohn Forte /* 617fcf3ce44SJohn Forte * ql_spurious_intr 618fcf3ce44SJohn Forte * Inform Solaris of spurious interrupts. 619fcf3ce44SJohn Forte * 620fcf3ce44SJohn Forte * Input: 621fcf3ce44SJohn Forte * ha: adapter state pointer. 622fcf3ce44SJohn Forte * intr_clr: early interrupt clear 623fcf3ce44SJohn Forte * 624fcf3ce44SJohn Forte * Context: 625fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 626fcf3ce44SJohn Forte */ 627fcf3ce44SJohn Forte static void 628fcf3ce44SJohn Forte ql_spurious_intr(ql_adapter_state_t *ha, int intr_clr) 629fcf3ce44SJohn Forte { 630fcf3ce44SJohn Forte ddi_devstate_t state; 631fcf3ce44SJohn Forte 632fcf3ce44SJohn Forte EL(ha, "Spurious interrupt\n"); 633fcf3ce44SJohn Forte 634fcf3ce44SJohn Forte /* Disable ISP interrupts. */ 635fcf3ce44SJohn Forte WRT16_IO_REG(ha, ictrl, 0); 636fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 637fcf3ce44SJohn Forte ha->flags &= ~INTERRUPTS_ENABLED; 638fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 639fcf3ce44SJohn Forte 640fcf3ce44SJohn Forte /* Clear RISC interrupt */ 641fcf3ce44SJohn Forte if (intr_clr) { 642eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_8021)) { 643eb82ff87SDaniel Beauregard ql_8021_clr_fw_intr(ha); 644eb82ff87SDaniel Beauregard } else if (CFG_IST(ha, CFG_CTRL_242581)) { 645eb82ff87SDaniel Beauregard WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT); 646eb82ff87SDaniel Beauregard } else { 647eb82ff87SDaniel Beauregard WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT); 648eb82ff87SDaniel Beauregard } 649fcf3ce44SJohn Forte } 650fcf3ce44SJohn Forte 651fcf3ce44SJohn Forte state = ddi_get_devstate(ha->dip); 652fcf3ce44SJohn Forte if (state == DDI_DEVSTATE_UP) { 653fcf3ce44SJohn Forte /*EMPTY*/ 654fcf3ce44SJohn Forte ddi_dev_report_fault(ha->dip, DDI_SERVICE_DEGRADED, 655fcf3ce44SJohn Forte DDI_DEVICE_FAULT, "spurious interrupts"); 656fcf3ce44SJohn Forte } 657fcf3ce44SJohn Forte } 658fcf3ce44SJohn Forte 659fcf3ce44SJohn Forte /* 660fcf3ce44SJohn Forte * ql_mbx_completion 661fcf3ce44SJohn Forte * Processes mailbox completions. 662fcf3ce44SJohn Forte * 663fcf3ce44SJohn Forte * Input: 664fcf3ce44SJohn Forte * ha: adapter state pointer. 665fcf3ce44SJohn Forte * mb0: Mailbox 0 contents. 666fcf3ce44SJohn Forte * set_flags: task daemon flags to set. 667fcf3ce44SJohn Forte * reset_flags: task daemon flags to reset. 668fcf3ce44SJohn Forte * intr_clr: early interrupt clear 669fcf3ce44SJohn Forte * 670fcf3ce44SJohn Forte * Context: 671fcf3ce44SJohn Forte * Interrupt context. 672fcf3ce44SJohn Forte */ 673fcf3ce44SJohn Forte /* ARGSUSED */ 674fcf3ce44SJohn Forte static void 675fcf3ce44SJohn Forte ql_mbx_completion(ql_adapter_state_t *ha, uint16_t mb0, uint32_t *set_flags, 676fcf3ce44SJohn Forte uint32_t *reset_flags, int intr_clr) 677fcf3ce44SJohn Forte { 678fcf3ce44SJohn Forte uint32_t index; 679fcf3ce44SJohn Forte uint16_t cnt; 680fcf3ce44SJohn Forte 681fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 682fcf3ce44SJohn Forte 683fcf3ce44SJohn Forte /* Load return mailbox registers. */ 684fcf3ce44SJohn Forte MBX_REGISTER_LOCK(ha); 685fcf3ce44SJohn Forte 686fcf3ce44SJohn Forte if (ha->mcp != NULL) { 687fcf3ce44SJohn Forte ha->mcp->mb[0] = mb0; 688fcf3ce44SJohn Forte index = ha->mcp->in_mb & ~MBX_0; 689fcf3ce44SJohn Forte 690fcf3ce44SJohn Forte for (cnt = 1; cnt < MAX_MBOX_COUNT && index != 0; cnt++) { 691fcf3ce44SJohn Forte index >>= 1; 692fcf3ce44SJohn Forte if (index & MBX_0) { 693fcf3ce44SJohn Forte ha->mcp->mb[cnt] = RD16_IO_REG(ha, 694eb82ff87SDaniel Beauregard mailbox_out[cnt]); 695fcf3ce44SJohn Forte } 696fcf3ce44SJohn Forte } 697fcf3ce44SJohn Forte 698fcf3ce44SJohn Forte } else { 699fcf3ce44SJohn Forte EL(ha, "mcp == NULL\n"); 700fcf3ce44SJohn Forte } 701fcf3ce44SJohn Forte 702fcf3ce44SJohn Forte if (intr_clr) { 703fcf3ce44SJohn Forte /* Clear RISC interrupt. */ 704eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_8021)) { 705eb82ff87SDaniel Beauregard ql_8021_clr_fw_intr(ha); 706eb82ff87SDaniel Beauregard } else if (CFG_IST(ha, CFG_CTRL_242581)) { 707eb82ff87SDaniel Beauregard WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT); 708eb82ff87SDaniel Beauregard } else { 709eb82ff87SDaniel Beauregard WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT); 710eb82ff87SDaniel Beauregard } 711fcf3ce44SJohn Forte } 712fcf3ce44SJohn Forte 713fcf3ce44SJohn Forte ha->mailbox_flags = (uint8_t)(ha->mailbox_flags | MBX_INTERRUPT); 714fcf3ce44SJohn Forte if (ha->flags & INTERRUPTS_ENABLED) { 715fcf3ce44SJohn Forte cv_broadcast(&ha->cv_mbx_intr); 716fcf3ce44SJohn Forte } 717fcf3ce44SJohn Forte 718fcf3ce44SJohn Forte MBX_REGISTER_UNLOCK(ha); 719fcf3ce44SJohn Forte 720fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 721fcf3ce44SJohn Forte } 722fcf3ce44SJohn Forte 723fcf3ce44SJohn Forte /* 724fcf3ce44SJohn Forte * ql_async_event 725fcf3ce44SJohn Forte * Processes asynchronous events. 726fcf3ce44SJohn Forte * 727fcf3ce44SJohn Forte * Input: 728fcf3ce44SJohn Forte * ha: adapter state pointer. 729fcf3ce44SJohn Forte * mbx: Mailbox 0 register. 730fcf3ce44SJohn Forte * done_q: head pointer to done queue. 731fcf3ce44SJohn Forte * set_flags: task daemon flags to set. 732fcf3ce44SJohn Forte * reset_flags: task daemon flags to reset. 733fcf3ce44SJohn Forte * intr_clr: early interrupt clear 734fcf3ce44SJohn Forte * 735fcf3ce44SJohn Forte * Context: 736fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 737fcf3ce44SJohn Forte */ 738fcf3ce44SJohn Forte static void 739fcf3ce44SJohn Forte ql_async_event(ql_adapter_state_t *ha, uint32_t mbx, ql_head_t *done_q, 740fcf3ce44SJohn Forte uint32_t *set_flags, uint32_t *reset_flags, int intr_clr) 741fcf3ce44SJohn Forte { 742fcf3ce44SJohn Forte uint32_t handle; 743fcf3ce44SJohn Forte uint32_t index; 744fcf3ce44SJohn Forte uint16_t cnt; 745fcf3ce44SJohn Forte uint16_t mb[MAX_MBOX_COUNT]; 746fcf3ce44SJohn Forte ql_srb_t *sp; 747fcf3ce44SJohn Forte port_id_t s_id; 748fcf3ce44SJohn Forte ql_tgt_t *tq; 749fcf3ce44SJohn Forte boolean_t intr = B_TRUE; 750fcf3ce44SJohn Forte ql_adapter_state_t *vha; 751fcf3ce44SJohn Forte 752fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 753fcf3ce44SJohn Forte 754fcf3ce44SJohn Forte /* Setup to process fast completion. */ 755fcf3ce44SJohn Forte mb[0] = LSW(mbx); 756fcf3ce44SJohn Forte switch (mb[0]) { 757fcf3ce44SJohn Forte case MBA_SCSI_COMPLETION: 758eb82ff87SDaniel Beauregard handle = SHORT_TO_LONG(RD16_IO_REG(ha, mailbox_out[1]), 759eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[2])); 760fcf3ce44SJohn Forte break; 761fcf3ce44SJohn Forte 762fcf3ce44SJohn Forte case MBA_CMPLT_1_16BIT: 763fcf3ce44SJohn Forte handle = MSW(mbx); 764fcf3ce44SJohn Forte mb[0] = MBA_SCSI_COMPLETION; 765fcf3ce44SJohn Forte break; 766fcf3ce44SJohn Forte 767fcf3ce44SJohn Forte case MBA_CMPLT_1_32BIT: 768eb82ff87SDaniel Beauregard handle = SHORT_TO_LONG(MSW(mbx), 769eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[2])); 770fcf3ce44SJohn Forte mb[0] = MBA_SCSI_COMPLETION; 771fcf3ce44SJohn Forte break; 772fcf3ce44SJohn Forte 773fcf3ce44SJohn Forte case MBA_CTIO_COMPLETION: 774fcf3ce44SJohn Forte case MBA_IP_COMPLETION: 775fcf3ce44SJohn Forte handle = CFG_IST(ha, CFG_CTRL_2200) ? SHORT_TO_LONG( 776eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[1]), 777eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[2])) : 778eb82ff87SDaniel Beauregard SHORT_TO_LONG(MSW(mbx), RD16_IO_REG(ha, mailbox_out[2])); 779fcf3ce44SJohn Forte mb[0] = MBA_SCSI_COMPLETION; 780fcf3ce44SJohn Forte break; 781fcf3ce44SJohn Forte 782fcf3ce44SJohn Forte default: 783fcf3ce44SJohn Forte break; 784fcf3ce44SJohn Forte } 785fcf3ce44SJohn Forte 786fcf3ce44SJohn Forte /* Handle asynchronous event */ 787fcf3ce44SJohn Forte switch (mb[0]) { 788fcf3ce44SJohn Forte case MBA_SCSI_COMPLETION: 789fcf3ce44SJohn Forte QL_PRINT_5(CE_CONT, "(%d): Fast post completion\n", 790fcf3ce44SJohn Forte ha->instance); 791fcf3ce44SJohn Forte 792fcf3ce44SJohn Forte if (intr_clr) { 793fcf3ce44SJohn Forte /* Clear RISC interrupt */ 794eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_8021)) { 795eb82ff87SDaniel Beauregard ql_8021_clr_fw_intr(ha); 796eb82ff87SDaniel Beauregard } else if (CFG_IST(ha, CFG_CTRL_242581)) { 797eb82ff87SDaniel Beauregard WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT); 798eb82ff87SDaniel Beauregard } else { 799eb82ff87SDaniel Beauregard WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT); 800eb82ff87SDaniel Beauregard } 801fcf3ce44SJohn Forte intr = B_FALSE; 802fcf3ce44SJohn Forte } 803fcf3ce44SJohn Forte 804fcf3ce44SJohn Forte if ((ha->flags & ONLINE) == 0) { 805fcf3ce44SJohn Forte break; 806fcf3ce44SJohn Forte } 807fcf3ce44SJohn Forte 808fcf3ce44SJohn Forte /* Get handle. */ 809fcf3ce44SJohn Forte index = handle & OSC_INDEX_MASK; 810fcf3ce44SJohn Forte 811fcf3ce44SJohn Forte /* Validate handle. */ 812fcf3ce44SJohn Forte sp = index < MAX_OUTSTANDING_COMMANDS ? 813fcf3ce44SJohn Forte ha->outstanding_cmds[index] : NULL; 814fcf3ce44SJohn Forte 815fcf3ce44SJohn Forte if (sp != NULL && sp->handle == handle) { 816fcf3ce44SJohn Forte ha->outstanding_cmds[index] = NULL; 817fcf3ce44SJohn Forte sp->handle = 0; 818fcf3ce44SJohn Forte sp->flags &= ~SRB_IN_TOKEN_ARRAY; 819fcf3ce44SJohn Forte 820fcf3ce44SJohn Forte /* Set completed status. */ 821fcf3ce44SJohn Forte sp->flags |= SRB_ISP_COMPLETED; 822fcf3ce44SJohn Forte 823fcf3ce44SJohn Forte /* Set completion status */ 824fcf3ce44SJohn Forte sp->pkt->pkt_reason = CS_COMPLETE; 825fcf3ce44SJohn Forte 826fcf3ce44SJohn Forte if (!(sp->flags & SRB_FCP_CMD_PKT)) { 827fcf3ce44SJohn Forte /* Place block on done queue */ 828fcf3ce44SJohn Forte ql_add_link_b(done_q, &sp->cmd); 829fcf3ce44SJohn Forte } else { 830fcf3ce44SJohn Forte ql_fast_fcp_post(sp); 831fcf3ce44SJohn Forte } 832fcf3ce44SJohn Forte } else if (handle != QL_FCA_BRAND) { 833fcf3ce44SJohn Forte if (sp == NULL) { 834fcf3ce44SJohn Forte EL(ha, "%xh unknown IOCB handle=%xh\n", 835fcf3ce44SJohn Forte mb[0], handle); 836fcf3ce44SJohn Forte } else { 837fcf3ce44SJohn Forte EL(ha, "%xh mismatch IOCB handle pkt=%xh, " 838fcf3ce44SJohn Forte "sp=%xh\n", mb[0], handle, sp->handle); 839fcf3ce44SJohn Forte } 840fcf3ce44SJohn Forte 841fcf3ce44SJohn Forte EL(ha, "%xh Fast post, mbx1=%xh, mbx2=%xh, mbx3=%xh," 842fcf3ce44SJohn Forte "mbx6=%xh, mbx7=%xh\n", mb[0], 843eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[1]), 844eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[2]), 845eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[3]), 846eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[6]), 847eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[7])); 848fcf3ce44SJohn Forte 849fcf3ce44SJohn Forte (void) ql_binary_fw_dump(ha, FALSE); 850fcf3ce44SJohn Forte 851fcf3ce44SJohn Forte if (!(ha->task_daemon_flags & 852fcf3ce44SJohn Forte (ISP_ABORT_NEEDED | ABORT_ISP_ACTIVE))) { 853fcf3ce44SJohn Forte EL(ha, "%xh ISP Invalid handle, " 854fcf3ce44SJohn Forte "isp_abort_needed\n", mb[0]); 855fcf3ce44SJohn Forte *set_flags |= ISP_ABORT_NEEDED; 856fcf3ce44SJohn Forte } 857fcf3ce44SJohn Forte } 858fcf3ce44SJohn Forte break; 859fcf3ce44SJohn Forte 860fcf3ce44SJohn Forte case MBA_RESET: /* Reset */ 861fcf3ce44SJohn Forte EL(ha, "%xh Reset received\n", mb[0]); 862fcf3ce44SJohn Forte *set_flags |= RESET_MARKER_NEEDED; 863fcf3ce44SJohn Forte break; 864fcf3ce44SJohn Forte 865fcf3ce44SJohn Forte case MBA_SYSTEM_ERR: /* System Error */ 866eb82ff87SDaniel Beauregard mb[1] = RD16_IO_REG(ha, mailbox_out[1]); 867eb82ff87SDaniel Beauregard mb[2] = RD16_IO_REG(ha, mailbox_out[2]); 868eb82ff87SDaniel Beauregard mb[3] = RD16_IO_REG(ha, mailbox_out[3]); 869eb82ff87SDaniel Beauregard mb[7] = RD16_IO_REG(ha, mailbox_out[7]); 870fcf3ce44SJohn Forte 871fcf3ce44SJohn Forte EL(ha, "%xh ISP System Error, isp_abort_needed\n mbx1=%xh, " 872fcf3ce44SJohn Forte "mbx2=%xh, mbx3=%xh, mbx4=%xh, mbx5=%xh, mbx6=%xh,\n " 873fcf3ce44SJohn Forte "mbx7=%xh, mbx8=%xh, mbx9=%xh, mbx10=%xh, mbx11=%xh, " 874fcf3ce44SJohn Forte "mbx12=%xh,\n", mb[0], mb[1], mb[2], mb[3], 875eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[4]), 876eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[5]), 877eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[6]), mb[7], 878eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[8]), 879eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[9]), 880eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[10]), 881eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[11]), 882eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[12])); 883fcf3ce44SJohn Forte 884fcf3ce44SJohn Forte EL(ha, "%xh ISP System Error, isp_abort_needed\n mbx13=%xh, " 885fcf3ce44SJohn Forte "mbx14=%xh, mbx15=%xh, mbx16=%xh, mbx17=%xh, mbx18=%xh,\n" 886fcf3ce44SJohn Forte "mbx19=%xh, mbx20=%xh, mbx21=%xh, mbx22=%xh, mbx23=%xh\n", 887eb82ff87SDaniel Beauregard mb[0], RD16_IO_REG(ha, mailbox_out[13]), 888eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[14]), 889eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[15]), 890eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[16]), 891eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[17]), 892eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[18]), 893eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[19]), 894eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[20]), 895eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[21]), 896eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[22]), 897eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[23])); 898fcf3ce44SJohn Forte 899fcf3ce44SJohn Forte if (ha->reg_off->mbox_cnt > 24) { 900fcf3ce44SJohn Forte EL(ha, "%xh ISP System Error, mbx24=%xh, mbx25=%xh, " 901fcf3ce44SJohn Forte "mbx26=%xh,\n mbx27=%xh, mbx28=%xh, mbx29=%xh, " 902fcf3ce44SJohn Forte "mbx30=%xh, mbx31=%xh\n", mb[0], 903eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[24]), 904eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[25]), 905eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[26]), 906eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[27]), 907eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[28]), 908eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[29]), 909eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[30]), 910eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[31])); 911fcf3ce44SJohn Forte } 912fcf3ce44SJohn Forte 913fcf3ce44SJohn Forte (void) ql_binary_fw_dump(ha, FALSE); 914fcf3ce44SJohn Forte 915fcf3ce44SJohn Forte (void) ql_flash_errlog(ha, FLASH_ERRLOG_AEN_8002, mb[1], 916fcf3ce44SJohn Forte mb[2], mb[3]); 917fcf3ce44SJohn Forte 9184f8b8adcSDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_81XX) && mb[7] & SE_MPI_RISC) { 9194f8b8adcSDaniel Beauregard ADAPTER_STATE_LOCK(ha); 9204f8b8adcSDaniel Beauregard ha->flags |= MPI_RESET_NEEDED; 9214f8b8adcSDaniel Beauregard ADAPTER_STATE_UNLOCK(ha); 9224f8b8adcSDaniel Beauregard } 9234f8b8adcSDaniel Beauregard 924fcf3ce44SJohn Forte *set_flags |= ISP_ABORT_NEEDED; 925fcf3ce44SJohn Forte ha->xioctl->ControllerErrorCount++; 926fcf3ce44SJohn Forte break; 927fcf3ce44SJohn Forte 928fcf3ce44SJohn Forte case MBA_REQ_TRANSFER_ERR: /* Request Transfer Error */ 929fcf3ce44SJohn Forte EL(ha, "%xh Request Transfer Error received, " 930fcf3ce44SJohn Forte "isp_abort_needed\n", mb[0]); 931fcf3ce44SJohn Forte 932fcf3ce44SJohn Forte (void) ql_flash_errlog(ha, FLASH_ERRLOG_AEN_8003, 933eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[1]), 934eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[2]), 935eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[3])); 936fcf3ce44SJohn Forte 937fcf3ce44SJohn Forte *set_flags |= ISP_ABORT_NEEDED; 938fcf3ce44SJohn Forte ha->xioctl->ControllerErrorCount++; 939fcf3ce44SJohn Forte break; 940fcf3ce44SJohn Forte 941fcf3ce44SJohn Forte case MBA_RSP_TRANSFER_ERR: /* Response Xfer Err */ 942fcf3ce44SJohn Forte EL(ha, "%xh Response Transfer Error received," 943fcf3ce44SJohn Forte " isp_abort_needed\n", mb[0]); 944fcf3ce44SJohn Forte 945fcf3ce44SJohn Forte (void) ql_flash_errlog(ha, FLASH_ERRLOG_AEN_8004, 946eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[1]), 947eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[2]), 948eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[3])); 949fcf3ce44SJohn Forte 950fcf3ce44SJohn Forte *set_flags |= ISP_ABORT_NEEDED; 951fcf3ce44SJohn Forte ha->xioctl->ControllerErrorCount++; 952fcf3ce44SJohn Forte break; 953fcf3ce44SJohn Forte 954fcf3ce44SJohn Forte case MBA_WAKEUP_THRES: /* Request Queue Wake-up */ 955fcf3ce44SJohn Forte EL(ha, "%xh Request Queue Wake-up received\n", 956fcf3ce44SJohn Forte mb[0]); 957fcf3ce44SJohn Forte break; 958fcf3ce44SJohn Forte 959fcf3ce44SJohn Forte case MBA_MENLO_ALERT: /* Menlo Alert Notification */ 960eb82ff87SDaniel Beauregard mb[1] = RD16_IO_REG(ha, mailbox_out[1]); 961eb82ff87SDaniel Beauregard mb[2] = RD16_IO_REG(ha, mailbox_out[2]); 962eb82ff87SDaniel Beauregard mb[3] = RD16_IO_REG(ha, mailbox_out[3]); 963fcf3ce44SJohn Forte 964fcf3ce44SJohn Forte EL(ha, "%xh Menlo Alert Notification received, mbx1=%xh," 965fcf3ce44SJohn Forte " mbx2=%xh, mbx3=%xh\n", mb[0], mb[1], mb[2], mb[3]); 966fcf3ce44SJohn Forte 967fcf3ce44SJohn Forte switch (mb[1]) { 968fcf3ce44SJohn Forte case MLA_LOGIN_OPERATIONAL_FW: 969fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 970fcf3ce44SJohn Forte ha->flags |= MENLO_LOGIN_OPERATIONAL; 971fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 972fcf3ce44SJohn Forte break; 973fcf3ce44SJohn Forte case MLA_PANIC_RECOVERY: 974fcf3ce44SJohn Forte case MLA_LOGIN_DIAGNOSTIC_FW: 975fcf3ce44SJohn Forte case MLA_LOGIN_GOLDEN_FW: 976fcf3ce44SJohn Forte case MLA_REJECT_RESPONSE: 977fcf3ce44SJohn Forte default: 978fcf3ce44SJohn Forte break; 979fcf3ce44SJohn Forte } 980fcf3ce44SJohn Forte break; 981fcf3ce44SJohn Forte 982fcf3ce44SJohn Forte case MBA_LIP_F8: /* Received a LIP F8. */ 983fcf3ce44SJohn Forte case MBA_LIP_RESET: /* LIP reset occurred. */ 984fcf3ce44SJohn Forte case MBA_LIP_OCCURRED: /* Loop Initialization Procedure */ 985eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_8081)) { 9865dfd244aSDaniel Beauregard EL(ha, "%xh DCBX_STARTED received, mbx1=%xh, mbx2=%xh" 987eb82ff87SDaniel Beauregard "\n", mb[0], RD16_IO_REG(ha, mailbox_out[1]), 988eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[2])); 9895dfd244aSDaniel Beauregard } else { 9905dfd244aSDaniel Beauregard EL(ha, "%xh LIP received\n", mb[0]); 9915dfd244aSDaniel Beauregard } 992fcf3ce44SJohn Forte 993fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 994fcf3ce44SJohn Forte ha->flags &= ~POINT_TO_POINT; 995fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 996fcf3ce44SJohn Forte 997fcf3ce44SJohn Forte if (!(ha->task_daemon_flags & LOOP_DOWN)) { 998fcf3ce44SJohn Forte *set_flags |= LOOP_DOWN; 999fcf3ce44SJohn Forte } 1000fcf3ce44SJohn Forte ql_port_state(ha, FC_STATE_OFFLINE, 1001fcf3ce44SJohn Forte FC_STATE_CHANGE | COMMAND_WAIT_NEEDED | LOOP_DOWN); 1002fcf3ce44SJohn Forte 1003fcf3ce44SJohn Forte if (ha->loop_down_timer == LOOP_DOWN_TIMER_OFF) { 1004fcf3ce44SJohn Forte ha->loop_down_timer = LOOP_DOWN_TIMER_START; 1005fcf3ce44SJohn Forte } 1006fcf3ce44SJohn Forte 1007fcf3ce44SJohn Forte ha->adapter_stats->lip_count++; 1008fcf3ce44SJohn Forte 1009fcf3ce44SJohn Forte /* Update AEN queue. */ 1010fcf3ce44SJohn Forte ha->xioctl->TotalLipResets++; 1011fcf3ce44SJohn Forte if (ha->xioctl->flags & QL_AEN_TRACKING_ENABLE) { 1012fcf3ce44SJohn Forte ql_enqueue_aen(ha, mb[0], NULL); 1013fcf3ce44SJohn Forte } 1014fcf3ce44SJohn Forte break; 1015fcf3ce44SJohn Forte 1016fcf3ce44SJohn Forte case MBA_LOOP_UP: 10175dfd244aSDaniel Beauregard if (CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322 | 1018eb82ff87SDaniel Beauregard CFG_CTRL_24258081))) { 1019*f885d00fSDaniel Beauregard ha->iidma_rate = RD16_IO_REG(ha, mailbox_out[1]); 1020*f885d00fSDaniel Beauregard if (ha->iidma_rate == IIDMA_RATE_1GB) { 1021fcf3ce44SJohn Forte ha->state = FC_PORT_STATE_MASK( 1022fcf3ce44SJohn Forte ha->state) | FC_STATE_1GBIT_SPEED; 1023fcf3ce44SJohn Forte index = 1; 1024*f885d00fSDaniel Beauregard } else if (ha->iidma_rate == IIDMA_RATE_2GB) { 1025fcf3ce44SJohn Forte ha->state = FC_PORT_STATE_MASK( 1026fcf3ce44SJohn Forte ha->state) | FC_STATE_2GBIT_SPEED; 1027fcf3ce44SJohn Forte index = 2; 1028*f885d00fSDaniel Beauregard } else if (ha->iidma_rate == IIDMA_RATE_4GB) { 1029fcf3ce44SJohn Forte ha->state = FC_PORT_STATE_MASK( 1030fcf3ce44SJohn Forte ha->state) | FC_STATE_4GBIT_SPEED; 1031fcf3ce44SJohn Forte index = 4; 1032*f885d00fSDaniel Beauregard } else if (ha->iidma_rate == IIDMA_RATE_8GB) { 1033fcf3ce44SJohn Forte ha->state = FC_PORT_STATE_MASK( 1034fcf3ce44SJohn Forte ha->state) | FC_STATE_8GBIT_SPEED; 1035fcf3ce44SJohn Forte index = 8; 1036*f885d00fSDaniel Beauregard } else if (ha->iidma_rate == IIDMA_RATE_10GB) { 10375dfd244aSDaniel Beauregard ha->state = FC_PORT_STATE_MASK( 10385dfd244aSDaniel Beauregard ha->state) | FC_STATE_10GBIT_SPEED; 10395dfd244aSDaniel Beauregard index = 10; 1040fcf3ce44SJohn Forte } else { 1041fcf3ce44SJohn Forte ha->state = FC_PORT_STATE_MASK( 1042fcf3ce44SJohn Forte ha->state); 1043fcf3ce44SJohn Forte index = 0; 1044fcf3ce44SJohn Forte } 1045fcf3ce44SJohn Forte } else { 1046*f885d00fSDaniel Beauregard ha->iidma_rate = IIDMA_RATE_1GB; 1047fcf3ce44SJohn Forte ha->state = FC_PORT_STATE_MASK(ha->state) | 1048fcf3ce44SJohn Forte FC_STATE_FULL_SPEED; 1049fcf3ce44SJohn Forte index = 1; 1050fcf3ce44SJohn Forte } 1051fcf3ce44SJohn Forte 1052fcf3ce44SJohn Forte for (vha = ha; vha != NULL; vha = vha->vp_next) { 1053fcf3ce44SJohn Forte vha->state = FC_PORT_STATE_MASK(vha->state) | 1054fcf3ce44SJohn Forte FC_PORT_SPEED_MASK(ha->state); 1055fcf3ce44SJohn Forte } 1056fcf3ce44SJohn Forte EL(ha, "%d GB %xh Loop Up received\n", index, mb[0]); 1057fcf3ce44SJohn Forte 1058fcf3ce44SJohn Forte /* Update AEN queue. */ 1059fcf3ce44SJohn Forte if (ha->xioctl->flags & QL_AEN_TRACKING_ENABLE) { 1060fcf3ce44SJohn Forte ql_enqueue_aen(ha, mb[0], NULL); 1061fcf3ce44SJohn Forte } 1062fcf3ce44SJohn Forte break; 1063fcf3ce44SJohn Forte 1064fcf3ce44SJohn Forte case MBA_LOOP_DOWN: 10654f8b8adcSDaniel Beauregard EL(ha, "%xh Loop Down received, mbx1=%xh, mbx2=%xh, mbx3=%xh, " 1066eb82ff87SDaniel Beauregard "mbx4=%xh\n", mb[0], RD16_IO_REG(ha, mailbox_out[1]), 1067eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[2]), 1068eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[3]), 1069eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[4])); 1070fcf3ce44SJohn Forte 1071fcf3ce44SJohn Forte if (!(ha->task_daemon_flags & LOOP_DOWN)) { 1072fcf3ce44SJohn Forte *set_flags |= LOOP_DOWN; 1073fcf3ce44SJohn Forte } 1074fcf3ce44SJohn Forte ql_port_state(ha, FC_STATE_OFFLINE, 1075fcf3ce44SJohn Forte FC_STATE_CHANGE | COMMAND_WAIT_NEEDED | LOOP_DOWN); 1076fcf3ce44SJohn Forte 1077fcf3ce44SJohn Forte if (ha->loop_down_timer == LOOP_DOWN_TIMER_OFF) { 1078fcf3ce44SJohn Forte ha->loop_down_timer = LOOP_DOWN_TIMER_START; 1079fcf3ce44SJohn Forte } 1080fcf3ce44SJohn Forte 1081eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_258081)) { 1082eb82ff87SDaniel Beauregard ha->sfp_stat = RD16_IO_REG(ha, mailbox_out[2]); 1083fcf3ce44SJohn Forte } 1084fcf3ce44SJohn Forte 1085fcf3ce44SJohn Forte /* Update AEN queue. */ 1086fcf3ce44SJohn Forte if (ha->xioctl->flags & QL_AEN_TRACKING_ENABLE) { 1087fcf3ce44SJohn Forte ql_enqueue_aen(ha, mb[0], NULL); 1088fcf3ce44SJohn Forte } 1089fcf3ce44SJohn Forte break; 1090fcf3ce44SJohn Forte 1091fcf3ce44SJohn Forte case MBA_PORT_UPDATE: 1092eb82ff87SDaniel Beauregard mb[1] = RD16_IO_REG(ha, mailbox_out[1]); 1093eb82ff87SDaniel Beauregard mb[2] = RD16_IO_REG(ha, mailbox_out[2]); 1094fcf3ce44SJohn Forte mb[3] = (uint16_t)(ha->flags & VP_ENABLED ? 1095eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[3]) : 0); 1096fcf3ce44SJohn Forte 1097fcf3ce44SJohn Forte /* Locate port state structure. */ 1098fcf3ce44SJohn Forte for (vha = ha; vha != NULL; vha = vha->vp_next) { 1099fcf3ce44SJohn Forte if (vha->vp_index == LSB(mb[3])) { 1100fcf3ce44SJohn Forte break; 1101fcf3ce44SJohn Forte } 1102fcf3ce44SJohn Forte } 1103fcf3ce44SJohn Forte if (vha == NULL) { 1104fcf3ce44SJohn Forte break; 1105fcf3ce44SJohn Forte } 1106eb82ff87SDaniel Beauregard 1107eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_8081) && mb[1] == 0xffff && 1108eb82ff87SDaniel Beauregard mb[2] == 7 && (MSB(mb[3]) == 0xe || MSB(mb[3]) == 0x1a || 1109eb82ff87SDaniel Beauregard MSB(mb[3]) == 0x1c || MSB(mb[3]) == 0x1d || 1110eb82ff87SDaniel Beauregard MSB(mb[3]) == 0x1e)) { 1111eb82ff87SDaniel Beauregard /* 1112eb82ff87SDaniel Beauregard * received FLOGI reject 1113eb82ff87SDaniel Beauregard * received FLOGO 1114eb82ff87SDaniel Beauregard * FCF configuration changed 1115eb82ff87SDaniel Beauregard * FIP Clear Virtual Link received 1116eb82ff87SDaniel Beauregard * FKA timeout 1117eb82ff87SDaniel Beauregard */ 1118eb82ff87SDaniel Beauregard if (!(ha->task_daemon_flags & LOOP_DOWN)) { 1119eb82ff87SDaniel Beauregard *set_flags |= LOOP_DOWN; 1120eb82ff87SDaniel Beauregard } 1121eb82ff87SDaniel Beauregard ql_port_state(ha, FC_STATE_OFFLINE, FC_STATE_CHANGE | 1122eb82ff87SDaniel Beauregard COMMAND_WAIT_NEEDED | LOOP_DOWN); 1123eb82ff87SDaniel Beauregard if (ha->loop_down_timer == LOOP_DOWN_TIMER_OFF) { 1124eb82ff87SDaniel Beauregard ha->loop_down_timer = LOOP_DOWN_TIMER_START; 1125eb82ff87SDaniel Beauregard } 11265dfd244aSDaniel Beauregard /* 11275dfd244aSDaniel Beauregard * In N port 2 N port topology the FW provides a port 11285dfd244aSDaniel Beauregard * database entry at loop_id 0x7fe which we use to 11295dfd244aSDaniel Beauregard * acquire the Ports WWPN. 11305dfd244aSDaniel Beauregard */ 1131eb82ff87SDaniel Beauregard } else if ((mb[1] != 0x7fe) && 11325dfd244aSDaniel Beauregard ((FC_PORT_STATE_MASK(vha->state) != FC_STATE_OFFLINE || 1133eb82ff87SDaniel Beauregard (CFG_IST(ha, CFG_CTRL_24258081) && 11345dfd244aSDaniel Beauregard (mb[1] != 0xffff || mb[2] != 6 || mb[3] != 0))))) { 1135fcf3ce44SJohn Forte EL(ha, "%xh Port Database Update, Login/Logout " 1136fcf3ce44SJohn Forte "received, mbx1=%xh, mbx2=%xh, mbx3=%xh\n", 1137fcf3ce44SJohn Forte mb[0], mb[1], mb[2], mb[3]); 1138fcf3ce44SJohn Forte } else { 1139fcf3ce44SJohn Forte EL(ha, "%xh Port Database Update received, mbx1=%xh," 1140fcf3ce44SJohn Forte " mbx2=%xh, mbx3=%xh\n", mb[0], mb[1], mb[2], 1141fcf3ce44SJohn Forte mb[3]); 1142fcf3ce44SJohn Forte *set_flags |= LOOP_RESYNC_NEEDED; 1143fcf3ce44SJohn Forte *set_flags &= ~LOOP_DOWN; 1144fcf3ce44SJohn Forte *reset_flags |= LOOP_DOWN; 1145fcf3ce44SJohn Forte *reset_flags &= ~LOOP_RESYNC_NEEDED; 1146fcf3ce44SJohn Forte vha->loop_down_timer = LOOP_DOWN_TIMER_OFF; 1147fcf3ce44SJohn Forte TASK_DAEMON_LOCK(ha); 1148fcf3ce44SJohn Forte vha->task_daemon_flags |= LOOP_RESYNC_NEEDED; 1149fcf3ce44SJohn Forte vha->task_daemon_flags &= ~LOOP_DOWN; 1150fcf3ce44SJohn Forte TASK_DAEMON_UNLOCK(ha); 1151fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 115216dd44c2SDaniel Beauregard vha->flags &= ~ABORT_CMDS_LOOP_DOWN_TMO; 1153fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 1154fcf3ce44SJohn Forte } 1155fcf3ce44SJohn Forte 1156fcf3ce44SJohn Forte /* Update AEN queue. */ 1157fcf3ce44SJohn Forte if (ha->xioctl->flags & QL_AEN_TRACKING_ENABLE) { 1158fcf3ce44SJohn Forte ql_enqueue_aen(ha, mb[0], NULL); 1159fcf3ce44SJohn Forte } 1160fcf3ce44SJohn Forte break; 1161fcf3ce44SJohn Forte 1162fcf3ce44SJohn Forte case MBA_RSCN_UPDATE: 1163eb82ff87SDaniel Beauregard mb[1] = RD16_IO_REG(ha, mailbox_out[1]); 1164eb82ff87SDaniel Beauregard mb[2] = RD16_IO_REG(ha, mailbox_out[2]); 1165fcf3ce44SJohn Forte mb[3] = (uint16_t)(ha->flags & VP_ENABLED ? 1166eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[3]) : 0); 1167fcf3ce44SJohn Forte 1168fcf3ce44SJohn Forte /* Locate port state structure. */ 1169fcf3ce44SJohn Forte for (vha = ha; vha != NULL; vha = vha->vp_next) { 1170fcf3ce44SJohn Forte if (vha->vp_index == LSB(mb[3])) { 1171fcf3ce44SJohn Forte break; 1172fcf3ce44SJohn Forte } 1173fcf3ce44SJohn Forte } 1174fcf3ce44SJohn Forte 1175fcf3ce44SJohn Forte if (vha == NULL) { 1176fcf3ce44SJohn Forte break; 1177fcf3ce44SJohn Forte } 1178fcf3ce44SJohn Forte 1179fcf3ce44SJohn Forte if (LSB(mb[1]) == vha->d_id.b.domain && 1180fcf3ce44SJohn Forte MSB(mb[2]) == vha->d_id.b.area && 1181fcf3ce44SJohn Forte LSB(mb[2]) == vha->d_id.b.al_pa) { 1182fcf3ce44SJohn Forte EL(ha, "%xh RSCN match adapter, mbx1=%xh, mbx2=%xh, " 1183fcf3ce44SJohn Forte "mbx3=%xh\n", mb[0], mb[1], mb[2], mb[3]); 1184fcf3ce44SJohn Forte } else { 1185fcf3ce44SJohn Forte EL(ha, "%xh RSCN received, mbx1=%xh, mbx2=%xh, " 1186fcf3ce44SJohn Forte "mbx3=%xh\n", mb[0], mb[1], mb[2], mb[3]); 1187fcf3ce44SJohn Forte if (FC_PORT_STATE_MASK(vha->state) != 1188fcf3ce44SJohn Forte FC_STATE_OFFLINE) { 1189fcf3ce44SJohn Forte ql_rcv_rscn_els(vha, &mb[0], done_q); 1190fcf3ce44SJohn Forte TASK_DAEMON_LOCK(ha); 1191fcf3ce44SJohn Forte vha->task_daemon_flags |= RSCN_UPDATE_NEEDED; 1192fcf3ce44SJohn Forte TASK_DAEMON_UNLOCK(ha); 1193fcf3ce44SJohn Forte *set_flags |= RSCN_UPDATE_NEEDED; 1194fcf3ce44SJohn Forte } 1195fcf3ce44SJohn Forte } 1196fcf3ce44SJohn Forte 1197fcf3ce44SJohn Forte /* Update AEN queue. */ 1198fcf3ce44SJohn Forte if (ha->xioctl->flags & QL_AEN_TRACKING_ENABLE) { 1199fcf3ce44SJohn Forte ql_enqueue_aen(ha, mb[0], NULL); 1200fcf3ce44SJohn Forte } 1201fcf3ce44SJohn Forte break; 1202fcf3ce44SJohn Forte 1203fcf3ce44SJohn Forte case MBA_LIP_ERROR: /* Loop initialization errors. */ 1204fcf3ce44SJohn Forte EL(ha, "%xh LIP error received, mbx1=%xh\n", mb[0], 1205eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[1])); 1206fcf3ce44SJohn Forte break; 1207fcf3ce44SJohn Forte 1208fcf3ce44SJohn Forte case MBA_IP_RECEIVE: 1209fcf3ce44SJohn Forte case MBA_IP_BROADCAST: 1210eb82ff87SDaniel Beauregard mb[1] = RD16_IO_REG(ha, mailbox_out[1]); 1211eb82ff87SDaniel Beauregard mb[2] = RD16_IO_REG(ha, mailbox_out[2]); 1212eb82ff87SDaniel Beauregard mb[3] = RD16_IO_REG(ha, mailbox_out[3]); 1213fcf3ce44SJohn Forte 1214fcf3ce44SJohn Forte EL(ha, "%xh IP packet/broadcast received, mbx1=%xh, " 1215fcf3ce44SJohn Forte "mbx2=%xh, mbx3=%xh\n", mb[0], mb[1], mb[2], mb[3]); 1216fcf3ce44SJohn Forte 1217fcf3ce44SJohn Forte /* Locate device queue. */ 1218fcf3ce44SJohn Forte s_id.b.al_pa = LSB(mb[2]); 1219fcf3ce44SJohn Forte s_id.b.area = MSB(mb[2]); 1220fcf3ce44SJohn Forte s_id.b.domain = LSB(mb[1]); 1221fcf3ce44SJohn Forte if ((tq = ql_d_id_to_queue(ha, s_id)) == NULL) { 1222fcf3ce44SJohn Forte EL(ha, "Unknown IP device=%xh\n", s_id.b24); 1223fcf3ce44SJohn Forte break; 1224fcf3ce44SJohn Forte } 1225fcf3ce44SJohn Forte 1226eb82ff87SDaniel Beauregard cnt = (uint16_t)(CFG_IST(ha, CFG_CTRL_24258081) ? 1227fcf3ce44SJohn Forte CHAR_TO_SHORT(ha->ip_init_ctrl_blk.cb24.buf_size[0], 1228fcf3ce44SJohn Forte ha->ip_init_ctrl_blk.cb24.buf_size[1]) : 1229fcf3ce44SJohn Forte CHAR_TO_SHORT(ha->ip_init_ctrl_blk.cb.buf_size[0], 1230fcf3ce44SJohn Forte ha->ip_init_ctrl_blk.cb.buf_size[1])); 1231fcf3ce44SJohn Forte 1232fcf3ce44SJohn Forte tq->ub_sequence_length = mb[3]; 1233fcf3ce44SJohn Forte tq->ub_total_seg_cnt = (uint8_t)(mb[3] / cnt); 1234fcf3ce44SJohn Forte if (mb[3] % cnt) { 1235fcf3ce44SJohn Forte tq->ub_total_seg_cnt++; 1236fcf3ce44SJohn Forte } 1237fcf3ce44SJohn Forte cnt = (uint16_t)(tq->ub_total_seg_cnt + 10); 1238fcf3ce44SJohn Forte 1239fcf3ce44SJohn Forte for (index = 10; index < ha->reg_off->mbox_cnt && index < cnt; 1240fcf3ce44SJohn Forte index++) { 1241eb82ff87SDaniel Beauregard mb[index] = RD16_IO_REG(ha, mailbox_out[index]); 1242fcf3ce44SJohn Forte } 1243fcf3ce44SJohn Forte 1244fcf3ce44SJohn Forte tq->ub_seq_id = ++ha->ub_seq_id; 1245fcf3ce44SJohn Forte tq->ub_seq_cnt = 0; 1246fcf3ce44SJohn Forte tq->ub_frame_ro = 0; 1247fcf3ce44SJohn Forte tq->ub_loop_id = (uint16_t)(mb[0] == MBA_IP_BROADCAST ? 1248eb82ff87SDaniel Beauregard (CFG_IST(ha, CFG_CTRL_24258081) ? BROADCAST_24XX_HDL : 1249fcf3ce44SJohn Forte IP_BROADCAST_LOOP_ID) : tq->loop_id); 1250fcf3ce44SJohn Forte ha->rcv_dev_q = tq; 1251fcf3ce44SJohn Forte 1252fcf3ce44SJohn Forte for (cnt = 10; cnt < ha->reg_off->mbox_cnt && 1253fcf3ce44SJohn Forte tq->ub_seq_cnt < tq->ub_total_seg_cnt; cnt++) { 1254fcf3ce44SJohn Forte if (ql_ub_frame_hdr(ha, tq, mb[cnt], done_q) != 1255fcf3ce44SJohn Forte QL_SUCCESS) { 1256fcf3ce44SJohn Forte EL(ha, "ql_ub_frame_hdr failed, " 1257fcf3ce44SJohn Forte "isp_abort_needed\n"); 1258fcf3ce44SJohn Forte *set_flags |= ISP_ABORT_NEEDED; 1259fcf3ce44SJohn Forte break; 1260fcf3ce44SJohn Forte } 1261fcf3ce44SJohn Forte } 1262fcf3ce44SJohn Forte break; 1263fcf3ce44SJohn Forte 1264fcf3ce44SJohn Forte case MBA_IP_LOW_WATER_MARK: 1265fcf3ce44SJohn Forte case MBA_IP_RCV_BUFFER_EMPTY: 1266fcf3ce44SJohn Forte EL(ha, "%xh IP low water mark / RCV buffer empty received\n", 1267fcf3ce44SJohn Forte mb[0]); 1268fcf3ce44SJohn Forte *set_flags |= NEED_UNSOLICITED_BUFFERS; 1269fcf3ce44SJohn Forte break; 1270fcf3ce44SJohn Forte 1271fcf3ce44SJohn Forte case MBA_IP_HDR_DATA_SPLIT: 1272fcf3ce44SJohn Forte EL(ha, "%xh IP HDR data split received\n", mb[0]); 1273fcf3ce44SJohn Forte break; 1274fcf3ce44SJohn Forte 12754f8b8adcSDaniel Beauregard case MBA_ERROR_LOGGING_DISABLED: 12764f8b8adcSDaniel Beauregard EL(ha, "%xh error logging disabled received, " 1277eb82ff87SDaniel Beauregard "mbx1=%xh\n", mb[0], RD16_IO_REG(ha, mailbox_out[1])); 12784f8b8adcSDaniel Beauregard break; 12794f8b8adcSDaniel Beauregard 1280fcf3ce44SJohn Forte case MBA_POINT_TO_POINT: 12815dfd244aSDaniel Beauregard /* case MBA_DCBX_COMPLETED: */ 1282eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_8081)) { 12835dfd244aSDaniel Beauregard EL(ha, "%xh DCBX completed received\n", mb[0]); 12845dfd244aSDaniel Beauregard } else { 12855dfd244aSDaniel Beauregard EL(ha, "%xh Point to Point Mode received\n", mb[0]); 12865dfd244aSDaniel Beauregard } 1287fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 1288fcf3ce44SJohn Forte ha->flags |= POINT_TO_POINT; 1289fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 12905dfd244aSDaniel Beauregard break; 1291fcf3ce44SJohn Forte 12925dfd244aSDaniel Beauregard case MBA_FCF_CONFIG_ERROR: 12934f8b8adcSDaniel Beauregard EL(ha, "%xh FCF configuration Error received, mbx1=%xh\n", 1294eb82ff87SDaniel Beauregard mb[0], RD16_IO_REG(ha, mailbox_out[1])); 12955dfd244aSDaniel Beauregard break; 1296fcf3ce44SJohn Forte 12974f8b8adcSDaniel Beauregard case MBA_DCBX_PARAM_CHANGED: 12984f8b8adcSDaniel Beauregard EL(ha, "%xh DCBX parameters changed received, mbx1=%xh\n", 1299eb82ff87SDaniel Beauregard mb[0], RD16_IO_REG(ha, mailbox_out[1])); 1300fcf3ce44SJohn Forte break; 1301fcf3ce44SJohn Forte 1302fcf3ce44SJohn Forte case MBA_CHG_IN_CONNECTION: 1303eb82ff87SDaniel Beauregard mb[1] = RD16_IO_REG(ha, mailbox_out[1]); 1304fcf3ce44SJohn Forte if (mb[1] == 2) { 1305fcf3ce44SJohn Forte EL(ha, "%xh Change In Connection received, " 1306fcf3ce44SJohn Forte "mbx1=%xh\n", mb[0], mb[1]); 1307fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 1308fcf3ce44SJohn Forte ha->flags &= ~POINT_TO_POINT; 1309fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 1310fcf3ce44SJohn Forte if (ha->topology & QL_N_PORT) { 1311fcf3ce44SJohn Forte ha->topology = (uint8_t)(ha->topology & 1312fcf3ce44SJohn Forte ~QL_N_PORT); 1313fcf3ce44SJohn Forte ha->topology = (uint8_t)(ha->topology | 1314fcf3ce44SJohn Forte QL_NL_PORT); 1315fcf3ce44SJohn Forte } 1316fcf3ce44SJohn Forte } else { 1317fcf3ce44SJohn Forte EL(ha, "%xh Change In Connection received, " 1318fcf3ce44SJohn Forte "mbx1=%xh, isp_abort_needed\n", mb[0], mb[1]); 1319fcf3ce44SJohn Forte *set_flags |= ISP_ABORT_NEEDED; 1320fcf3ce44SJohn Forte } 1321fcf3ce44SJohn Forte break; 1322fcf3ce44SJohn Forte 1323fcf3ce44SJohn Forte case MBA_ZIO_UPDATE: 1324fcf3ce44SJohn Forte EL(ha, "%xh ZIO response received\n", mb[0]); 1325fcf3ce44SJohn Forte 1326fcf3ce44SJohn Forte ha->isp_rsp_index = RD16_IO_REG(ha, resp_in); 1327fcf3ce44SJohn Forte ql_response_pkt(ha, done_q, set_flags, reset_flags, intr_clr); 1328fcf3ce44SJohn Forte intr = B_FALSE; 1329fcf3ce44SJohn Forte break; 1330fcf3ce44SJohn Forte 1331fcf3ce44SJohn Forte case MBA_PORT_BYPASS_CHANGED: 1332fcf3ce44SJohn Forte EL(ha, "%xh Port Bypass Changed received, mbx1=%xh\n", 1333eb82ff87SDaniel Beauregard mb[0], RD16_IO_REG(ha, mailbox_out[1])); 1334fcf3ce44SJohn Forte /* 1335fcf3ce44SJohn Forte * Event generated when there is a transition on 1336fcf3ce44SJohn Forte * port bypass of crystal+. 1337fcf3ce44SJohn Forte * Mailbox 1: Bit 0 - External. 1338fcf3ce44SJohn Forte * Bit 2 - Internal. 1339fcf3ce44SJohn Forte * When the bit is 0, the port is bypassed. 1340fcf3ce44SJohn Forte * 1341fcf3ce44SJohn Forte * For now we will generate a LIP for all cases. 1342fcf3ce44SJohn Forte */ 1343fcf3ce44SJohn Forte *set_flags |= HANDLE_PORT_BYPASS_CHANGE; 1344fcf3ce44SJohn Forte break; 1345fcf3ce44SJohn Forte 1346fcf3ce44SJohn Forte case MBA_RECEIVE_ERROR: 1347fcf3ce44SJohn Forte EL(ha, "%xh Receive Error received, mbx1=%xh, mbx2=%xh\n", 1348eb82ff87SDaniel Beauregard mb[0], RD16_IO_REG(ha, mailbox_out[1]), 1349eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[2])); 1350fcf3ce44SJohn Forte break; 1351fcf3ce44SJohn Forte 1352fcf3ce44SJohn Forte case MBA_LS_RJT_SENT: 1353fcf3ce44SJohn Forte EL(ha, "%xh LS_RJT Response Sent ELS=%xh\n", mb[0], 1354eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[1])); 1355fcf3ce44SJohn Forte break; 1356fcf3ce44SJohn Forte 1357fcf3ce44SJohn Forte case MBA_FW_RESTART_COMP: 1358fcf3ce44SJohn Forte EL(ha, "%xh firmware restart complete received mb1=%xh\n", 1359eb82ff87SDaniel Beauregard mb[0], RD16_IO_REG(ha, mailbox_out[1])); 1360fcf3ce44SJohn Forte break; 1361fcf3ce44SJohn Forte 1362*f885d00fSDaniel Beauregard /* 1363*f885d00fSDaniel Beauregard * MBA_IDC_COMPLETE & MBA_IDC_NOTIFICATION: We won't get another 1364*f885d00fSDaniel Beauregard * IDC async event until we ACK the current one. 1365*f885d00fSDaniel Beauregard */ 13665dfd244aSDaniel Beauregard case MBA_IDC_COMPLETE: 1367*f885d00fSDaniel Beauregard ha->idc_mb[0] = mb[0]; 1368*f885d00fSDaniel Beauregard ha->idc_mb[1] = RD16_IO_REG(ha, mailbox_out[1]); 1369*f885d00fSDaniel Beauregard ha->idc_mb[2] = RD16_IO_REG(ha, mailbox_out[2]); 1370*f885d00fSDaniel Beauregard ha->idc_mb[3] = RD16_IO_REG(ha, mailbox_out[3]); 1371*f885d00fSDaniel Beauregard ha->idc_mb[4] = RD16_IO_REG(ha, mailbox_out[4]); 1372*f885d00fSDaniel Beauregard ha->idc_mb[5] = RD16_IO_REG(ha, mailbox_out[5]); 1373*f885d00fSDaniel Beauregard ha->idc_mb[6] = RD16_IO_REG(ha, mailbox_out[6]); 1374*f885d00fSDaniel Beauregard ha->idc_mb[7] = RD16_IO_REG(ha, mailbox_out[7]); 13755dfd244aSDaniel Beauregard EL(ha, "%xh Inter-driver communication complete received, " 1376eb82ff87SDaniel Beauregard " mbx1=%xh, mbx2=%xh, mbx3=%xh, mbx4=%xh, mbx5=%xh," 1377*f885d00fSDaniel Beauregard " mbx6=%xh, mbx7=%xh\n", mb[0], ha->idc_mb[1], 1378*f885d00fSDaniel Beauregard ha->idc_mb[2], ha->idc_mb[3], ha->idc_mb[4], ha->idc_mb[5], 1379*f885d00fSDaniel Beauregard ha->idc_mb[6], ha->idc_mb[7]); 1380*f885d00fSDaniel Beauregard *set_flags |= IDC_EVENT; 13815dfd244aSDaniel Beauregard break; 13825dfd244aSDaniel Beauregard 13835dfd244aSDaniel Beauregard case MBA_IDC_NOTIFICATION: 1384*f885d00fSDaniel Beauregard ha->idc_mb[0] = mb[0]; 1385eb82ff87SDaniel Beauregard ha->idc_mb[1] = RD16_IO_REG(ha, mailbox_out[1]); 1386eb82ff87SDaniel Beauregard ha->idc_mb[2] = RD16_IO_REG(ha, mailbox_out[2]); 1387eb82ff87SDaniel Beauregard ha->idc_mb[3] = RD16_IO_REG(ha, mailbox_out[3]); 1388eb82ff87SDaniel Beauregard ha->idc_mb[4] = RD16_IO_REG(ha, mailbox_out[4]); 1389eb82ff87SDaniel Beauregard ha->idc_mb[5] = RD16_IO_REG(ha, mailbox_out[5]); 1390eb82ff87SDaniel Beauregard ha->idc_mb[6] = RD16_IO_REG(ha, mailbox_out[6]); 1391eb82ff87SDaniel Beauregard ha->idc_mb[7] = RD16_IO_REG(ha, mailbox_out[7]); 13925dfd244aSDaniel Beauregard EL(ha, "%xh Inter-driver communication request notification " 13935dfd244aSDaniel Beauregard "received, mbx1=%xh, mbx2=%xh, mbx3=%xh, mbx4=%xh, " 13945dfd244aSDaniel Beauregard "mbx5=%xh, mbx6=%xh, mbx7=%xh\n", mb[0], ha->idc_mb[1], 13955dfd244aSDaniel Beauregard ha->idc_mb[2], ha->idc_mb[3], ha->idc_mb[4], ha->idc_mb[5], 13965dfd244aSDaniel Beauregard ha->idc_mb[6], ha->idc_mb[7]); 1397*f885d00fSDaniel Beauregard *set_flags |= IDC_EVENT; 13985dfd244aSDaniel Beauregard break; 13995dfd244aSDaniel Beauregard 14005dfd244aSDaniel Beauregard case MBA_IDC_TIME_EXTENDED: 14015dfd244aSDaniel Beauregard EL(ha, "%xh Inter-driver communication time extended received," 14025dfd244aSDaniel Beauregard " mbx1=%xh, mbx2=%xh\n", mb[0], 1403eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[1]), 1404eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[2])); 14055dfd244aSDaniel Beauregard break; 14065dfd244aSDaniel Beauregard 1407fcf3ce44SJohn Forte default: 1408fcf3ce44SJohn Forte EL(ha, "%xh UNKNOWN event received, mbx1=%xh, mbx2=%xh, " 1409eb82ff87SDaniel Beauregard "mbx3=%xh\n", mb[0], RD16_IO_REG(ha, mailbox_out[1]), 1410eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[2]), 1411eb82ff87SDaniel Beauregard RD16_IO_REG(ha, mailbox_out[3])); 1412fcf3ce44SJohn Forte break; 1413fcf3ce44SJohn Forte } 1414fcf3ce44SJohn Forte 1415fcf3ce44SJohn Forte /* Clear RISC interrupt */ 1416fcf3ce44SJohn Forte if (intr && intr_clr) { 1417eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_8021)) { 1418eb82ff87SDaniel Beauregard ql_8021_clr_fw_intr(ha); 1419eb82ff87SDaniel Beauregard } else if (CFG_IST(ha, CFG_CTRL_242581)) { 1420eb82ff87SDaniel Beauregard WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT); 1421eb82ff87SDaniel Beauregard } else { 1422eb82ff87SDaniel Beauregard WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT); 1423eb82ff87SDaniel Beauregard } 1424fcf3ce44SJohn Forte } 1425fcf3ce44SJohn Forte 1426fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 1427fcf3ce44SJohn Forte } 1428fcf3ce44SJohn Forte 1429fcf3ce44SJohn Forte /* 1430fcf3ce44SJohn Forte * ql_fast_fcp_post 1431fcf3ce44SJohn Forte * Fast path for good SCSI I/O completion. 1432fcf3ce44SJohn Forte * 1433fcf3ce44SJohn Forte * Input: 1434fcf3ce44SJohn Forte * sp: SRB pointer. 1435fcf3ce44SJohn Forte * 1436fcf3ce44SJohn Forte * Context: 1437fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 1438fcf3ce44SJohn Forte */ 1439fcf3ce44SJohn Forte static void 1440fcf3ce44SJohn Forte ql_fast_fcp_post(ql_srb_t *sp) 1441fcf3ce44SJohn Forte { 1442fcf3ce44SJohn Forte ql_adapter_state_t *ha = sp->ha; 1443fcf3ce44SJohn Forte ql_lun_t *lq = sp->lun_queue; 1444fcf3ce44SJohn Forte ql_tgt_t *tq = lq->target_queue; 1445fcf3ce44SJohn Forte 1446fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 1447fcf3ce44SJohn Forte 1448fcf3ce44SJohn Forte /* Acquire device queue lock. */ 1449fcf3ce44SJohn Forte DEVICE_QUEUE_LOCK(tq); 1450fcf3ce44SJohn Forte 1451fcf3ce44SJohn Forte /* Decrement outstanding commands on device. */ 1452fcf3ce44SJohn Forte if (tq->outcnt != 0) { 1453fcf3ce44SJohn Forte tq->outcnt--; 1454fcf3ce44SJohn Forte } 1455fcf3ce44SJohn Forte 1456fcf3ce44SJohn Forte if (sp->flags & SRB_FCP_CMD_PKT) { 1457fcf3ce44SJohn Forte if (sp->fcp->fcp_cntl.cntl_qtype == FCP_QTYPE_UNTAGGED) { 1458fcf3ce44SJohn Forte /* 1459fcf3ce44SJohn Forte * Clear the flag for this LUN so that 1460fcf3ce44SJohn Forte * untagged commands can be submitted 1461fcf3ce44SJohn Forte * for it. 1462fcf3ce44SJohn Forte */ 1463fcf3ce44SJohn Forte lq->flags &= ~LQF_UNTAGGED_PENDING; 1464fcf3ce44SJohn Forte } 1465fcf3ce44SJohn Forte 1466fcf3ce44SJohn Forte if (lq->lun_outcnt != 0) { 1467fcf3ce44SJohn Forte lq->lun_outcnt--; 1468fcf3ce44SJohn Forte } 1469fcf3ce44SJohn Forte } 1470fcf3ce44SJohn Forte 1471fcf3ce44SJohn Forte /* Reset port down retry count on good completion. */ 1472fcf3ce44SJohn Forte tq->port_down_retry_count = ha->port_down_retry_count; 1473fcf3ce44SJohn Forte tq->qfull_retry_count = ha->qfull_retry_count; 1474*f885d00fSDaniel Beauregard ha->pha->timeout_cnt = 0; 1475fcf3ce44SJohn Forte 1476fcf3ce44SJohn Forte /* Remove command from watchdog queue. */ 1477fcf3ce44SJohn Forte if (sp->flags & SRB_WATCHDOG_ENABLED) { 1478fcf3ce44SJohn Forte ql_remove_link(&tq->wdg, &sp->wdg); 1479fcf3ce44SJohn Forte sp->flags &= ~SRB_WATCHDOG_ENABLED; 1480fcf3ce44SJohn Forte } 1481fcf3ce44SJohn Forte 1482fcf3ce44SJohn Forte if (lq->cmd.first != NULL) { 1483fcf3ce44SJohn Forte ql_next(ha, lq); 1484fcf3ce44SJohn Forte } else { 1485fcf3ce44SJohn Forte /* Release LU queue specific lock. */ 1486fcf3ce44SJohn Forte DEVICE_QUEUE_UNLOCK(tq); 1487fcf3ce44SJohn Forte if (ha->pha->pending_cmds.first != NULL) { 1488fcf3ce44SJohn Forte ql_start_iocb(ha, NULL); 1489fcf3ce44SJohn Forte } 1490fcf3ce44SJohn Forte } 1491fcf3ce44SJohn Forte 1492fcf3ce44SJohn Forte /* Sync buffers if required. */ 1493fcf3ce44SJohn Forte if (sp->flags & SRB_MS_PKT) { 1494fcf3ce44SJohn Forte (void) ddi_dma_sync(sp->pkt->pkt_resp_dma, 0, 0, 1495fcf3ce44SJohn Forte DDI_DMA_SYNC_FORCPU); 1496fcf3ce44SJohn Forte } 1497fcf3ce44SJohn Forte 1498fcf3ce44SJohn Forte /* Map ISP completion codes. */ 1499fcf3ce44SJohn Forte sp->pkt->pkt_expln = FC_EXPLN_NONE; 1500fcf3ce44SJohn Forte sp->pkt->pkt_action = FC_ACTION_RETRYABLE; 1501fcf3ce44SJohn Forte sp->pkt->pkt_state = FC_PKT_SUCCESS; 1502fcf3ce44SJohn Forte 1503fcf3ce44SJohn Forte /* Now call the pkt completion callback */ 1504fcf3ce44SJohn Forte if (sp->flags & SRB_POLL) { 1505fcf3ce44SJohn Forte sp->flags &= ~SRB_POLL; 1506fcf3ce44SJohn Forte } else if (sp->pkt->pkt_comp) { 1507fcf3ce44SJohn Forte INTR_UNLOCK(ha); 1508fcf3ce44SJohn Forte (*sp->pkt->pkt_comp)(sp->pkt); 1509fcf3ce44SJohn Forte INTR_LOCK(ha); 1510fcf3ce44SJohn Forte } 1511fcf3ce44SJohn Forte 1512fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 1513fcf3ce44SJohn Forte } 1514fcf3ce44SJohn Forte 1515fcf3ce44SJohn Forte /* 1516fcf3ce44SJohn Forte * ql_response_pkt 1517fcf3ce44SJohn Forte * Processes response entry. 1518fcf3ce44SJohn Forte * 1519fcf3ce44SJohn Forte * Input: 1520fcf3ce44SJohn Forte * ha: adapter state pointer. 1521fcf3ce44SJohn Forte * done_q: head pointer to done queue. 1522fcf3ce44SJohn Forte * set_flags: task daemon flags to set. 1523fcf3ce44SJohn Forte * reset_flags: task daemon flags to reset. 1524fcf3ce44SJohn Forte * intr_clr: early interrupt clear 1525fcf3ce44SJohn Forte * 1526fcf3ce44SJohn Forte * Context: 1527fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 1528fcf3ce44SJohn Forte */ 1529fcf3ce44SJohn Forte static void 1530fcf3ce44SJohn Forte ql_response_pkt(ql_adapter_state_t *ha, ql_head_t *done_q, uint32_t *set_flags, 1531fcf3ce44SJohn Forte uint32_t *reset_flags, int intr_clr) 1532fcf3ce44SJohn Forte { 1533fcf3ce44SJohn Forte response_t *pkt; 1534fcf3ce44SJohn Forte uint32_t dma_sync_size_1 = 0; 1535fcf3ce44SJohn Forte uint32_t dma_sync_size_2 = 0; 1536fcf3ce44SJohn Forte int status = 0; 1537fcf3ce44SJohn Forte 1538fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 1539fcf3ce44SJohn Forte 1540fcf3ce44SJohn Forte /* Clear RISC interrupt */ 1541fcf3ce44SJohn Forte if (intr_clr) { 1542eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_8021)) { 1543eb82ff87SDaniel Beauregard ql_8021_clr_fw_intr(ha); 1544eb82ff87SDaniel Beauregard } else if (CFG_IST(ha, CFG_CTRL_242581)) { 1545eb82ff87SDaniel Beauregard WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT); 1546eb82ff87SDaniel Beauregard } else { 1547eb82ff87SDaniel Beauregard WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT); 1548eb82ff87SDaniel Beauregard } 1549fcf3ce44SJohn Forte } 1550fcf3ce44SJohn Forte 1551fcf3ce44SJohn Forte if (ha->isp_rsp_index >= RESPONSE_ENTRY_CNT) { 1552fcf3ce44SJohn Forte EL(ha, "index error = %xh, isp_abort_needed", 1553fcf3ce44SJohn Forte ha->isp_rsp_index); 1554fcf3ce44SJohn Forte *set_flags |= ISP_ABORT_NEEDED; 1555fcf3ce44SJohn Forte return; 1556fcf3ce44SJohn Forte } 1557fcf3ce44SJohn Forte 1558fcf3ce44SJohn Forte if ((ha->flags & ONLINE) == 0) { 1559fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): not onlne, done\n", ha->instance); 1560fcf3ce44SJohn Forte return; 1561fcf3ce44SJohn Forte } 1562fcf3ce44SJohn Forte 1563fcf3ce44SJohn Forte /* Calculate size of response queue entries to sync. */ 1564fcf3ce44SJohn Forte if (ha->isp_rsp_index > ha->rsp_ring_index) { 1565fcf3ce44SJohn Forte dma_sync_size_1 = (uint32_t) 1566fcf3ce44SJohn Forte ((uint32_t)(ha->isp_rsp_index - ha->rsp_ring_index) * 1567fcf3ce44SJohn Forte RESPONSE_ENTRY_SIZE); 1568fcf3ce44SJohn Forte } else if (ha->isp_rsp_index == 0) { 1569fcf3ce44SJohn Forte dma_sync_size_1 = (uint32_t) 1570fcf3ce44SJohn Forte ((uint32_t)(RESPONSE_ENTRY_CNT - ha->rsp_ring_index) * 1571fcf3ce44SJohn Forte RESPONSE_ENTRY_SIZE); 1572fcf3ce44SJohn Forte } else { 1573fcf3ce44SJohn Forte /* Responses wrap around the Q */ 1574fcf3ce44SJohn Forte dma_sync_size_1 = (uint32_t) 1575fcf3ce44SJohn Forte ((uint32_t)(RESPONSE_ENTRY_CNT - ha->rsp_ring_index) * 1576fcf3ce44SJohn Forte RESPONSE_ENTRY_SIZE); 1577fcf3ce44SJohn Forte dma_sync_size_2 = (uint32_t) 1578fcf3ce44SJohn Forte (ha->isp_rsp_index * RESPONSE_ENTRY_SIZE); 1579fcf3ce44SJohn Forte } 1580fcf3ce44SJohn Forte 1581fcf3ce44SJohn Forte /* Sync DMA buffer. */ 1582fcf3ce44SJohn Forte (void) ddi_dma_sync(ha->hba_buf.dma_handle, 1583fcf3ce44SJohn Forte (off_t)(ha->rsp_ring_index * RESPONSE_ENTRY_SIZE + 1584fcf3ce44SJohn Forte RESPONSE_Q_BUFFER_OFFSET), dma_sync_size_1, 1585fcf3ce44SJohn Forte DDI_DMA_SYNC_FORKERNEL); 1586fcf3ce44SJohn Forte if (dma_sync_size_2) { 1587fcf3ce44SJohn Forte (void) ddi_dma_sync(ha->hba_buf.dma_handle, 1588fcf3ce44SJohn Forte RESPONSE_Q_BUFFER_OFFSET, dma_sync_size_2, 1589fcf3ce44SJohn Forte DDI_DMA_SYNC_FORKERNEL); 1590fcf3ce44SJohn Forte } 1591fcf3ce44SJohn Forte 1592fcf3ce44SJohn Forte while (ha->rsp_ring_index != ha->isp_rsp_index) { 1593fcf3ce44SJohn Forte pkt = ha->response_ring_ptr; 1594fcf3ce44SJohn Forte 1595fcf3ce44SJohn Forte QL_PRINT_5(CE_CONT, "(%d): ha->rsp_rg_idx=%xh, mbx[5]=%xh\n", 1596fcf3ce44SJohn Forte ha->instance, ha->rsp_ring_index, ha->isp_rsp_index); 1597fcf3ce44SJohn Forte QL_DUMP_5((uint8_t *)ha->response_ring_ptr, 8, 1598fcf3ce44SJohn Forte RESPONSE_ENTRY_SIZE); 1599fcf3ce44SJohn Forte 1600fcf3ce44SJohn Forte /* Adjust ring index. */ 1601fcf3ce44SJohn Forte ha->rsp_ring_index++; 1602fcf3ce44SJohn Forte if (ha->rsp_ring_index == RESPONSE_ENTRY_CNT) { 1603fcf3ce44SJohn Forte ha->rsp_ring_index = 0; 1604fcf3ce44SJohn Forte ha->response_ring_ptr = ha->response_ring_bp; 1605fcf3ce44SJohn Forte } else { 1606fcf3ce44SJohn Forte ha->response_ring_ptr++; 1607fcf3ce44SJohn Forte } 1608fcf3ce44SJohn Forte 1609fcf3ce44SJohn Forte /* Process packet. */ 1610fcf3ce44SJohn Forte if (ha->status_srb != NULL && pkt->entry_type != 1611fcf3ce44SJohn Forte STATUS_CONT_TYPE) { 1612fcf3ce44SJohn Forte ql_add_link_b(done_q, &ha->status_srb->cmd); 1613fcf3ce44SJohn Forte ha->status_srb = NULL; 1614fcf3ce44SJohn Forte } 1615fcf3ce44SJohn Forte 1616eb82ff87SDaniel Beauregard pkt->entry_status = (uint8_t)(CFG_IST(ha, CFG_CTRL_24258081) ? 1617fcf3ce44SJohn Forte pkt->entry_status & 0x3c : pkt->entry_status & 0x7e); 1618fcf3ce44SJohn Forte 1619fcf3ce44SJohn Forte if (pkt->entry_status != 0) { 1620fcf3ce44SJohn Forte ql_error_entry(ha, pkt, done_q, set_flags, 1621fcf3ce44SJohn Forte reset_flags); 1622fcf3ce44SJohn Forte } else { 1623fcf3ce44SJohn Forte switch (pkt->entry_type) { 1624fcf3ce44SJohn Forte case STATUS_TYPE: 1625eb82ff87SDaniel Beauregard status |= CFG_IST(ha, CFG_CTRL_24258081) ? 1626fcf3ce44SJohn Forte ql_24xx_status_entry(ha, 1627fcf3ce44SJohn Forte (sts_24xx_entry_t *)pkt, done_q, set_flags, 1628fcf3ce44SJohn Forte reset_flags) : 1629fcf3ce44SJohn Forte ql_status_entry(ha, (sts_entry_t *)pkt, 1630fcf3ce44SJohn Forte done_q, set_flags, reset_flags); 1631fcf3ce44SJohn Forte break; 1632fcf3ce44SJohn Forte case STATUS_CONT_TYPE: 1633fcf3ce44SJohn Forte ql_status_cont_entry(ha, 1634fcf3ce44SJohn Forte (sts_cont_entry_t *)pkt, done_q, set_flags, 1635fcf3ce44SJohn Forte reset_flags); 1636fcf3ce44SJohn Forte break; 1637fcf3ce44SJohn Forte case IP_TYPE: 1638fcf3ce44SJohn Forte case IP_A64_TYPE: 1639fcf3ce44SJohn Forte case IP_CMD_TYPE: 1640fcf3ce44SJohn Forte ql_ip_entry(ha, (ip_entry_t *)pkt, done_q, 1641fcf3ce44SJohn Forte set_flags, reset_flags); 1642fcf3ce44SJohn Forte break; 1643fcf3ce44SJohn Forte case IP_RECEIVE_TYPE: 1644fcf3ce44SJohn Forte ql_ip_rcv_entry(ha, 1645fcf3ce44SJohn Forte (ip_rcv_entry_t *)pkt, done_q, set_flags, 1646fcf3ce44SJohn Forte reset_flags); 1647fcf3ce44SJohn Forte break; 1648fcf3ce44SJohn Forte case IP_RECEIVE_CONT_TYPE: 1649fcf3ce44SJohn Forte ql_ip_rcv_cont_entry(ha, 1650fcf3ce44SJohn Forte (ip_rcv_cont_entry_t *)pkt, done_q, 1651fcf3ce44SJohn Forte set_flags, reset_flags); 1652fcf3ce44SJohn Forte break; 1653fcf3ce44SJohn Forte case IP_24XX_RECEIVE_TYPE: 1654fcf3ce44SJohn Forte ql_ip_24xx_rcv_entry(ha, 1655fcf3ce44SJohn Forte (ip_rcv_24xx_entry_t *)pkt, done_q, 1656fcf3ce44SJohn Forte set_flags, reset_flags); 1657fcf3ce44SJohn Forte break; 1658fcf3ce44SJohn Forte case MS_TYPE: 1659fcf3ce44SJohn Forte ql_ms_entry(ha, (ms_entry_t *)pkt, done_q, 1660fcf3ce44SJohn Forte set_flags, reset_flags); 1661fcf3ce44SJohn Forte break; 1662fcf3ce44SJohn Forte case REPORT_ID_TYPE: 1663fcf3ce44SJohn Forte ql_report_id_entry(ha, (report_id_1_t *)pkt, 1664fcf3ce44SJohn Forte done_q, set_flags, reset_flags); 1665fcf3ce44SJohn Forte break; 16665dfd244aSDaniel Beauregard case ELS_PASSTHRU_TYPE: 16675dfd244aSDaniel Beauregard ql_els_passthru_entry(ha, 16685dfd244aSDaniel Beauregard (els_passthru_entry_rsp_t *)pkt, 16695dfd244aSDaniel Beauregard done_q, set_flags, reset_flags); 16705dfd244aSDaniel Beauregard break; 1671fcf3ce44SJohn Forte case IP_BUF_POOL_TYPE: 1672fcf3ce44SJohn Forte case MARKER_TYPE: 1673fcf3ce44SJohn Forte case VP_MODIFY_TYPE: 1674fcf3ce44SJohn Forte case VP_CONTROL_TYPE: 1675fcf3ce44SJohn Forte break; 1676fcf3ce44SJohn Forte default: 1677fcf3ce44SJohn Forte EL(ha, "Unknown IOCB entry type=%xh\n", 1678fcf3ce44SJohn Forte pkt->entry_type); 1679fcf3ce44SJohn Forte break; 1680fcf3ce44SJohn Forte } 1681fcf3ce44SJohn Forte } 1682fcf3ce44SJohn Forte } 1683fcf3ce44SJohn Forte 1684fcf3ce44SJohn Forte /* Inform RISC of processed responses. */ 1685fcf3ce44SJohn Forte WRT16_IO_REG(ha, resp_out, ha->rsp_ring_index); 1686fcf3ce44SJohn Forte 1687fcf3ce44SJohn Forte /* RESET packet received delay for possible async event. */ 1688fcf3ce44SJohn Forte if (status & BIT_0) { 1689fcf3ce44SJohn Forte drv_usecwait(500000); 1690fcf3ce44SJohn Forte } 1691fcf3ce44SJohn Forte 1692fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 1693fcf3ce44SJohn Forte } 1694fcf3ce44SJohn Forte 1695fcf3ce44SJohn Forte /* 1696fcf3ce44SJohn Forte * ql_error_entry 1697fcf3ce44SJohn Forte * Processes error entry. 1698fcf3ce44SJohn Forte * 1699fcf3ce44SJohn Forte * Input: 1700fcf3ce44SJohn Forte * ha = adapter state pointer. 1701fcf3ce44SJohn Forte * pkt = entry pointer. 1702fcf3ce44SJohn Forte * done_q = head pointer to done queue. 1703fcf3ce44SJohn Forte * set_flags = task daemon flags to set. 1704fcf3ce44SJohn Forte * reset_flags = task daemon flags to reset. 1705fcf3ce44SJohn Forte * 1706fcf3ce44SJohn Forte * Context: 1707fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 1708fcf3ce44SJohn Forte */ 1709fcf3ce44SJohn Forte /* ARGSUSED */ 1710fcf3ce44SJohn Forte static void 1711fcf3ce44SJohn Forte ql_error_entry(ql_adapter_state_t *ha, response_t *pkt, ql_head_t *done_q, 1712fcf3ce44SJohn Forte uint32_t *set_flags, uint32_t *reset_flags) 1713fcf3ce44SJohn Forte { 1714fcf3ce44SJohn Forte ql_srb_t *sp; 1715a2b3ff35SDaniel Beauregard uint32_t index, resp_identifier; 1716fcf3ce44SJohn Forte 1717fcf3ce44SJohn Forte if (pkt->entry_type == INVALID_ENTRY_TYPE) { 1718fcf3ce44SJohn Forte EL(ha, "Aborted command\n"); 1719fcf3ce44SJohn Forte return; 1720fcf3ce44SJohn Forte } 1721fcf3ce44SJohn Forte 1722fcf3ce44SJohn Forte QL_PRINT_2(CE_CONT, "(%d): started, packet:\n", ha->instance); 1723fcf3ce44SJohn Forte QL_DUMP_2((uint8_t *)pkt, 8, RESPONSE_ENTRY_SIZE); 1724fcf3ce44SJohn Forte 1725fcf3ce44SJohn Forte if (pkt->entry_status & BIT_6) { 1726fcf3ce44SJohn Forte EL(ha, "Request Queue DMA error\n"); 1727fcf3ce44SJohn Forte } else if (pkt->entry_status & BIT_5) { 1728fcf3ce44SJohn Forte EL(ha, "Invalid Entry Order\n"); 1729fcf3ce44SJohn Forte } else if (pkt->entry_status & BIT_4) { 1730fcf3ce44SJohn Forte EL(ha, "Invalid Entry Count\n"); 1731fcf3ce44SJohn Forte } else if (pkt->entry_status & BIT_3) { 1732fcf3ce44SJohn Forte EL(ha, "Invalid Entry Parameter\n"); 1733fcf3ce44SJohn Forte } else if (pkt->entry_status & BIT_2) { 1734fcf3ce44SJohn Forte EL(ha, "Invalid Entry Type\n"); 1735fcf3ce44SJohn Forte } else if (pkt->entry_status & BIT_1) { 1736fcf3ce44SJohn Forte EL(ha, "Busy\n"); 1737fcf3ce44SJohn Forte } else { 1738fcf3ce44SJohn Forte EL(ha, "UNKNOWN flag = %xh error\n", pkt->entry_status); 1739fcf3ce44SJohn Forte } 1740fcf3ce44SJohn Forte 1741a2b3ff35SDaniel Beauregard /* Validate the response entry handle. */ 1742a2b3ff35SDaniel Beauregard resp_identifier = ddi_get32(ha->hba_buf.acc_handle, &pkt->handle); 1743a2b3ff35SDaniel Beauregard index = resp_identifier & OSC_INDEX_MASK; 1744a2b3ff35SDaniel Beauregard if (index < MAX_OUTSTANDING_COMMANDS) { 1745a2b3ff35SDaniel Beauregard /* the index seems reasonable */ 1746a2b3ff35SDaniel Beauregard sp = ha->outstanding_cmds[index]; 1747a2b3ff35SDaniel Beauregard if (sp != NULL) { 1748a2b3ff35SDaniel Beauregard if (sp->handle == resp_identifier) { 1749a2b3ff35SDaniel Beauregard /* Neo, you're the one... */ 1750a2b3ff35SDaniel Beauregard ha->outstanding_cmds[index] = NULL; 1751a2b3ff35SDaniel Beauregard sp->handle = 0; 1752a2b3ff35SDaniel Beauregard sp->flags &= ~SRB_IN_TOKEN_ARRAY; 1753a2b3ff35SDaniel Beauregard } else { 1754a2b3ff35SDaniel Beauregard EL(ha, "IOCB handle mismatch pkt=%xh, sp=%xh\n", 1755a2b3ff35SDaniel Beauregard resp_identifier, sp->handle); 1756a2b3ff35SDaniel Beauregard sp = NULL; 1757a2b3ff35SDaniel Beauregard ql_signal_abort(ha, set_flags); 1758a2b3ff35SDaniel Beauregard } 1759a2b3ff35SDaniel Beauregard } else { 1760a2b3ff35SDaniel Beauregard sp = ql_verify_preprocessed_cmd(ha, 1761a2b3ff35SDaniel Beauregard (uint32_t *)&pkt->handle, set_flags, reset_flags); 1762a2b3ff35SDaniel Beauregard } 1763a2b3ff35SDaniel Beauregard } else { 1764a2b3ff35SDaniel Beauregard EL(ha, "osc index out of range, index=%xh, handle=%xh\n", 1765a2b3ff35SDaniel Beauregard index, resp_identifier); 1766a2b3ff35SDaniel Beauregard ql_signal_abort(ha, set_flags); 1767a2b3ff35SDaniel Beauregard } 1768fcf3ce44SJohn Forte 1769a2b3ff35SDaniel Beauregard if (sp != NULL) { 1770fcf3ce44SJohn Forte /* Bad payload or header */ 1771fcf3ce44SJohn Forte if (pkt->entry_status & (BIT_5 + BIT_4 + BIT_3 + BIT_2)) { 1772fcf3ce44SJohn Forte /* Bad payload or header, set error status. */ 1773fcf3ce44SJohn Forte sp->pkt->pkt_reason = CS_BAD_PAYLOAD; 1774fcf3ce44SJohn Forte } else if (pkt->entry_status & BIT_1) /* FULL flag */ { 1775fcf3ce44SJohn Forte sp->pkt->pkt_reason = CS_QUEUE_FULL; 1776fcf3ce44SJohn Forte } else { 1777fcf3ce44SJohn Forte /* Set error status. */ 1778fcf3ce44SJohn Forte sp->pkt->pkt_reason = CS_UNKNOWN; 1779fcf3ce44SJohn Forte } 1780fcf3ce44SJohn Forte 1781fcf3ce44SJohn Forte /* Set completed status. */ 1782fcf3ce44SJohn Forte sp->flags |= SRB_ISP_COMPLETED; 1783fcf3ce44SJohn Forte 1784fcf3ce44SJohn Forte /* Place command on done queue. */ 1785fcf3ce44SJohn Forte ql_add_link_b(done_q, &sp->cmd); 1786fcf3ce44SJohn Forte 1787fcf3ce44SJohn Forte } 1788fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 1789fcf3ce44SJohn Forte } 1790fcf3ce44SJohn Forte 1791fcf3ce44SJohn Forte /* 1792fcf3ce44SJohn Forte * ql_status_entry 1793fcf3ce44SJohn Forte * Processes received ISP2200-2300 status entry. 1794fcf3ce44SJohn Forte * 1795fcf3ce44SJohn Forte * Input: 1796fcf3ce44SJohn Forte * ha: adapter state pointer. 1797fcf3ce44SJohn Forte * pkt: entry pointer. 1798fcf3ce44SJohn Forte * done_q: done queue pointer. 1799fcf3ce44SJohn Forte * set_flags: task daemon flags to set. 1800fcf3ce44SJohn Forte * reset_flags: task daemon flags to reset. 1801fcf3ce44SJohn Forte * 1802fcf3ce44SJohn Forte * Returns: 1803fcf3ce44SJohn Forte * BIT_0 = CS_RESET status received. 1804fcf3ce44SJohn Forte * 1805fcf3ce44SJohn Forte * Context: 1806fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 1807fcf3ce44SJohn Forte */ 1808fcf3ce44SJohn Forte /* ARGSUSED */ 1809fcf3ce44SJohn Forte static int 1810fcf3ce44SJohn Forte ql_status_entry(ql_adapter_state_t *ha, sts_entry_t *pkt, 1811fcf3ce44SJohn Forte ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags) 1812fcf3ce44SJohn Forte { 1813fcf3ce44SJohn Forte ql_srb_t *sp; 1814a2b3ff35SDaniel Beauregard uint32_t index, resp_identifier; 1815fcf3ce44SJohn Forte uint16_t comp_status; 1816fcf3ce44SJohn Forte int rval = 0; 1817fcf3ce44SJohn Forte 1818fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 1819fcf3ce44SJohn Forte 1820a2b3ff35SDaniel Beauregard /* Validate the response entry handle. */ 1821a2b3ff35SDaniel Beauregard resp_identifier = ddi_get32(ha->hba_buf.acc_handle, &pkt->handle); 1822a2b3ff35SDaniel Beauregard index = resp_identifier & OSC_INDEX_MASK; 1823a2b3ff35SDaniel Beauregard if (index < MAX_OUTSTANDING_COMMANDS) { 1824a2b3ff35SDaniel Beauregard /* the index seems reasonable */ 1825a2b3ff35SDaniel Beauregard sp = ha->outstanding_cmds[index]; 1826a2b3ff35SDaniel Beauregard if (sp != NULL) { 1827a2b3ff35SDaniel Beauregard if (sp->handle == resp_identifier) { 1828a2b3ff35SDaniel Beauregard /* Neo, you're the one... */ 1829a2b3ff35SDaniel Beauregard ha->outstanding_cmds[index] = NULL; 1830a2b3ff35SDaniel Beauregard sp->handle = 0; 1831a2b3ff35SDaniel Beauregard sp->flags &= ~SRB_IN_TOKEN_ARRAY; 1832a2b3ff35SDaniel Beauregard } else { 1833a2b3ff35SDaniel Beauregard EL(ha, "IOCB handle mismatch pkt=%xh, sp=%xh\n", 1834a2b3ff35SDaniel Beauregard resp_identifier, sp->handle); 1835a2b3ff35SDaniel Beauregard sp = NULL; 1836a2b3ff35SDaniel Beauregard ql_signal_abort(ha, set_flags); 1837a2b3ff35SDaniel Beauregard } 1838a2b3ff35SDaniel Beauregard } else { 1839a2b3ff35SDaniel Beauregard sp = ql_verify_preprocessed_cmd(ha, 1840a2b3ff35SDaniel Beauregard (uint32_t *)&pkt->handle, set_flags, reset_flags); 1841a2b3ff35SDaniel Beauregard } 1842a2b3ff35SDaniel Beauregard } else { 1843a2b3ff35SDaniel Beauregard EL(ha, "osc index out of range, index=%xh, handle=%xh\n", 1844a2b3ff35SDaniel Beauregard index, resp_identifier); 1845a2b3ff35SDaniel Beauregard ql_signal_abort(ha, set_flags); 1846a2b3ff35SDaniel Beauregard } 1847fcf3ce44SJohn Forte 1848a2b3ff35SDaniel Beauregard if (sp != NULL) { 1849fcf3ce44SJohn Forte comp_status = (uint16_t)ddi_get16(ha->hba_buf.acc_handle, 1850fcf3ce44SJohn Forte &pkt->comp_status); 1851fcf3ce44SJohn Forte 1852fcf3ce44SJohn Forte /* 1853fcf3ce44SJohn Forte * We dont care about SCSI QFULLs. 1854fcf3ce44SJohn Forte */ 1855fcf3ce44SJohn Forte if (comp_status == CS_QUEUE_FULL) { 1856fcf3ce44SJohn Forte EL(ha, "CS_QUEUE_FULL, d_id=%xh, lun=%xh\n", 1857fcf3ce44SJohn Forte sp->lun_queue->target_queue->d_id.b24, 1858fcf3ce44SJohn Forte sp->lun_queue->lun_no); 1859fcf3ce44SJohn Forte comp_status = CS_COMPLETE; 1860fcf3ce44SJohn Forte } 1861fcf3ce44SJohn Forte 1862fcf3ce44SJohn Forte /* 1863fcf3ce44SJohn Forte * 2300 firmware marks completion status as data underrun 1864fcf3ce44SJohn Forte * for scsi qfulls. Make it transport complete. 1865fcf3ce44SJohn Forte */ 1866fcf3ce44SJohn Forte if ((CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322))) && 1867fcf3ce44SJohn Forte (comp_status == CS_DATA_UNDERRUN) && 1868fcf3ce44SJohn Forte (pkt->scsi_status_l != 0)) { 1869fcf3ce44SJohn Forte comp_status = CS_COMPLETE; 1870fcf3ce44SJohn Forte } 1871fcf3ce44SJohn Forte 1872fcf3ce44SJohn Forte /* 1873fcf3ce44SJohn Forte * Workaround T3 issue where we do not get any data xferred 1874fcf3ce44SJohn Forte * but get back a good status. 1875fcf3ce44SJohn Forte */ 1876fcf3ce44SJohn Forte if ((pkt->state_flags_h & SF_XFERRED_DATA) == 0 && 1877fcf3ce44SJohn Forte comp_status == CS_COMPLETE && 1878fcf3ce44SJohn Forte pkt->scsi_status_l == 0 && 1879fcf3ce44SJohn Forte (pkt->scsi_status_h & FCP_RSP_MASK) == 0 && 1880fcf3ce44SJohn Forte pkt->residual_length == 0 && 1881fcf3ce44SJohn Forte sp->fcp && 1882fcf3ce44SJohn Forte sp->fcp->fcp_data_len != 0 && 1883fcf3ce44SJohn Forte (pkt->state_flags_l & (SF_DATA_OUT | SF_DATA_IN)) == 1884fcf3ce44SJohn Forte SF_DATA_OUT) { 1885fcf3ce44SJohn Forte comp_status = CS_ABORTED; 1886fcf3ce44SJohn Forte } 1887fcf3ce44SJohn Forte 1888fcf3ce44SJohn Forte if (sp->flags & SRB_MS_PKT) { 1889fcf3ce44SJohn Forte /* 1890fcf3ce44SJohn Forte * Ideally it should never be true. But there 1891fcf3ce44SJohn Forte * is a bug in FW which upon receiving invalid 1892fcf3ce44SJohn Forte * parameters in MS IOCB returns it as 1893fcf3ce44SJohn Forte * status entry and not as ms entry type. 1894fcf3ce44SJohn Forte */ 1895fcf3ce44SJohn Forte ql_ms_entry(ha, (ms_entry_t *)pkt, done_q, 1896fcf3ce44SJohn Forte set_flags, reset_flags); 1897fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): ql_ms_entry done\n", 1898fcf3ce44SJohn Forte ha->instance); 1899fcf3ce44SJohn Forte return (0); 1900fcf3ce44SJohn Forte } 1901fcf3ce44SJohn Forte 1902fcf3ce44SJohn Forte /* 1903fcf3ce44SJohn Forte * Fast path to good SCSI I/O completion 1904fcf3ce44SJohn Forte */ 1905fcf3ce44SJohn Forte if ((comp_status == CS_COMPLETE) & 1906fcf3ce44SJohn Forte (!pkt->scsi_status_l) & 1907fcf3ce44SJohn Forte (!(pkt->scsi_status_h & FCP_RSP_MASK))) { 1908fcf3ce44SJohn Forte /* Set completed status. */ 1909fcf3ce44SJohn Forte sp->flags |= SRB_ISP_COMPLETED; 1910fcf3ce44SJohn Forte sp->pkt->pkt_reason = comp_status; 1911fcf3ce44SJohn Forte ql_fast_fcp_post(sp); 1912fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): ql_fast_fcp_post done\n", 1913fcf3ce44SJohn Forte ha->instance); 1914fcf3ce44SJohn Forte return (0); 1915fcf3ce44SJohn Forte } 1916fcf3ce44SJohn Forte rval = ql_status_error(ha, sp, pkt, done_q, set_flags, 1917fcf3ce44SJohn Forte reset_flags); 1918fcf3ce44SJohn Forte } 1919fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 1920fcf3ce44SJohn Forte 1921fcf3ce44SJohn Forte return (rval); 1922fcf3ce44SJohn Forte } 1923fcf3ce44SJohn Forte 1924fcf3ce44SJohn Forte /* 1925fcf3ce44SJohn Forte * ql_24xx_status_entry 1926fcf3ce44SJohn Forte * Processes received ISP24xx status entry. 1927fcf3ce44SJohn Forte * 1928fcf3ce44SJohn Forte * Input: 1929fcf3ce44SJohn Forte * ha: adapter state pointer. 1930fcf3ce44SJohn Forte * pkt: entry pointer. 1931fcf3ce44SJohn Forte * done_q: done queue pointer. 1932fcf3ce44SJohn Forte * set_flags: task daemon flags to set. 1933fcf3ce44SJohn Forte * reset_flags: task daemon flags to reset. 1934fcf3ce44SJohn Forte * 1935fcf3ce44SJohn Forte * Returns: 1936fcf3ce44SJohn Forte * BIT_0 = CS_RESET status received. 1937fcf3ce44SJohn Forte * 1938fcf3ce44SJohn Forte * Context: 1939fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 1940fcf3ce44SJohn Forte */ 1941fcf3ce44SJohn Forte /* ARGSUSED */ 1942fcf3ce44SJohn Forte static int 1943fcf3ce44SJohn Forte ql_24xx_status_entry(ql_adapter_state_t *ha, sts_24xx_entry_t *pkt, 1944fcf3ce44SJohn Forte ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags) 1945fcf3ce44SJohn Forte { 1946a2b3ff35SDaniel Beauregard ql_srb_t *sp = NULL; 1947fcf3ce44SJohn Forte uint16_t comp_status; 1948a2b3ff35SDaniel Beauregard uint32_t index, resp_identifier; 1949fcf3ce44SJohn Forte int rval = 0; 1950fcf3ce44SJohn Forte 1951fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 1952fcf3ce44SJohn Forte 1953a2b3ff35SDaniel Beauregard /* Validate the response entry handle. */ 195416dd44c2SDaniel Beauregard resp_identifier = ddi_get32(ha->hba_buf.acc_handle, &pkt->handle); 195516dd44c2SDaniel Beauregard index = resp_identifier & OSC_INDEX_MASK; 1956a2b3ff35SDaniel Beauregard if (index < MAX_OUTSTANDING_COMMANDS) { 1957a2b3ff35SDaniel Beauregard /* the index seems reasonable */ 1958a2b3ff35SDaniel Beauregard sp = ha->outstanding_cmds[index]; 1959a2b3ff35SDaniel Beauregard if (sp != NULL) { 1960a2b3ff35SDaniel Beauregard if (sp->handle == resp_identifier) { 1961a2b3ff35SDaniel Beauregard /* Neo, you're the one... */ 1962a2b3ff35SDaniel Beauregard ha->outstanding_cmds[index] = NULL; 1963a2b3ff35SDaniel Beauregard sp->handle = 0; 1964a2b3ff35SDaniel Beauregard sp->flags &= ~SRB_IN_TOKEN_ARRAY; 1965a2b3ff35SDaniel Beauregard } else { 1966a2b3ff35SDaniel Beauregard EL(ha, "IOCB handle mismatch pkt=%xh, sp=%xh\n", 1967a2b3ff35SDaniel Beauregard resp_identifier, sp->handle); 1968a2b3ff35SDaniel Beauregard sp = NULL; 1969a2b3ff35SDaniel Beauregard ql_signal_abort(ha, set_flags); 1970a2b3ff35SDaniel Beauregard } 1971a2b3ff35SDaniel Beauregard } else { 1972a2b3ff35SDaniel Beauregard sp = ql_verify_preprocessed_cmd(ha, 1973a2b3ff35SDaniel Beauregard (uint32_t *)&pkt->handle, set_flags, reset_flags); 1974a2b3ff35SDaniel Beauregard } 1975a2b3ff35SDaniel Beauregard } else { 1976a2b3ff35SDaniel Beauregard EL(ha, "osc index out of range, index=%xh, handle=%xh\n", 1977a2b3ff35SDaniel Beauregard index, resp_identifier); 1978a2b3ff35SDaniel Beauregard ql_signal_abort(ha, set_flags); 1979a2b3ff35SDaniel Beauregard } 198016dd44c2SDaniel Beauregard 1981a2b3ff35SDaniel Beauregard if (sp != NULL) { 1982fcf3ce44SJohn Forte comp_status = (uint16_t)ddi_get16(ha->hba_buf.acc_handle, 1983fcf3ce44SJohn Forte &pkt->comp_status); 1984fcf3ce44SJohn Forte 1985a2b3ff35SDaniel Beauregard /* We dont care about SCSI QFULLs. */ 1986fcf3ce44SJohn Forte if (comp_status == CS_QUEUE_FULL) { 1987fcf3ce44SJohn Forte EL(sp->ha, "CS_QUEUE_FULL, d_id=%xh, lun=%xh\n", 1988fcf3ce44SJohn Forte sp->lun_queue->target_queue->d_id.b24, 1989fcf3ce44SJohn Forte sp->lun_queue->lun_no); 1990fcf3ce44SJohn Forte comp_status = CS_COMPLETE; 1991fcf3ce44SJohn Forte } 1992fcf3ce44SJohn Forte 1993fcf3ce44SJohn Forte /* 1994fcf3ce44SJohn Forte * 2300 firmware marks completion status as data underrun 1995fcf3ce44SJohn Forte * for scsi qfulls. Make it transport complete. 1996fcf3ce44SJohn Forte */ 1997fcf3ce44SJohn Forte if ((comp_status == CS_DATA_UNDERRUN) && 1998fcf3ce44SJohn Forte (pkt->scsi_status_l != 0)) { 1999fcf3ce44SJohn Forte comp_status = CS_COMPLETE; 2000fcf3ce44SJohn Forte } 2001fcf3ce44SJohn Forte 2002fcf3ce44SJohn Forte /* 2003fcf3ce44SJohn Forte * Workaround T3 issue where we do not get any data xferred 2004fcf3ce44SJohn Forte * but get back a good status. 2005fcf3ce44SJohn Forte */ 2006fcf3ce44SJohn Forte if (comp_status == CS_COMPLETE && 2007fcf3ce44SJohn Forte pkt->scsi_status_l == 0 && 2008fcf3ce44SJohn Forte (pkt->scsi_status_h & FCP_RSP_MASK) == 0 && 2009fcf3ce44SJohn Forte pkt->residual_length != 0 && 2010fcf3ce44SJohn Forte sp->fcp && 2011fcf3ce44SJohn Forte sp->fcp->fcp_data_len != 0 && 2012fcf3ce44SJohn Forte sp->fcp->fcp_cntl.cntl_write_data) { 2013fcf3ce44SJohn Forte comp_status = CS_ABORTED; 2014fcf3ce44SJohn Forte } 2015fcf3ce44SJohn Forte 2016fcf3ce44SJohn Forte /* 2017fcf3ce44SJohn Forte * Fast path to good SCSI I/O completion 2018fcf3ce44SJohn Forte */ 2019fcf3ce44SJohn Forte if ((comp_status == CS_COMPLETE) & 2020fcf3ce44SJohn Forte (!pkt->scsi_status_l) & 2021fcf3ce44SJohn Forte (!(pkt->scsi_status_h & FCP_RSP_MASK))) { 2022fcf3ce44SJohn Forte /* Set completed status. */ 2023fcf3ce44SJohn Forte sp->flags |= SRB_ISP_COMPLETED; 2024fcf3ce44SJohn Forte sp->pkt->pkt_reason = comp_status; 2025fcf3ce44SJohn Forte ql_fast_fcp_post(sp); 2026fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): ql_fast_fcp_post done\n", 2027fcf3ce44SJohn Forte ha->instance); 2028fcf3ce44SJohn Forte return (0); 2029fcf3ce44SJohn Forte } 2030fcf3ce44SJohn Forte rval = ql_status_error(ha, sp, (sts_entry_t *)pkt, done_q, 2031fcf3ce44SJohn Forte set_flags, reset_flags); 2032a2b3ff35SDaniel Beauregard } 2033a2b3ff35SDaniel Beauregard QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 2034fcf3ce44SJohn Forte 2035a2b3ff35SDaniel Beauregard return (rval); 2036a2b3ff35SDaniel Beauregard } 2037fcf3ce44SJohn Forte 2038a2b3ff35SDaniel Beauregard /* 2039a2b3ff35SDaniel Beauregard * ql_verify_preprocessed_cmd 2040a2b3ff35SDaniel Beauregard * Handles preprocessed cmds.. 2041a2b3ff35SDaniel Beauregard * 2042a2b3ff35SDaniel Beauregard * Input: 2043a2b3ff35SDaniel Beauregard * ha: adapter state pointer. 2044a2b3ff35SDaniel Beauregard * pkt_handle: handle pointer. 2045a2b3ff35SDaniel Beauregard * set_flags: task daemon flags to set. 2046a2b3ff35SDaniel Beauregard * reset_flags: task daemon flags to reset. 2047a2b3ff35SDaniel Beauregard * 2048a2b3ff35SDaniel Beauregard * Returns: 2049a2b3ff35SDaniel Beauregard * srb pointer or NULL 2050a2b3ff35SDaniel Beauregard * 2051a2b3ff35SDaniel Beauregard * Context: 2052a2b3ff35SDaniel Beauregard * Interrupt or Kernel context, no mailbox commands allowed. 2053a2b3ff35SDaniel Beauregard */ 2054a2b3ff35SDaniel Beauregard /* ARGSUSED */ 2055a2b3ff35SDaniel Beauregard ql_srb_t * 2056a2b3ff35SDaniel Beauregard ql_verify_preprocessed_cmd(ql_adapter_state_t *ha, uint32_t *pkt_handle, 2057a2b3ff35SDaniel Beauregard uint32_t *set_flags, uint32_t *reset_flags) 2058a2b3ff35SDaniel Beauregard { 2059a2b3ff35SDaniel Beauregard ql_srb_t *sp = NULL; 2060a2b3ff35SDaniel Beauregard uint32_t index, resp_identifier; 2061a2b3ff35SDaniel Beauregard uint32_t get_handle = 10; 2062a2b3ff35SDaniel Beauregard 2063a2b3ff35SDaniel Beauregard while (get_handle) { 2064a2b3ff35SDaniel Beauregard /* Get handle. */ 2065a2b3ff35SDaniel Beauregard resp_identifier = ddi_get32(ha->hba_buf.acc_handle, pkt_handle); 2066a2b3ff35SDaniel Beauregard index = resp_identifier & OSC_INDEX_MASK; 2067a2b3ff35SDaniel Beauregard /* Validate handle. */ 2068a2b3ff35SDaniel Beauregard if (index < MAX_OUTSTANDING_COMMANDS) { 2069a2b3ff35SDaniel Beauregard sp = ha->outstanding_cmds[index]; 2070fcf3ce44SJohn Forte } 2071fcf3ce44SJohn Forte 2072a2b3ff35SDaniel Beauregard if (sp != NULL) { 2073f33c1cdbSDaniel Beauregard EL(ha, "sp=%xh, resp_id=%xh, get=%d, index=%xh\n", sp, 2074f33c1cdbSDaniel Beauregard resp_identifier, get_handle, index); 2075a2b3ff35SDaniel Beauregard break; 2076a2b3ff35SDaniel Beauregard } else { 2077a2b3ff35SDaniel Beauregard get_handle -= 1; 2078a2b3ff35SDaniel Beauregard drv_usecwait(10000); 2079a2b3ff35SDaniel Beauregard if (get_handle == 1) { 2080a2b3ff35SDaniel Beauregard /* Last chance, Sync whole DMA buffer. */ 2081a2b3ff35SDaniel Beauregard (void) ddi_dma_sync(ha->hba_buf.dma_handle, 2082a2b3ff35SDaniel Beauregard RESPONSE_Q_BUFFER_OFFSET, 2083a2b3ff35SDaniel Beauregard RESPONSE_QUEUE_SIZE, 2084a2b3ff35SDaniel Beauregard DDI_DMA_SYNC_FORKERNEL); 2085f33c1cdbSDaniel Beauregard EL(ha, "last chance DMA sync, index=%xh\n", 2086f33c1cdbSDaniel Beauregard index); 2087a2b3ff35SDaniel Beauregard } 2088a2b3ff35SDaniel Beauregard } 2089a2b3ff35SDaniel Beauregard } 2090fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 2091fcf3ce44SJohn Forte 2092a2b3ff35SDaniel Beauregard return (sp); 2093fcf3ce44SJohn Forte } 2094fcf3ce44SJohn Forte 2095a2b3ff35SDaniel Beauregard 2096fcf3ce44SJohn Forte /* 2097fcf3ce44SJohn Forte * ql_status_error 2098fcf3ce44SJohn Forte * Processes received ISP status entry error. 2099fcf3ce44SJohn Forte * 2100fcf3ce44SJohn Forte * Input: 2101fcf3ce44SJohn Forte * ha: adapter state pointer. 2102fcf3ce44SJohn Forte * sp: SRB pointer. 2103fcf3ce44SJohn Forte * pkt: entry pointer. 2104fcf3ce44SJohn Forte * done_q: done queue pointer. 2105fcf3ce44SJohn Forte * set_flags: task daemon flags to set. 2106fcf3ce44SJohn Forte * reset_flags: task daemon flags to reset. 2107fcf3ce44SJohn Forte * 2108fcf3ce44SJohn Forte * Returns: 2109fcf3ce44SJohn Forte * BIT_0 = CS_RESET status received. 2110fcf3ce44SJohn Forte * 2111fcf3ce44SJohn Forte * Context: 2112fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 2113fcf3ce44SJohn Forte */ 2114fcf3ce44SJohn Forte /* ARGSUSED */ 2115fcf3ce44SJohn Forte static int 2116fcf3ce44SJohn Forte ql_status_error(ql_adapter_state_t *ha, ql_srb_t *sp, sts_entry_t *pkt23, 2117fcf3ce44SJohn Forte ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags) 2118fcf3ce44SJohn Forte { 2119fcf3ce44SJohn Forte uint32_t sense_sz = 0; 2120fcf3ce44SJohn Forte uint32_t cnt; 2121fcf3ce44SJohn Forte ql_tgt_t *tq; 2122fcf3ce44SJohn Forte fcp_rsp_t *fcpr; 2123fcf3ce44SJohn Forte struct fcp_rsp_info *rsp; 2124fcf3ce44SJohn Forte int rval = 0; 2125fcf3ce44SJohn Forte 2126fcf3ce44SJohn Forte struct { 2127fcf3ce44SJohn Forte uint8_t *rsp_info; 2128fcf3ce44SJohn Forte uint8_t *req_sense_data; 2129fcf3ce44SJohn Forte uint32_t residual_length; 2130fcf3ce44SJohn Forte uint32_t fcp_residual_length; 2131fcf3ce44SJohn Forte uint32_t rsp_info_length; 2132fcf3ce44SJohn Forte uint32_t req_sense_length; 2133fcf3ce44SJohn Forte uint16_t comp_status; 2134fcf3ce44SJohn Forte uint8_t state_flags_l; 2135fcf3ce44SJohn Forte uint8_t state_flags_h; 2136fcf3ce44SJohn Forte uint8_t scsi_status_l; 2137fcf3ce44SJohn Forte uint8_t scsi_status_h; 2138fcf3ce44SJohn Forte } sts; 2139fcf3ce44SJohn Forte 2140fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 2141fcf3ce44SJohn Forte 2142eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_24258081)) { 2143fcf3ce44SJohn Forte sts_24xx_entry_t *pkt24 = (sts_24xx_entry_t *)pkt23; 2144fcf3ce44SJohn Forte 2145fcf3ce44SJohn Forte /* Setup status. */ 2146fcf3ce44SJohn Forte sts.comp_status = (uint16_t)ddi_get16(ha->hba_buf.acc_handle, 2147fcf3ce44SJohn Forte &pkt24->comp_status); 2148fcf3ce44SJohn Forte sts.scsi_status_l = pkt24->scsi_status_l; 2149fcf3ce44SJohn Forte sts.scsi_status_h = pkt24->scsi_status_h; 2150fcf3ce44SJohn Forte 2151fcf3ce44SJohn Forte /* Setup firmware residuals. */ 2152fcf3ce44SJohn Forte sts.residual_length = sts.comp_status == CS_DATA_UNDERRUN ? 2153fcf3ce44SJohn Forte ddi_get32(ha->hba_buf.acc_handle, 2154fcf3ce44SJohn Forte (uint32_t *)&pkt24->residual_length) : 0; 2155fcf3ce44SJohn Forte 2156fcf3ce44SJohn Forte /* Setup FCP residuals. */ 2157fcf3ce44SJohn Forte sts.fcp_residual_length = sts.scsi_status_h & 2158fcf3ce44SJohn Forte (FCP_RESID_UNDER | FCP_RESID_OVER) ? 2159fcf3ce44SJohn Forte ddi_get32(ha->hba_buf.acc_handle, 2160fcf3ce44SJohn Forte (uint32_t *)&pkt24->fcp_rsp_residual_count) : 0; 2161fcf3ce44SJohn Forte 2162fcf3ce44SJohn Forte if ((sts.comp_status == CS_DATA_UNDERRUN) && 2163fcf3ce44SJohn Forte (sts.scsi_status_h & FCP_RESID_UNDER) && 2164fcf3ce44SJohn Forte (sts.residual_length != pkt24->fcp_rsp_residual_count)) { 2165fcf3ce44SJohn Forte 2166fcf3ce44SJohn Forte EL(sp->ha, "mismatch resid's: fw=%xh, pkt=%xh\n", 2167fcf3ce44SJohn Forte sts.residual_length, 2168fcf3ce44SJohn Forte pkt24->fcp_rsp_residual_count); 2169fcf3ce44SJohn Forte sts.scsi_status_h = (uint8_t) 2170fcf3ce44SJohn Forte (sts.scsi_status_h & ~FCP_RESID_UNDER); 2171fcf3ce44SJohn Forte } 2172fcf3ce44SJohn Forte 2173fcf3ce44SJohn Forte /* Setup state flags. */ 2174fcf3ce44SJohn Forte sts.state_flags_l = pkt24->state_flags_l; 2175fcf3ce44SJohn Forte sts.state_flags_h = pkt24->state_flags_h; 2176fcf3ce44SJohn Forte 2177fcf3ce44SJohn Forte if (sp->fcp->fcp_data_len && 2178fcf3ce44SJohn Forte (sts.comp_status != CS_DATA_UNDERRUN || 2179fcf3ce44SJohn Forte sts.residual_length != sp->fcp->fcp_data_len)) { 2180fcf3ce44SJohn Forte sts.state_flags_h = (uint8_t) 2181fcf3ce44SJohn Forte (sts.state_flags_h | SF_GOT_BUS | 2182fcf3ce44SJohn Forte SF_GOT_TARGET | SF_SENT_CMD | 2183fcf3ce44SJohn Forte SF_XFERRED_DATA | SF_GOT_STATUS); 2184fcf3ce44SJohn Forte } else { 2185fcf3ce44SJohn Forte sts.state_flags_h = (uint8_t) 2186fcf3ce44SJohn Forte (sts.state_flags_h | SF_GOT_BUS | 2187fcf3ce44SJohn Forte SF_GOT_TARGET | SF_SENT_CMD | 2188fcf3ce44SJohn Forte SF_GOT_STATUS); 2189fcf3ce44SJohn Forte } 2190fcf3ce44SJohn Forte if (sp->fcp->fcp_cntl.cntl_write_data) { 2191fcf3ce44SJohn Forte sts.state_flags_l = (uint8_t) 2192fcf3ce44SJohn Forte (sts.state_flags_l | SF_DATA_OUT); 2193fcf3ce44SJohn Forte } else if (sp->fcp->fcp_cntl.cntl_read_data) { 2194fcf3ce44SJohn Forte sts.state_flags_l = (uint8_t) 2195fcf3ce44SJohn Forte (sts.state_flags_l | SF_DATA_IN); 2196fcf3ce44SJohn Forte } 2197fcf3ce44SJohn Forte if (sp->fcp->fcp_cntl.cntl_qtype == FCP_QTYPE_HEAD_OF_Q) { 2198fcf3ce44SJohn Forte sts.state_flags_l = (uint8_t) 2199fcf3ce44SJohn Forte (sts.state_flags_l | SF_HEAD_OF_Q); 2200fcf3ce44SJohn Forte } else if (sp->fcp->fcp_cntl.cntl_qtype == FCP_QTYPE_ORDERED) { 2201fcf3ce44SJohn Forte sts.state_flags_l = (uint8_t) 2202fcf3ce44SJohn Forte (sts.state_flags_l | SF_ORDERED_Q); 2203fcf3ce44SJohn Forte } else if (sp->fcp->fcp_cntl.cntl_qtype == FCP_QTYPE_SIMPLE) { 2204fcf3ce44SJohn Forte sts.state_flags_l = (uint8_t) 2205fcf3ce44SJohn Forte (sts.state_flags_l | SF_SIMPLE_Q); 2206fcf3ce44SJohn Forte } 2207fcf3ce44SJohn Forte 2208fcf3ce44SJohn Forte /* Setup FCP response info. */ 2209fcf3ce44SJohn Forte sts.rsp_info = &pkt24->rsp_sense_data[0]; 2210fcf3ce44SJohn Forte if ((sts.scsi_status_h & FCP_RSP_LEN_VALID) != 0) { 2211fcf3ce44SJohn Forte sts.rsp_info_length = ddi_get32(ha->hba_buf.acc_handle, 2212fcf3ce44SJohn Forte (uint32_t *)&pkt24->fcp_rsp_data_length); 2213fcf3ce44SJohn Forte if (sts.rsp_info_length > 2214fcf3ce44SJohn Forte sizeof (struct fcp_rsp_info)) { 2215fcf3ce44SJohn Forte sts.rsp_info_length = 2216fcf3ce44SJohn Forte sizeof (struct fcp_rsp_info); 2217fcf3ce44SJohn Forte } 2218fcf3ce44SJohn Forte for (cnt = 0; cnt < sts.rsp_info_length; cnt += 4) { 2219fcf3ce44SJohn Forte ql_chg_endian(sts.rsp_info + cnt, 4); 2220fcf3ce44SJohn Forte } 2221fcf3ce44SJohn Forte } else { 2222fcf3ce44SJohn Forte sts.rsp_info_length = 0; 2223fcf3ce44SJohn Forte } 2224fcf3ce44SJohn Forte 2225fcf3ce44SJohn Forte /* Setup sense data. */ 2226fcf3ce44SJohn Forte sts.req_sense_data = 2227fcf3ce44SJohn Forte &pkt24->rsp_sense_data[sts.rsp_info_length]; 2228fcf3ce44SJohn Forte if (sts.scsi_status_h & FCP_SNS_LEN_VALID) { 2229fcf3ce44SJohn Forte sts.req_sense_length = 2230fcf3ce44SJohn Forte ddi_get32(ha->hba_buf.acc_handle, 2231fcf3ce44SJohn Forte (uint32_t *)&pkt24->fcp_sense_length); 2232fcf3ce44SJohn Forte sts.state_flags_h = (uint8_t) 2233fcf3ce44SJohn Forte (sts.state_flags_h | SF_ARQ_DONE); 2234fcf3ce44SJohn Forte sense_sz = (uint32_t) 2235fcf3ce44SJohn Forte (((uintptr_t)pkt24 + sizeof (sts_24xx_entry_t)) - 2236fcf3ce44SJohn Forte (uintptr_t)sts.req_sense_data); 2237fcf3ce44SJohn Forte for (cnt = 0; cnt < sense_sz; cnt += 4) { 2238fcf3ce44SJohn Forte ql_chg_endian(sts.req_sense_data + cnt, 4); 2239fcf3ce44SJohn Forte } 2240fcf3ce44SJohn Forte } else { 2241fcf3ce44SJohn Forte sts.req_sense_length = 0; 2242fcf3ce44SJohn Forte } 2243fcf3ce44SJohn Forte } else { 2244fcf3ce44SJohn Forte /* Setup status. */ 2245fcf3ce44SJohn Forte sts.comp_status = (uint16_t)ddi_get16( 2246fcf3ce44SJohn Forte ha->hba_buf.acc_handle, &pkt23->comp_status); 2247fcf3ce44SJohn Forte sts.scsi_status_l = pkt23->scsi_status_l; 2248fcf3ce44SJohn Forte sts.scsi_status_h = pkt23->scsi_status_h; 2249fcf3ce44SJohn Forte 2250fcf3ce44SJohn Forte /* Setup firmware residuals. */ 2251fcf3ce44SJohn Forte sts.residual_length = sts.comp_status == CS_DATA_UNDERRUN ? 2252fcf3ce44SJohn Forte ddi_get32(ha->hba_buf.acc_handle, 2253fcf3ce44SJohn Forte (uint32_t *)&pkt23->residual_length) : 0; 2254fcf3ce44SJohn Forte 2255fcf3ce44SJohn Forte /* Setup FCP residuals. */ 2256fcf3ce44SJohn Forte sts.fcp_residual_length = sts.scsi_status_h & 2257fcf3ce44SJohn Forte (FCP_RESID_UNDER | FCP_RESID_OVER) ? 2258fcf3ce44SJohn Forte sts.residual_length : 0; 2259fcf3ce44SJohn Forte 2260fcf3ce44SJohn Forte /* Setup state flags. */ 2261fcf3ce44SJohn Forte sts.state_flags_l = pkt23->state_flags_l; 2262fcf3ce44SJohn Forte sts.state_flags_h = pkt23->state_flags_h; 2263fcf3ce44SJohn Forte 2264fcf3ce44SJohn Forte /* Setup FCP response info. */ 2265fcf3ce44SJohn Forte sts.rsp_info = &pkt23->rsp_info[0]; 2266fcf3ce44SJohn Forte if ((sts.scsi_status_h & FCP_RSP_LEN_VALID) != 0) { 2267fcf3ce44SJohn Forte sts.rsp_info_length = ddi_get16( 2268fcf3ce44SJohn Forte ha->hba_buf.acc_handle, 2269fcf3ce44SJohn Forte (uint16_t *)&pkt23->rsp_info_length); 2270fcf3ce44SJohn Forte if (sts.rsp_info_length > 2271fcf3ce44SJohn Forte sizeof (struct fcp_rsp_info)) { 2272fcf3ce44SJohn Forte sts.rsp_info_length = 2273fcf3ce44SJohn Forte sizeof (struct fcp_rsp_info); 2274fcf3ce44SJohn Forte } 2275fcf3ce44SJohn Forte } else { 2276fcf3ce44SJohn Forte sts.rsp_info_length = 0; 2277fcf3ce44SJohn Forte } 2278fcf3ce44SJohn Forte 2279fcf3ce44SJohn Forte /* Setup sense data. */ 2280fcf3ce44SJohn Forte sts.req_sense_data = &pkt23->req_sense_data[0]; 2281fcf3ce44SJohn Forte sts.req_sense_length = sts.scsi_status_h & FCP_SNS_LEN_VALID ? 2282fcf3ce44SJohn Forte ddi_get16(ha->hba_buf.acc_handle, 2283fcf3ce44SJohn Forte (uint16_t *)&pkt23->req_sense_length) : 0; 2284fcf3ce44SJohn Forte } 2285fcf3ce44SJohn Forte 2286fcf3ce44SJohn Forte bzero(sp->pkt->pkt_resp, sp->pkt->pkt_rsplen); 2287fcf3ce44SJohn Forte 2288fcf3ce44SJohn Forte fcpr = (fcp_rsp_t *)sp->pkt->pkt_resp; 2289fcf3ce44SJohn Forte rsp = (struct fcp_rsp_info *)(sp->pkt->pkt_resp + 2290fcf3ce44SJohn Forte sizeof (fcp_rsp_t)); 2291fcf3ce44SJohn Forte 2292fcf3ce44SJohn Forte tq = sp->lun_queue->target_queue; 2293fcf3ce44SJohn Forte 2294fcf3ce44SJohn Forte fcpr->fcp_u.fcp_status.scsi_status = sts.scsi_status_l; 2295fcf3ce44SJohn Forte if (sts.scsi_status_h & FCP_RSP_LEN_VALID) { 2296fcf3ce44SJohn Forte fcpr->fcp_u.fcp_status.rsp_len_set = 1; 2297fcf3ce44SJohn Forte } 2298fcf3ce44SJohn Forte if (sts.scsi_status_h & FCP_SNS_LEN_VALID) { 2299fcf3ce44SJohn Forte fcpr->fcp_u.fcp_status.sense_len_set = 1; 2300fcf3ce44SJohn Forte } 2301fcf3ce44SJohn Forte if (sts.scsi_status_h & FCP_RESID_OVER) { 2302fcf3ce44SJohn Forte fcpr->fcp_u.fcp_status.resid_over = 1; 2303fcf3ce44SJohn Forte } 2304fcf3ce44SJohn Forte if (sts.scsi_status_h & FCP_RESID_UNDER) { 2305fcf3ce44SJohn Forte fcpr->fcp_u.fcp_status.resid_under = 1; 2306fcf3ce44SJohn Forte } 2307fcf3ce44SJohn Forte fcpr->fcp_u.fcp_status.reserved_1 = 0; 2308fcf3ce44SJohn Forte 2309fcf3ce44SJohn Forte /* Set ISP completion status */ 2310fcf3ce44SJohn Forte sp->pkt->pkt_reason = sts.comp_status; 2311fcf3ce44SJohn Forte 2312fcf3ce44SJohn Forte /* Update statistics. */ 2313fcf3ce44SJohn Forte if ((sts.scsi_status_h & FCP_RSP_LEN_VALID) && 2314fcf3ce44SJohn Forte (sp->pkt->pkt_rsplen > sizeof (fcp_rsp_t))) { 2315fcf3ce44SJohn Forte 2316fcf3ce44SJohn Forte sense_sz = sp->pkt->pkt_rsplen - (uint32_t)sizeof (fcp_rsp_t); 2317fcf3ce44SJohn Forte if (sense_sz > sts.rsp_info_length) { 2318fcf3ce44SJohn Forte sense_sz = sts.rsp_info_length; 2319fcf3ce44SJohn Forte } 2320fcf3ce44SJohn Forte 2321fcf3ce44SJohn Forte /* copy response information data. */ 2322fcf3ce44SJohn Forte if (sense_sz) { 2323fcf3ce44SJohn Forte ddi_rep_get8(ha->hba_buf.acc_handle, (uint8_t *)rsp, 2324fcf3ce44SJohn Forte sts.rsp_info, sense_sz, DDI_DEV_AUTOINCR); 2325fcf3ce44SJohn Forte } 2326fcf3ce44SJohn Forte fcpr->fcp_response_len = sense_sz; 2327fcf3ce44SJohn Forte 2328fcf3ce44SJohn Forte rsp = (struct fcp_rsp_info *)((caddr_t)rsp + 2329fcf3ce44SJohn Forte fcpr->fcp_response_len); 2330fcf3ce44SJohn Forte 2331fcf3ce44SJohn Forte switch (*(sts.rsp_info + 3)) { 2332fcf3ce44SJohn Forte case FCP_NO_FAILURE: 2333fcf3ce44SJohn Forte break; 2334fcf3ce44SJohn Forte case FCP_DL_LEN_MISMATCH: 2335fcf3ce44SJohn Forte ha->adapter_stats->d_stats[lobyte( 2336fcf3ce44SJohn Forte tq->loop_id)].dl_len_mismatches++; 2337fcf3ce44SJohn Forte break; 2338fcf3ce44SJohn Forte case FCP_CMND_INVALID: 2339fcf3ce44SJohn Forte break; 2340fcf3ce44SJohn Forte case FCP_DATA_RO_MISMATCH: 2341fcf3ce44SJohn Forte ha->adapter_stats->d_stats[lobyte( 2342fcf3ce44SJohn Forte tq->loop_id)].data_ro_mismatches++; 2343fcf3ce44SJohn Forte break; 2344fcf3ce44SJohn Forte case FCP_TASK_MGMT_NOT_SUPPTD: 2345fcf3ce44SJohn Forte break; 2346fcf3ce44SJohn Forte case FCP_TASK_MGMT_FAILED: 2347fcf3ce44SJohn Forte ha->adapter_stats->d_stats[lobyte( 2348fcf3ce44SJohn Forte tq->loop_id)].task_mgmt_failures++; 2349fcf3ce44SJohn Forte break; 2350fcf3ce44SJohn Forte default: 2351fcf3ce44SJohn Forte break; 2352fcf3ce44SJohn Forte } 2353fcf3ce44SJohn Forte } else { 2354fcf3ce44SJohn Forte /* 2355fcf3ce44SJohn Forte * EL(sp->ha, "scsi_h=%xh, pkt_rsplen=%xh\n", 2356fcf3ce44SJohn Forte * sts.scsi_status_h, sp->pkt->pkt_rsplen); 2357fcf3ce44SJohn Forte */ 2358fcf3ce44SJohn Forte fcpr->fcp_response_len = 0; 2359fcf3ce44SJohn Forte } 2360fcf3ce44SJohn Forte 2361fcf3ce44SJohn Forte /* Set reset status received. */ 2362fcf3ce44SJohn Forte if (sts.comp_status == CS_RESET && LOOP_READY(ha)) { 2363fcf3ce44SJohn Forte rval |= BIT_0; 2364fcf3ce44SJohn Forte } 2365fcf3ce44SJohn Forte 2366fcf3ce44SJohn Forte if (!(tq->flags & TQF_TAPE_DEVICE) && 2367fcf3ce44SJohn Forte (!(CFG_IST(ha, CFG_ENABLE_LINK_DOWN_REPORTING)) || 2368fcf3ce44SJohn Forte ha->loop_down_abort_time < LOOP_DOWN_TIMER_START) && 2369fcf3ce44SJohn Forte ha->task_daemon_flags & LOOP_DOWN) { 2370fcf3ce44SJohn Forte EL(sp->ha, "Loop Not Ready Retry, d_id=%xh, lun=%xh\n", 2371fcf3ce44SJohn Forte tq->d_id.b24, sp->lun_queue->lun_no); 2372fcf3ce44SJohn Forte 2373fcf3ce44SJohn Forte /* Set retry status. */ 2374fcf3ce44SJohn Forte sp->flags |= SRB_RETRY; 2375fcf3ce44SJohn Forte } else if (!(tq->flags & TQF_TAPE_DEVICE) && 2376fcf3ce44SJohn Forte tq->port_down_retry_count != 0 && 2377fcf3ce44SJohn Forte (sts.comp_status == CS_INCOMPLETE || 2378fcf3ce44SJohn Forte sts.comp_status == CS_PORT_UNAVAILABLE || 2379fcf3ce44SJohn Forte sts.comp_status == CS_PORT_LOGGED_OUT || 2380fcf3ce44SJohn Forte sts.comp_status == CS_PORT_CONFIG_CHG || 2381fcf3ce44SJohn Forte sts.comp_status == CS_PORT_BUSY)) { 2382fcf3ce44SJohn Forte EL(sp->ha, "Port Down Retry=%xh, d_id=%xh, lun=%xh, count=%d" 2383fcf3ce44SJohn Forte "\n", sts.comp_status, tq->d_id.b24, sp->lun_queue->lun_no, 2384fcf3ce44SJohn Forte tq->port_down_retry_count); 2385fcf3ce44SJohn Forte 2386fcf3ce44SJohn Forte /* Set retry status. */ 2387fcf3ce44SJohn Forte sp->flags |= SRB_RETRY; 2388fcf3ce44SJohn Forte 2389fcf3ce44SJohn Forte if ((tq->flags & TQF_QUEUE_SUSPENDED) == 0) { 2390fcf3ce44SJohn Forte /* Acquire device queue lock. */ 2391fcf3ce44SJohn Forte DEVICE_QUEUE_LOCK(tq); 2392fcf3ce44SJohn Forte 2393fcf3ce44SJohn Forte tq->flags |= TQF_QUEUE_SUSPENDED; 2394fcf3ce44SJohn Forte 2395fcf3ce44SJohn Forte /* Decrement port down count. */ 2396fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_ENABLE_LINK_DOWN_REPORTING)) { 2397fcf3ce44SJohn Forte tq->port_down_retry_count--; 2398fcf3ce44SJohn Forte } 2399fcf3ce44SJohn Forte 2400fcf3ce44SJohn Forte DEVICE_QUEUE_UNLOCK(tq); 2401fcf3ce44SJohn Forte 2402fcf3ce44SJohn Forte if ((ha->task_daemon_flags & ABORT_ISP_ACTIVE) 2403fcf3ce44SJohn Forte == 0 && 2404fcf3ce44SJohn Forte (sts.comp_status == CS_PORT_LOGGED_OUT || 2405fcf3ce44SJohn Forte sts.comp_status == CS_PORT_UNAVAILABLE)) { 2406fcf3ce44SJohn Forte sp->ha->adapter_stats->d_stats[lobyte( 2407fcf3ce44SJohn Forte tq->loop_id)].logouts_recvd++; 2408fcf3ce44SJohn Forte ql_send_logo(sp->ha, tq, done_q); 2409fcf3ce44SJohn Forte } 2410fcf3ce44SJohn Forte 2411fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 2412fcf3ce44SJohn Forte if (ha->port_retry_timer == 0) { 2413fcf3ce44SJohn Forte if ((ha->port_retry_timer = 2414fcf3ce44SJohn Forte ha->port_down_retry_delay) == 0) { 2415fcf3ce44SJohn Forte *set_flags |= 2416fcf3ce44SJohn Forte PORT_RETRY_NEEDED; 2417fcf3ce44SJohn Forte } 2418fcf3ce44SJohn Forte } 2419fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 2420fcf3ce44SJohn Forte } 2421fcf3ce44SJohn Forte } else if (!(tq->flags & TQF_TAPE_DEVICE) && 2422fcf3ce44SJohn Forte (sts.comp_status == CS_RESET || 2423fcf3ce44SJohn Forte (sts.comp_status == CS_QUEUE_FULL && tq->qfull_retry_count != 0) || 2424fcf3ce44SJohn Forte (sts.comp_status == CS_ABORTED && !(sp->flags & SRB_ABORTING)))) { 2425fcf3ce44SJohn Forte if (sts.comp_status == CS_RESET) { 2426fcf3ce44SJohn Forte EL(sp->ha, "Reset Retry, d_id=%xh, lun=%xh\n", 2427fcf3ce44SJohn Forte tq->d_id.b24, sp->lun_queue->lun_no); 2428fcf3ce44SJohn Forte } else if (sts.comp_status == CS_QUEUE_FULL) { 2429fcf3ce44SJohn Forte EL(sp->ha, "Queue Full Retry, d_id=%xh, lun=%xh, " 2430fcf3ce44SJohn Forte "cnt=%d\n", tq->d_id.b24, sp->lun_queue->lun_no, 2431fcf3ce44SJohn Forte tq->qfull_retry_count); 2432fcf3ce44SJohn Forte if ((tq->flags & TQF_QUEUE_SUSPENDED) == 0) { 2433fcf3ce44SJohn Forte tq->flags |= TQF_QUEUE_SUSPENDED; 2434fcf3ce44SJohn Forte 2435fcf3ce44SJohn Forte tq->qfull_retry_count--; 2436fcf3ce44SJohn Forte 2437fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 2438fcf3ce44SJohn Forte if (ha->port_retry_timer == 0) { 2439fcf3ce44SJohn Forte if ((ha->port_retry_timer = 2440fcf3ce44SJohn Forte ha->qfull_retry_delay) == 2441fcf3ce44SJohn Forte 0) { 2442fcf3ce44SJohn Forte *set_flags |= 2443fcf3ce44SJohn Forte PORT_RETRY_NEEDED; 2444fcf3ce44SJohn Forte } 2445fcf3ce44SJohn Forte } 2446fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 2447fcf3ce44SJohn Forte } 2448fcf3ce44SJohn Forte } else { 2449fcf3ce44SJohn Forte EL(sp->ha, "Abort Retry, d_id=%xh, lun=%xh\n", 2450fcf3ce44SJohn Forte tq->d_id.b24, sp->lun_queue->lun_no); 2451fcf3ce44SJohn Forte } 2452fcf3ce44SJohn Forte 2453fcf3ce44SJohn Forte /* Set retry status. */ 2454fcf3ce44SJohn Forte sp->flags |= SRB_RETRY; 2455fcf3ce44SJohn Forte } else { 2456fcf3ce44SJohn Forte fcpr->fcp_resid = 2457fcf3ce44SJohn Forte sts.fcp_residual_length > sp->fcp->fcp_data_len ? 2458fcf3ce44SJohn Forte sp->fcp->fcp_data_len : sts.fcp_residual_length; 2459fcf3ce44SJohn Forte 2460fcf3ce44SJohn Forte if ((sts.comp_status == CS_DATA_UNDERRUN) && 2461fcf3ce44SJohn Forte (sts.scsi_status_h & FCP_RESID_UNDER) == 0) { 2462fcf3ce44SJohn Forte 2463fcf3ce44SJohn Forte if (sts.scsi_status_l == STATUS_CHECK) { 2464fcf3ce44SJohn Forte sp->pkt->pkt_reason = CS_COMPLETE; 2465fcf3ce44SJohn Forte } else { 2466fcf3ce44SJohn Forte EL(ha, "transport error - " 2467fcf3ce44SJohn Forte "underrun & invalid resid\n"); 2468fcf3ce44SJohn Forte EL(ha, "ssh=%xh, ssl=%xh\n", 2469fcf3ce44SJohn Forte sts.scsi_status_h, sts.scsi_status_l); 2470fcf3ce44SJohn Forte sp->pkt->pkt_reason = CS_FCP_RESPONSE_ERROR; 2471fcf3ce44SJohn Forte } 2472fcf3ce44SJohn Forte } 2473fcf3ce44SJohn Forte 2474fcf3ce44SJohn Forte /* Ignore firmware underrun error. */ 2475fcf3ce44SJohn Forte if (sts.comp_status == CS_DATA_UNDERRUN && 2476fcf3ce44SJohn Forte (sts.scsi_status_h & FCP_RESID_UNDER || 2477fcf3ce44SJohn Forte (sts.scsi_status_l != STATUS_CHECK && 2478fcf3ce44SJohn Forte sts.scsi_status_l != STATUS_GOOD))) { 2479fcf3ce44SJohn Forte sp->pkt->pkt_reason = CS_COMPLETE; 2480fcf3ce44SJohn Forte } 2481fcf3ce44SJohn Forte 2482fcf3ce44SJohn Forte if (sp->pkt->pkt_reason != CS_COMPLETE) { 2483fcf3ce44SJohn Forte ha->xioctl->DeviceErrorCount++; 2484fcf3ce44SJohn Forte EL(sp->ha, "Cmplt status err = %xh, d_id=%xh, lun=%xh" 2485fcf3ce44SJohn Forte "\n", sts.comp_status, tq->d_id.b24, 2486fcf3ce44SJohn Forte sp->lun_queue->lun_no); 2487fcf3ce44SJohn Forte } 2488fcf3ce44SJohn Forte 2489fcf3ce44SJohn Forte /* Set target request sense data. */ 2490fcf3ce44SJohn Forte if (sts.scsi_status_l == STATUS_CHECK) { 2491fcf3ce44SJohn Forte if (sts.scsi_status_h & FCP_SNS_LEN_VALID) { 2492fcf3ce44SJohn Forte 2493fcf3ce44SJohn Forte if (sp->pkt->pkt_reason == CS_COMPLETE && 2494fcf3ce44SJohn Forte sts.req_sense_data[2] != KEY_NO_SENSE && 2495fcf3ce44SJohn Forte sts.req_sense_data[2] != 2496fcf3ce44SJohn Forte KEY_UNIT_ATTENTION) { 2497fcf3ce44SJohn Forte ha->xioctl->DeviceErrorCount++; 2498fcf3ce44SJohn Forte } 2499fcf3ce44SJohn Forte 2500fcf3ce44SJohn Forte sense_sz = sts.req_sense_length; 2501fcf3ce44SJohn Forte 2502fcf3ce44SJohn Forte /* Insure data does not exceed buf. */ 2503fcf3ce44SJohn Forte if (sp->pkt->pkt_rsplen <= 2504fcf3ce44SJohn Forte (uint32_t)sizeof (fcp_rsp_t) + 2505fcf3ce44SJohn Forte fcpr->fcp_response_len) { 2506fcf3ce44SJohn Forte sp->request_sense_length = 0; 2507fcf3ce44SJohn Forte } else { 2508fcf3ce44SJohn Forte sp->request_sense_length = (uint32_t) 2509fcf3ce44SJohn Forte (sp->pkt->pkt_rsplen - 2510fcf3ce44SJohn Forte sizeof (fcp_rsp_t) - 2511fcf3ce44SJohn Forte fcpr->fcp_response_len); 2512fcf3ce44SJohn Forte } 2513fcf3ce44SJohn Forte 2514fcf3ce44SJohn Forte if (sense_sz < 2515fcf3ce44SJohn Forte sp->request_sense_length) { 2516fcf3ce44SJohn Forte sp->request_sense_length = 2517fcf3ce44SJohn Forte sense_sz; 2518fcf3ce44SJohn Forte } 2519fcf3ce44SJohn Forte 2520fcf3ce44SJohn Forte sp->request_sense_ptr = (caddr_t)rsp; 2521fcf3ce44SJohn Forte 2522fcf3ce44SJohn Forte sense_sz = (uint32_t) 2523fcf3ce44SJohn Forte (((uintptr_t)pkt23 + 2524fcf3ce44SJohn Forte sizeof (sts_entry_t)) - 2525fcf3ce44SJohn Forte (uintptr_t)sts.req_sense_data); 2526fcf3ce44SJohn Forte if (sp->request_sense_length < 2527fcf3ce44SJohn Forte sense_sz) { 2528fcf3ce44SJohn Forte sense_sz = 2529fcf3ce44SJohn Forte sp->request_sense_length; 2530fcf3ce44SJohn Forte } 2531fcf3ce44SJohn Forte 2532fcf3ce44SJohn Forte fcpr->fcp_sense_len = sense_sz; 2533fcf3ce44SJohn Forte 2534fcf3ce44SJohn Forte /* Move sense data. */ 2535fcf3ce44SJohn Forte ddi_rep_get8(ha->hba_buf.acc_handle, 2536fcf3ce44SJohn Forte (uint8_t *)sp->request_sense_ptr, 2537fcf3ce44SJohn Forte sts.req_sense_data, 2538fcf3ce44SJohn Forte (size_t)sense_sz, 2539fcf3ce44SJohn Forte DDI_DEV_AUTOINCR); 2540fcf3ce44SJohn Forte 2541fcf3ce44SJohn Forte sp->request_sense_ptr += sense_sz; 2542fcf3ce44SJohn Forte sp->request_sense_length -= sense_sz; 2543eb82ff87SDaniel Beauregard if (sp->request_sense_length != 0 && 2544eb82ff87SDaniel Beauregard !(CFG_IST(ha, CFG_CTRL_8021))) { 2545fcf3ce44SJohn Forte ha->status_srb = sp; 2546fcf3ce44SJohn Forte } 2547fcf3ce44SJohn Forte } 2548fcf3ce44SJohn Forte 2549fcf3ce44SJohn Forte if (sense_sz != 0) { 2550fcf3ce44SJohn Forte EL(sp->ha, "check condition sense data, " 2551fcf3ce44SJohn Forte "d_id=%xh, lun=%xh\n%2xh%3xh%3xh%3xh" 2552fcf3ce44SJohn Forte "%3xh%3xh%3xh%3xh%3xh%3xh%3xh%3xh%3xh" 2553fcf3ce44SJohn Forte "%3xh%3xh%3xh%3xh%3xh\n", tq->d_id.b24, 2554fcf3ce44SJohn Forte sp->lun_queue->lun_no, 2555fcf3ce44SJohn Forte sts.req_sense_data[0], 2556fcf3ce44SJohn Forte sts.req_sense_data[1], 2557fcf3ce44SJohn Forte sts.req_sense_data[2], 2558fcf3ce44SJohn Forte sts.req_sense_data[3], 2559fcf3ce44SJohn Forte sts.req_sense_data[4], 2560fcf3ce44SJohn Forte sts.req_sense_data[5], 2561fcf3ce44SJohn Forte sts.req_sense_data[6], 2562fcf3ce44SJohn Forte sts.req_sense_data[7], 2563fcf3ce44SJohn Forte sts.req_sense_data[8], 2564fcf3ce44SJohn Forte sts.req_sense_data[9], 2565fcf3ce44SJohn Forte sts.req_sense_data[10], 2566fcf3ce44SJohn Forte sts.req_sense_data[11], 2567fcf3ce44SJohn Forte sts.req_sense_data[12], 2568fcf3ce44SJohn Forte sts.req_sense_data[13], 2569fcf3ce44SJohn Forte sts.req_sense_data[14], 2570fcf3ce44SJohn Forte sts.req_sense_data[15], 2571fcf3ce44SJohn Forte sts.req_sense_data[16], 2572fcf3ce44SJohn Forte sts.req_sense_data[17]); 2573fcf3ce44SJohn Forte } else { 2574fcf3ce44SJohn Forte EL(sp->ha, "check condition, d_id=%xh, lun=%xh" 2575fcf3ce44SJohn Forte "\n", tq->d_id.b24, sp->lun_queue->lun_no); 2576fcf3ce44SJohn Forte } 2577fcf3ce44SJohn Forte } 2578fcf3ce44SJohn Forte } 2579fcf3ce44SJohn Forte 2580fcf3ce44SJohn Forte /* Set completed status. */ 2581fcf3ce44SJohn Forte sp->flags |= SRB_ISP_COMPLETED; 2582fcf3ce44SJohn Forte 2583fcf3ce44SJohn Forte /* Place command on done queue. */ 2584fcf3ce44SJohn Forte if (ha->status_srb == NULL) { 2585fcf3ce44SJohn Forte ql_add_link_b(done_q, &sp->cmd); 2586fcf3ce44SJohn Forte } 2587fcf3ce44SJohn Forte 2588fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 2589fcf3ce44SJohn Forte 2590fcf3ce44SJohn Forte return (rval); 2591fcf3ce44SJohn Forte } 2592fcf3ce44SJohn Forte 2593fcf3ce44SJohn Forte /* 2594fcf3ce44SJohn Forte * ql_status_cont_entry 2595fcf3ce44SJohn Forte * Processes status continuation entry. 2596fcf3ce44SJohn Forte * 2597fcf3ce44SJohn Forte * Input: 2598fcf3ce44SJohn Forte * ha: adapter state pointer. 2599fcf3ce44SJohn Forte * pkt: entry pointer. 2600fcf3ce44SJohn Forte * done_q: done queue pointer. 2601fcf3ce44SJohn Forte * set_flags: task daemon flags to set. 2602fcf3ce44SJohn Forte * reset_flags: task daemon flags to reset. 2603fcf3ce44SJohn Forte * 2604fcf3ce44SJohn Forte * Context: 2605fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 2606fcf3ce44SJohn Forte */ 2607fcf3ce44SJohn Forte /* ARGSUSED */ 2608fcf3ce44SJohn Forte static void 2609fcf3ce44SJohn Forte ql_status_cont_entry(ql_adapter_state_t *ha, sts_cont_entry_t *pkt, 2610fcf3ce44SJohn Forte ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags) 2611fcf3ce44SJohn Forte { 2612fcf3ce44SJohn Forte uint32_t sense_sz, index; 2613fcf3ce44SJohn Forte ql_srb_t *sp = ha->status_srb; 2614fcf3ce44SJohn Forte 2615fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 2616fcf3ce44SJohn Forte 2617fcf3ce44SJohn Forte if (sp != NULL && sp->request_sense_length) { 2618fcf3ce44SJohn Forte if (sp->request_sense_length > sizeof (pkt->req_sense_data)) { 2619fcf3ce44SJohn Forte sense_sz = sizeof (pkt->req_sense_data); 2620fcf3ce44SJohn Forte } else { 2621fcf3ce44SJohn Forte sense_sz = sp->request_sense_length; 2622fcf3ce44SJohn Forte } 2623fcf3ce44SJohn Forte 2624eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_24258081)) { 2625fcf3ce44SJohn Forte for (index = 0; index < sense_sz; index += 4) { 2626fcf3ce44SJohn Forte ql_chg_endian((uint8_t *) 2627fcf3ce44SJohn Forte &pkt->req_sense_data[0] + index, 4); 2628fcf3ce44SJohn Forte } 2629fcf3ce44SJohn Forte } 2630fcf3ce44SJohn Forte 2631fcf3ce44SJohn Forte /* Move sense data. */ 2632fcf3ce44SJohn Forte ddi_rep_get8(ha->hba_buf.acc_handle, 2633fcf3ce44SJohn Forte (uint8_t *)sp->request_sense_ptr, 2634fcf3ce44SJohn Forte (uint8_t *)&pkt->req_sense_data[0], (size_t)sense_sz, 2635fcf3ce44SJohn Forte DDI_DEV_AUTOINCR); 2636fcf3ce44SJohn Forte 2637fcf3ce44SJohn Forte sp->request_sense_ptr += sense_sz; 2638fcf3ce44SJohn Forte sp->request_sense_length -= sense_sz; 2639fcf3ce44SJohn Forte 2640fcf3ce44SJohn Forte /* Place command on done queue. */ 2641fcf3ce44SJohn Forte if (sp->request_sense_length == 0) { 2642fcf3ce44SJohn Forte ql_add_link_b(done_q, &sp->cmd); 2643fcf3ce44SJohn Forte ha->status_srb = NULL; 2644fcf3ce44SJohn Forte } 2645fcf3ce44SJohn Forte } 2646fcf3ce44SJohn Forte 2647fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 2648fcf3ce44SJohn Forte } 2649fcf3ce44SJohn Forte 2650fcf3ce44SJohn Forte /* 2651fcf3ce44SJohn Forte * ql_ip_entry 2652fcf3ce44SJohn Forte * Processes received ISP IP entry. 2653fcf3ce44SJohn Forte * 2654fcf3ce44SJohn Forte * Input: 2655fcf3ce44SJohn Forte * ha: adapter state pointer. 2656fcf3ce44SJohn Forte * pkt: entry pointer. 2657fcf3ce44SJohn Forte * done_q: done queue pointer. 2658fcf3ce44SJohn Forte * set_flags: task daemon flags to set. 2659fcf3ce44SJohn Forte * reset_flags: task daemon flags to reset. 2660fcf3ce44SJohn Forte * 2661fcf3ce44SJohn Forte * Context: 2662fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 2663fcf3ce44SJohn Forte */ 2664fcf3ce44SJohn Forte /* ARGSUSED */ 2665fcf3ce44SJohn Forte static void 2666fcf3ce44SJohn Forte ql_ip_entry(ql_adapter_state_t *ha, ip_entry_t *pkt23, ql_head_t *done_q, 2667fcf3ce44SJohn Forte uint32_t *set_flags, uint32_t *reset_flags) 2668fcf3ce44SJohn Forte { 2669fcf3ce44SJohn Forte ql_srb_t *sp; 2670a2b3ff35SDaniel Beauregard uint32_t index, resp_identifier; 2671fcf3ce44SJohn Forte ql_tgt_t *tq; 2672fcf3ce44SJohn Forte 2673fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 2674fcf3ce44SJohn Forte 2675a2b3ff35SDaniel Beauregard /* Validate the response entry handle. */ 2676a2b3ff35SDaniel Beauregard resp_identifier = ddi_get32(ha->hba_buf.acc_handle, &pkt23->handle); 2677a2b3ff35SDaniel Beauregard index = resp_identifier & OSC_INDEX_MASK; 2678a2b3ff35SDaniel Beauregard if (index < MAX_OUTSTANDING_COMMANDS) { 2679a2b3ff35SDaniel Beauregard /* the index seems reasonable */ 2680a2b3ff35SDaniel Beauregard sp = ha->outstanding_cmds[index]; 2681a2b3ff35SDaniel Beauregard if (sp != NULL) { 2682a2b3ff35SDaniel Beauregard if (sp->handle == resp_identifier) { 2683a2b3ff35SDaniel Beauregard /* Neo, you're the one... */ 2684a2b3ff35SDaniel Beauregard ha->outstanding_cmds[index] = NULL; 2685a2b3ff35SDaniel Beauregard sp->handle = 0; 2686a2b3ff35SDaniel Beauregard sp->flags &= ~SRB_IN_TOKEN_ARRAY; 2687a2b3ff35SDaniel Beauregard } else { 2688a2b3ff35SDaniel Beauregard EL(ha, "IOCB handle mismatch pkt=%xh, sp=%xh\n", 2689a2b3ff35SDaniel Beauregard resp_identifier, sp->handle); 2690a2b3ff35SDaniel Beauregard sp = NULL; 2691a2b3ff35SDaniel Beauregard ql_signal_abort(ha, set_flags); 2692a2b3ff35SDaniel Beauregard } 2693a2b3ff35SDaniel Beauregard } else { 2694a2b3ff35SDaniel Beauregard sp = ql_verify_preprocessed_cmd(ha, 2695a2b3ff35SDaniel Beauregard (uint32_t *)&pkt23->handle, set_flags, reset_flags); 2696a2b3ff35SDaniel Beauregard } 2697a2b3ff35SDaniel Beauregard } else { 2698a2b3ff35SDaniel Beauregard EL(ha, "osc index out of range, index=%xh, handle=%xh\n", 2699a2b3ff35SDaniel Beauregard index, resp_identifier); 2700a2b3ff35SDaniel Beauregard ql_signal_abort(ha, set_flags); 2701a2b3ff35SDaniel Beauregard } 2702fcf3ce44SJohn Forte 2703a2b3ff35SDaniel Beauregard if (sp != NULL) { 2704fcf3ce44SJohn Forte tq = sp->lun_queue->target_queue; 2705fcf3ce44SJohn Forte 2706fcf3ce44SJohn Forte /* Set ISP completion status */ 2707eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_24258081)) { 2708fcf3ce44SJohn Forte ip_cmd_entry_t *pkt24 = (ip_cmd_entry_t *)pkt23; 2709fcf3ce44SJohn Forte 2710fcf3ce44SJohn Forte sp->pkt->pkt_reason = ddi_get16( 2711fcf3ce44SJohn Forte ha->hba_buf.acc_handle, &pkt24->hdl_status); 2712fcf3ce44SJohn Forte } else { 2713fcf3ce44SJohn Forte sp->pkt->pkt_reason = ddi_get16( 2714fcf3ce44SJohn Forte ha->hba_buf.acc_handle, &pkt23->comp_status); 2715fcf3ce44SJohn Forte } 2716fcf3ce44SJohn Forte 2717fcf3ce44SJohn Forte if (ha->task_daemon_flags & LOOP_DOWN) { 2718fcf3ce44SJohn Forte EL(ha, "Loop Not Ready Retry, d_id=%xh\n", 2719fcf3ce44SJohn Forte tq->d_id.b24); 2720fcf3ce44SJohn Forte 2721fcf3ce44SJohn Forte /* Set retry status. */ 2722fcf3ce44SJohn Forte sp->flags |= SRB_RETRY; 2723fcf3ce44SJohn Forte 2724fcf3ce44SJohn Forte } else if (tq->port_down_retry_count && 2725fcf3ce44SJohn Forte (sp->pkt->pkt_reason == CS_INCOMPLETE || 2726fcf3ce44SJohn Forte sp->pkt->pkt_reason == CS_PORT_UNAVAILABLE || 2727fcf3ce44SJohn Forte sp->pkt->pkt_reason == CS_PORT_LOGGED_OUT || 2728fcf3ce44SJohn Forte sp->pkt->pkt_reason == CS_PORT_CONFIG_CHG || 2729fcf3ce44SJohn Forte sp->pkt->pkt_reason == CS_PORT_BUSY)) { 2730fcf3ce44SJohn Forte EL(ha, "Port Down Retry=%xh, d_id=%xh, count=%d\n", 2731fcf3ce44SJohn Forte sp->pkt->pkt_reason, tq->d_id.b24, 2732fcf3ce44SJohn Forte tq->port_down_retry_count); 2733fcf3ce44SJohn Forte 2734fcf3ce44SJohn Forte /* Set retry status. */ 2735fcf3ce44SJohn Forte sp->flags |= SRB_RETRY; 2736fcf3ce44SJohn Forte 2737fcf3ce44SJohn Forte if (sp->pkt->pkt_reason == CS_PORT_LOGGED_OUT || 2738fcf3ce44SJohn Forte sp->pkt->pkt_reason == CS_PORT_UNAVAILABLE) { 2739fcf3ce44SJohn Forte ha->adapter_stats->d_stats[lobyte( 2740fcf3ce44SJohn Forte tq->loop_id)].logouts_recvd++; 2741fcf3ce44SJohn Forte ql_send_logo(ha, tq, done_q); 2742fcf3ce44SJohn Forte } 2743fcf3ce44SJohn Forte 2744fcf3ce44SJohn Forte /* Acquire device queue lock. */ 2745fcf3ce44SJohn Forte DEVICE_QUEUE_LOCK(tq); 2746fcf3ce44SJohn Forte 2747fcf3ce44SJohn Forte if ((tq->flags & TQF_QUEUE_SUSPENDED) == 0) { 2748fcf3ce44SJohn Forte tq->flags |= TQF_QUEUE_SUSPENDED; 2749fcf3ce44SJohn Forte 2750fcf3ce44SJohn Forte tq->port_down_retry_count--; 2751fcf3ce44SJohn Forte 2752fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 2753fcf3ce44SJohn Forte if (ha->port_retry_timer == 0) { 2754fcf3ce44SJohn Forte if ((ha->port_retry_timer = 2755fcf3ce44SJohn Forte ha->port_down_retry_delay) == 0) { 2756fcf3ce44SJohn Forte *set_flags |= 2757fcf3ce44SJohn Forte PORT_RETRY_NEEDED; 2758fcf3ce44SJohn Forte } 2759fcf3ce44SJohn Forte } 2760fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 2761fcf3ce44SJohn Forte } 2762fcf3ce44SJohn Forte 2763fcf3ce44SJohn Forte /* Release device queue specific lock. */ 2764fcf3ce44SJohn Forte DEVICE_QUEUE_UNLOCK(tq); 2765fcf3ce44SJohn Forte 2766fcf3ce44SJohn Forte } else if (sp->pkt->pkt_reason == CS_RESET) { 2767fcf3ce44SJohn Forte EL(ha, "Reset Retry, d_id=%xh\n", tq->d_id.b24); 2768fcf3ce44SJohn Forte 2769fcf3ce44SJohn Forte /* Set retry status. */ 2770fcf3ce44SJohn Forte sp->flags |= SRB_RETRY; 2771fcf3ce44SJohn Forte } else { 2772fcf3ce44SJohn Forte if (sp->pkt->pkt_reason != CS_COMPLETE) { 2773fcf3ce44SJohn Forte EL(ha, "Cmplt status err=%xh, d_id=%xh\n", 2774fcf3ce44SJohn Forte sp->pkt->pkt_reason, tq->d_id.b24); 2775fcf3ce44SJohn Forte } 2776fcf3ce44SJohn Forte } 2777fcf3ce44SJohn Forte 2778fcf3ce44SJohn Forte /* Set completed status. */ 2779fcf3ce44SJohn Forte sp->flags |= SRB_ISP_COMPLETED; 2780fcf3ce44SJohn Forte 2781fcf3ce44SJohn Forte ql_add_link_b(done_q, &sp->cmd); 2782fcf3ce44SJohn Forte 2783fcf3ce44SJohn Forte } 2784fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 2785fcf3ce44SJohn Forte } 2786fcf3ce44SJohn Forte 2787fcf3ce44SJohn Forte /* 2788fcf3ce44SJohn Forte * ql_ip_rcv_entry 2789fcf3ce44SJohn Forte * Processes received ISP IP buffers entry. 2790fcf3ce44SJohn Forte * 2791fcf3ce44SJohn Forte * Input: 2792fcf3ce44SJohn Forte * ha: adapter state pointer. 2793fcf3ce44SJohn Forte * pkt: entry pointer. 2794fcf3ce44SJohn Forte * done_q: done queue pointer. 2795fcf3ce44SJohn Forte * set_flags: task daemon flags to set. 2796fcf3ce44SJohn Forte * reset_flags: task daemon flags to reset. 2797fcf3ce44SJohn Forte * 2798fcf3ce44SJohn Forte * Context: 2799fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 2800fcf3ce44SJohn Forte */ 2801fcf3ce44SJohn Forte /* ARGSUSED */ 2802fcf3ce44SJohn Forte static void 2803fcf3ce44SJohn Forte ql_ip_rcv_entry(ql_adapter_state_t *ha, ip_rcv_entry_t *pkt, 2804fcf3ce44SJohn Forte ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags) 2805fcf3ce44SJohn Forte { 2806fcf3ce44SJohn Forte port_id_t s_id; 2807fcf3ce44SJohn Forte uint16_t index; 2808fcf3ce44SJohn Forte uint8_t cnt; 2809fcf3ce44SJohn Forte ql_tgt_t *tq; 2810fcf3ce44SJohn Forte 2811fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 2812fcf3ce44SJohn Forte 2813fcf3ce44SJohn Forte /* Locate device queue. */ 2814fcf3ce44SJohn Forte s_id.b.al_pa = pkt->s_id[0]; 2815fcf3ce44SJohn Forte s_id.b.area = pkt->s_id[1]; 2816fcf3ce44SJohn Forte s_id.b.domain = pkt->s_id[2]; 2817fcf3ce44SJohn Forte if ((tq = ql_d_id_to_queue(ha, s_id)) == NULL) { 2818fcf3ce44SJohn Forte EL(ha, "Unknown IP device ID=%xh\n", s_id.b24); 2819fcf3ce44SJohn Forte return; 2820fcf3ce44SJohn Forte } 2821fcf3ce44SJohn Forte 2822fcf3ce44SJohn Forte tq->ub_sequence_length = (uint16_t)ddi_get16(ha->hba_buf.acc_handle, 2823fcf3ce44SJohn Forte &pkt->seq_length); 2824fcf3ce44SJohn Forte tq->ub_total_seg_cnt = pkt->segment_count; 2825fcf3ce44SJohn Forte tq->ub_seq_id = ++ha->ub_seq_id; 2826fcf3ce44SJohn Forte tq->ub_seq_cnt = 0; 2827fcf3ce44SJohn Forte tq->ub_frame_ro = 0; 2828fcf3ce44SJohn Forte tq->ub_loop_id = pkt->loop_id; 2829fcf3ce44SJohn Forte ha->rcv_dev_q = tq; 2830fcf3ce44SJohn Forte 2831fcf3ce44SJohn Forte for (cnt = 0; cnt < IP_RCVBUF_HANDLES && tq->ub_seq_cnt < 2832fcf3ce44SJohn Forte tq->ub_total_seg_cnt; cnt++) { 2833fcf3ce44SJohn Forte 2834fcf3ce44SJohn Forte index = (uint16_t)ddi_get16(ha->hba_buf.acc_handle, 2835fcf3ce44SJohn Forte &pkt->buffer_handle[cnt]); 2836fcf3ce44SJohn Forte 2837fcf3ce44SJohn Forte if (ql_ub_frame_hdr(ha, tq, index, done_q) != QL_SUCCESS) { 2838fcf3ce44SJohn Forte EL(ha, "ql_ub_frame_hdr failed, isp_abort_needed\n"); 2839fcf3ce44SJohn Forte *set_flags |= ISP_ABORT_NEEDED; 2840fcf3ce44SJohn Forte break; 2841fcf3ce44SJohn Forte } 2842fcf3ce44SJohn Forte } 2843fcf3ce44SJohn Forte 2844fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 2845fcf3ce44SJohn Forte } 2846fcf3ce44SJohn Forte 2847fcf3ce44SJohn Forte /* 2848fcf3ce44SJohn Forte * ql_ip_rcv_cont_entry 2849fcf3ce44SJohn Forte * Processes received ISP IP buffers continuation entry. 2850fcf3ce44SJohn Forte * 2851fcf3ce44SJohn Forte * Input: 2852fcf3ce44SJohn Forte * ha: adapter state pointer. 2853fcf3ce44SJohn Forte * pkt: entry pointer. 2854fcf3ce44SJohn Forte * done_q: done queue pointer. 2855fcf3ce44SJohn Forte * set_flags: task daemon flags to set. 2856fcf3ce44SJohn Forte * reset_flags: task daemon flags to reset. 2857fcf3ce44SJohn Forte * 2858fcf3ce44SJohn Forte * Context: 2859fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 2860fcf3ce44SJohn Forte */ 2861fcf3ce44SJohn Forte /* ARGSUSED */ 2862fcf3ce44SJohn Forte static void 2863fcf3ce44SJohn Forte ql_ip_rcv_cont_entry(ql_adapter_state_t *ha, ip_rcv_cont_entry_t *pkt, 2864fcf3ce44SJohn Forte ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags) 2865fcf3ce44SJohn Forte { 2866fcf3ce44SJohn Forte uint16_t index; 2867fcf3ce44SJohn Forte uint8_t cnt; 2868fcf3ce44SJohn Forte ql_tgt_t *tq; 2869fcf3ce44SJohn Forte 2870fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 2871fcf3ce44SJohn Forte 2872fcf3ce44SJohn Forte if ((tq = ha->rcv_dev_q) == NULL) { 2873fcf3ce44SJohn Forte EL(ha, "No IP receive device\n"); 2874fcf3ce44SJohn Forte return; 2875fcf3ce44SJohn Forte } 2876fcf3ce44SJohn Forte 2877fcf3ce44SJohn Forte for (cnt = 0; cnt < IP_RCVBUF_CONT_HANDLES && 2878fcf3ce44SJohn Forte tq->ub_seq_cnt < tq->ub_total_seg_cnt; cnt++) { 2879fcf3ce44SJohn Forte 2880fcf3ce44SJohn Forte index = (uint16_t)ddi_get16(ha->hba_buf.acc_handle, 2881fcf3ce44SJohn Forte &pkt->buffer_handle[cnt]); 2882fcf3ce44SJohn Forte 2883fcf3ce44SJohn Forte if (ql_ub_frame_hdr(ha, tq, index, done_q) != QL_SUCCESS) { 2884fcf3ce44SJohn Forte EL(ha, "ql_ub_frame_hdr failed, isp_abort_needed\n"); 2885fcf3ce44SJohn Forte *set_flags |= ISP_ABORT_NEEDED; 2886fcf3ce44SJohn Forte break; 2887fcf3ce44SJohn Forte } 2888fcf3ce44SJohn Forte } 2889fcf3ce44SJohn Forte 2890fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 2891fcf3ce44SJohn Forte } 2892fcf3ce44SJohn Forte 2893fcf3ce44SJohn Forte /* 2894fcf3ce44SJohn Forte * ip_rcv_24xx_entry_t 2895fcf3ce44SJohn Forte * Processes received ISP24xx IP buffers entry. 2896fcf3ce44SJohn Forte * 2897fcf3ce44SJohn Forte * Input: 2898fcf3ce44SJohn Forte * ha: adapter state pointer. 2899fcf3ce44SJohn Forte * pkt: entry pointer. 2900fcf3ce44SJohn Forte * done_q: done queue pointer. 2901fcf3ce44SJohn Forte * set_flags: task daemon flags to set. 2902fcf3ce44SJohn Forte * reset_flags: task daemon flags to reset. 2903fcf3ce44SJohn Forte * 2904fcf3ce44SJohn Forte * Context: 2905fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 2906fcf3ce44SJohn Forte */ 2907fcf3ce44SJohn Forte /* ARGSUSED */ 2908fcf3ce44SJohn Forte static void 2909fcf3ce44SJohn Forte ql_ip_24xx_rcv_entry(ql_adapter_state_t *ha, ip_rcv_24xx_entry_t *pkt, 2910fcf3ce44SJohn Forte ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags) 2911fcf3ce44SJohn Forte { 2912fcf3ce44SJohn Forte port_id_t s_id; 2913fcf3ce44SJohn Forte uint16_t index; 2914fcf3ce44SJohn Forte uint8_t cnt; 2915fcf3ce44SJohn Forte ql_tgt_t *tq; 2916fcf3ce44SJohn Forte 2917fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 2918fcf3ce44SJohn Forte 2919fcf3ce44SJohn Forte /* Locate device queue. */ 2920fcf3ce44SJohn Forte s_id.b.al_pa = pkt->s_id[0]; 2921fcf3ce44SJohn Forte s_id.b.area = pkt->s_id[1]; 2922fcf3ce44SJohn Forte s_id.b.domain = pkt->s_id[2]; 2923fcf3ce44SJohn Forte if ((tq = ql_d_id_to_queue(ha, s_id)) == NULL) { 2924fcf3ce44SJohn Forte EL(ha, "Unknown IP device ID=%xh\n", s_id.b24); 2925fcf3ce44SJohn Forte return; 2926fcf3ce44SJohn Forte } 2927fcf3ce44SJohn Forte 2928fcf3ce44SJohn Forte if (tq->ub_total_seg_cnt == 0) { 2929fcf3ce44SJohn Forte tq->ub_sequence_length = (uint16_t)ddi_get16( 2930fcf3ce44SJohn Forte ha->hba_buf.acc_handle, &pkt->seq_length); 2931fcf3ce44SJohn Forte tq->ub_total_seg_cnt = pkt->segment_count; 2932fcf3ce44SJohn Forte tq->ub_seq_id = ++ha->ub_seq_id; 2933fcf3ce44SJohn Forte tq->ub_seq_cnt = 0; 2934fcf3ce44SJohn Forte tq->ub_frame_ro = 0; 2935fcf3ce44SJohn Forte tq->ub_loop_id = (uint16_t)ddi_get16( 2936fcf3ce44SJohn Forte ha->hba_buf.acc_handle, &pkt->n_port_hdl); 2937fcf3ce44SJohn Forte } 2938fcf3ce44SJohn Forte 2939fcf3ce44SJohn Forte for (cnt = 0; cnt < IP_24XX_RCVBUF_HANDLES && tq->ub_seq_cnt < 2940fcf3ce44SJohn Forte tq->ub_total_seg_cnt; cnt++) { 2941fcf3ce44SJohn Forte 2942fcf3ce44SJohn Forte index = (uint16_t)ddi_get16(ha->hba_buf.acc_handle, 2943fcf3ce44SJohn Forte &pkt->buffer_handle[cnt]); 2944fcf3ce44SJohn Forte 2945fcf3ce44SJohn Forte if (ql_ub_frame_hdr(ha, tq, index, done_q) != QL_SUCCESS) { 2946fcf3ce44SJohn Forte EL(ha, "ql_ub_frame_hdr failed, isp_abort_needed\n"); 2947fcf3ce44SJohn Forte *set_flags |= ISP_ABORT_NEEDED; 2948fcf3ce44SJohn Forte break; 2949fcf3ce44SJohn Forte } 2950fcf3ce44SJohn Forte } 2951fcf3ce44SJohn Forte 2952fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 2953fcf3ce44SJohn Forte } 2954fcf3ce44SJohn Forte 2955fcf3ce44SJohn Forte /* 2956fcf3ce44SJohn Forte * ql_ms_entry 2957fcf3ce44SJohn Forte * Processes received Name/Management/CT Pass-Through entry. 2958fcf3ce44SJohn Forte * 2959fcf3ce44SJohn Forte * Input: 2960fcf3ce44SJohn Forte * ha: adapter state pointer. 2961fcf3ce44SJohn Forte * pkt23: entry pointer. 2962fcf3ce44SJohn Forte * done_q: done queue pointer. 2963fcf3ce44SJohn Forte * set_flags: task daemon flags to set. 2964fcf3ce44SJohn Forte * reset_flags: task daemon flags to reset. 2965fcf3ce44SJohn Forte * 2966fcf3ce44SJohn Forte * Context: 2967fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 2968fcf3ce44SJohn Forte */ 2969fcf3ce44SJohn Forte /* ARGSUSED */ 2970fcf3ce44SJohn Forte static void 2971fcf3ce44SJohn Forte ql_ms_entry(ql_adapter_state_t *ha, ms_entry_t *pkt23, ql_head_t *done_q, 2972fcf3ce44SJohn Forte uint32_t *set_flags, uint32_t *reset_flags) 2973fcf3ce44SJohn Forte { 2974fcf3ce44SJohn Forte ql_srb_t *sp; 2975a2b3ff35SDaniel Beauregard uint32_t index, cnt, resp_identifier; 2976fcf3ce44SJohn Forte ql_tgt_t *tq; 2977fcf3ce44SJohn Forte ct_passthru_entry_t *pkt24 = (ct_passthru_entry_t *)pkt23; 2978fcf3ce44SJohn Forte 2979fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 2980fcf3ce44SJohn Forte 2981a2b3ff35SDaniel Beauregard /* Validate the response entry handle. */ 2982a2b3ff35SDaniel Beauregard resp_identifier = ddi_get32(ha->hba_buf.acc_handle, &pkt23->handle); 2983a2b3ff35SDaniel Beauregard index = resp_identifier & OSC_INDEX_MASK; 2984a2b3ff35SDaniel Beauregard if (index < MAX_OUTSTANDING_COMMANDS) { 2985a2b3ff35SDaniel Beauregard /* the index seems reasonable */ 2986a2b3ff35SDaniel Beauregard sp = ha->outstanding_cmds[index]; 2987a2b3ff35SDaniel Beauregard if (sp != NULL) { 2988a2b3ff35SDaniel Beauregard if (sp->handle == resp_identifier) { 2989a2b3ff35SDaniel Beauregard /* Neo, you're the one... */ 2990a2b3ff35SDaniel Beauregard ha->outstanding_cmds[index] = NULL; 2991a2b3ff35SDaniel Beauregard sp->handle = 0; 2992a2b3ff35SDaniel Beauregard sp->flags &= ~SRB_IN_TOKEN_ARRAY; 2993a2b3ff35SDaniel Beauregard } else { 2994a2b3ff35SDaniel Beauregard EL(ha, "IOCB handle mismatch pkt=%xh, sp=%xh\n", 2995a2b3ff35SDaniel Beauregard resp_identifier, sp->handle); 2996a2b3ff35SDaniel Beauregard sp = NULL; 2997a2b3ff35SDaniel Beauregard ql_signal_abort(ha, set_flags); 2998a2b3ff35SDaniel Beauregard } 2999a2b3ff35SDaniel Beauregard } else { 3000a2b3ff35SDaniel Beauregard sp = ql_verify_preprocessed_cmd(ha, 3001a2b3ff35SDaniel Beauregard (uint32_t *)&pkt23->handle, set_flags, reset_flags); 3002a2b3ff35SDaniel Beauregard } 3003a2b3ff35SDaniel Beauregard } else { 3004a2b3ff35SDaniel Beauregard EL(ha, "osc index out of range, index=%xh, handle=%xh\n", 3005a2b3ff35SDaniel Beauregard index, resp_identifier); 3006a2b3ff35SDaniel Beauregard ql_signal_abort(ha, set_flags); 3007a2b3ff35SDaniel Beauregard } 3008fcf3ce44SJohn Forte 3009a2b3ff35SDaniel Beauregard if (sp != NULL) { 3010fcf3ce44SJohn Forte if (!(sp->flags & SRB_MS_PKT)) { 3011fcf3ce44SJohn Forte EL(ha, "Not SRB_MS_PKT flags=%xh, isp_abort_needed", 3012fcf3ce44SJohn Forte sp->flags); 3013fcf3ce44SJohn Forte *set_flags |= ISP_ABORT_NEEDED; 3014fcf3ce44SJohn Forte return; 3015fcf3ce44SJohn Forte } 3016fcf3ce44SJohn Forte 3017fcf3ce44SJohn Forte tq = sp->lun_queue->target_queue; 3018fcf3ce44SJohn Forte 3019fcf3ce44SJohn Forte /* Set ISP completion status */ 3020eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_24258081)) { 3021fcf3ce44SJohn Forte sp->pkt->pkt_reason = ddi_get16( 3022fcf3ce44SJohn Forte ha->hba_buf.acc_handle, &pkt24->status); 3023fcf3ce44SJohn Forte } else { 3024fcf3ce44SJohn Forte sp->pkt->pkt_reason = ddi_get16( 3025fcf3ce44SJohn Forte ha->hba_buf.acc_handle, &pkt23->comp_status); 3026fcf3ce44SJohn Forte } 3027fcf3ce44SJohn Forte 3028fcf3ce44SJohn Forte if (sp->pkt->pkt_reason == CS_RESOUCE_UNAVAILABLE && 3029fcf3ce44SJohn Forte sp->retry_count) { 3030fcf3ce44SJohn Forte EL(ha, "Resouce Unavailable Retry = %d\n", 3031fcf3ce44SJohn Forte sp->retry_count); 3032fcf3ce44SJohn Forte 3033fcf3ce44SJohn Forte /* Set retry status. */ 3034fcf3ce44SJohn Forte sp->retry_count--; 3035fcf3ce44SJohn Forte sp->flags |= SRB_RETRY; 3036fcf3ce44SJohn Forte 3037fcf3ce44SJohn Forte /* Acquire device queue lock. */ 3038fcf3ce44SJohn Forte DEVICE_QUEUE_LOCK(tq); 3039fcf3ce44SJohn Forte 3040fcf3ce44SJohn Forte if (!(tq->flags & TQF_QUEUE_SUSPENDED)) { 3041fcf3ce44SJohn Forte tq->flags |= TQF_QUEUE_SUSPENDED; 3042fcf3ce44SJohn Forte 3043fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 3044fcf3ce44SJohn Forte if (ha->port_retry_timer == 0) { 3045fcf3ce44SJohn Forte ha->port_retry_timer = 2; 3046fcf3ce44SJohn Forte } 3047fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 3048fcf3ce44SJohn Forte } 3049fcf3ce44SJohn Forte 3050fcf3ce44SJohn Forte /* Release device queue specific lock. */ 3051fcf3ce44SJohn Forte DEVICE_QUEUE_UNLOCK(tq); 3052fcf3ce44SJohn Forte 3053fcf3ce44SJohn Forte } else if (tq->port_down_retry_count && 3054fcf3ce44SJohn Forte (sp->pkt->pkt_reason == CS_PORT_CONFIG_CHG || 3055fcf3ce44SJohn Forte sp->pkt->pkt_reason == CS_PORT_BUSY)) { 3056fcf3ce44SJohn Forte EL(ha, "Port Down Retry\n"); 3057fcf3ce44SJohn Forte 3058fcf3ce44SJohn Forte /* Set retry status. */ 3059fcf3ce44SJohn Forte sp->flags |= SRB_RETRY; 3060fcf3ce44SJohn Forte 3061fcf3ce44SJohn Forte /* Acquire device queue lock. */ 3062fcf3ce44SJohn Forte DEVICE_QUEUE_LOCK(tq); 3063fcf3ce44SJohn Forte 3064fcf3ce44SJohn Forte if ((tq->flags & TQF_QUEUE_SUSPENDED) == 0) { 3065fcf3ce44SJohn Forte tq->flags |= TQF_QUEUE_SUSPENDED; 3066fcf3ce44SJohn Forte 3067fcf3ce44SJohn Forte tq->port_down_retry_count--; 3068fcf3ce44SJohn Forte 3069fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 3070fcf3ce44SJohn Forte if (ha->port_retry_timer == 0) { 3071fcf3ce44SJohn Forte if ((ha->port_retry_timer = 3072fcf3ce44SJohn Forte ha->port_down_retry_delay) == 0) { 3073fcf3ce44SJohn Forte *set_flags |= 3074fcf3ce44SJohn Forte PORT_RETRY_NEEDED; 3075fcf3ce44SJohn Forte } 3076fcf3ce44SJohn Forte } 3077fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 3078fcf3ce44SJohn Forte } 3079fcf3ce44SJohn Forte /* Release device queue specific lock. */ 3080fcf3ce44SJohn Forte DEVICE_QUEUE_UNLOCK(tq); 3081fcf3ce44SJohn Forte 3082fcf3ce44SJohn Forte } else if (sp->pkt->pkt_reason == CS_RESET) { 3083fcf3ce44SJohn Forte EL(ha, "Reset Retry\n"); 3084fcf3ce44SJohn Forte 3085fcf3ce44SJohn Forte /* Set retry status. */ 3086fcf3ce44SJohn Forte sp->flags |= SRB_RETRY; 3087fcf3ce44SJohn Forte 3088eb82ff87SDaniel Beauregard } else if (CFG_IST(ha, CFG_CTRL_24258081) && 3089fcf3ce44SJohn Forte sp->pkt->pkt_reason == CS_DATA_UNDERRUN) { 3090fcf3ce44SJohn Forte cnt = ddi_get32(ha->hba_buf.acc_handle, 3091fcf3ce44SJohn Forte &pkt24->resp_byte_count); 3092fcf3ce44SJohn Forte if (cnt < sizeof (fc_ct_header_t)) { 309316dd44c2SDaniel Beauregard EL(ha, "Data underrun\n"); 3094fcf3ce44SJohn Forte } else { 3095fcf3ce44SJohn Forte sp->pkt->pkt_reason = CS_COMPLETE; 3096fcf3ce44SJohn Forte } 3097fcf3ce44SJohn Forte 3098fcf3ce44SJohn Forte } else if (sp->pkt->pkt_reason != CS_COMPLETE) { 3099fcf3ce44SJohn Forte EL(ha, "status err=%xh\n", sp->pkt->pkt_reason); 3100fcf3ce44SJohn Forte } 3101fcf3ce44SJohn Forte 3102fcf3ce44SJohn Forte if (sp->pkt->pkt_reason == CS_COMPLETE) { 3103fcf3ce44SJohn Forte /*EMPTY*/ 31045dfd244aSDaniel Beauregard QL_PRINT_3(CE_CONT, "(%d): ct_cmdrsp=%x%02xh resp\n", 31055dfd244aSDaniel Beauregard ha->instance, sp->pkt->pkt_cmd[8], 31065dfd244aSDaniel Beauregard sp->pkt->pkt_cmd[9]); 3107fcf3ce44SJohn Forte QL_DUMP_3(sp->pkt->pkt_resp, 8, sp->pkt->pkt_rsplen); 3108fcf3ce44SJohn Forte } 3109fcf3ce44SJohn Forte 3110fcf3ce44SJohn Forte /* For nameserver restore command, management change header. */ 3111fcf3ce44SJohn Forte if ((sp->flags & SRB_RETRY) == 0) { 3112fcf3ce44SJohn Forte tq->d_id.b24 == 0xfffffc ? 3113fcf3ce44SJohn Forte ql_cthdr_endian(sp->pkt->pkt_cmd_acc, 3114fcf3ce44SJohn Forte sp->pkt->pkt_cmd, B_TRUE) : 3115fcf3ce44SJohn Forte ql_cthdr_endian(sp->pkt->pkt_resp_acc, 3116fcf3ce44SJohn Forte sp->pkt->pkt_resp, B_TRUE); 3117fcf3ce44SJohn Forte } 3118fcf3ce44SJohn Forte 3119fcf3ce44SJohn Forte /* Set completed status. */ 3120fcf3ce44SJohn Forte sp->flags |= SRB_ISP_COMPLETED; 3121fcf3ce44SJohn Forte 3122fcf3ce44SJohn Forte /* Place command on done queue. */ 3123fcf3ce44SJohn Forte ql_add_link_b(done_q, &sp->cmd); 3124fcf3ce44SJohn Forte 3125fcf3ce44SJohn Forte } 3126fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 3127fcf3ce44SJohn Forte } 3128fcf3ce44SJohn Forte 3129fcf3ce44SJohn Forte /* 3130fcf3ce44SJohn Forte * ql_report_id_entry 3131fcf3ce44SJohn Forte * Processes received Name/Management/CT Pass-Through entry. 3132fcf3ce44SJohn Forte * 3133fcf3ce44SJohn Forte * Input: 3134fcf3ce44SJohn Forte * ha: adapter state pointer. 3135eb82ff87SDaniel Beauregard * pkt: entry pointer. 3136fcf3ce44SJohn Forte * done_q: done queue pointer. 3137fcf3ce44SJohn Forte * set_flags: task daemon flags to set. 3138fcf3ce44SJohn Forte * reset_flags: task daemon flags to reset. 3139fcf3ce44SJohn Forte * 3140fcf3ce44SJohn Forte * Context: 3141fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 3142fcf3ce44SJohn Forte */ 3143fcf3ce44SJohn Forte /* ARGSUSED */ 3144fcf3ce44SJohn Forte static void 3145fcf3ce44SJohn Forte ql_report_id_entry(ql_adapter_state_t *ha, report_id_1_t *pkt, 3146fcf3ce44SJohn Forte ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags) 3147fcf3ce44SJohn Forte { 3148fcf3ce44SJohn Forte ql_adapter_state_t *vha; 3149fcf3ce44SJohn Forte 3150fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 3151fcf3ce44SJohn Forte 3152fcf3ce44SJohn Forte EL(ha, "format=%d, vp=%d, status=%d\n", 3153fcf3ce44SJohn Forte pkt->format, pkt->vp_index, pkt->status); 3154fcf3ce44SJohn Forte 3155fcf3ce44SJohn Forte if (pkt->format == 1) { 3156fcf3ce44SJohn Forte /* Locate port state structure. */ 3157fcf3ce44SJohn Forte for (vha = ha; vha != NULL; vha = vha->vp_next) { 3158fcf3ce44SJohn Forte if (vha->vp_index == pkt->vp_index) { 3159fcf3ce44SJohn Forte break; 3160fcf3ce44SJohn Forte } 3161fcf3ce44SJohn Forte } 31625dfd244aSDaniel Beauregard if (vha != NULL && vha->vp_index != 0 && 31635dfd244aSDaniel Beauregard (pkt->status == CS_COMPLETE || 3164fcf3ce44SJohn Forte pkt->status == CS_PORT_ID_CHANGE)) { 3165fcf3ce44SJohn Forte *set_flags |= LOOP_RESYNC_NEEDED; 3166fcf3ce44SJohn Forte *reset_flags &= ~LOOP_RESYNC_NEEDED; 3167fcf3ce44SJohn Forte vha->loop_down_timer = LOOP_DOWN_TIMER_OFF; 3168fcf3ce44SJohn Forte TASK_DAEMON_LOCK(ha); 3169fcf3ce44SJohn Forte vha->task_daemon_flags |= LOOP_RESYNC_NEEDED; 3170fcf3ce44SJohn Forte vha->task_daemon_flags &= ~LOOP_DOWN; 3171fcf3ce44SJohn Forte TASK_DAEMON_UNLOCK(ha); 3172fcf3ce44SJohn Forte } 3173fcf3ce44SJohn Forte } 3174fcf3ce44SJohn Forte 3175fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 3176fcf3ce44SJohn Forte } 31775dfd244aSDaniel Beauregard 31785dfd244aSDaniel Beauregard /* 31795dfd244aSDaniel Beauregard * ql_els_entry 31805dfd244aSDaniel Beauregard * Processes received ELS Pass-Through entry. 31815dfd244aSDaniel Beauregard * 31825dfd244aSDaniel Beauregard * Input: 31835dfd244aSDaniel Beauregard * ha: adapter state pointer. 31845dfd244aSDaniel Beauregard * pkt23: entry pointer. 31855dfd244aSDaniel Beauregard * done_q: done queue pointer. 31865dfd244aSDaniel Beauregard * set_flags: task daemon flags to set. 31875dfd244aSDaniel Beauregard * reset_flags: task daemon flags to reset. 31885dfd244aSDaniel Beauregard * 31895dfd244aSDaniel Beauregard * Context: 31905dfd244aSDaniel Beauregard * Interrupt or Kernel context, no mailbox commands allowed. 31915dfd244aSDaniel Beauregard */ 31925dfd244aSDaniel Beauregard /* ARGSUSED */ 31935dfd244aSDaniel Beauregard static void 31945dfd244aSDaniel Beauregard ql_els_passthru_entry(ql_adapter_state_t *ha, els_passthru_entry_rsp_t *rsp, 31955dfd244aSDaniel Beauregard ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags) 31965dfd244aSDaniel Beauregard { 31975dfd244aSDaniel Beauregard ql_tgt_t *tq; 31985dfd244aSDaniel Beauregard port_id_t d_id, s_id; 31995dfd244aSDaniel Beauregard ql_srb_t *srb; 3200a2b3ff35SDaniel Beauregard uint32_t index, resp_identifier; 32015dfd244aSDaniel Beauregard 32025dfd244aSDaniel Beauregard QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 32035dfd244aSDaniel Beauregard 3204a2b3ff35SDaniel Beauregard /* Validate the response entry handle. */ 3205a2b3ff35SDaniel Beauregard resp_identifier = ddi_get32(ha->hba_buf.acc_handle, &rsp->handle); 3206a2b3ff35SDaniel Beauregard index = resp_identifier & OSC_INDEX_MASK; 3207a2b3ff35SDaniel Beauregard if (index < MAX_OUTSTANDING_COMMANDS) { 3208a2b3ff35SDaniel Beauregard /* the index seems reasonable */ 3209a2b3ff35SDaniel Beauregard srb = ha->outstanding_cmds[index]; 3210a2b3ff35SDaniel Beauregard if (srb != NULL) { 3211a2b3ff35SDaniel Beauregard if (srb->handle == resp_identifier) { 3212a2b3ff35SDaniel Beauregard /* Neo, you're the one... */ 3213a2b3ff35SDaniel Beauregard ha->outstanding_cmds[index] = NULL; 3214a2b3ff35SDaniel Beauregard srb->handle = 0; 3215a2b3ff35SDaniel Beauregard srb->flags &= ~SRB_IN_TOKEN_ARRAY; 3216a2b3ff35SDaniel Beauregard } else { 3217a2b3ff35SDaniel Beauregard EL(ha, "IOCB handle mismatch pkt=%xh, sp=%xh\n", 3218a2b3ff35SDaniel Beauregard resp_identifier, srb->handle); 3219a2b3ff35SDaniel Beauregard srb = NULL; 3220a2b3ff35SDaniel Beauregard ql_signal_abort(ha, set_flags); 3221a2b3ff35SDaniel Beauregard } 3222a2b3ff35SDaniel Beauregard } else { 3223a2b3ff35SDaniel Beauregard srb = ql_verify_preprocessed_cmd(ha, 3224a2b3ff35SDaniel Beauregard (uint32_t *)&rsp->handle, set_flags, reset_flags); 3225a2b3ff35SDaniel Beauregard } 3226a2b3ff35SDaniel Beauregard } else { 3227a2b3ff35SDaniel Beauregard EL(ha, "osc index out of range, index=%xh, handle=%xh\n", 3228a2b3ff35SDaniel Beauregard index, resp_identifier); 3229a2b3ff35SDaniel Beauregard ql_signal_abort(ha, set_flags); 3230a2b3ff35SDaniel Beauregard } 32315dfd244aSDaniel Beauregard 3232a2b3ff35SDaniel Beauregard if (srb != NULL) { 32335dfd244aSDaniel Beauregard if (!(srb->flags & SRB_ELS_PKT)) { 32345dfd244aSDaniel Beauregard EL(ha, "Not SRB_ELS_PKT flags=%xh, isp_abort_needed", 32355dfd244aSDaniel Beauregard srb->flags); 32365dfd244aSDaniel Beauregard *set_flags |= ISP_ABORT_NEEDED; 32375dfd244aSDaniel Beauregard return; 32385dfd244aSDaniel Beauregard } 3239a2b3ff35SDaniel Beauregard 3240a2b3ff35SDaniel Beauregard (void) ddi_dma_sync(srb->pkt->pkt_resp_dma, 0, 0, 3241a2b3ff35SDaniel Beauregard DDI_DMA_SYNC_FORKERNEL); 32425dfd244aSDaniel Beauregard 32435dfd244aSDaniel Beauregard /* Set ISP completion status */ 32445dfd244aSDaniel Beauregard srb->pkt->pkt_reason = ddi_get16( 32455dfd244aSDaniel Beauregard ha->hba_buf.acc_handle, &rsp->comp_status); 32465dfd244aSDaniel Beauregard 32475dfd244aSDaniel Beauregard if (srb->pkt->pkt_reason != CS_COMPLETE) { 32485dfd244aSDaniel Beauregard la_els_rjt_t rjt; 32495dfd244aSDaniel Beauregard EL(ha, "status err=%xh\n", srb->pkt->pkt_reason); 32505dfd244aSDaniel Beauregard 32515dfd244aSDaniel Beauregard if (srb->pkt->pkt_reason == CS_LOGIN_LOGOUT_ERROR) { 32525dfd244aSDaniel Beauregard EL(ha, "e1=%xh e2=%xh\n", 32535dfd244aSDaniel Beauregard rsp->error_subcode1, rsp->error_subcode2); 32545dfd244aSDaniel Beauregard } 32555dfd244aSDaniel Beauregard 32565dfd244aSDaniel Beauregard srb->pkt->pkt_state = FC_PKT_TRAN_ERROR; 32575dfd244aSDaniel Beauregard 32585dfd244aSDaniel Beauregard /* Build RJT in the response. */ 32595dfd244aSDaniel Beauregard rjt.ls_code.ls_code = LA_ELS_RJT; 32605dfd244aSDaniel Beauregard rjt.reason = FC_REASON_NO_CONNECTION; 32615dfd244aSDaniel Beauregard 32625dfd244aSDaniel Beauregard ddi_rep_put8(srb->pkt->pkt_resp_acc, (uint8_t *)&rjt, 32635dfd244aSDaniel Beauregard (uint8_t *)srb->pkt->pkt_resp, 32645dfd244aSDaniel Beauregard sizeof (rjt), DDI_DEV_AUTOINCR); 32655dfd244aSDaniel Beauregard 32665dfd244aSDaniel Beauregard srb->pkt->pkt_state = FC_PKT_TRAN_ERROR; 32675dfd244aSDaniel Beauregard srb->pkt->pkt_reason = FC_REASON_NO_CONNECTION; 32685dfd244aSDaniel Beauregard } 32695dfd244aSDaniel Beauregard 32705dfd244aSDaniel Beauregard if (srb->pkt->pkt_reason == CS_COMPLETE) { 32715dfd244aSDaniel Beauregard uint8_t opcode; 32725dfd244aSDaniel Beauregard uint16_t loop_id; 32735dfd244aSDaniel Beauregard 32745dfd244aSDaniel Beauregard /* Indicate ISP completion */ 32755dfd244aSDaniel Beauregard srb->flags |= SRB_ISP_COMPLETED; 32765dfd244aSDaniel Beauregard 32775dfd244aSDaniel Beauregard loop_id = ddi_get16(ha->hba_buf.acc_handle, 32785dfd244aSDaniel Beauregard &rsp->n_port_hdl); 32795dfd244aSDaniel Beauregard 32805dfd244aSDaniel Beauregard if (ha->topology & QL_N_PORT) { 32815dfd244aSDaniel Beauregard /* create a target Q if there isn't one */ 32825dfd244aSDaniel Beauregard tq = ql_loop_id_to_queue(ha, loop_id); 32835dfd244aSDaniel Beauregard if (tq == NULL) { 32845dfd244aSDaniel Beauregard d_id.b.al_pa = rsp->d_id_7_0; 32855dfd244aSDaniel Beauregard d_id.b.area = rsp->d_id_15_8; 32865dfd244aSDaniel Beauregard d_id.b.domain = rsp->d_id_23_16; 32875dfd244aSDaniel Beauregard /* Acquire adapter state lock. */ 32885dfd244aSDaniel Beauregard ADAPTER_STATE_LOCK(ha); 32895dfd244aSDaniel Beauregard 32905dfd244aSDaniel Beauregard tq = ql_dev_init(ha, d_id, loop_id); 32915dfd244aSDaniel Beauregard EL(ha, " tq = %x\n", tq); 32925dfd244aSDaniel Beauregard 32935dfd244aSDaniel Beauregard ADAPTER_STATE_UNLOCK(ha); 32945dfd244aSDaniel Beauregard } 32955dfd244aSDaniel Beauregard 32965dfd244aSDaniel Beauregard /* on plogi success assume the chosen s_id */ 32975dfd244aSDaniel Beauregard opcode = ddi_get8(ha->hba_buf.acc_handle, 32985dfd244aSDaniel Beauregard &rsp->els_cmd_opcode); 32995dfd244aSDaniel Beauregard 33005dfd244aSDaniel Beauregard EL(ha, "els_cmd_opcode=%x srb->pkt=%x\n", 33015dfd244aSDaniel Beauregard opcode, srb->pkt); 33025dfd244aSDaniel Beauregard 33035dfd244aSDaniel Beauregard if (opcode == LA_ELS_PLOGI) { 33045dfd244aSDaniel Beauregard s_id.b.al_pa = rsp->s_id_7_0; 33055dfd244aSDaniel Beauregard s_id.b.area = rsp->s_id_15_8; 33065dfd244aSDaniel Beauregard s_id.b.domain = rsp->s_id_23_16; 33075dfd244aSDaniel Beauregard 33085dfd244aSDaniel Beauregard ha->d_id.b24 = s_id.b24; 33095dfd244aSDaniel Beauregard EL(ha, "Set port's source ID %xh\n", 33105dfd244aSDaniel Beauregard ha->d_id.b24); 33115dfd244aSDaniel Beauregard } 33125dfd244aSDaniel Beauregard } 33135dfd244aSDaniel Beauregard ql_isp_els_handle_rsp_endian(ha, srb); 33145dfd244aSDaniel Beauregard 33155dfd244aSDaniel Beauregard if (ha != srb->ha) { 33165dfd244aSDaniel Beauregard EL(ha, "ha=%x srb->ha=%x\n", ha, srb->ha); 33175dfd244aSDaniel Beauregard } 33185dfd244aSDaniel Beauregard 33195dfd244aSDaniel Beauregard if (tq != NULL) { 33205dfd244aSDaniel Beauregard tq->logout_sent = 0; 33215dfd244aSDaniel Beauregard tq->flags &= ~TQF_NEED_AUTHENTICATION; 33225dfd244aSDaniel Beauregard 3323eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_24258081)) { 33245dfd244aSDaniel Beauregard tq->flags |= TQF_IIDMA_NEEDED; 33255dfd244aSDaniel Beauregard } 33265dfd244aSDaniel Beauregard srb->pkt->pkt_state = FC_PKT_SUCCESS; 33275dfd244aSDaniel Beauregard } 33285dfd244aSDaniel Beauregard } 33295dfd244aSDaniel Beauregard /* invoke the callback */ 33305dfd244aSDaniel Beauregard ql_awaken_task_daemon(ha, srb, 0, 0); 33315dfd244aSDaniel Beauregard } 33325dfd244aSDaniel Beauregard QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 33335dfd244aSDaniel Beauregard } 3334a2b3ff35SDaniel Beauregard 3335a2b3ff35SDaniel Beauregard /* 3336a2b3ff35SDaniel Beauregard * ql_signal_abort 3337a2b3ff35SDaniel Beauregard * Signal to the task daemon that a condition warranting an 3338a2b3ff35SDaniel Beauregard * isp reset has been detected. 3339a2b3ff35SDaniel Beauregard * 3340a2b3ff35SDaniel Beauregard * Input: 3341a2b3ff35SDaniel Beauregard * ha: adapter state pointer. 3342a2b3ff35SDaniel Beauregard * set_flags: task daemon flags to set. 3343a2b3ff35SDaniel Beauregard * 3344a2b3ff35SDaniel Beauregard * Context: 3345a2b3ff35SDaniel Beauregard * Interrupt or Kernel context, no mailbox commands allowed. 3346a2b3ff35SDaniel Beauregard */ 3347a2b3ff35SDaniel Beauregard static void 3348a2b3ff35SDaniel Beauregard ql_signal_abort(ql_adapter_state_t *ha, uint32_t *set_flags) 3349a2b3ff35SDaniel Beauregard { 3350*f885d00fSDaniel Beauregard if (!CFG_IST(ha, CFG_CTRL_8021) && 3351*f885d00fSDaniel Beauregard !(ha->task_daemon_flags & (ISP_ABORT_NEEDED | ABORT_ISP_ACTIVE))) { 3352a2b3ff35SDaniel Beauregard *set_flags |= ISP_ABORT_NEEDED; 3353a2b3ff35SDaniel Beauregard } 3354a2b3ff35SDaniel Beauregard } 3355