Print this page
NEX-5717 import QLogic 16G FC drivers
Reviewed by: Steve Peng <steve.peng@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
*** 17,41 ****
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
! /* Copyright 2010 QLogic Corporation */
/*
! * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
*/
! #pragma ident "Copyright 2010 QLogic Corporation; ql_isr.c"
/*
* ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file.
*
* ***********************************************************************
* * **
* * NOTICE **
! * * COPYRIGHT (C) 1996-2010 QLOGIC CORPORATION **
* * ALL RIGHTS RESERVED **
* * **
* ***********************************************************************
*
*/
--- 17,41 ----
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
! /* Copyright 2015 QLogic Corporation */
/*
! * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
*/
! #pragma ident "Copyright 2015 QLogic Corporation; ql_isr.c"
/*
* ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file.
*
* ***********************************************************************
* * **
* * NOTICE **
! * * COPYRIGHT (C) 1996-2015 QLOGIC CORPORATION **
* * ALL RIGHTS RESERVED **
* * **
* ***********************************************************************
*
*/
*** 47,569 ****
#include <ql_isr.h>
#include <ql_init.h>
#include <ql_mbx.h>
#include <ql_nx.h>
#include <ql_xioctl.h>
/*
* Local Function Prototypes.
*/
! static void ql_handle_uncommon_risc_intr(ql_adapter_state_t *, uint32_t,
! uint32_t *);
! static void ql_spurious_intr(ql_adapter_state_t *, int);
! static void ql_mbx_completion(ql_adapter_state_t *, uint16_t, uint32_t *,
! uint32_t *, int);
! static void ql_async_event(ql_adapter_state_t *, uint32_t, ql_head_t *,
! uint32_t *, uint32_t *, int);
! static void ql_fast_fcp_post(ql_srb_t *);
! static void ql_response_pkt(ql_adapter_state_t *, ql_head_t *, uint32_t *,
! uint32_t *, int);
! static void ql_error_entry(ql_adapter_state_t *, response_t *, ql_head_t *,
! uint32_t *, uint32_t *);
! static int ql_status_entry(ql_adapter_state_t *, sts_entry_t *, ql_head_t *,
! uint32_t *, uint32_t *);
! static int ql_24xx_status_entry(ql_adapter_state_t *, sts_24xx_entry_t *,
! ql_head_t *, uint32_t *, uint32_t *);
! static int ql_status_error(ql_adapter_state_t *, ql_srb_t *, sts_entry_t *,
! ql_head_t *, uint32_t *, uint32_t *);
! static void ql_status_cont_entry(ql_adapter_state_t *, sts_cont_entry_t *,
! ql_head_t *, uint32_t *, uint32_t *);
! static void ql_ip_entry(ql_adapter_state_t *, ip_entry_t *, ql_head_t *,
! uint32_t *, uint32_t *);
! static void ql_ip_rcv_entry(ql_adapter_state_t *, ip_rcv_entry_t *,
! ql_head_t *, uint32_t *, uint32_t *);
! static void ql_ip_rcv_cont_entry(ql_adapter_state_t *,
! ip_rcv_cont_entry_t *, ql_head_t *, uint32_t *, uint32_t *);
! static void ql_ip_24xx_rcv_entry(ql_adapter_state_t *, ip_rcv_24xx_entry_t *,
! ql_head_t *, uint32_t *, uint32_t *);
! static void ql_ms_entry(ql_adapter_state_t *, ms_entry_t *, ql_head_t *,
! uint32_t *, uint32_t *);
! static void ql_report_id_entry(ql_adapter_state_t *, report_id_1_t *,
! ql_head_t *, uint32_t *, uint32_t *);
! static void ql_els_passthru_entry(ql_adapter_state_t *,
! els_passthru_entry_rsp_t *, ql_head_t *, uint32_t *, uint32_t *);
! static ql_srb_t *ql_verify_preprocessed_cmd(ql_adapter_state_t *, uint32_t *,
! uint32_t *, uint32_t *);
! static void ql_signal_abort(ql_adapter_state_t *ha, uint32_t *set_flags);
/*
! * Spurious interrupt counter
*/
! uint32_t ql_spurious_cnt = 4;
! uint32_t ql_max_intr_loop = 16;
/*
! * ql_isr
! * Process all INTX intr types.
*
* Input:
! * arg1: adapter state pointer.
*
! * Returns:
! * DDI_INTR_CLAIMED or DDI_INTR_UNCLAIMED
*
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
! /* ARGSUSED */
! uint_t
! ql_isr(caddr_t arg1)
{
! return (ql_isr_aif(arg1, 0));
}
/*
! * ql_isr_default
! * Process unknown/unvectored intr types
*
* Input:
* arg1: adapter state pointer.
- * arg2: interrupt vector.
*
* Returns:
* DDI_INTR_CLAIMED or DDI_INTR_UNCLAIMED
*
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
/* ARGSUSED */
uint_t
! ql_isr_default(caddr_t arg1, caddr_t arg2)
{
! ql_adapter_state_t *ha = (void *)arg1;
!
! EL(ha, "isr_default called: idx=%x\n", arg2);
! return (ql_isr_aif(arg1, arg2));
}
/*
* ql_isr_aif
* Process mailbox and I/O command completions.
*
* Input:
* arg: adapter state pointer.
! * intvec: interrupt vector.
*
* Returns:
* DDI_INTR_CLAIMED or DDI_INTR_UNCLAIMED
*
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
/* ARGSUSED */
uint_t
! ql_isr_aif(caddr_t arg, caddr_t intvec)
{
! uint16_t mbx;
! uint32_t stat;
ql_adapter_state_t *ha = (void *)arg;
! uint32_t set_flags = 0;
! uint32_t reset_flags = 0;
ql_head_t isr_done_q = {NULL, NULL};
uint_t rval = DDI_INTR_UNCLAIMED;
! int spurious_intr = 0;
! boolean_t intr = B_FALSE, daemon = B_FALSE;
! int intr_loop = 4;
! boolean_t clear_spurious = B_TRUE;
! QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
! QL_PM_LOCK(ha);
if (ha->power_level != PM_LEVEL_D0) {
! /*
! * Looks like we are about to go down soon, exit early.
! */
! QL_PM_UNLOCK(ha);
! QL_PRINT_3(CE_CONT, "(%d): power down exit\n", ha->instance);
return (DDI_INTR_UNCLAIMED);
}
! ha->busy++;
QL_PM_UNLOCK(ha);
/* Acquire interrupt lock. */
! INTR_LOCK(ha);
!
! if (CFG_IST(ha, CFG_CTRL_2200)) {
! while (RD16_IO_REG(ha, istatus) & RISC_INT) {
! /* Reset idle timer. */
! ha->idle_timer = 0;
! rval = DDI_INTR_CLAIMED;
! if (intr_loop) {
! intr_loop--;
}
! /* Special Fast Post 2200. */
! stat = 0;
! if (ha->task_daemon_flags & FIRMWARE_LOADED &&
! ha->flags & ONLINE) {
! ql_srb_t *sp;
!
! mbx = RD16_IO_REG(ha, mailbox_out[23]);
!
! if ((mbx & 3) == MBX23_SCSI_COMPLETION) {
! /* Release mailbox registers. */
! WRT16_IO_REG(ha, semaphore, 0);
!
! if (intr_loop) {
! WRT16_IO_REG(ha, hccr,
! HC_CLR_RISC_INT);
}
! /* Get handle. */
! mbx >>= 4;
! stat = mbx & OSC_INDEX_MASK;
!
! /* Validate handle. */
! sp = stat < MAX_OUTSTANDING_COMMANDS ?
! ha->outstanding_cmds[stat] : NULL;
!
! if (sp != NULL && (sp->handle & 0xfff)
! == mbx) {
! ha->outstanding_cmds[stat] =
! NULL;
! sp->handle = 0;
! sp->flags &=
! ~SRB_IN_TOKEN_ARRAY;
!
! /* Set completed status. */
! sp->flags |= SRB_ISP_COMPLETED;
!
! /* Set completion status */
! sp->pkt->pkt_reason =
! CS_COMPLETE;
!
! ql_fast_fcp_post(sp);
! } else if (mbx !=
! (QL_FCA_BRAND & 0xfff)) {
! if (sp == NULL) {
! EL(ha, "unknown IOCB"
! " handle=%xh\n",
! mbx);
} else {
! EL(ha, "mismatch IOCB"
! " handle pkt=%xh, "
! "sp=%xh\n", mbx,
! sp->handle & 0xfff);
}
! (void) ql_binary_fw_dump(ha,
! FALSE);
!
! if (!(ha->task_daemon_flags &
! (ISP_ABORT_NEEDED |
! ABORT_ISP_ACTIVE))) {
! EL(ha, "ISP Invalid "
! "handle, "
! "isp_abort_needed"
! "\n");
! set_flags |=
! ISP_ABORT_NEEDED;
}
- }
- }
- }
! if (stat == 0) {
! /* Check for mailbox interrupt. */
! mbx = RD16_IO_REG(ha, semaphore);
! if (mbx & BIT_0) {
! /* Release mailbox registers. */
! WRT16_IO_REG(ha, semaphore, 0);
/* Get mailbox data. */
mbx = RD16_IO_REG(ha, mailbox_out[0]);
if (mbx > 0x3fff && mbx < 0x8000) {
ql_mbx_completion(ha, mbx,
! &set_flags, &reset_flags,
! intr_loop);
! } else if (mbx > 0x7fff &&
! mbx < 0xc000) {
! ql_async_event(ha, mbx,
&isr_done_q, &set_flags,
! &reset_flags, intr_loop);
} else {
! EL(ha, "UNKNOWN interrupt "
! "type\n");
! intr = B_TRUE;
}
} else {
! ha->isp_rsp_index = RD16_IO_REG(ha,
! resp_in);
!
! if (ha->isp_rsp_index !=
! ha->rsp_ring_index) {
! ql_response_pkt(ha,
&isr_done_q, &set_flags,
! &reset_flags, intr_loop);
! } else if (++spurious_intr ==
! MAX_SPURIOUS_INTR) {
! /*
! * Process excessive
! * spurious intrrupts
! */
! ql_spurious_intr(ha,
! intr_loop);
! EL(ha, "excessive spurious "
! "interrupts, "
! "isp_abort_needed\n");
! set_flags |= ISP_ABORT_NEEDED;
} else {
! intr = B_TRUE;
}
}
- }
-
/* Clear RISC interrupt */
! if (intr || intr_loop == 0) {
! intr = B_FALSE;
! WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT);
}
-
- if (set_flags != 0 || reset_flags != 0) {
- TASK_DAEMON_LOCK(ha);
- ha->task_daemon_flags |= set_flags;
- ha->task_daemon_flags &= ~reset_flags;
- TASK_DAEMON_UNLOCK(ha);
- set_flags = 0;
- reset_flags = 0;
- daemon = B_TRUE;
- }
- }
} else {
! uint32_t ql_max_intr_loop_cnt = 0;
!
! if (CFG_IST(ha, CFG_CTRL_8021)) {
ql_8021_clr_hw_intr(ha);
- intr_loop = 1;
}
- while (((stat = RD32_IO_REG(ha, risc2host)) & RH_RISC_INT) &&
- (++ql_max_intr_loop_cnt < ql_max_intr_loop)) {
! clear_spurious = B_TRUE; /* assume ok */
/* Capture FW defined interrupt info */
mbx = MSW(stat);
! /* Reset idle timer. */
! ha->idle_timer = 0;
! rval = DDI_INTR_CLAIMED;
!
! if (CFG_IST(ha, CFG_CTRL_8021) &&
! (RD32_IO_REG(ha, nx_risc_int) == 0 ||
! intr_loop == 0)) {
! break;
}
- if (intr_loop) {
- intr_loop--;
- }
-
switch (stat & 0x1ff) {
case ROM_MBX_SUCCESS:
case ROM_MBX_ERR:
ql_mbx_completion(ha, mbx, &set_flags,
! &reset_flags, intr_loop);
!
! /* Release mailbox registers. */
! if ((CFG_IST(ha, CFG_CTRL_24258081)) == 0) {
! WRT16_IO_REG(ha, semaphore, 0);
! }
break;
case MBX_SUCCESS:
case MBX_ERR:
- /* Sun FW, Release mailbox registers. */
- if ((CFG_IST(ha, CFG_CTRL_24258081)) == 0) {
- WRT16_IO_REG(ha, semaphore, 0);
- }
ql_mbx_completion(ha, mbx, &set_flags,
! &reset_flags, intr_loop);
break;
case ASYNC_EVENT:
! /* Sun FW, Release mailbox registers. */
! if ((CFG_IST(ha, CFG_CTRL_24258081)) == 0) {
! WRT16_IO_REG(ha, semaphore, 0);
! }
! ql_async_event(ha, (uint32_t)mbx, &isr_done_q,
! &set_flags, &reset_flags, intr_loop);
break;
case RESP_UPDATE:
! if (mbx != ha->rsp_ring_index) {
! ha->isp_rsp_index = mbx;
! ql_response_pkt(ha, &isr_done_q,
! &set_flags, &reset_flags,
! intr_loop);
! } else if (++spurious_intr ==
! ql_spurious_cnt) {
! /* Process excessive spurious intr. */
! ql_spurious_intr(ha, intr_loop);
! EL(ha, "excessive spurious "
! "interrupts, isp_abort_needed\n");
! set_flags |= ISP_ABORT_NEEDED;
! clear_spurious = B_FALSE;
} else {
! QL_PRINT_10(CE_CONT, "(%d): response "
! "ring index same as before\n",
! ha->instance);
! intr = B_TRUE;
! clear_spurious = B_FALSE;
}
break;
case SCSI_FAST_POST_16:
stat = (stat & 0xffff0000) | MBA_CMPLT_1_16BIT;
! ql_async_event(ha, stat, &isr_done_q,
! &set_flags, &reset_flags, intr_loop);
break;
case SCSI_FAST_POST_32:
stat = (stat & 0xffff0000) | MBA_CMPLT_1_32BIT;
! ql_async_event(ha, stat, &isr_done_q,
! &set_flags, &reset_flags, intr_loop);
break;
case CTIO_FAST_POST:
stat = (stat & 0xffff0000) |
MBA_CTIO_COMPLETION;
! ql_async_event(ha, stat, &isr_done_q,
! &set_flags, &reset_flags, intr_loop);
break;
case IP_FAST_POST_XMT:
stat = (stat & 0xffff0000) | MBA_IP_COMPLETION;
! ql_async_event(ha, stat, &isr_done_q,
! &set_flags, &reset_flags, intr_loop);
break;
case IP_FAST_POST_RCV:
stat = (stat & 0xffff0000) | MBA_IP_RECEIVE;
! ql_async_event(ha, stat, &isr_done_q,
! &set_flags, &reset_flags, intr_loop);
break;
case IP_FAST_POST_BRD:
stat = (stat & 0xffff0000) | MBA_IP_BROADCAST;
! ql_async_event(ha, stat, &isr_done_q,
! &set_flags, &reset_flags, intr_loop);
break;
case IP_FAST_POST_RCV_ALN:
stat = (stat & 0xffff0000) |
MBA_IP_HDR_DATA_SPLIT;
! ql_async_event(ha, stat, &isr_done_q,
! &set_flags, &reset_flags, intr_loop);
break;
case ATIO_UPDATE:
EL(ha, "unsupported ATIO queue update"
" interrupt, status=%xh\n", stat);
- intr = B_TRUE;
break;
case ATIO_RESP_UPDATE:
EL(ha, "unsupported ATIO response queue "
"update interrupt, status=%xh\n", stat);
- intr = B_TRUE;
break;
default:
! ql_handle_uncommon_risc_intr(ha, stat,
&set_flags);
- intr = B_TRUE;
break;
}
/* Clear RISC interrupt */
! if (intr || intr_loop == 0) {
! intr = B_FALSE;
! if (CFG_IST(ha, CFG_CTRL_8021)) {
! ql_8021_clr_fw_intr(ha);
! } else if (CFG_IST(ha, CFG_CTRL_242581)) {
! WRT32_IO_REG(ha, hccr,
! HC24_CLR_RISC_INT);
! } else {
! WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT);
}
- }
! if (set_flags != 0 || reset_flags != 0) {
! TASK_DAEMON_LOCK(ha);
! ha->task_daemon_flags |= set_flags;
! ha->task_daemon_flags &= ~reset_flags;
! TASK_DAEMON_UNLOCK(ha);
! set_flags = 0;
! reset_flags = 0;
! daemon = B_TRUE;
}
-
- if (ha->flags & PARITY_ERROR) {
- EL(ha, "parity/pause exit\n");
- mbx = RD16_IO_REG(ha, hccr); /* PCI posting */
- break;
}
- if (clear_spurious) {
- spurious_intr = 0;
- }
- }
- }
-
/* Process claimed interrupts during polls. */
if (rval == DDI_INTR_UNCLAIMED && ha->intr_claimed == B_TRUE) {
ha->intr_claimed = B_FALSE;
rval = DDI_INTR_CLAIMED;
}
/* Release interrupt lock. */
! INTR_UNLOCK(ha);
! if (daemon) {
! ql_awaken_task_daemon(ha, NULL, 0, 0);
}
if (isr_done_q.first != NULL) {
! ql_done(isr_done_q.first);
}
if (rval == DDI_INTR_CLAIMED) {
! QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
ha->xioctl->TotalInterrupts++;
} else {
/*EMPTY*/
! QL_PRINT_3(CE_CONT, "(%d): interrupt not claimed\n",
! ha->instance);
}
- QL_PM_LOCK(ha);
- ha->busy--;
- QL_PM_UNLOCK(ha);
-
return (rval);
}
/*
* ql_handle_uncommon_risc_intr
* Handle an uncommon RISC interrupt.
*
* Input:
* ha: adapter state pointer.
* stat: interrupt status
*
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
static void
! ql_handle_uncommon_risc_intr(ql_adapter_state_t *ha, uint32_t stat,
! uint32_t *set_flags)
{
uint16_t hccr_reg;
hccr_reg = RD16_IO_REG(ha, hccr);
--- 47,589 ----
#include <ql_isr.h>
#include <ql_init.h>
#include <ql_mbx.h>
#include <ql_nx.h>
#include <ql_xioctl.h>
+ #include <ql_fm.h>
/*
* Local Function Prototypes.
*/
! static void ql_clr_risc_intr(ql_adapter_state_t *);
! static void ql_handle_uncommon_risc_intr(ql_adapter_state_t *, int, uint32_t,
! uint64_t *);
! static void ql_mbx_completion(ql_adapter_state_t *, uint16_t, uint64_t *,
! uint64_t *);
! static void ql_async_event(ql_adapter_state_t *, ql_response_q_t *, uint32_t,
! ql_head_t *, uint64_t *, uint64_t *);
! static void ql_fast_fcp_post(ql_srb_t *, ql_response_q_t *);
! static void ql_response_pkt(ql_adapter_state_t *, ql_response_q_t *,
! ql_head_t *, uint64_t *, uint64_t *);
! static void ql_error_entry(ql_adapter_state_t *, ql_response_q_t *,
! response_t *, ql_head_t *, uint64_t *, uint64_t *);
! static int ql_status_entry(ql_adapter_state_t *, ql_response_q_t *,
! sts_entry_t *, ql_head_t *, uint64_t *, uint64_t *);
! static int ql_24xx_status_entry(ql_adapter_state_t *, ql_response_q_t *,
! sts_24xx_entry_t *, ql_head_t *, uint64_t *, uint64_t *);
! static int ql_status_error(ql_adapter_state_t *, ql_response_q_t *, ql_srb_t *,
! sts_entry_t *, ql_head_t *, uint64_t *, uint64_t *);
! static void ql_status_cont_entry(ql_adapter_state_t *, ql_response_q_t *,
! sts_cont_entry_t *, ql_head_t *, uint64_t *, uint64_t *);
! static void ql_ip_entry(ql_adapter_state_t *, ql_response_q_t *, ip_entry_t *,
! ql_head_t *, uint64_t *, uint64_t *);
! static void ql_ip_rcv_entry(ql_adapter_state_t *, ql_response_q_t *,
! ip_rcv_entry_t *, ql_head_t *, uint64_t *, uint64_t *);
! static void ql_ip_rcv_cont_entry(ql_adapter_state_t *, ql_response_q_t *,
! ip_rcv_cont_entry_t *, ql_head_t *, uint64_t *, uint64_t *);
! static void ql_ip_24xx_rcv_entry(ql_adapter_state_t *, ql_response_q_t *,
! ip_rcv_24xx_entry_t *, ql_head_t *, uint64_t *, uint64_t *);
! static void ql_ms_entry(ql_adapter_state_t *, ql_response_q_t *, ms_entry_t *,
! ql_head_t *, uint64_t *, uint64_t *);
! static void ql_report_id_entry(ql_adapter_state_t *, ql_response_q_t *,
! report_id_acq_t *, ql_head_t *, uint64_t *, uint64_t *);
! static void ql_els_passthru_entry(ql_adapter_state_t *, ql_response_q_t *,
! els_passthru_entry_rsp_t *, ql_head_t *, uint64_t *, uint64_t *);
! static ql_srb_t *ql_verify_preprocessed_cmd(ql_adapter_state_t *,
! ql_response_q_t *, uint32_t *, uint32_t *, uint64_t *, uint64_t *);
! static void ql_signal_abort(ql_adapter_state_t *, uint64_t *);
/*
! * ql_disable_intr
! * Disable interrupts.
! *
! * Input:
! * ha: adapter state pointer.
! *
! * Context:
! * Interrupt or Kernel context, no mailbox commands allowed.
*/
! void
! ql_disable_intr(ql_adapter_state_t *ha)
! {
! int i, rval;
+ QL_PRINT_10(ha, "started\n");
+
+ if (CFG_IST(ha, CFG_CTRL_82XX)) {
+ ql_8021_disable_intrs(ha);
+ } else {
+ if (CFG_IST(ha, CFG_ISP_FW_TYPE_2)) {
+ WRT32_IO_REG(ha, ictrl, 0);
+ (void) RD32_IO_REG(ha, ictrl); /* PCI posting */
+ } else {
+ WRT16_IO_REG(ha, ictrl, 0);
+ (void) RD16_IO_REG(ha, ictrl); /* PCI posting */
+ }
+ }
+ if (ha->intr_cap & DDI_INTR_FLAG_MASKABLE) {
+ for (i = 0; i < ha->intr_cnt; i++) {
+ QL_PRINT_10(ha, "intr_set_mask %d\n", i);
+ if ((rval = ddi_intr_set_mask(ha->htable[i])) !=
+ DDI_SUCCESS) {
+ EL(ha, "intr_set_mask status=%xh\n", rval);
+ }
+ }
+ }
+ ADAPTER_STATE_LOCK(ha);
+ ha->flags &= ~INTERRUPTS_ENABLED;
+ ADAPTER_STATE_UNLOCK(ha);
+
+ QL_PRINT_10(ha, "done\n");
+ }
+
/*
! * ql_enaable_intr
! * Enable interrupts.
*
* Input:
! * ha: adapter state pointer.
*
! * Context:
! * Interrupt or Kernel context, no mailbox commands allowed.
! */
! void
! ql_enable_intr(ql_adapter_state_t *ha)
! {
! int i, rval;
!
! QL_PRINT_10(ha, "started\n");
!
! if (CFG_IST(ha, CFG_CTRL_82XX)) {
! ql_8021_enable_intrs(ha);
! } else {
! if (CFG_IST(ha, CFG_ISP_FW_TYPE_2)) {
! WRT32_IO_REG(ha, ictrl, ISP_EN_RISC);
! (void) RD32_IO_REG(ha, ictrl); /* PCI posting */
! } else {
! WRT16_IO_REG(ha, ictrl, ISP_EN_INT + ISP_EN_RISC);
! (void) RD16_IO_REG(ha, ictrl); /* PCI posting */
! }
! }
! if (ha->intr_cap & DDI_INTR_FLAG_MASKABLE) {
! for (i = 0; i < ha->intr_cnt; i++) {
! QL_PRINT_10(ha, "intr_clr_mask %d\n", i);
! if ((rval = ddi_intr_clr_mask(ha->htable[i])) !=
! DDI_SUCCESS) {
! EL(ha, "intr_clr_mask status=%xh\n", rval);
! }
! }
! }
! ADAPTER_STATE_LOCK(ha);
! ha->flags |= INTERRUPTS_ENABLED;
! ADAPTER_STATE_UNLOCK(ha);
!
! QL_PRINT_10(ha, "done\n");
! }
!
! /*
! * ql_clr_risc_intr
! * Clear firmware interrupt.
*
+ * Input:
+ * ha: adapter state pointer.
+ *
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
! static void
! ql_clr_risc_intr(ql_adapter_state_t *ha)
{
! QL_PRINT_3(ha, "started\n");
!
! if (CFG_IST(ha, CFG_CTRL_82XX)) {
! ql_8021_clr_fw_intr(ha);
! } else if (CFG_IST(ha, CFG_ISP_FW_TYPE_2)) {
! WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
! RD32_IO_REG(ha, hccr); /* PCI posting. */
! } else {
! WRT16_IO_REG(ha, semaphore, 0);
! WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT);
! RD16_IO_REG(ha, hccr); /* PCI posting. */
! }
!
! QL_PRINT_3(ha, "done\n");
}
/*
! * ql_isr
! * Process all INTX intr types.
*
* Input:
* arg1: adapter state pointer.
*
* Returns:
* DDI_INTR_CLAIMED or DDI_INTR_UNCLAIMED
*
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
/* ARGSUSED */
uint_t
! ql_isr(caddr_t arg1)
{
! return (ql_isr_aif(arg1, 0));
}
/*
* ql_isr_aif
* Process mailbox and I/O command completions.
*
* Input:
* arg: adapter state pointer.
! * arg2: interrupt vector.
*
* Returns:
* DDI_INTR_CLAIMED or DDI_INTR_UNCLAIMED
*
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
/* ARGSUSED */
uint_t
! ql_isr_aif(caddr_t arg, caddr_t arg2)
{
! uint32_t mbx, stat;
ql_adapter_state_t *ha = (void *)arg;
! uint64_t set_flags = 0, reset_flags = 0;
ql_head_t isr_done_q = {NULL, NULL};
uint_t rval = DDI_INTR_UNCLAIMED;
! ql_response_q_t *rsp_q = NULL;
! int intr, index = (int)((uintptr_t)arg2);
! QL_PRINT_3(ha, "started, index=%d\n", index);
! /* Exit if not attached. */
! if (ha == NULL || ha->intr_pri == NULL) {
! EL(ha, "ha=%p, intr_pri=%p not attached\n", (void *)ha,
! ha != NULL ? ha->intr_pri : NULL);
! return (DDI_INTR_UNCLAIMED);
! }
!
! /* Exit if chip not powered up. */
if (ha->power_level != PM_LEVEL_D0) {
! EL(ha, "power down exit\n");
return (DDI_INTR_UNCLAIMED);
}
! QL_PM_LOCK(ha);
! ha->pm_busy++;
QL_PM_UNLOCK(ha);
/* Acquire interrupt lock. */
! if (index > ha->rsp_queues_cnt) {
! intr = index = 0;
! } else if (index) {
! intr = index - 1;
! } else {
! intr = 0;
}
+ INDX_INTR_LOCK(ha, intr);
! if (index && ha->flags & NO_INTR_HANDSHAKE) {
! QL_PRINT_3(ha, "MULTI_Q_RSP_UPDATE, index=%xh\n", index);
! index--;
! if (index < ha->rsp_queues_cnt) {
! rsp_q = ha->rsp_queues[index];
}
+ if (rsp_q == NULL) {
+ EL(ha, "unsupported MULTI_Q_RSP_UPDATE, index=%d\n",
+ index);
+ rsp_q = ha->rsp_queues[0];
+ }
! if (ha->flags & QUEUE_SHADOW_PTRS) {
! (void) ddi_dma_sync(rsp_q->rsp_ring.dma_handle,
! (off_t)rsp_q->rsp_in_shadow_ofst,
! SHADOW_ENTRY_SIZE, DDI_DMA_SYNC_FORCPU);
! mbx = ddi_get32(rsp_q->rsp_ring.acc_handle,
! rsp_q->rsp_in_shadow_ptr);
} else {
! mbx = RD32_MBAR_REG(ha, rsp_q->mbar_rsp_in);
}
! if (mbx != rsp_q->rsp_ring_index) {
! rsp_q->isp_rsp_index = (uint16_t)mbx;
! ql_response_pkt(ha, rsp_q, &isr_done_q,
! &set_flags, &reset_flags);
! /* PCI posting */
! (void) RD32_MBAR_REG(ha, rsp_q->mbar_rsp_in);
! } else if (ha->flags & INTERRUPTS_ENABLED) {
! /*EMPTY*/
! QL_PRINT_3(ha, "MULTI_Q_RSP_UPDATE mbar_rsp_in "
! "same as before\n");
}
! /* Set interrupt claimed status. */
! rval = DDI_INTR_CLAIMED;
+ } else if (CFG_IST(ha, CFG_CTRL_22XX)) {
+ rsp_q = ha->rsp_queues[0];
+ if (RD16_IO_REG(ha, istatus) & RISC_INT) {
+ rval = DDI_INTR_CLAIMED;
+
+ /* Check for mailbox interrupt. */
+ stat = RD16_IO_REG(ha, semaphore);
+ if (stat & BIT_0) {
/* Get mailbox data. */
mbx = RD16_IO_REG(ha, mailbox_out[0]);
if (mbx > 0x3fff && mbx < 0x8000) {
ql_mbx_completion(ha, mbx,
! &set_flags, &reset_flags);
! } else if (mbx > 0x7fff && mbx < 0xc000) {
! ql_async_event(ha, rsp_q, mbx,
&isr_done_q, &set_flags,
! &reset_flags);
} else {
! EL(ha, "22XX unknown interrupt type\n");
}
} else {
! rsp_q->isp_rsp_index = RD16_IO_REG(ha, resp_in);
! if (rsp_q->isp_rsp_index !=
! rsp_q->rsp_ring_index) {
! ql_response_pkt(ha, rsp_q,
&isr_done_q, &set_flags,
! &reset_flags);
} else {
! /*EMPTY*/
! QL_PRINT_10(ha, "22XX isp_rsp_index "
! "same as before\n");
}
}
/* Clear RISC interrupt */
! ql_clr_risc_intr(ha);
}
} else {
! if (CFG_IST(ha, CFG_CTRL_82XX)) {
ql_8021_clr_hw_intr(ha);
}
! if (((stat = RD32_IO_REG(ha, risc2host)) & RH_RISC_INT) == 0) {
! QL_PRINT_10(ha, "done, index=%d, no interrupt "
! "stat=%xh\n", index, stat);
! rval = DDI_INTR_UNCLAIMED;
! } else if (ha->ql_dump_state & QL_DUMPING) {
! EL(ha, "fw_dump, index=%d, active stat=%xh\n",
! index, stat);
! rval = DDI_INTR_CLAIMED;
! } else if (CFG_IST(ha, CFG_CTRL_82XX) &&
! RD32_IO_REG(ha, nx_risc_int) == 0) {
! QL_PRINT_10(ha, "done, index=%d, no nx_risc_int "
! "stat=%xh\n", index, stat);
! rval = DDI_INTR_UNCLAIMED;
! } else {
! rval = DDI_INTR_CLAIMED;
! QL_PRINT_3(ha, "index=%d, interrupt stat=%xh\n",
! index, stat);
/* Capture FW defined interrupt info */
mbx = MSW(stat);
! if (qlc_fm_check_acc_handle(ha, ha->dev_handle)
! != DDI_FM_OK) {
! qlc_fm_report_err_impact(ha,
! QL_FM_EREPORT_ACC_HANDLE_CHECK);
}
switch (stat & 0x1ff) {
case ROM_MBX_SUCCESS:
case ROM_MBX_ERR:
ql_mbx_completion(ha, mbx, &set_flags,
! &reset_flags);
break;
case MBX_SUCCESS:
case MBX_ERR:
ql_mbx_completion(ha, mbx, &set_flags,
! &reset_flags);
break;
case ASYNC_EVENT:
! ql_async_event(ha, ha->rsp_queues[0],
! (uint32_t)mbx, &isr_done_q,
! &set_flags, &reset_flags);
break;
+ case MULTI_Q_RSP_UPDATE:
+ QL_PRINT_3(ha, "MULTI_Q_RSP_UPDATE mbx=%xh\n",
+ mbx);
+ if (mbx < ha->rsp_queues_cnt) {
+ rsp_q = ha->rsp_queues[mbx];
+ }
+ if (rsp_q == NULL) {
+ EL(ha, "unsupported MULTI_Q_RSP_UPDATE"
+ " mbx=%d\n", mbx);
+ rsp_q = ha->rsp_queues[0];
+ }
+ if (ha->flags & QUEUE_SHADOW_PTRS) {
+ (void) ddi_dma_sync(
+ rsp_q->rsp_ring.dma_handle,
+ (off_t)rsp_q->rsp_in_shadow_ofst,
+ SHADOW_ENTRY_SIZE,
+ DDI_DMA_SYNC_FORCPU);
+ mbx = ddi_get32(
+ rsp_q->rsp_ring.acc_handle,
+ rsp_q->rsp_in_shadow_ptr);
+ } else {
+ mbx = RD32_MBAR_REG(ha,
+ rsp_q->mbar_rsp_in);
+ }
+ /* FALLTHRU */
+
case RESP_UPDATE:
! /* Clear RISC interrupt */
! ql_clr_risc_intr(ha);
!
! if (rsp_q == NULL) {
! rsp_q = ha->rsp_queues[0];
! }
! if (mbx != rsp_q->rsp_ring_index) {
! rsp_q->isp_rsp_index = (uint16_t)mbx;
! ql_response_pkt(ha, rsp_q, &isr_done_q,
! &set_flags, &reset_flags);
} else {
! /*EMPTY*/
! QL_PRINT_3(ha, "response "
! "ring index same as before\n");
}
break;
case SCSI_FAST_POST_16:
stat = (stat & 0xffff0000) | MBA_CMPLT_1_16BIT;
! ql_async_event(ha, ha->rsp_queues[0],
! stat, &isr_done_q, &set_flags,
! &reset_flags);
break;
case SCSI_FAST_POST_32:
stat = (stat & 0xffff0000) | MBA_CMPLT_1_32BIT;
! ql_async_event(ha, ha->rsp_queues[0],
! stat, &isr_done_q, &set_flags,
! &reset_flags);
break;
case CTIO_FAST_POST:
stat = (stat & 0xffff0000) |
MBA_CTIO_COMPLETION;
! ql_async_event(ha, ha->rsp_queues[0],
! stat, &isr_done_q, &set_flags,
! &reset_flags);
break;
case IP_FAST_POST_XMT:
stat = (stat & 0xffff0000) | MBA_IP_COMPLETION;
! ql_async_event(ha, ha->rsp_queues[0],
! stat, &isr_done_q, &set_flags,
! &reset_flags);
break;
case IP_FAST_POST_RCV:
stat = (stat & 0xffff0000) | MBA_IP_RECEIVE;
! ql_async_event(ha, ha->rsp_queues[0],
! stat, &isr_done_q, &set_flags,
! &reset_flags);
break;
case IP_FAST_POST_BRD:
stat = (stat & 0xffff0000) | MBA_IP_BROADCAST;
! ql_async_event(ha, ha->rsp_queues[0],
! stat, &isr_done_q, &set_flags,
! &reset_flags);
break;
case IP_FAST_POST_RCV_ALN:
stat = (stat & 0xffff0000) |
MBA_IP_HDR_DATA_SPLIT;
! ql_async_event(ha, ha->rsp_queues[0],
! stat, &isr_done_q, &set_flags,
! &reset_flags);
break;
case ATIO_UPDATE:
EL(ha, "unsupported ATIO queue update"
" interrupt, status=%xh\n", stat);
break;
case ATIO_RESP_UPDATE:
EL(ha, "unsupported ATIO response queue "
"update interrupt, status=%xh\n", stat);
break;
default:
! ql_handle_uncommon_risc_intr(ha, intr, stat,
&set_flags);
break;
}
+ }
/* Clear RISC interrupt */
! if (rval == DDI_INTR_CLAIMED && rsp_q == NULL) {
! ql_clr_risc_intr(ha);
}
! /* A0 chip delay */
! if (CFG_IST(ha, CFG_CTRL_83XX) && ha->rev_id == 1 &&
! ha->iflags & (IFLG_INTR_LEGACY | IFLG_INTR_FIXED)) {
! drv_usecwait(4);
}
}
/* Process claimed interrupts during polls. */
if (rval == DDI_INTR_UNCLAIMED && ha->intr_claimed == B_TRUE) {
ha->intr_claimed = B_FALSE;
rval = DDI_INTR_CLAIMED;
}
/* Release interrupt lock. */
! INDX_INTR_UNLOCK(ha, intr);
! if (set_flags || reset_flags) {
! ql_awaken_task_daemon(ha, NULL, set_flags, reset_flags);
}
if (isr_done_q.first != NULL) {
! ql_done(isr_done_q.first, B_FALSE);
}
+ QL_PM_LOCK(ha);
+ if (ha->pm_busy) {
+ ha->pm_busy--;
+ }
+ QL_PM_UNLOCK(ha);
+
if (rval == DDI_INTR_CLAIMED) {
! QL_PRINT_3(ha, "done\n");
! ha->idle_timer = 0;
ha->xioctl->TotalInterrupts++;
} else {
/*EMPTY*/
! QL_PRINT_10(ha, "interrupt not claimed\n");
}
return (rval);
}
/*
* ql_handle_uncommon_risc_intr
* Handle an uncommon RISC interrupt.
*
* Input:
* ha: adapter state pointer.
+ * intr: interrupt index.
* stat: interrupt status
+ * set_flags: task daemon flags to set.
*
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
static void
! ql_handle_uncommon_risc_intr(ql_adapter_state_t *ha, int intr, uint32_t stat,
! uint64_t *set_flags)
{
uint16_t hccr_reg;
hccr_reg = RD16_IO_REG(ha, hccr);
*** 585,597 ****
--- 605,619 ----
ha->parity_stat_err = stat;
}
EL(ha, "parity/pause error, isp_abort_needed\n");
+ INDX_INTR_UNLOCK(ha, intr);
if (ql_binary_fw_dump(ha, FALSE) != QL_SUCCESS) {
ql_reset_chip(ha);
}
+ INDX_INTR_LOCK(ha, intr);
if (ha->parity_pause_errors == 0) {
ha->log_parity_pause = B_TRUE;
}
*** 600,686 ****
}
*set_flags |= ISP_ABORT_NEEDED;
/* Disable ISP interrupts. */
! CFG_IST(ha, CFG_CTRL_8021) ? ql_8021_disable_intrs(ha) :
! WRT16_IO_REG(ha, ictrl, 0);
! ADAPTER_STATE_LOCK(ha);
! ha->flags &= ~INTERRUPTS_ENABLED;
! ADAPTER_STATE_UNLOCK(ha);
} else {
EL(ha, "UNKNOWN interrupt status=%xh, hccr=%xh\n",
stat, hccr_reg);
}
}
/*
- * ql_spurious_intr
- * Inform Solaris of spurious interrupts.
- *
- * Input:
- * ha: adapter state pointer.
- * intr_clr: early interrupt clear
- *
- * Context:
- * Interrupt or Kernel context, no mailbox commands allowed.
- */
- static void
- ql_spurious_intr(ql_adapter_state_t *ha, int intr_clr)
- {
- ddi_devstate_t state;
-
- EL(ha, "Spurious interrupt\n");
-
- /* Disable ISP interrupts. */
- WRT16_IO_REG(ha, ictrl, 0);
- ADAPTER_STATE_LOCK(ha);
- ha->flags &= ~INTERRUPTS_ENABLED;
- ADAPTER_STATE_UNLOCK(ha);
-
- /* Clear RISC interrupt */
- if (intr_clr) {
- if (CFG_IST(ha, CFG_CTRL_8021)) {
- ql_8021_clr_fw_intr(ha);
- } else if (CFG_IST(ha, CFG_CTRL_242581)) {
- WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
- } else {
- WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT);
- }
- }
-
- state = ddi_get_devstate(ha->dip);
- if (state == DDI_DEVSTATE_UP) {
- /*EMPTY*/
- ddi_dev_report_fault(ha->dip, DDI_SERVICE_DEGRADED,
- DDI_DEVICE_FAULT, "spurious interrupts");
- }
- }
-
- /*
* ql_mbx_completion
* Processes mailbox completions.
*
* Input:
* ha: adapter state pointer.
* mb0: Mailbox 0 contents.
* set_flags: task daemon flags to set.
* reset_flags: task daemon flags to reset.
- * intr_clr: early interrupt clear
*
* Context:
* Interrupt context.
*/
/* ARGSUSED */
static void
! ql_mbx_completion(ql_adapter_state_t *ha, uint16_t mb0, uint32_t *set_flags,
! uint32_t *reset_flags, int intr_clr)
{
uint32_t index;
uint16_t cnt;
! QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
/* Load return mailbox registers. */
MBX_REGISTER_LOCK(ha);
if (ha->mcp != NULL) {
--- 622,660 ----
}
*set_flags |= ISP_ABORT_NEEDED;
/* Disable ISP interrupts. */
! ql_disable_intr(ha);
} else {
EL(ha, "UNKNOWN interrupt status=%xh, hccr=%xh\n",
stat, hccr_reg);
}
}
/*
* ql_mbx_completion
* Processes mailbox completions.
*
* Input:
* ha: adapter state pointer.
* mb0: Mailbox 0 contents.
* set_flags: task daemon flags to set.
* reset_flags: task daemon flags to reset.
*
* Context:
* Interrupt context.
*/
/* ARGSUSED */
static void
! ql_mbx_completion(ql_adapter_state_t *ha, uint16_t mb0, uint64_t *set_flags,
! uint64_t *reset_flags)
{
uint32_t index;
uint16_t cnt;
! QL_PRINT_3(ha, "started\n");
/* Load return mailbox registers. */
MBX_REGISTER_LOCK(ha);
if (ha->mcp != NULL) {
*** 697,783 ****
} else {
EL(ha, "mcp == NULL\n");
}
- if (intr_clr) {
- /* Clear RISC interrupt. */
- if (CFG_IST(ha, CFG_CTRL_8021)) {
- ql_8021_clr_fw_intr(ha);
- } else if (CFG_IST(ha, CFG_CTRL_242581)) {
- WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
- } else {
- WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT);
- }
- }
-
ha->mailbox_flags = (uint8_t)(ha->mailbox_flags | MBX_INTERRUPT);
if (ha->flags & INTERRUPTS_ENABLED) {
cv_broadcast(&ha->cv_mbx_intr);
}
MBX_REGISTER_UNLOCK(ha);
! QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
}
/*
* ql_async_event
* Processes asynchronous events.
*
* Input:
* ha: adapter state pointer.
* mbx: Mailbox 0 register.
* done_q: head pointer to done queue.
* set_flags: task daemon flags to set.
* reset_flags: task daemon flags to reset.
- * intr_clr: early interrupt clear
*
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
static void
! ql_async_event(ql_adapter_state_t *ha, uint32_t mbx, ql_head_t *done_q,
! uint32_t *set_flags, uint32_t *reset_flags, int intr_clr)
{
! uint32_t handle;
! uint32_t index;
! uint16_t cnt;
! uint16_t mb[MAX_MBOX_COUNT];
ql_srb_t *sp;
port_id_t s_id;
ql_tgt_t *tq;
- boolean_t intr = B_TRUE;
ql_adapter_state_t *vha;
! QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
/* Setup to process fast completion. */
mb[0] = LSW(mbx);
switch (mb[0]) {
case MBA_SCSI_COMPLETION:
! handle = SHORT_TO_LONG(RD16_IO_REG(ha, mailbox_out[1]),
RD16_IO_REG(ha, mailbox_out[2]));
break;
case MBA_CMPLT_1_16BIT:
! handle = MSW(mbx);
mb[0] = MBA_SCSI_COMPLETION;
break;
case MBA_CMPLT_1_32BIT:
! handle = SHORT_TO_LONG(MSW(mbx),
RD16_IO_REG(ha, mailbox_out[2]));
mb[0] = MBA_SCSI_COMPLETION;
break;
case MBA_CTIO_COMPLETION:
case MBA_IP_COMPLETION:
! handle = CFG_IST(ha, CFG_CTRL_2200) ? SHORT_TO_LONG(
RD16_IO_REG(ha, mailbox_out[1]),
RD16_IO_REG(ha, mailbox_out[2])) :
SHORT_TO_LONG(MSW(mbx), RD16_IO_REG(ha, mailbox_out[2]));
mb[0] = MBA_SCSI_COMPLETION;
break;
default:
break;
--- 671,792 ----
} else {
EL(ha, "mcp == NULL\n");
}
ha->mailbox_flags = (uint8_t)(ha->mailbox_flags | MBX_INTERRUPT);
if (ha->flags & INTERRUPTS_ENABLED) {
cv_broadcast(&ha->cv_mbx_intr);
}
MBX_REGISTER_UNLOCK(ha);
! QL_PRINT_3(ha, "done\n");
}
/*
* ql_async_event
* Processes asynchronous events.
*
* Input:
* ha: adapter state pointer.
+ * rsp_q: response queue structure pointer.
* mbx: Mailbox 0 register.
* done_q: head pointer to done queue.
* set_flags: task daemon flags to set.
* reset_flags: task daemon flags to reset.
*
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
static void
! ql_async_event(ql_adapter_state_t *ha, ql_response_q_t *rsp_q, uint32_t mbx,
! ql_head_t *done_q, uint64_t *set_flags, uint64_t *reset_flags)
{
! uint32_t index, handles[5];
! uint16_t cnt, handle_cnt, mb[MAX_MBOX_COUNT];
ql_srb_t *sp;
port_id_t s_id;
ql_tgt_t *tq;
ql_adapter_state_t *vha;
! QL_PRINT_3(ha, "started\n");
/* Setup to process fast completion. */
mb[0] = LSW(mbx);
switch (mb[0]) {
case MBA_SCSI_COMPLETION:
! handles[0] = SHORT_TO_LONG(RD16_IO_REG(ha, mailbox_out[1]),
RD16_IO_REG(ha, mailbox_out[2]));
+ handle_cnt = 1;
break;
case MBA_CMPLT_1_16BIT:
! handles[0] = MSW(mbx);
! handle_cnt = 1;
mb[0] = MBA_SCSI_COMPLETION;
break;
+ case MBA_CMPLT_2_16BIT:
+ handles[0] = (uint32_t)RD16_IO_REG(ha, mailbox_out[1]);
+ handles[1] = (uint32_t)RD16_IO_REG(ha, mailbox_out[2]);
+ handle_cnt = 2;
+ mb[0] = MBA_SCSI_COMPLETION;
+ break;
+
+ case MBA_CMPLT_3_16BIT:
+ handles[0] = (uint32_t)RD16_IO_REG(ha, mailbox_out[1]);
+ handles[1] = (uint32_t)RD16_IO_REG(ha, mailbox_out[2]);
+ handles[2] = (uint32_t)RD16_IO_REG(ha, mailbox_out[3]);
+ handle_cnt = 3;
+ mb[0] = MBA_SCSI_COMPLETION;
+ break;
+
+ case MBA_CMPLT_4_16BIT:
+ handles[0] = (uint32_t)RD16_IO_REG(ha, mailbox_out[1]);
+ handles[1] = (uint32_t)RD16_IO_REG(ha, mailbox_out[2]);
+ handles[2] = (uint32_t)RD16_IO_REG(ha, mailbox_out[3]);
+ handles[3] = (uint32_t)RD16_IO_REG(ha, mailbox_out[6]);
+ handle_cnt = 4;
+ mb[0] = MBA_SCSI_COMPLETION;
+ break;
+
+ case MBA_CMPLT_5_16BIT:
+ handles[0] = (uint32_t)RD16_IO_REG(ha, mailbox_out[1]);
+ handles[1] = (uint32_t)RD16_IO_REG(ha, mailbox_out[2]);
+ handles[2] = (uint32_t)RD16_IO_REG(ha, mailbox_out[3]);
+ handles[3] = (uint32_t)RD16_IO_REG(ha, mailbox_out[6]);
+ handles[4] = (uint32_t)RD16_IO_REG(ha, mailbox_out[7]);
+ handle_cnt = 5;
+ mb[0] = MBA_SCSI_COMPLETION;
+ break;
+
case MBA_CMPLT_1_32BIT:
! handles[0] = SHORT_TO_LONG(MSW(mbx),
RD16_IO_REG(ha, mailbox_out[2]));
+ handle_cnt = 1;
mb[0] = MBA_SCSI_COMPLETION;
break;
+ case MBA_CMPLT_2_32BIT:
+ handles[0] = SHORT_TO_LONG(
+ RD16_IO_REG(ha, mailbox_out[1]),
+ RD16_IO_REG(ha, mailbox_out[2]));
+ handles[1] = SHORT_TO_LONG(
+ RD16_IO_REG(ha, mailbox_out[6]),
+ RD16_IO_REG(ha, mailbox_out[7]));
+ handle_cnt = 2;
+ mb[0] = MBA_SCSI_COMPLETION;
+ break;
+
case MBA_CTIO_COMPLETION:
case MBA_IP_COMPLETION:
! handles[0] = CFG_IST(ha, CFG_CTRL_22XX) ? SHORT_TO_LONG(
RD16_IO_REG(ha, mailbox_out[1]),
RD16_IO_REG(ha, mailbox_out[2])) :
SHORT_TO_LONG(MSW(mbx), RD16_IO_REG(ha, mailbox_out[2]));
+ handle_cnt = 1;
mb[0] = MBA_SCSI_COMPLETION;
break;
default:
break;
*** 784,821 ****
}
/* Handle asynchronous event */
switch (mb[0]) {
case MBA_SCSI_COMPLETION:
! QL_PRINT_5(CE_CONT, "(%d): Fast post completion\n",
! ha->instance);
- if (intr_clr) {
- /* Clear RISC interrupt */
- if (CFG_IST(ha, CFG_CTRL_8021)) {
- ql_8021_clr_fw_intr(ha);
- } else if (CFG_IST(ha, CFG_CTRL_242581)) {
- WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
- } else {
- WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT);
- }
- intr = B_FALSE;
- }
-
if ((ha->flags & ONLINE) == 0) {
break;
}
/* Get handle. */
! index = handle & OSC_INDEX_MASK;
/* Validate handle. */
! sp = index < MAX_OUTSTANDING_COMMANDS ?
ha->outstanding_cmds[index] : NULL;
! if (sp != NULL && sp->handle == handle) {
ha->outstanding_cmds[index] = NULL;
sp->handle = 0;
sp->flags &= ~SRB_IN_TOKEN_ARRAY;
/* Set completed status. */
sp->flags |= SRB_ISP_COMPLETED;
--- 793,827 ----
}
/* Handle asynchronous event */
switch (mb[0]) {
case MBA_SCSI_COMPLETION:
! QL_PRINT_5(ha, "Fast post completion\n");
if ((ha->flags & ONLINE) == 0) {
break;
}
+ for (cnt = 0; cnt < handle_cnt; cnt++) {
+ QL_PRINT_5(ha, "Fast post completion, handle=%xh\n",
+ handles[cnt]);
+
/* Get handle. */
! index = handles[cnt] & OSC_INDEX_MASK;
/* Validate handle. */
! sp = index < ha->osc_max_cnt ?
ha->outstanding_cmds[index] : NULL;
! if (sp == QL_ABORTED_SRB(ha)) {
! EL(ha, "QL_ABORTED_SRB handle=%xh\n",
! handles[cnt]);
ha->outstanding_cmds[index] = NULL;
+ continue;
+ }
+ if (sp != NULL && sp->handle == handles[cnt]) {
+ ha->outstanding_cmds[index] = NULL;
sp->handle = 0;
sp->flags &= ~SRB_IN_TOKEN_ARRAY;
/* Set completed status. */
sp->flags |= SRB_ISP_COMPLETED;
*** 825,867 ****
if (!(sp->flags & SRB_FCP_CMD_PKT)) {
/* Place block on done queue */
ql_add_link_b(done_q, &sp->cmd);
} else {
! ql_fast_fcp_post(sp);
}
! } else if (handle != QL_FCA_BRAND) {
if (sp == NULL) {
EL(ha, "%xh unknown IOCB handle=%xh\n",
! mb[0], handle);
} else {
! EL(ha, "%xh mismatch IOCB handle pkt=%xh, "
! "sp=%xh\n", mb[0], handle, sp->handle);
}
! EL(ha, "%xh Fast post, mbx1=%xh, mbx2=%xh, mbx3=%xh,"
! "mbx6=%xh, mbx7=%xh\n", mb[0],
RD16_IO_REG(ha, mailbox_out[1]),
RD16_IO_REG(ha, mailbox_out[2]),
RD16_IO_REG(ha, mailbox_out[3]),
RD16_IO_REG(ha, mailbox_out[6]),
RD16_IO_REG(ha, mailbox_out[7]));
! (void) ql_binary_fw_dump(ha, FALSE);
if (!(ha->task_daemon_flags &
! (ISP_ABORT_NEEDED | ABORT_ISP_ACTIVE))) {
EL(ha, "%xh ISP Invalid handle, "
"isp_abort_needed\n", mb[0]);
*set_flags |= ISP_ABORT_NEEDED;
}
}
break;
case MBA_RESET: /* Reset */
EL(ha, "%xh Reset received\n", mb[0]);
! *set_flags |= RESET_MARKER_NEEDED;
break;
case MBA_SYSTEM_ERR: /* System Error */
mb[1] = RD16_IO_REG(ha, mailbox_out[1]);
mb[2] = RD16_IO_REG(ha, mailbox_out[2]);
--- 831,877 ----
if (!(sp->flags & SRB_FCP_CMD_PKT)) {
/* Place block on done queue */
ql_add_link_b(done_q, &sp->cmd);
} else {
! ql_fast_fcp_post(sp, rsp_q);
}
! } else if (handles[cnt] != QL_FCA_BRAND) {
if (sp == NULL) {
EL(ha, "%xh unknown IOCB handle=%xh\n",
! mb[0], handles[cnt]);
} else {
! EL(ha, "%xh mismatch IOCB handle "
! "pkt=%xh, sp=%xh\n", mb[0],
! handles[cnt], sp->handle);
}
! EL(ha, "%xh Fast post, mbx1=%xh, mbx2=%xh, "
! "mbx3=%xh, mbx6=%xh, mbx7=%xh\n", mb[0],
RD16_IO_REG(ha, mailbox_out[1]),
RD16_IO_REG(ha, mailbox_out[2]),
RD16_IO_REG(ha, mailbox_out[3]),
RD16_IO_REG(ha, mailbox_out[6]),
RD16_IO_REG(ha, mailbox_out[7]));
! ADAPTER_STATE_LOCK(ha);
! ha->flags |= FW_DUMP_NEEDED;
! ADAPTER_STATE_UNLOCK(ha);
if (!(ha->task_daemon_flags &
! ISP_ABORT_NEEDED)) {
EL(ha, "%xh ISP Invalid handle, "
"isp_abort_needed\n", mb[0]);
*set_flags |= ISP_ABORT_NEEDED;
}
}
+ }
break;
case MBA_RESET: /* Reset */
EL(ha, "%xh Reset received\n", mb[0]);
! *set_flags |= MARKER_NEEDED;
break;
case MBA_SYSTEM_ERR: /* System Error */
mb[1] = RD16_IO_REG(ha, mailbox_out[1]);
mb[2] = RD16_IO_REG(ha, mailbox_out[2]);
*** 908,921 ****
RD16_IO_REG(ha, mailbox_out[29]),
RD16_IO_REG(ha, mailbox_out[30]),
RD16_IO_REG(ha, mailbox_out[31]));
}
! (void) ql_binary_fw_dump(ha, FALSE);
! (void) ql_flash_errlog(ha, FLASH_ERRLOG_AEN_8002, mb[1],
! mb[2], mb[3]);
if (CFG_IST(ha, CFG_CTRL_81XX) && mb[7] & SE_MPI_RISC) {
ADAPTER_STATE_LOCK(ha);
ha->flags |= MPI_RESET_NEEDED;
ADAPTER_STATE_UNLOCK(ha);
--- 918,938 ----
RD16_IO_REG(ha, mailbox_out[29]),
RD16_IO_REG(ha, mailbox_out[30]),
RD16_IO_REG(ha, mailbox_out[31]));
}
! ADAPTER_STATE_LOCK(ha);
! ha->flags |= FW_DUMP_NEEDED;
! ADAPTER_STATE_UNLOCK(ha);
! /* Signal task daemon to store error log. */
! if (ha->errlog[0] == 0) {
! ha->errlog[3] = mb[3];
! ha->errlog[2] = mb[2];
! ha->errlog[1] = mb[1];
! ha->errlog[0] = FLASH_ERRLOG_AEN_8002;
! }
if (CFG_IST(ha, CFG_CTRL_81XX) && mb[7] & SE_MPI_RISC) {
ADAPTER_STATE_LOCK(ha);
ha->flags |= MPI_RESET_NEEDED;
ADAPTER_STATE_UNLOCK(ha);
*** 927,961 ****
case MBA_REQ_TRANSFER_ERR: /* Request Transfer Error */
EL(ha, "%xh Request Transfer Error received, "
"isp_abort_needed\n", mb[0]);
! (void) ql_flash_errlog(ha, FLASH_ERRLOG_AEN_8003,
! RD16_IO_REG(ha, mailbox_out[1]),
! RD16_IO_REG(ha, mailbox_out[2]),
! RD16_IO_REG(ha, mailbox_out[3]));
*set_flags |= ISP_ABORT_NEEDED;
ha->xioctl->ControllerErrorCount++;
break;
case MBA_RSP_TRANSFER_ERR: /* Response Xfer Err */
EL(ha, "%xh Response Transfer Error received,"
" isp_abort_needed\n", mb[0]);
! (void) ql_flash_errlog(ha, FLASH_ERRLOG_AEN_8004,
! RD16_IO_REG(ha, mailbox_out[1]),
! RD16_IO_REG(ha, mailbox_out[2]),
! RD16_IO_REG(ha, mailbox_out[3]));
*set_flags |= ISP_ABORT_NEEDED;
ha->xioctl->ControllerErrorCount++;
break;
case MBA_WAKEUP_THRES: /* Request Queue Wake-up */
! EL(ha, "%xh Request Queue Wake-up received\n",
! mb[0]);
break;
case MBA_MENLO_ALERT: /* Menlo Alert Notification */
mb[1] = RD16_IO_REG(ha, mailbox_out[1]);
mb[2] = RD16_IO_REG(ha, mailbox_out[2]);
--- 944,993 ----
case MBA_REQ_TRANSFER_ERR: /* Request Transfer Error */
EL(ha, "%xh Request Transfer Error received, "
"isp_abort_needed\n", mb[0]);
! /* Signal task daemon to store error log. */
! if (ha->errlog[0] == 0) {
! ha->errlog[3] = RD16_IO_REG(ha, mailbox_out[3]);
! ha->errlog[2] = RD16_IO_REG(ha, mailbox_out[2]);
! ha->errlog[1] = RD16_IO_REG(ha, mailbox_out[1]);
! ha->errlog[0] = FLASH_ERRLOG_AEN_8003;
! }
*set_flags |= ISP_ABORT_NEEDED;
ha->xioctl->ControllerErrorCount++;
+
+ (void) qlc_fm_report_err_impact(ha,
+ QL_FM_EREPORT_MBA_REQ_TRANSFER_ERR);
+
break;
case MBA_RSP_TRANSFER_ERR: /* Response Xfer Err */
EL(ha, "%xh Response Transfer Error received,"
" isp_abort_needed\n", mb[0]);
! /* Signal task daemon to store error log. */
! if (ha->errlog[0] == 0) {
! ha->errlog[3] = RD16_IO_REG(ha, mailbox_out[3]);
! ha->errlog[2] = RD16_IO_REG(ha, mailbox_out[2]);
! ha->errlog[1] = RD16_IO_REG(ha, mailbox_out[1]);
! ha->errlog[0] = FLASH_ERRLOG_AEN_8004;
! }
*set_flags |= ISP_ABORT_NEEDED;
ha->xioctl->ControllerErrorCount++;
+
+ (void) qlc_fm_report_err_impact(ha,
+ QL_FM_EREPORT_MBA_RSP_TRANSFER_ERR);
+
break;
case MBA_WAKEUP_THRES: /* Request Queue Wake-up */
! EL(ha, "%xh Request Queue Wake-up "
! "received, mbx1=%xh\n", mb[0],
! RD16_IO_REG(ha, mailbox_out[1]));
break;
case MBA_MENLO_ALERT: /* Menlo Alert Notification */
mb[1] = RD16_IO_REG(ha, mailbox_out[1]);
mb[2] = RD16_IO_REG(ha, mailbox_out[2]);
*** 980,990 ****
break;
case MBA_LIP_F8: /* Received a LIP F8. */
case MBA_LIP_RESET: /* LIP reset occurred. */
case MBA_LIP_OCCURRED: /* Loop Initialization Procedure */
! if (CFG_IST(ha, CFG_CTRL_8081)) {
EL(ha, "%xh DCBX_STARTED received, mbx1=%xh, mbx2=%xh"
"\n", mb[0], RD16_IO_REG(ha, mailbox_out[1]),
RD16_IO_REG(ha, mailbox_out[2]));
} else {
EL(ha, "%xh LIP received\n", mb[0]);
--- 1012,1022 ----
break;
case MBA_LIP_F8: /* Received a LIP F8. */
case MBA_LIP_RESET: /* LIP reset occurred. */
case MBA_LIP_OCCURRED: /* Loop Initialization Procedure */
! if (CFG_IST(ha, CFG_FCOE_SUPPORT)) {
EL(ha, "%xh DCBX_STARTED received, mbx1=%xh, mbx2=%xh"
"\n", mb[0], RD16_IO_REG(ha, mailbox_out[1]),
RD16_IO_REG(ha, mailbox_out[2]));
} else {
EL(ha, "%xh LIP received\n", mb[0]);
*** 1012,1023 ****
ql_enqueue_aen(ha, mb[0], NULL);
}
break;
case MBA_LOOP_UP:
! if (CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322 |
! CFG_CTRL_24258081))) {
ha->iidma_rate = RD16_IO_REG(ha, mailbox_out[1]);
if (ha->iidma_rate == IIDMA_RATE_1GB) {
ha->state = FC_PORT_STATE_MASK(
ha->state) | FC_STATE_1GBIT_SPEED;
index = 1;
--- 1044,1054 ----
ql_enqueue_aen(ha, mb[0], NULL);
}
break;
case MBA_LOOP_UP:
! if (!CFG_IST(ha, CFG_CTRL_22XX)) {
ha->iidma_rate = RD16_IO_REG(ha, mailbox_out[1]);
if (ha->iidma_rate == IIDMA_RATE_1GB) {
ha->state = FC_PORT_STATE_MASK(
ha->state) | FC_STATE_1GBIT_SPEED;
index = 1;
*** 1035,1044 ****
--- 1066,1083 ----
index = 8;
} else if (ha->iidma_rate == IIDMA_RATE_10GB) {
ha->state = FC_PORT_STATE_MASK(
ha->state) | FC_STATE_10GBIT_SPEED;
index = 10;
+ } else if (ha->iidma_rate == IIDMA_RATE_16GB) {
+ ha->state = FC_PORT_STATE_MASK(
+ ha->state) | FC_STATE_16GBIT_SPEED;
+ index = 16;
+ } else if (ha->iidma_rate == IIDMA_RATE_32GB) {
+ ha->state = FC_PORT_STATE_MASK(
+ ha->state) | FC_STATE_32GBIT_SPEED;
+ index = 32;
} else {
ha->state = FC_PORT_STATE_MASK(
ha->state);
index = 0;
}
*** 1076,1086 ****
if (ha->loop_down_timer == LOOP_DOWN_TIMER_OFF) {
ha->loop_down_timer = LOOP_DOWN_TIMER_START;
}
! if (CFG_IST(ha, CFG_CTRL_258081)) {
ha->sfp_stat = RD16_IO_REG(ha, mailbox_out[2]);
}
/* Update AEN queue. */
if (ha->xioctl->flags & QL_AEN_TRACKING_ENABLE) {
--- 1115,1125 ----
if (ha->loop_down_timer == LOOP_DOWN_TIMER_OFF) {
ha->loop_down_timer = LOOP_DOWN_TIMER_START;
}
! if (CFG_IST(ha, CFG_CTRL_252780818283)) {
ha->sfp_stat = RD16_IO_REG(ha, mailbox_out[2]);
}
/* Update AEN queue. */
if (ha->xioctl->flags & QL_AEN_TRACKING_ENABLE) {
*** 1102,1121 ****
}
if (vha == NULL) {
break;
}
! if (CFG_IST(ha, CFG_CTRL_8081) && mb[1] == 0xffff &&
mb[2] == 7 && (MSB(mb[3]) == 0xe || MSB(mb[3]) == 0x1a ||
MSB(mb[3]) == 0x1c || MSB(mb[3]) == 0x1d ||
MSB(mb[3]) == 0x1e)) {
/*
* received FLOGI reject
* received FLOGO
* FCF configuration changed
* FIP Clear Virtual Link received
! * FKA timeout
*/
if (!(ha->task_daemon_flags & LOOP_DOWN)) {
*set_flags |= LOOP_DOWN;
}
ql_port_state(ha, FC_STATE_OFFLINE, FC_STATE_CHANGE |
--- 1141,1163 ----
}
if (vha == NULL) {
break;
}
! if (mb[1] == 0xffff &&
mb[2] == 7 && (MSB(mb[3]) == 0xe || MSB(mb[3]) == 0x1a ||
MSB(mb[3]) == 0x1c || MSB(mb[3]) == 0x1d ||
MSB(mb[3]) == 0x1e)) {
+ EL(ha, "%xh Port Database Update, Loop down "
+ "received, mbx1=%xh, mbx2=%xh, mbx3=%xh\n",
+ mb[0], mb[1], mb[2], mb[3]);
/*
* received FLOGI reject
* received FLOGO
* FCF configuration changed
* FIP Clear Virtual Link received
! * FCF timeout
*/
if (!(ha->task_daemon_flags & LOOP_DOWN)) {
*set_flags |= LOOP_DOWN;
}
ql_port_state(ha, FC_STATE_OFFLINE, FC_STATE_CHANGE |
*** 1128,1139 ****
* database entry at loop_id 0x7fe which we use to
* acquire the Ports WWPN.
*/
} else if ((mb[1] != 0x7fe) &&
((FC_PORT_STATE_MASK(vha->state) != FC_STATE_OFFLINE ||
! (CFG_IST(ha, CFG_CTRL_24258081) &&
! (mb[1] != 0xffff || mb[2] != 6 || mb[3] != 0))))) {
EL(ha, "%xh Port Database Update, Login/Logout "
"received, mbx1=%xh, mbx2=%xh, mbx3=%xh\n",
mb[0], mb[1], mb[2], mb[3]);
} else {
EL(ha, "%xh Port Database Update received, mbx1=%xh,"
--- 1170,1181 ----
* database entry at loop_id 0x7fe which we use to
* acquire the Ports WWPN.
*/
} else if ((mb[1] != 0x7fe) &&
((FC_PORT_STATE_MASK(vha->state) != FC_STATE_OFFLINE ||
! (CFG_IST(ha, CFG_ISP_FW_TYPE_2) &&
! (mb[2] != 6 || mb[3] != 0))))) {
EL(ha, "%xh Port Database Update, Login/Logout "
"received, mbx1=%xh, mbx2=%xh, mbx3=%xh\n",
mb[0], mb[1], mb[2], mb[3]);
} else {
EL(ha, "%xh Port Database Update received, mbx1=%xh,"
*** 1221,1231 ****
if ((tq = ql_d_id_to_queue(ha, s_id)) == NULL) {
EL(ha, "Unknown IP device=%xh\n", s_id.b24);
break;
}
! cnt = (uint16_t)(CFG_IST(ha, CFG_CTRL_24258081) ?
CHAR_TO_SHORT(ha->ip_init_ctrl_blk.cb24.buf_size[0],
ha->ip_init_ctrl_blk.cb24.buf_size[1]) :
CHAR_TO_SHORT(ha->ip_init_ctrl_blk.cb.buf_size[0],
ha->ip_init_ctrl_blk.cb.buf_size[1]));
--- 1263,1273 ----
if ((tq = ql_d_id_to_queue(ha, s_id)) == NULL) {
EL(ha, "Unknown IP device=%xh\n", s_id.b24);
break;
}
! cnt = (uint16_t)(CFG_IST(ha, CFG_ISP_FW_TYPE_2) ?
CHAR_TO_SHORT(ha->ip_init_ctrl_blk.cb24.buf_size[0],
ha->ip_init_ctrl_blk.cb24.buf_size[1]) :
CHAR_TO_SHORT(ha->ip_init_ctrl_blk.cb.buf_size[0],
ha->ip_init_ctrl_blk.cb.buf_size[1]));
*** 1243,1253 ****
tq->ub_seq_id = ++ha->ub_seq_id;
tq->ub_seq_cnt = 0;
tq->ub_frame_ro = 0;
tq->ub_loop_id = (uint16_t)(mb[0] == MBA_IP_BROADCAST ?
! (CFG_IST(ha, CFG_CTRL_24258081) ? BROADCAST_24XX_HDL :
IP_BROADCAST_LOOP_ID) : tq->loop_id);
ha->rcv_dev_q = tq;
for (cnt = 10; cnt < ha->reg_off->mbox_cnt &&
tq->ub_seq_cnt < tq->ub_total_seg_cnt; cnt++) {
--- 1285,1295 ----
tq->ub_seq_id = ++ha->ub_seq_id;
tq->ub_seq_cnt = 0;
tq->ub_frame_ro = 0;
tq->ub_loop_id = (uint16_t)(mb[0] == MBA_IP_BROADCAST ?
! (CFG_IST(ha, CFG_CTRL_24XX) ? BROADCAST_24XX_HDL :
IP_BROADCAST_LOOP_ID) : tq->loop_id);
ha->rcv_dev_q = tq;
for (cnt = 10; cnt < ha->reg_off->mbox_cnt &&
tq->ub_seq_cnt < tq->ub_total_seg_cnt; cnt++) {
*** 1277,1294 ****
"mbx1=%xh\n", mb[0], RD16_IO_REG(ha, mailbox_out[1]));
break;
case MBA_POINT_TO_POINT:
/* case MBA_DCBX_COMPLETED: */
! if (CFG_IST(ha, CFG_CTRL_8081)) {
EL(ha, "%xh DCBX completed received\n", mb[0]);
} else {
EL(ha, "%xh Point to Point Mode received\n", mb[0]);
}
ADAPTER_STATE_LOCK(ha);
ha->flags |= POINT_TO_POINT;
ADAPTER_STATE_UNLOCK(ha);
break;
case MBA_FCF_CONFIG_ERROR:
EL(ha, "%xh FCF configuration Error received, mbx1=%xh\n",
mb[0], RD16_IO_REG(ha, mailbox_out[1]));
--- 1319,1344 ----
"mbx1=%xh\n", mb[0], RD16_IO_REG(ha, mailbox_out[1]));
break;
case MBA_POINT_TO_POINT:
/* case MBA_DCBX_COMPLETED: */
! if (CFG_IST(ha, CFG_FCOE_SUPPORT)) {
EL(ha, "%xh DCBX completed received\n", mb[0]);
} else {
EL(ha, "%xh Point to Point Mode received\n", mb[0]);
}
ADAPTER_STATE_LOCK(ha);
ha->flags |= POINT_TO_POINT;
ADAPTER_STATE_UNLOCK(ha);
+ if (!(ha->task_daemon_flags & LOOP_DOWN)) {
+ *set_flags |= LOOP_DOWN;
+ }
+ if (ha->loop_down_timer == LOOP_DOWN_TIMER_OFF) {
+ ha->loop_down_timer = LOOP_DOWN_TIMER_START;
+ }
+ ql_port_state(ha, FC_STATE_OFFLINE,
+ FC_STATE_CHANGE | COMMAND_WAIT_NEEDED | LOOP_DOWN);
break;
case MBA_FCF_CONFIG_ERROR:
EL(ha, "%xh FCF configuration Error received, mbx1=%xh\n",
mb[0], RD16_IO_REG(ha, mailbox_out[1]));
*** 1321,1333 ****
break;
case MBA_ZIO_UPDATE:
EL(ha, "%xh ZIO response received\n", mb[0]);
! ha->isp_rsp_index = RD16_IO_REG(ha, resp_in);
! ql_response_pkt(ha, done_q, set_flags, reset_flags, intr_clr);
! intr = B_FALSE;
break;
case MBA_PORT_BYPASS_CHANGED:
EL(ha, "%xh Port Bypass Changed received, mbx1=%xh\n",
mb[0], RD16_IO_REG(ha, mailbox_out[1]));
--- 1371,1382 ----
break;
case MBA_ZIO_UPDATE:
EL(ha, "%xh ZIO response received\n", mb[0]);
! rsp_q->isp_rsp_index = RD16_IO_REG(ha, resp_in);
! ql_response_pkt(ha, rsp_q, done_q, set_flags, reset_flags);
break;
case MBA_PORT_BYPASS_CHANGED:
EL(ha, "%xh Port Bypass Changed received, mbx1=%xh\n",
mb[0], RD16_IO_REG(ha, mailbox_out[1]));
*** 1362,1409 ****
/*
* MBA_IDC_COMPLETE & MBA_IDC_NOTIFICATION: We won't get another
* IDC async event until we ACK the current one.
*/
case MBA_IDC_COMPLETE:
! ha->idc_mb[0] = mb[0];
! ha->idc_mb[1] = RD16_IO_REG(ha, mailbox_out[1]);
! ha->idc_mb[2] = RD16_IO_REG(ha, mailbox_out[2]);
! ha->idc_mb[3] = RD16_IO_REG(ha, mailbox_out[3]);
! ha->idc_mb[4] = RD16_IO_REG(ha, mailbox_out[4]);
! ha->idc_mb[5] = RD16_IO_REG(ha, mailbox_out[5]);
! ha->idc_mb[6] = RD16_IO_REG(ha, mailbox_out[6]);
! ha->idc_mb[7] = RD16_IO_REG(ha, mailbox_out[7]);
! EL(ha, "%xh Inter-driver communication complete received, "
! " mbx1=%xh, mbx2=%xh, mbx3=%xh, mbx4=%xh, mbx5=%xh,"
! " mbx6=%xh, mbx7=%xh\n", mb[0], ha->idc_mb[1],
! ha->idc_mb[2], ha->idc_mb[3], ha->idc_mb[4], ha->idc_mb[5],
! ha->idc_mb[6], ha->idc_mb[7]);
! *set_flags |= IDC_EVENT;
break;
case MBA_IDC_NOTIFICATION:
! ha->idc_mb[0] = mb[0];
! ha->idc_mb[1] = RD16_IO_REG(ha, mailbox_out[1]);
! ha->idc_mb[2] = RD16_IO_REG(ha, mailbox_out[2]);
! ha->idc_mb[3] = RD16_IO_REG(ha, mailbox_out[3]);
! ha->idc_mb[4] = RD16_IO_REG(ha, mailbox_out[4]);
! ha->idc_mb[5] = RD16_IO_REG(ha, mailbox_out[5]);
! ha->idc_mb[6] = RD16_IO_REG(ha, mailbox_out[6]);
! ha->idc_mb[7] = RD16_IO_REG(ha, mailbox_out[7]);
! EL(ha, "%xh Inter-driver communication request notification "
! "received, mbx1=%xh, mbx2=%xh, mbx3=%xh, mbx4=%xh, "
! "mbx5=%xh, mbx6=%xh, mbx7=%xh\n", mb[0], ha->idc_mb[1],
! ha->idc_mb[2], ha->idc_mb[3], ha->idc_mb[4], ha->idc_mb[5],
! ha->idc_mb[6], ha->idc_mb[7]);
! *set_flags |= IDC_EVENT;
break;
case MBA_IDC_TIME_EXTENDED:
! EL(ha, "%xh Inter-driver communication time extended received,"
! " mbx1=%xh, mbx2=%xh\n", mb[0],
! RD16_IO_REG(ha, mailbox_out[1]),
! RD16_IO_REG(ha, mailbox_out[2]));
break;
default:
EL(ha, "%xh UNKNOWN event received, mbx1=%xh, mbx2=%xh, "
"mbx3=%xh\n", mb[0], RD16_IO_REG(ha, mailbox_out[1]),
--- 1411,1480 ----
/*
* MBA_IDC_COMPLETE & MBA_IDC_NOTIFICATION: We won't get another
* IDC async event until we ACK the current one.
*/
case MBA_IDC_COMPLETE:
! mb[2] = RD16_IO_REG(ha, mailbox_out[2]);
! EL(ha, "%xh MBA_IDC_COMPLETE received, mbx2=%xh\n", mb[0],
! mb[2]);
! switch (mb[2]) {
! case IDC_OPC_FLASH_ACC:
! case IDC_OPC_RESTART_MPI:
! case IDC_OPC_PORT_RESET_MBC:
! case IDC_OPC_SET_PORT_CONFIG_MBC:
! ADAPTER_STATE_LOCK(ha);
! ha->flags |= IDC_RESTART_NEEDED;
! ADAPTER_STATE_UNLOCK(ha);
break;
+ default:
+ EL(ha, "unknown IDC completion opcode=%xh\n", mb[2]);
+ break;
+ }
+ break;
case MBA_IDC_NOTIFICATION:
! for (cnt = 1; cnt < 8; cnt++) {
! ha->idc_mb[cnt] = RD16_IO_REG(ha, mailbox_out[cnt]);
! }
! EL(ha, "%xh MBA_IDC_REQ_NOTIFICATION received, mbx1=%xh, "
! "mbx2=%xh, mbx3=%xh, mbx4=%xh, mbx5=%xh, mbx6=%xh, "
! "mbx7=%xh\n", mb[0], ha->idc_mb[1], ha->idc_mb[2],
! ha->idc_mb[3], ha->idc_mb[4], ha->idc_mb[5], ha->idc_mb[6],
! ha->idc_mb[7]);
!
! ADAPTER_STATE_LOCK(ha);
! switch (ha->idc_mb[2]) {
! case IDC_OPC_DRV_START:
! ha->flags |= IDC_RESTART_NEEDED;
break;
+ case IDC_OPC_FLASH_ACC:
+ case IDC_OPC_RESTART_MPI:
+ case IDC_OPC_PORT_RESET_MBC:
+ case IDC_OPC_SET_PORT_CONFIG_MBC:
+ ha->flags |= IDC_STALL_NEEDED;
+ break;
+ default:
+ EL(ha, "unknown IDC request opcode=%xh\n",
+ ha->idc_mb[2]);
+ break;
+ }
+ /*
+ * If there is a timeout value associated with this IDC
+ * notification then there is an implied requirement
+ * that we return an ACK.
+ */
+ if (ha->idc_mb[1] & IDC_TIMEOUT_MASK) {
+ ha->flags |= IDC_ACK_NEEDED;
+ }
+ ADAPTER_STATE_UNLOCK(ha);
+ ql_awaken_task_daemon(ha, NULL, 0, 0);
+ break;
+
case MBA_IDC_TIME_EXTENDED:
! EL(ha, "%xh MBA_IDC_TIME_EXTENDED received, mbx2=%xh\n",
! mb[0], RD16_IO_REG(ha, mailbox_out[2]));
break;
default:
EL(ha, "%xh UNKNOWN event received, mbx1=%xh, mbx2=%xh, "
"mbx3=%xh\n", mb[0], RD16_IO_REG(ha, mailbox_out[1]),
*** 1410,1451 ****
RD16_IO_REG(ha, mailbox_out[2]),
RD16_IO_REG(ha, mailbox_out[3]));
break;
}
! /* Clear RISC interrupt */
! if (intr && intr_clr) {
! if (CFG_IST(ha, CFG_CTRL_8021)) {
! ql_8021_clr_fw_intr(ha);
! } else if (CFG_IST(ha, CFG_CTRL_242581)) {
! WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
! } else {
! WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT);
! }
! }
!
! QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
}
/*
* ql_fast_fcp_post
* Fast path for good SCSI I/O completion.
*
* Input:
* sp: SRB pointer.
*
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
static void
! ql_fast_fcp_post(ql_srb_t *sp)
{
ql_adapter_state_t *ha = sp->ha;
ql_lun_t *lq = sp->lun_queue;
ql_tgt_t *tq = lq->target_queue;
! QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
/* Acquire device queue lock. */
DEVICE_QUEUE_LOCK(tq);
/* Decrement outstanding commands on device. */
--- 1481,1512 ----
RD16_IO_REG(ha, mailbox_out[2]),
RD16_IO_REG(ha, mailbox_out[3]));
break;
}
! QL_PRINT_3(ha, "done\n");
}
/*
* ql_fast_fcp_post
* Fast path for good SCSI I/O completion.
*
* Input:
* sp: SRB pointer.
+ * rsp_q: response queue structure pointer.
*
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
static void
! ql_fast_fcp_post(ql_srb_t *sp, ql_response_q_t *rsp_q)
{
ql_adapter_state_t *ha = sp->ha;
ql_lun_t *lq = sp->lun_queue;
ql_tgt_t *tq = lq->target_queue;
! QL_PRINT_3(ha, "started\n");
/* Acquire device queue lock. */
DEVICE_QUEUE_LOCK(tq);
/* Decrement outstanding commands on device. */
*** 1498,1674 ****
/* Map ISP completion codes. */
sp->pkt->pkt_expln = FC_EXPLN_NONE;
sp->pkt->pkt_action = FC_ACTION_RETRYABLE;
sp->pkt->pkt_state = FC_PKT_SUCCESS;
/* Now call the pkt completion callback */
if (sp->flags & SRB_POLL) {
sp->flags &= ~SRB_POLL;
! } else if (sp->pkt->pkt_comp) {
! INTR_UNLOCK(ha);
(*sp->pkt->pkt_comp)(sp->pkt);
! INTR_LOCK(ha);
}
! QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
}
/*
* ql_response_pkt
* Processes response entry.
*
* Input:
* ha: adapter state pointer.
* done_q: head pointer to done queue.
* set_flags: task daemon flags to set.
* reset_flags: task daemon flags to reset.
- * intr_clr: early interrupt clear
*
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
static void
! ql_response_pkt(ql_adapter_state_t *ha, ql_head_t *done_q, uint32_t *set_flags,
! uint32_t *reset_flags, int intr_clr)
{
response_t *pkt;
uint32_t dma_sync_size_1 = 0;
uint32_t dma_sync_size_2 = 0;
int status = 0;
! QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
! /* Clear RISC interrupt */
! if (intr_clr) {
! if (CFG_IST(ha, CFG_CTRL_8021)) {
! ql_8021_clr_fw_intr(ha);
! } else if (CFG_IST(ha, CFG_CTRL_242581)) {
! WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
! } else {
! WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT);
! }
! }
!
! if (ha->isp_rsp_index >= RESPONSE_ENTRY_CNT) {
EL(ha, "index error = %xh, isp_abort_needed",
! ha->isp_rsp_index);
*set_flags |= ISP_ABORT_NEEDED;
return;
}
if ((ha->flags & ONLINE) == 0) {
! QL_PRINT_3(CE_CONT, "(%d): not onlne, done\n", ha->instance);
return;
}
/* Calculate size of response queue entries to sync. */
! if (ha->isp_rsp_index > ha->rsp_ring_index) {
dma_sync_size_1 = (uint32_t)
! ((uint32_t)(ha->isp_rsp_index - ha->rsp_ring_index) *
RESPONSE_ENTRY_SIZE);
! } else if (ha->isp_rsp_index == 0) {
dma_sync_size_1 = (uint32_t)
! ((uint32_t)(RESPONSE_ENTRY_CNT - ha->rsp_ring_index) *
RESPONSE_ENTRY_SIZE);
} else {
/* Responses wrap around the Q */
dma_sync_size_1 = (uint32_t)
! ((uint32_t)(RESPONSE_ENTRY_CNT - ha->rsp_ring_index) *
RESPONSE_ENTRY_SIZE);
dma_sync_size_2 = (uint32_t)
! (ha->isp_rsp_index * RESPONSE_ENTRY_SIZE);
}
/* Sync DMA buffer. */
! (void) ddi_dma_sync(ha->hba_buf.dma_handle,
! (off_t)(ha->rsp_ring_index * RESPONSE_ENTRY_SIZE +
! RESPONSE_Q_BUFFER_OFFSET), dma_sync_size_1,
! DDI_DMA_SYNC_FORKERNEL);
if (dma_sync_size_2) {
! (void) ddi_dma_sync(ha->hba_buf.dma_handle,
! RESPONSE_Q_BUFFER_OFFSET, dma_sync_size_2,
! DDI_DMA_SYNC_FORKERNEL);
}
! while (ha->rsp_ring_index != ha->isp_rsp_index) {
! pkt = ha->response_ring_ptr;
! QL_PRINT_5(CE_CONT, "(%d): ha->rsp_rg_idx=%xh, mbx[5]=%xh\n",
! ha->instance, ha->rsp_ring_index, ha->isp_rsp_index);
! QL_DUMP_5((uint8_t *)ha->response_ring_ptr, 8,
RESPONSE_ENTRY_SIZE);
/* Adjust ring index. */
! ha->rsp_ring_index++;
! if (ha->rsp_ring_index == RESPONSE_ENTRY_CNT) {
! ha->rsp_ring_index = 0;
! ha->response_ring_ptr = ha->response_ring_bp;
} else {
! ha->response_ring_ptr++;
}
/* Process packet. */
! if (ha->status_srb != NULL && pkt->entry_type !=
! STATUS_CONT_TYPE) {
! ql_add_link_b(done_q, &ha->status_srb->cmd);
! ha->status_srb = NULL;
}
! pkt->entry_status = (uint8_t)(CFG_IST(ha, CFG_CTRL_24258081) ?
pkt->entry_status & 0x3c : pkt->entry_status & 0x7e);
! if (pkt->entry_status != 0) {
! ql_error_entry(ha, pkt, done_q, set_flags,
! reset_flags);
} else {
switch (pkt->entry_type) {
case STATUS_TYPE:
! status |= CFG_IST(ha, CFG_CTRL_24258081) ?
! ql_24xx_status_entry(ha,
! (sts_24xx_entry_t *)pkt, done_q, set_flags,
! reset_flags) :
! ql_status_entry(ha, (sts_entry_t *)pkt,
done_q, set_flags, reset_flags);
break;
case STATUS_CONT_TYPE:
! ql_status_cont_entry(ha,
! (sts_cont_entry_t *)pkt, done_q, set_flags,
! reset_flags);
break;
case IP_TYPE:
case IP_A64_TYPE:
case IP_CMD_TYPE:
! ql_ip_entry(ha, (ip_entry_t *)pkt, done_q,
set_flags, reset_flags);
break;
case IP_RECEIVE_TYPE:
! ql_ip_rcv_entry(ha,
! (ip_rcv_entry_t *)pkt, done_q, set_flags,
! reset_flags);
break;
case IP_RECEIVE_CONT_TYPE:
! ql_ip_rcv_cont_entry(ha,
(ip_rcv_cont_entry_t *)pkt, done_q,
set_flags, reset_flags);
break;
case IP_24XX_RECEIVE_TYPE:
! ql_ip_24xx_rcv_entry(ha,
(ip_rcv_24xx_entry_t *)pkt, done_q,
set_flags, reset_flags);
break;
case MS_TYPE:
! ql_ms_entry(ha, (ms_entry_t *)pkt, done_q,
set_flags, reset_flags);
break;
case REPORT_ID_TYPE:
! ql_report_id_entry(ha, (report_id_1_t *)pkt,
! done_q, set_flags, reset_flags);
break;
case ELS_PASSTHRU_TYPE:
! ql_els_passthru_entry(ha,
! (els_passthru_entry_rsp_t *)pkt,
! done_q, set_flags, reset_flags);
break;
case IP_BUF_POOL_TYPE:
case MARKER_TYPE:
case VP_MODIFY_TYPE:
case VP_CONTROL_TYPE:
--- 1559,1746 ----
/* Map ISP completion codes. */
sp->pkt->pkt_expln = FC_EXPLN_NONE;
sp->pkt->pkt_action = FC_ACTION_RETRYABLE;
sp->pkt->pkt_state = FC_PKT_SUCCESS;
+ (void) qlc_fm_check_pkt_dma_handle(ha, sp);
+
/* Now call the pkt completion callback */
if (sp->flags & SRB_POLL) {
sp->flags &= ~SRB_POLL;
! } else if (ha->completion_thds == 1 && sp->pkt->pkt_comp &&
! !(ha->flags & POLL_INTR)) {
! INDX_INTR_UNLOCK(ha, rsp_q->rsp_q_number);
(*sp->pkt->pkt_comp)(sp->pkt);
! INDX_INTR_LOCK(ha, rsp_q->rsp_q_number);
! } else {
! ql_io_comp(sp);
}
! if (qlc_fm_check_acc_handle(ha, ha->dev_handle)
! != DDI_FM_OK) {
! qlc_fm_report_err_impact(ha,
! QL_FM_EREPORT_ACC_HANDLE_CHECK);
! }
!
! QL_PRINT_3(ha, "done\n");
}
/*
* ql_response_pkt
* Processes response entry.
*
* Input:
* ha: adapter state pointer.
+ * rsp_q: response queue structure pointer.
* done_q: head pointer to done queue.
* set_flags: task daemon flags to set.
* reset_flags: task daemon flags to reset.
*
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
static void
! ql_response_pkt(ql_adapter_state_t *ha, ql_response_q_t *rsp_q,
! ql_head_t *done_q, uint64_t *set_flags, uint64_t *reset_flags)
{
response_t *pkt;
uint32_t dma_sync_size_1 = 0;
uint32_t dma_sync_size_2 = 0;
int status = 0;
! QL_PRINT_3(ha, "started\n");
! if (rsp_q->isp_rsp_index >= rsp_q->rsp_entry_cnt) {
EL(ha, "index error = %xh, isp_abort_needed",
! rsp_q->isp_rsp_index);
*set_flags |= ISP_ABORT_NEEDED;
return;
}
if ((ha->flags & ONLINE) == 0) {
! QL_PRINT_10(ha, "not onlne, done\n");
return;
}
/* Calculate size of response queue entries to sync. */
! if (rsp_q->isp_rsp_index > rsp_q->rsp_ring_index) {
dma_sync_size_1 = (uint32_t)
! ((uint32_t)(rsp_q->isp_rsp_index - rsp_q->rsp_ring_index) *
RESPONSE_ENTRY_SIZE);
! } else if (rsp_q->isp_rsp_index == 0) {
dma_sync_size_1 = (uint32_t)
! ((uint32_t)(rsp_q->rsp_entry_cnt - rsp_q->rsp_ring_index) *
RESPONSE_ENTRY_SIZE);
} else {
/* Responses wrap around the Q */
dma_sync_size_1 = (uint32_t)
! ((uint32_t)(rsp_q->rsp_entry_cnt - rsp_q->rsp_ring_index) *
RESPONSE_ENTRY_SIZE);
dma_sync_size_2 = (uint32_t)
! (rsp_q->isp_rsp_index * RESPONSE_ENTRY_SIZE);
}
/* Sync DMA buffer. */
! (void) ddi_dma_sync(rsp_q->rsp_ring.dma_handle,
! (off_t)(rsp_q->rsp_ring_index * RESPONSE_ENTRY_SIZE),
! dma_sync_size_1, DDI_DMA_SYNC_FORCPU);
if (dma_sync_size_2) {
! (void) ddi_dma_sync(rsp_q->rsp_ring.dma_handle, 0,
! dma_sync_size_2, DDI_DMA_SYNC_FORCPU);
}
! if (qlc_fm_check_acc_handle(ha, ha->dev_handle)
! != DDI_FM_OK) {
! qlc_fm_report_err_impact(ha,
! QL_FM_EREPORT_ACC_HANDLE_CHECK);
! }
! while (rsp_q->rsp_ring_index != rsp_q->isp_rsp_index) {
! pkt = rsp_q->rsp_ring_ptr;
!
! QL_PRINT_5(ha, "ha->rsp_rg_idx=%xh, mbx[5]=%xh\n",
! rsp_q->rsp_ring_index, rsp_q->isp_rsp_index);
! QL_DUMP_5((uint8_t *)rsp_q->rsp_ring_ptr, 8,
RESPONSE_ENTRY_SIZE);
/* Adjust ring index. */
! rsp_q->rsp_ring_index++;
! if (rsp_q->rsp_ring_index == rsp_q->rsp_entry_cnt) {
! rsp_q->rsp_ring_index = 0;
! rsp_q->rsp_ring_ptr = rsp_q->rsp_ring.bp;
} else {
! rsp_q->rsp_ring_ptr++;
}
/* Process packet. */
! if (rsp_q->status_srb != NULL &&
! pkt->entry_type != STATUS_CONT_TYPE) {
! ql_add_link_b(done_q, &rsp_q->status_srb->cmd);
! rsp_q->status_srb = NULL;
}
! pkt->entry_status = (uint8_t)
! (CFG_IST(ha, CFG_ISP_FW_TYPE_2) ?
pkt->entry_status & 0x3c : pkt->entry_status & 0x7e);
! if (pkt->entry_status != 0 ||
! pkt->entry_type == ABORTED_ENTRY_TYPE) {
! ql_error_entry(ha, rsp_q,
! pkt, done_q,
! set_flags, reset_flags);
} else {
switch (pkt->entry_type) {
case STATUS_TYPE:
! status |= CFG_IST(ha, CFG_ISP_FW_TYPE_2) ?
! ql_24xx_status_entry(ha, rsp_q,
! (sts_24xx_entry_t *)pkt, done_q,
! set_flags, reset_flags) :
! ql_status_entry(ha, rsp_q,
! (sts_entry_t *)pkt,
done_q, set_flags, reset_flags);
break;
case STATUS_CONT_TYPE:
! ql_status_cont_entry(ha, rsp_q,
! (sts_cont_entry_t *)pkt, done_q,
! set_flags, reset_flags);
break;
case IP_TYPE:
case IP_A64_TYPE:
case IP_CMD_TYPE:
! ql_ip_entry(ha, rsp_q,
! (ip_entry_t *)pkt, done_q,
set_flags, reset_flags);
break;
case IP_RECEIVE_TYPE:
! ql_ip_rcv_entry(ha, rsp_q,
! (ip_rcv_entry_t *)pkt, done_q,
! set_flags, reset_flags);
break;
case IP_RECEIVE_CONT_TYPE:
! ql_ip_rcv_cont_entry(ha, rsp_q,
(ip_rcv_cont_entry_t *)pkt, done_q,
set_flags, reset_flags);
break;
case IP_24XX_RECEIVE_TYPE:
! ql_ip_24xx_rcv_entry(ha, rsp_q,
(ip_rcv_24xx_entry_t *)pkt, done_q,
set_flags, reset_flags);
break;
case MS_TYPE:
! ql_ms_entry(ha, rsp_q,
! (ms_entry_t *)pkt, done_q,
set_flags, reset_flags);
break;
case REPORT_ID_TYPE:
! ql_report_id_entry(ha, rsp_q,
! (report_id_acq_t *)pkt, done_q,
! set_flags, reset_flags);
break;
case ELS_PASSTHRU_TYPE:
! ql_els_passthru_entry(ha, rsp_q,
! (els_passthru_entry_rsp_t *)pkt, done_q,
! set_flags, reset_flags);
break;
case IP_BUF_POOL_TYPE:
case MARKER_TYPE:
case VP_MODIFY_TYPE:
case VP_CONTROL_TYPE:
*** 1680,1727 ****
}
}
}
/* Inform RISC of processed responses. */
- WRT16_IO_REG(ha, resp_out, ha->rsp_ring_index);
/* RESET packet received delay for possible async event. */
if (status & BIT_0) {
drv_usecwait(500000);
}
! QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
}
/*
* ql_error_entry
* Processes error entry.
*
* Input:
! * ha = adapter state pointer.
! * pkt = entry pointer.
! * done_q = head pointer to done queue.
! * set_flags = task daemon flags to set.
! * reset_flags = task daemon flags to reset.
*
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
/* ARGSUSED */
static void
! ql_error_entry(ql_adapter_state_t *ha, response_t *pkt, ql_head_t *done_q,
! uint32_t *set_flags, uint32_t *reset_flags)
{
! ql_srb_t *sp;
uint32_t index, resp_identifier;
! if (pkt->entry_type == INVALID_ENTRY_TYPE) {
! EL(ha, "Aborted command\n");
return;
}
! QL_PRINT_2(CE_CONT, "(%d): started, packet:\n", ha->instance);
QL_DUMP_2((uint8_t *)pkt, 8, RESPONSE_ENTRY_SIZE);
if (pkt->entry_status & BIT_6) {
EL(ha, "Request Queue DMA error\n");
} else if (pkt->entry_status & BIT_5) {
--- 1752,1828 ----
}
}
}
/* Inform RISC of processed responses. */
+ if (ha->flags & MULTI_QUEUE) {
+ WR32_MBAR_REG(ha, rsp_q->mbar_rsp_out, rsp_q->rsp_ring_index);
+ } else {
+ WRT16_IO_REG(ha, resp_out, rsp_q->rsp_ring_index);
+ }
+
+ if (qlc_fm_check_acc_handle(ha, ha->dev_handle)
+ != DDI_FM_OK) {
+ qlc_fm_report_err_impact(ha,
+ QL_FM_EREPORT_ACC_HANDLE_CHECK);
+ }
+
/* RESET packet received delay for possible async event. */
if (status & BIT_0) {
drv_usecwait(500000);
}
! QL_PRINT_3(ha, "done\n");
}
/*
* ql_error_entry
* Processes error entry.
*
* Input:
! * ha: adapter state pointer.
! * rsp_q: response queue structure pointer.
! * pkt: entry pointer.
! * done_q: head pointer to done queue.
! * set_flags: task daemon flags to set.
! * reset_flags: task daemon flags to reset.
*
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
/* ARGSUSED */
static void
! ql_error_entry(ql_adapter_state_t *ha, ql_response_q_t *rsp_q, response_t *pkt,
! ql_head_t *done_q, uint64_t *set_flags, uint64_t *reset_flags)
{
! ql_srb_t *sp = NULL;
uint32_t index, resp_identifier;
! if (pkt->entry_type == ABORTED_ENTRY_TYPE) {
! resp_identifier = ddi_get32(rsp_q->rsp_ring.acc_handle,
! &pkt->handle);
! index = resp_identifier & OSC_INDEX_MASK;
! if (index < ha->osc_max_cnt) {
! if (ha->outstanding_cmds[index] ==
! QL_ABORTED_SRB(ha)) {
! EL(ha, "Aborted command sp=QL_ABORTED_SRB, "
! "handle=%xh\n", resp_identifier);
! ha->outstanding_cmds[index] = NULL;
! } else {
! EL(ha, "Aborted command sp=%ph, handle=%xh\n",
! (void *) ha->outstanding_cmds[index],
! resp_identifier);
! }
! } else {
! EL(ha, "Aborted command handle=%xh, out of range "
! "index=%xh\n", resp_identifier, index);
! }
return;
}
! QL_PRINT_2(ha, "started, packet:\n");
QL_DUMP_2((uint8_t *)pkt, 8, RESPONSE_ENTRY_SIZE);
if (pkt->entry_status & BIT_6) {
EL(ha, "Request Queue DMA error\n");
} else if (pkt->entry_status & BIT_5) {
*** 1737,1753 ****
} else {
EL(ha, "UNKNOWN flag = %xh error\n", pkt->entry_status);
}
/* Validate the response entry handle. */
! resp_identifier = ddi_get32(ha->hba_buf.acc_handle, &pkt->handle);
index = resp_identifier & OSC_INDEX_MASK;
! if (index < MAX_OUTSTANDING_COMMANDS) {
/* the index seems reasonable */
! sp = ha->outstanding_cmds[index];
if (sp != NULL) {
! if (sp->handle == resp_identifier) {
/* Neo, you're the one... */
ha->outstanding_cmds[index] = NULL;
sp->handle = 0;
sp->flags &= ~SRB_IN_TOKEN_ARRAY;
} else {
--- 1838,1864 ----
} else {
EL(ha, "UNKNOWN flag = %xh error\n", pkt->entry_status);
}
/* Validate the response entry handle. */
! resp_identifier = ddi_get32(rsp_q->rsp_ring.acc_handle, &pkt->handle);
index = resp_identifier & OSC_INDEX_MASK;
! if (index < ha->osc_max_cnt) {
/* the index seems reasonable */
! if ((sp = ha->outstanding_cmds[index]) == NULL) {
! sp = ql_verify_preprocessed_cmd(ha, rsp_q,
! (uint32_t *)&pkt->handle,
! (uint32_t *)&resp_identifier, set_flags,
! reset_flags);
! }
if (sp != NULL) {
! if (sp == QL_ABORTED_SRB(ha)) {
! EL(ha, "QL_ABORTED_SRB handle=%xh\n",
! resp_identifier);
! sp = NULL;
! ha->outstanding_cmds[index] = NULL;
! } else if (sp->handle == resp_identifier) {
/* Neo, you're the one... */
ha->outstanding_cmds[index] = NULL;
sp->handle = 0;
sp->flags &= ~SRB_IN_TOKEN_ARRAY;
} else {
*** 1754,1766 ****
EL(ha, "IOCB handle mismatch pkt=%xh, sp=%xh\n",
resp_identifier, sp->handle);
sp = NULL;
ql_signal_abort(ha, set_flags);
}
- } else {
- sp = ql_verify_preprocessed_cmd(ha,
- (uint32_t *)&pkt->handle, set_flags, reset_flags);
}
} else {
EL(ha, "osc index out of range, index=%xh, handle=%xh\n",
index, resp_identifier);
ql_signal_abort(ha, set_flags);
--- 1865,1874 ----
*** 1783,1801 ****
/* Place command on done queue. */
ql_add_link_b(done_q, &sp->cmd);
}
! QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
}
/*
* ql_status_entry
* Processes received ISP2200-2300 status entry.
*
* Input:
* ha: adapter state pointer.
* pkt: entry pointer.
* done_q: done queue pointer.
* set_flags: task daemon flags to set.
* reset_flags: task daemon flags to reset.
*
--- 1891,1910 ----
/* Place command on done queue. */
ql_add_link_b(done_q, &sp->cmd);
}
! QL_PRINT_3(ha, "done\n");
}
/*
* ql_status_entry
* Processes received ISP2200-2300 status entry.
*
* Input:
* ha: adapter state pointer.
+ * rsp_q: response queue structure pointer.
* pkt: entry pointer.
* done_q: done queue pointer.
* set_flags: task daemon flags to set.
* reset_flags: task daemon flags to reset.
*
*** 1805,1832 ****
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
/* ARGSUSED */
static int
! ql_status_entry(ql_adapter_state_t *ha, sts_entry_t *pkt,
! ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags)
{
! ql_srb_t *sp;
uint32_t index, resp_identifier;
uint16_t comp_status;
int rval = 0;
! QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
/* Validate the response entry handle. */
! resp_identifier = ddi_get32(ha->hba_buf.acc_handle, &pkt->handle);
index = resp_identifier & OSC_INDEX_MASK;
! if (index < MAX_OUTSTANDING_COMMANDS) {
/* the index seems reasonable */
! sp = ha->outstanding_cmds[index];
if (sp != NULL) {
! if (sp->handle == resp_identifier) {
/* Neo, you're the one... */
ha->outstanding_cmds[index] = NULL;
sp->handle = 0;
sp->flags &= ~SRB_IN_TOKEN_ARRAY;
} else {
--- 1914,1952 ----
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
/* ARGSUSED */
static int
! ql_status_entry(ql_adapter_state_t *ha, ql_response_q_t *rsp_q,
! sts_entry_t *pkt, ql_head_t *done_q, uint64_t *set_flags,
! uint64_t *reset_flags)
{
! ql_srb_t *sp = NULL;
uint32_t index, resp_identifier;
uint16_t comp_status;
int rval = 0;
! QL_PRINT_3(ha, "started\n");
/* Validate the response entry handle. */
! resp_identifier = ddi_get32(rsp_q->rsp_ring.acc_handle, &pkt->handle);
index = resp_identifier & OSC_INDEX_MASK;
! if (index < ha->osc_max_cnt) {
/* the index seems reasonable */
! if ((sp = ha->outstanding_cmds[index]) == NULL) {
! sp = ql_verify_preprocessed_cmd(ha, rsp_q,
! (uint32_t *)&pkt->handle,
! (uint32_t *)&resp_identifier, set_flags,
! reset_flags);
! }
if (sp != NULL) {
! if (sp == QL_ABORTED_SRB(ha)) {
! EL(ha, "QL_ABORTED_SRB handle=%xh\n",
! resp_identifier);
! sp = NULL;
! ha->outstanding_cmds[index] = NULL;
! } else if (sp->handle == resp_identifier) {
/* Neo, you're the one... */
ha->outstanding_cmds[index] = NULL;
sp->handle = 0;
sp->flags &= ~SRB_IN_TOKEN_ARRAY;
} else {
*** 1833,1854 ****
EL(ha, "IOCB handle mismatch pkt=%xh, sp=%xh\n",
resp_identifier, sp->handle);
sp = NULL;
ql_signal_abort(ha, set_flags);
}
- } else {
- sp = ql_verify_preprocessed_cmd(ha,
- (uint32_t *)&pkt->handle, set_flags, reset_flags);
}
} else {
EL(ha, "osc index out of range, index=%xh, handle=%xh\n",
index, resp_identifier);
ql_signal_abort(ha, set_flags);
}
if (sp != NULL) {
! comp_status = (uint16_t)ddi_get16(ha->hba_buf.acc_handle,
&pkt->comp_status);
/*
* We dont care about SCSI QFULLs.
*/
--- 1953,1971 ----
EL(ha, "IOCB handle mismatch pkt=%xh, sp=%xh\n",
resp_identifier, sp->handle);
sp = NULL;
ql_signal_abort(ha, set_flags);
}
}
} else {
EL(ha, "osc index out of range, index=%xh, handle=%xh\n",
index, resp_identifier);
ql_signal_abort(ha, set_flags);
}
if (sp != NULL) {
! comp_status = (uint16_t)ddi_get16(rsp_q->rsp_ring.acc_handle,
&pkt->comp_status);
/*
* We dont care about SCSI QFULLs.
*/
*** 1861,1883 ****
/*
* 2300 firmware marks completion status as data underrun
* for scsi qfulls. Make it transport complete.
*/
! if ((CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322))) &&
! (comp_status == CS_DATA_UNDERRUN) &&
! (pkt->scsi_status_l != 0)) {
comp_status = CS_COMPLETE;
}
/*
* Workaround T3 issue where we do not get any data xferred
* but get back a good status.
*/
if ((pkt->state_flags_h & SF_XFERRED_DATA) == 0 &&
comp_status == CS_COMPLETE &&
! pkt->scsi_status_l == 0 &&
(pkt->scsi_status_h & FCP_RSP_MASK) == 0 &&
pkt->residual_length == 0 &&
sp->fcp &&
sp->fcp->fcp_data_len != 0 &&
(pkt->state_flags_l & (SF_DATA_OUT | SF_DATA_IN)) ==
--- 1978,2000 ----
/*
* 2300 firmware marks completion status as data underrun
* for scsi qfulls. Make it transport complete.
*/
! if (CFG_IST(ha, CFG_CTRL_2363) &&
! comp_status == CS_DATA_UNDERRUN &&
! pkt->scsi_status_l != STATUS_GOOD) {
comp_status = CS_COMPLETE;
}
/*
* Workaround T3 issue where we do not get any data xferred
* but get back a good status.
*/
if ((pkt->state_flags_h & SF_XFERRED_DATA) == 0 &&
comp_status == CS_COMPLETE &&
! pkt->scsi_status_l == STATUS_GOOD &&
(pkt->scsi_status_h & FCP_RSP_MASK) == 0 &&
pkt->residual_length == 0 &&
sp->fcp &&
sp->fcp->fcp_data_len != 0 &&
(pkt->state_flags_l & (SF_DATA_OUT | SF_DATA_IN)) ==
*** 1890,1924 ****
* Ideally it should never be true. But there
* is a bug in FW which upon receiving invalid
* parameters in MS IOCB returns it as
* status entry and not as ms entry type.
*/
! ql_ms_entry(ha, (ms_entry_t *)pkt, done_q,
set_flags, reset_flags);
! QL_PRINT_3(CE_CONT, "(%d): ql_ms_entry done\n",
! ha->instance);
return (0);
}
/*
* Fast path to good SCSI I/O completion
*/
! if ((comp_status == CS_COMPLETE) &
! (!pkt->scsi_status_l) &
! (!(pkt->scsi_status_h & FCP_RSP_MASK))) {
/* Set completed status. */
sp->flags |= SRB_ISP_COMPLETED;
sp->pkt->pkt_reason = comp_status;
! ql_fast_fcp_post(sp);
! QL_PRINT_3(CE_CONT, "(%d): ql_fast_fcp_post done\n",
! ha->instance);
return (0);
}
! rval = ql_status_error(ha, sp, pkt, done_q, set_flags,
reset_flags);
}
! QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
return (rval);
}
/*
--- 2007,2039 ----
* Ideally it should never be true. But there
* is a bug in FW which upon receiving invalid
* parameters in MS IOCB returns it as
* status entry and not as ms entry type.
*/
! ql_ms_entry(ha, rsp_q, (ms_entry_t *)pkt, done_q,
set_flags, reset_flags);
! QL_PRINT_3(ha, "ql_ms_entry done\n");
return (0);
}
/*
* Fast path to good SCSI I/O completion
*/
! if (comp_status == CS_COMPLETE &&
! pkt->scsi_status_l == STATUS_GOOD &&
! (pkt->scsi_status_h & FCP_RSP_MASK) == 0) {
/* Set completed status. */
sp->flags |= SRB_ISP_COMPLETED;
sp->pkt->pkt_reason = comp_status;
! ql_fast_fcp_post(sp, rsp_q);
! QL_PRINT_3(ha, "ql_fast_fcp_post done\n");
return (0);
}
! rval = ql_status_error(ha, rsp_q, sp, pkt, done_q, set_flags,
reset_flags);
}
! QL_PRINT_3(ha, "done\n");
return (rval);
}
/*
*** 1925,1934 ****
--- 2040,2050 ----
* ql_24xx_status_entry
* Processes received ISP24xx status entry.
*
* Input:
* ha: adapter state pointer.
+ * rsp_q: response queue structure pointer.
* pkt: entry pointer.
* done_q: done queue pointer.
* set_flags: task daemon flags to set.
* reset_flags: task daemon flags to reset.
*
*** 1938,1965 ****
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
/* ARGSUSED */
static int
! ql_24xx_status_entry(ql_adapter_state_t *ha, sts_24xx_entry_t *pkt,
! ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags)
{
ql_srb_t *sp = NULL;
uint16_t comp_status;
uint32_t index, resp_identifier;
int rval = 0;
! QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
/* Validate the response entry handle. */
! resp_identifier = ddi_get32(ha->hba_buf.acc_handle, &pkt->handle);
index = resp_identifier & OSC_INDEX_MASK;
! if (index < MAX_OUTSTANDING_COMMANDS) {
/* the index seems reasonable */
! sp = ha->outstanding_cmds[index];
if (sp != NULL) {
! if (sp->handle == resp_identifier) {
/* Neo, you're the one... */
ha->outstanding_cmds[index] = NULL;
sp->handle = 0;
sp->flags &= ~SRB_IN_TOKEN_ARRAY;
} else {
--- 2054,2092 ----
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
/* ARGSUSED */
static int
! ql_24xx_status_entry(ql_adapter_state_t *ha, ql_response_q_t *rsp_q,
! sts_24xx_entry_t *pkt, ql_head_t *done_q, uint64_t *set_flags,
! uint64_t *reset_flags)
{
ql_srb_t *sp = NULL;
uint16_t comp_status;
uint32_t index, resp_identifier;
int rval = 0;
! QL_PRINT_3(ha, "started\n");
/* Validate the response entry handle. */
! resp_identifier = ddi_get32(rsp_q->rsp_ring.acc_handle, &pkt->handle);
index = resp_identifier & OSC_INDEX_MASK;
! if (index < ha->osc_max_cnt) {
/* the index seems reasonable */
! if ((sp = ha->outstanding_cmds[index]) == NULL) {
! sp = ql_verify_preprocessed_cmd(ha, rsp_q,
! (uint32_t *)&pkt->handle,
! (uint32_t *)&resp_identifier, set_flags,
! reset_flags);
! }
if (sp != NULL) {
! if (sp == QL_ABORTED_SRB(ha)) {
! EL(ha, "QL_ABORTED_SRB handle=%xh\n",
! resp_identifier);
! sp = NULL;
! ha->outstanding_cmds[index] = NULL;
! } else if (sp->handle == resp_identifier) {
/* Neo, you're the one... */
ha->outstanding_cmds[index] = NULL;
sp->handle = 0;
sp->flags &= ~SRB_IN_TOKEN_ARRAY;
} else {
*** 1966,1987 ****
EL(ha, "IOCB handle mismatch pkt=%xh, sp=%xh\n",
resp_identifier, sp->handle);
sp = NULL;
ql_signal_abort(ha, set_flags);
}
- } else {
- sp = ql_verify_preprocessed_cmd(ha,
- (uint32_t *)&pkt->handle, set_flags, reset_flags);
}
} else {
EL(ha, "osc index out of range, index=%xh, handle=%xh\n",
index, resp_identifier);
ql_signal_abort(ha, set_flags);
}
if (sp != NULL) {
! comp_status = (uint16_t)ddi_get16(ha->hba_buf.acc_handle,
&pkt->comp_status);
/* We dont care about SCSI QFULLs. */
if (comp_status == CS_QUEUE_FULL) {
EL(sp->ha, "CS_QUEUE_FULL, d_id=%xh, lun=%xh\n",
--- 2093,2111 ----
EL(ha, "IOCB handle mismatch pkt=%xh, sp=%xh\n",
resp_identifier, sp->handle);
sp = NULL;
ql_signal_abort(ha, set_flags);
}
}
} else {
EL(ha, "osc index out of range, index=%xh, handle=%xh\n",
index, resp_identifier);
ql_signal_abort(ha, set_flags);
}
if (sp != NULL) {
! comp_status = (uint16_t)ddi_get16(rsp_q->rsp_ring.acc_handle,
&pkt->comp_status);
/* We dont care about SCSI QFULLs. */
if (comp_status == CS_QUEUE_FULL) {
EL(sp->ha, "CS_QUEUE_FULL, d_id=%xh, lun=%xh\n",
*** 1992,2012 ****
/*
* 2300 firmware marks completion status as data underrun
* for scsi qfulls. Make it transport complete.
*/
! if ((comp_status == CS_DATA_UNDERRUN) &&
! (pkt->scsi_status_l != 0)) {
comp_status = CS_COMPLETE;
}
/*
* Workaround T3 issue where we do not get any data xferred
* but get back a good status.
*/
if (comp_status == CS_COMPLETE &&
! pkt->scsi_status_l == 0 &&
(pkt->scsi_status_h & FCP_RSP_MASK) == 0 &&
pkt->residual_length != 0 &&
sp->fcp &&
sp->fcp->fcp_data_len != 0 &&
sp->fcp->fcp_cntl.cntl_write_data) {
--- 2116,2136 ----
/*
* 2300 firmware marks completion status as data underrun
* for scsi qfulls. Make it transport complete.
*/
! if (comp_status == CS_DATA_UNDERRUN &&
! pkt->scsi_status_l != STATUS_GOOD) {
comp_status = CS_COMPLETE;
}
/*
* Workaround T3 issue where we do not get any data xferred
* but get back a good status.
*/
if (comp_status == CS_COMPLETE &&
! pkt->scsi_status_l == STATUS_GOOD &&
(pkt->scsi_status_h & FCP_RSP_MASK) == 0 &&
pkt->residual_length != 0 &&
sp->fcp &&
sp->fcp->fcp_data_len != 0 &&
sp->fcp->fcp_cntl.cntl_write_data) {
*** 2014,2038 ****
}
/*
* Fast path to good SCSI I/O completion
*/
! if ((comp_status == CS_COMPLETE) &
! (!pkt->scsi_status_l) &
! (!(pkt->scsi_status_h & FCP_RSP_MASK))) {
/* Set completed status. */
sp->flags |= SRB_ISP_COMPLETED;
sp->pkt->pkt_reason = comp_status;
! ql_fast_fcp_post(sp);
! QL_PRINT_3(CE_CONT, "(%d): ql_fast_fcp_post done\n",
! ha->instance);
return (0);
}
! rval = ql_status_error(ha, sp, (sts_entry_t *)pkt, done_q,
! set_flags, reset_flags);
}
! QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
return (rval);
}
/*
--- 2138,2161 ----
}
/*
* Fast path to good SCSI I/O completion
*/
! if (comp_status == CS_COMPLETE &&
! pkt->scsi_status_l == STATUS_GOOD &&
! (pkt->scsi_status_h & FCP_RSP_MASK) == 0) {
/* Set completed status. */
sp->flags |= SRB_ISP_COMPLETED;
sp->pkt->pkt_reason = comp_status;
! ql_fast_fcp_post(sp, rsp_q);
! QL_PRINT_3(ha, "ql_fast_fcp_post done\n");
return (0);
}
! rval = ql_status_error(ha, rsp_q, sp, (sts_entry_t *)pkt,
! done_q, set_flags, reset_flags);
}
! QL_PRINT_3(ha, "done\n");
return (rval);
}
/*
*** 2039,2049 ****
--- 2162,2174 ----
* ql_verify_preprocessed_cmd
* Handles preprocessed cmds..
*
* Input:
* ha: adapter state pointer.
+ * rsp_q: response queue structure pointer.
* pkt_handle: handle pointer.
+ * resp_identifier: resp_identifier pointer.
* set_flags: task daemon flags to set.
* reset_flags: task daemon flags to reset.
*
* Returns:
* srb pointer or NULL
*** 2051,2095 ****
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
/* ARGSUSED */
ql_srb_t *
! ql_verify_preprocessed_cmd(ql_adapter_state_t *ha, uint32_t *pkt_handle,
! uint32_t *set_flags, uint32_t *reset_flags)
{
ql_srb_t *sp = NULL;
! uint32_t index, resp_identifier;
uint32_t get_handle = 10;
while (get_handle) {
/* Get handle. */
! resp_identifier = ddi_get32(ha->hba_buf.acc_handle, pkt_handle);
! index = resp_identifier & OSC_INDEX_MASK;
/* Validate handle. */
! if (index < MAX_OUTSTANDING_COMMANDS) {
sp = ha->outstanding_cmds[index];
}
if (sp != NULL) {
EL(ha, "sp=%xh, resp_id=%xh, get=%d, index=%xh\n", sp,
! resp_identifier, get_handle, index);
break;
} else {
get_handle -= 1;
drv_usecwait(10000);
! if (get_handle == 1) {
/* Last chance, Sync whole DMA buffer. */
! (void) ddi_dma_sync(ha->hba_buf.dma_handle,
! RESPONSE_Q_BUFFER_OFFSET,
! RESPONSE_QUEUE_SIZE,
! DDI_DMA_SYNC_FORKERNEL);
EL(ha, "last chance DMA sync, index=%xh\n",
index);
}
}
}
! QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
return (sp);
}
--- 2176,2220 ----
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
/* ARGSUSED */
ql_srb_t *
! ql_verify_preprocessed_cmd(ql_adapter_state_t *ha, ql_response_q_t *rsp_q,
! uint32_t *pkt_handle, uint32_t *resp_identifier, uint64_t *set_flags,
! uint64_t *reset_flags)
{
ql_srb_t *sp = NULL;
! uint32_t index;
uint32_t get_handle = 10;
while (get_handle) {
/* Get handle. */
! *resp_identifier = ddi_get32(rsp_q->rsp_ring.acc_handle,
! pkt_handle);
! index = *resp_identifier & OSC_INDEX_MASK;
/* Validate handle. */
! if (index < ha->osc_max_cnt) {
sp = ha->outstanding_cmds[index];
}
if (sp != NULL) {
EL(ha, "sp=%xh, resp_id=%xh, get=%d, index=%xh\n", sp,
! *resp_identifier, get_handle, index);
break;
} else {
get_handle -= 1;
drv_usecwait(10000);
! if (get_handle == 1 && rsp_q->rsp_ring.dma_handle) {
/* Last chance, Sync whole DMA buffer. */
! (void) ddi_dma_sync(rsp_q->rsp_ring.dma_handle,
! 0, 0, DDI_DMA_SYNC_FORCPU);
EL(ha, "last chance DMA sync, index=%xh\n",
index);
}
}
}
! QL_PRINT_3(ha, "done\n");
return (sp);
}
*** 2097,2106 ****
--- 2222,2232 ----
* ql_status_error
* Processes received ISP status entry error.
*
* Input:
* ha: adapter state pointer.
+ * rsp_q: response queue structure pointer.
* sp: SRB pointer.
* pkt: entry pointer.
* done_q: done queue pointer.
* set_flags: task daemon flags to set.
* reset_flags: task daemon flags to reset.
*** 2111,2122 ****
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
/* ARGSUSED */
static int
! ql_status_error(ql_adapter_state_t *ha, ql_srb_t *sp, sts_entry_t *pkt23,
! ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags)
{
uint32_t sense_sz = 0;
uint32_t cnt;
ql_tgt_t *tq;
fcp_rsp_t *fcpr;
--- 2237,2249 ----
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
/* ARGSUSED */
static int
! ql_status_error(ql_adapter_state_t *ha, ql_response_q_t *rsp_q, ql_srb_t *sp,
! sts_entry_t *pkt23, ql_head_t *done_q, uint64_t *set_flags,
! uint64_t *reset_flags)
{
uint32_t sense_sz = 0;
uint32_t cnt;
ql_tgt_t *tq;
fcp_rsp_t *fcpr;
*** 2135,2164 ****
uint8_t state_flags_h;
uint8_t scsi_status_l;
uint8_t scsi_status_h;
} sts;
! QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
! if (CFG_IST(ha, CFG_CTRL_24258081)) {
sts_24xx_entry_t *pkt24 = (sts_24xx_entry_t *)pkt23;
/* Setup status. */
! sts.comp_status = (uint16_t)ddi_get16(ha->hba_buf.acc_handle,
! &pkt24->comp_status);
sts.scsi_status_l = pkt24->scsi_status_l;
sts.scsi_status_h = pkt24->scsi_status_h;
/* Setup firmware residuals. */
sts.residual_length = sts.comp_status == CS_DATA_UNDERRUN ?
! ddi_get32(ha->hba_buf.acc_handle,
(uint32_t *)&pkt24->residual_length) : 0;
/* Setup FCP residuals. */
sts.fcp_residual_length = sts.scsi_status_h &
(FCP_RESID_UNDER | FCP_RESID_OVER) ?
! ddi_get32(ha->hba_buf.acc_handle,
(uint32_t *)&pkt24->fcp_rsp_residual_count) : 0;
if ((sts.comp_status == CS_DATA_UNDERRUN) &&
(sts.scsi_status_h & FCP_RESID_UNDER) &&
(sts.residual_length != pkt24->fcp_rsp_residual_count)) {
--- 2262,2291 ----
uint8_t state_flags_h;
uint8_t scsi_status_l;
uint8_t scsi_status_h;
} sts;
! QL_PRINT_3(ha, "started\n");
! if (CFG_IST(ha, CFG_ISP_FW_TYPE_2)) {
sts_24xx_entry_t *pkt24 = (sts_24xx_entry_t *)pkt23;
/* Setup status. */
! sts.comp_status = (uint16_t)ddi_get16(
! rsp_q->rsp_ring.acc_handle, &pkt24->comp_status);
sts.scsi_status_l = pkt24->scsi_status_l;
sts.scsi_status_h = pkt24->scsi_status_h;
/* Setup firmware residuals. */
sts.residual_length = sts.comp_status == CS_DATA_UNDERRUN ?
! ddi_get32(rsp_q->rsp_ring.acc_handle,
(uint32_t *)&pkt24->residual_length) : 0;
/* Setup FCP residuals. */
sts.fcp_residual_length = sts.scsi_status_h &
(FCP_RESID_UNDER | FCP_RESID_OVER) ?
! ddi_get32(rsp_q->rsp_ring.acc_handle,
(uint32_t *)&pkt24->fcp_rsp_residual_count) : 0;
if ((sts.comp_status == CS_DATA_UNDERRUN) &&
(sts.scsi_status_h & FCP_RESID_UNDER) &&
(sts.residual_length != pkt24->fcp_rsp_residual_count)) {
*** 2206,2216 ****
}
/* Setup FCP response info. */
sts.rsp_info = &pkt24->rsp_sense_data[0];
if ((sts.scsi_status_h & FCP_RSP_LEN_VALID) != 0) {
! sts.rsp_info_length = ddi_get32(ha->hba_buf.acc_handle,
(uint32_t *)&pkt24->fcp_rsp_data_length);
if (sts.rsp_info_length >
sizeof (struct fcp_rsp_info)) {
sts.rsp_info_length =
sizeof (struct fcp_rsp_info);
--- 2333,2344 ----
}
/* Setup FCP response info. */
sts.rsp_info = &pkt24->rsp_sense_data[0];
if ((sts.scsi_status_h & FCP_RSP_LEN_VALID) != 0) {
! sts.rsp_info_length = ddi_get32(
! rsp_q->rsp_ring.acc_handle,
(uint32_t *)&pkt24->fcp_rsp_data_length);
if (sts.rsp_info_length >
sizeof (struct fcp_rsp_info)) {
sts.rsp_info_length =
sizeof (struct fcp_rsp_info);
*** 2225,2235 ****
/* Setup sense data. */
sts.req_sense_data =
&pkt24->rsp_sense_data[sts.rsp_info_length];
if (sts.scsi_status_h & FCP_SNS_LEN_VALID) {
sts.req_sense_length =
! ddi_get32(ha->hba_buf.acc_handle,
(uint32_t *)&pkt24->fcp_sense_length);
sts.state_flags_h = (uint8_t)
(sts.state_flags_h | SF_ARQ_DONE);
sense_sz = (uint32_t)
(((uintptr_t)pkt24 + sizeof (sts_24xx_entry_t)) -
--- 2353,2363 ----
/* Setup sense data. */
sts.req_sense_data =
&pkt24->rsp_sense_data[sts.rsp_info_length];
if (sts.scsi_status_h & FCP_SNS_LEN_VALID) {
sts.req_sense_length =
! ddi_get32(rsp_q->rsp_ring.acc_handle,
(uint32_t *)&pkt24->fcp_sense_length);
sts.state_flags_h = (uint8_t)
(sts.state_flags_h | SF_ARQ_DONE);
sense_sz = (uint32_t)
(((uintptr_t)pkt24 + sizeof (sts_24xx_entry_t)) -
*** 2241,2257 ****
sts.req_sense_length = 0;
}
} else {
/* Setup status. */
sts.comp_status = (uint16_t)ddi_get16(
! ha->hba_buf.acc_handle, &pkt23->comp_status);
sts.scsi_status_l = pkt23->scsi_status_l;
sts.scsi_status_h = pkt23->scsi_status_h;
/* Setup firmware residuals. */
sts.residual_length = sts.comp_status == CS_DATA_UNDERRUN ?
! ddi_get32(ha->hba_buf.acc_handle,
(uint32_t *)&pkt23->residual_length) : 0;
/* Setup FCP residuals. */
sts.fcp_residual_length = sts.scsi_status_h &
(FCP_RESID_UNDER | FCP_RESID_OVER) ?
--- 2369,2385 ----
sts.req_sense_length = 0;
}
} else {
/* Setup status. */
sts.comp_status = (uint16_t)ddi_get16(
! rsp_q->rsp_ring.acc_handle, &pkt23->comp_status);
sts.scsi_status_l = pkt23->scsi_status_l;
sts.scsi_status_h = pkt23->scsi_status_h;
/* Setup firmware residuals. */
sts.residual_length = sts.comp_status == CS_DATA_UNDERRUN ?
! ddi_get32(rsp_q->rsp_ring.acc_handle,
(uint32_t *)&pkt23->residual_length) : 0;
/* Setup FCP residuals. */
sts.fcp_residual_length = sts.scsi_status_h &
(FCP_RESID_UNDER | FCP_RESID_OVER) ?
*** 2263,2273 ****
/* Setup FCP response info. */
sts.rsp_info = &pkt23->rsp_info[0];
if ((sts.scsi_status_h & FCP_RSP_LEN_VALID) != 0) {
sts.rsp_info_length = ddi_get16(
! ha->hba_buf.acc_handle,
(uint16_t *)&pkt23->rsp_info_length);
if (sts.rsp_info_length >
sizeof (struct fcp_rsp_info)) {
sts.rsp_info_length =
sizeof (struct fcp_rsp_info);
--- 2391,2401 ----
/* Setup FCP response info. */
sts.rsp_info = &pkt23->rsp_info[0];
if ((sts.scsi_status_h & FCP_RSP_LEN_VALID) != 0) {
sts.rsp_info_length = ddi_get16(
! rsp_q->rsp_ring.acc_handle,
(uint16_t *)&pkt23->rsp_info_length);
if (sts.rsp_info_length >
sizeof (struct fcp_rsp_info)) {
sts.rsp_info_length =
sizeof (struct fcp_rsp_info);
*** 2277,2287 ****
}
/* Setup sense data. */
sts.req_sense_data = &pkt23->req_sense_data[0];
sts.req_sense_length = sts.scsi_status_h & FCP_SNS_LEN_VALID ?
! ddi_get16(ha->hba_buf.acc_handle,
(uint16_t *)&pkt23->req_sense_length) : 0;
}
bzero(sp->pkt->pkt_resp, sp->pkt->pkt_rsplen);
--- 2405,2415 ----
}
/* Setup sense data. */
sts.req_sense_data = &pkt23->req_sense_data[0];
sts.req_sense_length = sts.scsi_status_h & FCP_SNS_LEN_VALID ?
! ddi_get16(rsp_q->rsp_ring.acc_handle,
(uint16_t *)&pkt23->req_sense_length) : 0;
}
bzero(sp->pkt->pkt_resp, sp->pkt->pkt_rsplen);
*** 2318,2329 ****
sense_sz = sts.rsp_info_length;
}
/* copy response information data. */
if (sense_sz) {
! ddi_rep_get8(ha->hba_buf.acc_handle, (uint8_t *)rsp,
! sts.rsp_info, sense_sz, DDI_DEV_AUTOINCR);
}
fcpr->fcp_response_len = sense_sz;
rsp = (struct fcp_rsp_info *)((caddr_t)rsp +
fcpr->fcp_response_len);
--- 2446,2458 ----
sense_sz = sts.rsp_info_length;
}
/* copy response information data. */
if (sense_sz) {
! ddi_rep_get8(rsp_q->rsp_ring.acc_handle,
! (uint8_t *)rsp, sts.rsp_info, sense_sz,
! DDI_DEV_AUTOINCR);
}
fcpr->fcp_response_len = sense_sz;
rsp = (struct fcp_rsp_info *)((caddr_t)rsp +
fcpr->fcp_response_len);
*** 2358,2367 ****
--- 2487,2497 ----
fcpr->fcp_response_len = 0;
}
/* Set reset status received. */
if (sts.comp_status == CS_RESET && LOOP_READY(ha)) {
+ *set_flags |= MARKER_NEEDED;
rval |= BIT_0;
}
if (!(tq->flags & TQF_TAPE_DEVICE) &&
(!(CFG_IST(ha, CFG_ENABLE_LINK_DOWN_REPORTING)) ||
*** 2446,2456 ****
--- 2576,2591 ----
ADAPTER_STATE_UNLOCK(ha);
}
} else {
EL(sp->ha, "Abort Retry, d_id=%xh, lun=%xh\n",
tq->d_id.b24, sp->lun_queue->lun_no);
+
+ if (CFG_IST(ha, CFG_ISP_FW_TYPE_2) && LOOP_READY(ha)) {
+ *set_flags |= MARKER_NEEDED;
+ rval |= BIT_0;
}
+ }
/* Set retry status. */
sp->flags |= SRB_RETRY;
} else {
fcpr->fcp_resid =
*** 2479,2491 ****
sp->pkt->pkt_reason = CS_COMPLETE;
}
if (sp->pkt->pkt_reason != CS_COMPLETE) {
ha->xioctl->DeviceErrorCount++;
! EL(sp->ha, "Cmplt status err = %xh, d_id=%xh, lun=%xh"
! "\n", sts.comp_status, tq->d_id.b24,
! sp->lun_queue->lun_no);
}
/* Set target request sense data. */
if (sts.scsi_status_l == STATUS_CHECK) {
if (sts.scsi_status_h & FCP_SNS_LEN_VALID) {
--- 2614,2628 ----
sp->pkt->pkt_reason = CS_COMPLETE;
}
if (sp->pkt->pkt_reason != CS_COMPLETE) {
ha->xioctl->DeviceErrorCount++;
! EL(sp->ha, "Cmplt status err = %xh, d_id=%xh, lun=%xh,"
! " pkt_reason=%xh, spf=%xh, sp=%ph\n",
! sts.comp_status, tq->d_id.b24,
! sp->lun_queue->lun_no, sp->pkt->pkt_reason,
! sp->flags, sp);
}
/* Set target request sense data. */
if (sts.scsi_status_l == STATUS_CHECK) {
if (sts.scsi_status_h & FCP_SNS_LEN_VALID) {
*** 2530,2550 ****
}
fcpr->fcp_sense_len = sense_sz;
/* Move sense data. */
! ddi_rep_get8(ha->hba_buf.acc_handle,
(uint8_t *)sp->request_sense_ptr,
sts.req_sense_data,
(size_t)sense_sz,
DDI_DEV_AUTOINCR);
sp->request_sense_ptr += sense_sz;
sp->request_sense_length -= sense_sz;
if (sp->request_sense_length != 0 &&
! !(CFG_IST(ha, CFG_CTRL_8021))) {
! ha->status_srb = sp;
}
}
if (sense_sz != 0) {
EL(sp->ha, "check condition sense data, "
--- 2667,2687 ----
}
fcpr->fcp_sense_len = sense_sz;
/* Move sense data. */
! ddi_rep_get8(rsp_q->rsp_ring.acc_handle,
(uint8_t *)sp->request_sense_ptr,
sts.req_sense_data,
(size_t)sense_sz,
DDI_DEV_AUTOINCR);
sp->request_sense_ptr += sense_sz;
sp->request_sense_length -= sense_sz;
if (sp->request_sense_length != 0 &&
! !(CFG_IST(ha, CFG_CTRL_82XX))) {
! rsp_q->status_srb = sp;
}
}
if (sense_sz != 0) {
EL(sp->ha, "check condition sense data, "
*** 2579,2593 ****
/* Set completed status. */
sp->flags |= SRB_ISP_COMPLETED;
/* Place command on done queue. */
! if (ha->status_srb == NULL) {
ql_add_link_b(done_q, &sp->cmd);
}
! QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
return (rval);
}
/*
--- 2716,2730 ----
/* Set completed status. */
sp->flags |= SRB_ISP_COMPLETED;
/* Place command on done queue. */
! if (rsp_q->status_srb == NULL) {
ql_add_link_b(done_q, &sp->cmd);
}
! QL_PRINT_3(ha, "done\n");
return (rval);
}
/*
*** 2594,2603 ****
--- 2731,2741 ----
* ql_status_cont_entry
* Processes status continuation entry.
*
* Input:
* ha: adapter state pointer.
+ * rsp_q: response queue structure pointer.
* pkt: entry pointer.
* done_q: done queue pointer.
* set_flags: task daemon flags to set.
* reset_flags: task daemon flags to reset.
*
*** 2604,2637 ****
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
/* ARGSUSED */
static void
! ql_status_cont_entry(ql_adapter_state_t *ha, sts_cont_entry_t *pkt,
! ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags)
{
uint32_t sense_sz, index;
! ql_srb_t *sp = ha->status_srb;
! QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
if (sp != NULL && sp->request_sense_length) {
if (sp->request_sense_length > sizeof (pkt->req_sense_data)) {
sense_sz = sizeof (pkt->req_sense_data);
} else {
sense_sz = sp->request_sense_length;
}
! if (CFG_IST(ha, CFG_CTRL_24258081)) {
for (index = 0; index < sense_sz; index += 4) {
ql_chg_endian((uint8_t *)
&pkt->req_sense_data[0] + index, 4);
}
}
/* Move sense data. */
! ddi_rep_get8(ha->hba_buf.acc_handle,
(uint8_t *)sp->request_sense_ptr,
(uint8_t *)&pkt->req_sense_data[0], (size_t)sense_sz,
DDI_DEV_AUTOINCR);
sp->request_sense_ptr += sense_sz;
--- 2742,2776 ----
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
/* ARGSUSED */
static void
! ql_status_cont_entry(ql_adapter_state_t *ha, ql_response_q_t *rsp_q,
! sts_cont_entry_t *pkt, ql_head_t *done_q, uint64_t *set_flags,
! uint64_t *reset_flags)
{
uint32_t sense_sz, index;
! ql_srb_t *sp = rsp_q->status_srb;
! QL_PRINT_3(ha, "started\n");
if (sp != NULL && sp->request_sense_length) {
if (sp->request_sense_length > sizeof (pkt->req_sense_data)) {
sense_sz = sizeof (pkt->req_sense_data);
} else {
sense_sz = sp->request_sense_length;
}
! if (CFG_IST(ha, CFG_ISP_FW_TYPE_2)) {
for (index = 0; index < sense_sz; index += 4) {
ql_chg_endian((uint8_t *)
&pkt->req_sense_data[0] + index, 4);
}
}
/* Move sense data. */
! ddi_rep_get8(rsp_q->rsp_ring.acc_handle,
(uint8_t *)sp->request_sense_ptr,
(uint8_t *)&pkt->req_sense_data[0], (size_t)sense_sz,
DDI_DEV_AUTOINCR);
sp->request_sense_ptr += sense_sz;
*** 2638,2660 ****
sp->request_sense_length -= sense_sz;
/* Place command on done queue. */
if (sp->request_sense_length == 0) {
ql_add_link_b(done_q, &sp->cmd);
! ha->status_srb = NULL;
}
}
! QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
}
/*
* ql_ip_entry
* Processes received ISP IP entry.
*
* Input:
* ha: adapter state pointer.
* pkt: entry pointer.
* done_q: done queue pointer.
* set_flags: task daemon flags to set.
* reset_flags: task daemon flags to reset.
*
--- 2777,2800 ----
sp->request_sense_length -= sense_sz;
/* Place command on done queue. */
if (sp->request_sense_length == 0) {
ql_add_link_b(done_q, &sp->cmd);
! rsp_q->status_srb = NULL;
}
}
! QL_PRINT_3(ha, "done\n");
}
/*
* ql_ip_entry
* Processes received ISP IP entry.
*
* Input:
* ha: adapter state pointer.
+ * rsp_q: response queue structure pointer.
* pkt: entry pointer.
* done_q: done queue pointer.
* set_flags: task daemon flags to set.
* reset_flags: task daemon flags to reset.
*
*** 2661,2687 ****
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
/* ARGSUSED */
static void
! ql_ip_entry(ql_adapter_state_t *ha, ip_entry_t *pkt23, ql_head_t *done_q,
! uint32_t *set_flags, uint32_t *reset_flags)
{
! ql_srb_t *sp;
uint32_t index, resp_identifier;
ql_tgt_t *tq;
! QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
/* Validate the response entry handle. */
! resp_identifier = ddi_get32(ha->hba_buf.acc_handle, &pkt23->handle);
index = resp_identifier & OSC_INDEX_MASK;
! if (index < MAX_OUTSTANDING_COMMANDS) {
/* the index seems reasonable */
! sp = ha->outstanding_cmds[index];
if (sp != NULL) {
! if (sp->handle == resp_identifier) {
/* Neo, you're the one... */
ha->outstanding_cmds[index] = NULL;
sp->handle = 0;
sp->flags &= ~SRB_IN_TOKEN_ARRAY;
} else {
--- 2801,2838 ----
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
/* ARGSUSED */
static void
! ql_ip_entry(ql_adapter_state_t *ha, ql_response_q_t *rsp_q, ip_entry_t *pkt23,
! ql_head_t *done_q, uint64_t *set_flags, uint64_t *reset_flags)
{
! ql_srb_t *sp = NULL;
uint32_t index, resp_identifier;
ql_tgt_t *tq;
! QL_PRINT_3(ha, "started\n");
/* Validate the response entry handle. */
! resp_identifier = ddi_get32(rsp_q->rsp_ring.acc_handle,
! &pkt23->handle);
index = resp_identifier & OSC_INDEX_MASK;
! if (index < ha->osc_max_cnt) {
/* the index seems reasonable */
! if ((sp = ha->outstanding_cmds[index]) == NULL) {
! sp = ql_verify_preprocessed_cmd(ha, rsp_q,
! (uint32_t *)&pkt23->handle,
! (uint32_t *)&resp_identifier, set_flags,
! reset_flags);
! }
if (sp != NULL) {
! if (sp == QL_ABORTED_SRB(ha)) {
! EL(ha, "QL_ABORTED_SRB handle=%xh\n",
! resp_identifier);
! sp = NULL;
! ha->outstanding_cmds[index] = NULL;
! } else if (sp->handle == resp_identifier) {
/* Neo, you're the one... */
ha->outstanding_cmds[index] = NULL;
sp->handle = 0;
sp->flags &= ~SRB_IN_TOKEN_ARRAY;
} else {
*** 2688,2700 ****
EL(ha, "IOCB handle mismatch pkt=%xh, sp=%xh\n",
resp_identifier, sp->handle);
sp = NULL;
ql_signal_abort(ha, set_flags);
}
- } else {
- sp = ql_verify_preprocessed_cmd(ha,
- (uint32_t *)&pkt23->handle, set_flags, reset_flags);
}
} else {
EL(ha, "osc index out of range, index=%xh, handle=%xh\n",
index, resp_identifier);
ql_signal_abort(ha, set_flags);
--- 2839,2848 ----
*** 2702,2719 ****
if (sp != NULL) {
tq = sp->lun_queue->target_queue;
/* Set ISP completion status */
! if (CFG_IST(ha, CFG_CTRL_24258081)) {
ip_cmd_entry_t *pkt24 = (ip_cmd_entry_t *)pkt23;
sp->pkt->pkt_reason = ddi_get16(
! ha->hba_buf.acc_handle, &pkt24->hdl_status);
} else {
sp->pkt->pkt_reason = ddi_get16(
! ha->hba_buf.acc_handle, &pkt23->comp_status);
}
if (ha->task_daemon_flags & LOOP_DOWN) {
EL(ha, "Loop Not Ready Retry, d_id=%xh\n",
tq->d_id.b24);
--- 2850,2867 ----
if (sp != NULL) {
tq = sp->lun_queue->target_queue;
/* Set ISP completion status */
! if (CFG_IST(ha, CFG_CTRL_24XX)) {
ip_cmd_entry_t *pkt24 = (ip_cmd_entry_t *)pkt23;
sp->pkt->pkt_reason = ddi_get16(
! rsp_q->rsp_ring.acc_handle, &pkt24->hdl_status);
} else {
sp->pkt->pkt_reason = ddi_get16(
! rsp_q->rsp_ring.acc_handle, &pkt23->comp_status);
}
if (ha->task_daemon_flags & LOOP_DOWN) {
EL(ha, "Loop Not Ready Retry, d_id=%xh\n",
tq->d_id.b24);
*** 2779,2797 ****
sp->flags |= SRB_ISP_COMPLETED;
ql_add_link_b(done_q, &sp->cmd);
}
! QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
}
/*
* ql_ip_rcv_entry
* Processes received ISP IP buffers entry.
*
* Input:
* ha: adapter state pointer.
* pkt: entry pointer.
* done_q: done queue pointer.
* set_flags: task daemon flags to set.
* reset_flags: task daemon flags to reset.
*
--- 2927,2946 ----
sp->flags |= SRB_ISP_COMPLETED;
ql_add_link_b(done_q, &sp->cmd);
}
! QL_PRINT_3(ha, "done\n");
}
/*
* ql_ip_rcv_entry
* Processes received ISP IP buffers entry.
*
* Input:
* ha: adapter state pointer.
+ * rsp_q: response queue structure pointer.
* pkt: entry pointer.
* done_q: done queue pointer.
* set_flags: task daemon flags to set.
* reset_flags: task daemon flags to reset.
*
*** 2798,2816 ****
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
/* ARGSUSED */
static void
! ql_ip_rcv_entry(ql_adapter_state_t *ha, ip_rcv_entry_t *pkt,
! ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags)
{
port_id_t s_id;
uint16_t index;
uint8_t cnt;
ql_tgt_t *tq;
! QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
/* Locate device queue. */
s_id.b.al_pa = pkt->s_id[0];
s_id.b.area = pkt->s_id[1];
s_id.b.domain = pkt->s_id[2];
--- 2947,2966 ----
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
/* ARGSUSED */
static void
! ql_ip_rcv_entry(ql_adapter_state_t *ha, ql_response_q_t *rsp_q,
! ip_rcv_entry_t *pkt, ql_head_t *done_q, uint64_t *set_flags,
! uint64_t *reset_flags)
{
port_id_t s_id;
uint16_t index;
uint8_t cnt;
ql_tgt_t *tq;
! QL_PRINT_3(ha, "started\n");
/* Locate device queue. */
s_id.b.al_pa = pkt->s_id[0];
s_id.b.area = pkt->s_id[1];
s_id.b.domain = pkt->s_id[2];
*** 2817,2828 ****
if ((tq = ql_d_id_to_queue(ha, s_id)) == NULL) {
EL(ha, "Unknown IP device ID=%xh\n", s_id.b24);
return;
}
! tq->ub_sequence_length = (uint16_t)ddi_get16(ha->hba_buf.acc_handle,
! &pkt->seq_length);
tq->ub_total_seg_cnt = pkt->segment_count;
tq->ub_seq_id = ++ha->ub_seq_id;
tq->ub_seq_cnt = 0;
tq->ub_frame_ro = 0;
tq->ub_loop_id = pkt->loop_id;
--- 2967,2978 ----
if ((tq = ql_d_id_to_queue(ha, s_id)) == NULL) {
EL(ha, "Unknown IP device ID=%xh\n", s_id.b24);
return;
}
! tq->ub_sequence_length = (uint16_t)ddi_get16(
! rsp_q->rsp_ring.acc_handle, &pkt->seq_length);
tq->ub_total_seg_cnt = pkt->segment_count;
tq->ub_seq_id = ++ha->ub_seq_id;
tq->ub_seq_cnt = 0;
tq->ub_frame_ro = 0;
tq->ub_loop_id = pkt->loop_id;
*** 2829,2857 ****
ha->rcv_dev_q = tq;
for (cnt = 0; cnt < IP_RCVBUF_HANDLES && tq->ub_seq_cnt <
tq->ub_total_seg_cnt; cnt++) {
! index = (uint16_t)ddi_get16(ha->hba_buf.acc_handle,
&pkt->buffer_handle[cnt]);
if (ql_ub_frame_hdr(ha, tq, index, done_q) != QL_SUCCESS) {
EL(ha, "ql_ub_frame_hdr failed, isp_abort_needed\n");
*set_flags |= ISP_ABORT_NEEDED;
break;
}
}
! QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
}
/*
* ql_ip_rcv_cont_entry
* Processes received ISP IP buffers continuation entry.
*
* Input:
* ha: adapter state pointer.
* pkt: entry pointer.
* done_q: done queue pointer.
* set_flags: task daemon flags to set.
* reset_flags: task daemon flags to reset.
*
--- 2979,3008 ----
ha->rcv_dev_q = tq;
for (cnt = 0; cnt < IP_RCVBUF_HANDLES && tq->ub_seq_cnt <
tq->ub_total_seg_cnt; cnt++) {
! index = (uint16_t)ddi_get16(rsp_q->rsp_ring.acc_handle,
&pkt->buffer_handle[cnt]);
if (ql_ub_frame_hdr(ha, tq, index, done_q) != QL_SUCCESS) {
EL(ha, "ql_ub_frame_hdr failed, isp_abort_needed\n");
*set_flags |= ISP_ABORT_NEEDED;
break;
}
}
! QL_PRINT_3(ha, "done\n");
}
/*
* ql_ip_rcv_cont_entry
* Processes received ISP IP buffers continuation entry.
*
* Input:
* ha: adapter state pointer.
+ * rsp_q: response queue structure pointer.
* pkt: entry pointer.
* done_q: done queue pointer.
* set_flags: task daemon flags to set.
* reset_flags: task daemon flags to reset.
*
*** 2858,2903 ****
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
/* ARGSUSED */
static void
! ql_ip_rcv_cont_entry(ql_adapter_state_t *ha, ip_rcv_cont_entry_t *pkt,
! ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags)
{
uint16_t index;
uint8_t cnt;
ql_tgt_t *tq;
! QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
if ((tq = ha->rcv_dev_q) == NULL) {
EL(ha, "No IP receive device\n");
return;
}
for (cnt = 0; cnt < IP_RCVBUF_CONT_HANDLES &&
tq->ub_seq_cnt < tq->ub_total_seg_cnt; cnt++) {
! index = (uint16_t)ddi_get16(ha->hba_buf.acc_handle,
&pkt->buffer_handle[cnt]);
if (ql_ub_frame_hdr(ha, tq, index, done_q) != QL_SUCCESS) {
EL(ha, "ql_ub_frame_hdr failed, isp_abort_needed\n");
*set_flags |= ISP_ABORT_NEEDED;
break;
}
}
! QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
}
/*
* ip_rcv_24xx_entry_t
* Processes received ISP24xx IP buffers entry.
*
* Input:
* ha: adapter state pointer.
* pkt: entry pointer.
* done_q: done queue pointer.
* set_flags: task daemon flags to set.
* reset_flags: task daemon flags to reset.
*
--- 3009,3056 ----
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
/* ARGSUSED */
static void
! ql_ip_rcv_cont_entry(ql_adapter_state_t *ha, ql_response_q_t *rsp_q,
! ip_rcv_cont_entry_t *pkt, ql_head_t *done_q, uint64_t *set_flags,
! uint64_t *reset_flags)
{
uint16_t index;
uint8_t cnt;
ql_tgt_t *tq;
! QL_PRINT_3(ha, "started\n");
if ((tq = ha->rcv_dev_q) == NULL) {
EL(ha, "No IP receive device\n");
return;
}
for (cnt = 0; cnt < IP_RCVBUF_CONT_HANDLES &&
tq->ub_seq_cnt < tq->ub_total_seg_cnt; cnt++) {
! index = (uint16_t)ddi_get16(rsp_q->rsp_ring.acc_handle,
&pkt->buffer_handle[cnt]);
if (ql_ub_frame_hdr(ha, tq, index, done_q) != QL_SUCCESS) {
EL(ha, "ql_ub_frame_hdr failed, isp_abort_needed\n");
*set_flags |= ISP_ABORT_NEEDED;
break;
}
}
! QL_PRINT_3(ha, "done\n");
}
/*
* ip_rcv_24xx_entry_t
* Processes received ISP24xx IP buffers entry.
*
* Input:
* ha: adapter state pointer.
+ * rsp_q: response queue structure pointer.
* pkt: entry pointer.
* done_q: done queue pointer.
* set_flags: task daemon flags to set.
* reset_flags: task daemon flags to reset.
*
*** 2904,2922 ****
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
/* ARGSUSED */
static void
! ql_ip_24xx_rcv_entry(ql_adapter_state_t *ha, ip_rcv_24xx_entry_t *pkt,
! ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags)
{
port_id_t s_id;
uint16_t index;
uint8_t cnt;
ql_tgt_t *tq;
! QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
/* Locate device queue. */
s_id.b.al_pa = pkt->s_id[0];
s_id.b.area = pkt->s_id[1];
s_id.b.domain = pkt->s_id[2];
--- 3057,3076 ----
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
/* ARGSUSED */
static void
! ql_ip_24xx_rcv_entry(ql_adapter_state_t *ha, ql_response_q_t *rsp_q,
! ip_rcv_24xx_entry_t *pkt, ql_head_t *done_q, uint64_t *set_flags,
! uint64_t *reset_flags)
{
port_id_t s_id;
uint16_t index;
uint8_t cnt;
ql_tgt_t *tq;
! QL_PRINT_3(ha, "started\n");
/* Locate device queue. */
s_id.b.al_pa = pkt->s_id[0];
s_id.b.area = pkt->s_id[1];
s_id.b.domain = pkt->s_id[2];
*** 2925,2965 ****
return;
}
if (tq->ub_total_seg_cnt == 0) {
tq->ub_sequence_length = (uint16_t)ddi_get16(
! ha->hba_buf.acc_handle, &pkt->seq_length);
tq->ub_total_seg_cnt = pkt->segment_count;
tq->ub_seq_id = ++ha->ub_seq_id;
tq->ub_seq_cnt = 0;
tq->ub_frame_ro = 0;
tq->ub_loop_id = (uint16_t)ddi_get16(
! ha->hba_buf.acc_handle, &pkt->n_port_hdl);
}
for (cnt = 0; cnt < IP_24XX_RCVBUF_HANDLES && tq->ub_seq_cnt <
tq->ub_total_seg_cnt; cnt++) {
! index = (uint16_t)ddi_get16(ha->hba_buf.acc_handle,
&pkt->buffer_handle[cnt]);
if (ql_ub_frame_hdr(ha, tq, index, done_q) != QL_SUCCESS) {
EL(ha, "ql_ub_frame_hdr failed, isp_abort_needed\n");
*set_flags |= ISP_ABORT_NEEDED;
break;
}
}
! QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
}
/*
* ql_ms_entry
* Processes received Name/Management/CT Pass-Through entry.
*
* Input:
* ha: adapter state pointer.
* pkt23: entry pointer.
* done_q: done queue pointer.
* set_flags: task daemon flags to set.
* reset_flags: task daemon flags to reset.
*
--- 3079,3120 ----
return;
}
if (tq->ub_total_seg_cnt == 0) {
tq->ub_sequence_length = (uint16_t)ddi_get16(
! rsp_q->rsp_ring.acc_handle, &pkt->seq_length);
tq->ub_total_seg_cnt = pkt->segment_count;
tq->ub_seq_id = ++ha->ub_seq_id;
tq->ub_seq_cnt = 0;
tq->ub_frame_ro = 0;
tq->ub_loop_id = (uint16_t)ddi_get16(
! rsp_q->rsp_ring.acc_handle, &pkt->n_port_hdl);
}
for (cnt = 0; cnt < IP_24XX_RCVBUF_HANDLES && tq->ub_seq_cnt <
tq->ub_total_seg_cnt; cnt++) {
! index = (uint16_t)ddi_get16(rsp_q->rsp_ring.acc_handle,
&pkt->buffer_handle[cnt]);
if (ql_ub_frame_hdr(ha, tq, index, done_q) != QL_SUCCESS) {
EL(ha, "ql_ub_frame_hdr failed, isp_abort_needed\n");
*set_flags |= ISP_ABORT_NEEDED;
break;
}
}
! QL_PRINT_3(ha, "done\n");
}
/*
* ql_ms_entry
* Processes received Name/Management/CT Pass-Through entry.
*
* Input:
* ha: adapter state pointer.
+ * rsp_q: response queue structure pointer.
* pkt23: entry pointer.
* done_q: done queue pointer.
* set_flags: task daemon flags to set.
* reset_flags: task daemon flags to reset.
*
*** 2966,2993 ****
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
/* ARGSUSED */
static void
! ql_ms_entry(ql_adapter_state_t *ha, ms_entry_t *pkt23, ql_head_t *done_q,
! uint32_t *set_flags, uint32_t *reset_flags)
{
! ql_srb_t *sp;
uint32_t index, cnt, resp_identifier;
ql_tgt_t *tq;
ct_passthru_entry_t *pkt24 = (ct_passthru_entry_t *)pkt23;
! QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
/* Validate the response entry handle. */
! resp_identifier = ddi_get32(ha->hba_buf.acc_handle, &pkt23->handle);
index = resp_identifier & OSC_INDEX_MASK;
! if (index < MAX_OUTSTANDING_COMMANDS) {
/* the index seems reasonable */
! sp = ha->outstanding_cmds[index];
if (sp != NULL) {
! if (sp->handle == resp_identifier) {
/* Neo, you're the one... */
ha->outstanding_cmds[index] = NULL;
sp->handle = 0;
sp->flags &= ~SRB_IN_TOKEN_ARRAY;
} else {
--- 3121,3159 ----
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
/* ARGSUSED */
static void
! ql_ms_entry(ql_adapter_state_t *ha, ql_response_q_t *rsp_q, ms_entry_t *pkt23,
! ql_head_t *done_q, uint64_t *set_flags, uint64_t *reset_flags)
{
! ql_srb_t *sp = NULL;
uint32_t index, cnt, resp_identifier;
ql_tgt_t *tq;
ct_passthru_entry_t *pkt24 = (ct_passthru_entry_t *)pkt23;
! QL_PRINT_3(ha, "started\n");
/* Validate the response entry handle. */
! resp_identifier = ddi_get32(rsp_q->rsp_ring.acc_handle,
! &pkt23->handle);
index = resp_identifier & OSC_INDEX_MASK;
! if (index < ha->osc_max_cnt) {
/* the index seems reasonable */
! if ((sp = ha->outstanding_cmds[index]) == NULL) {
! sp = ql_verify_preprocessed_cmd(ha, rsp_q,
! (uint32_t *)&pkt23->handle,
! (uint32_t *)&resp_identifier, set_flags,
! reset_flags);
! }
if (sp != NULL) {
! if (sp == QL_ABORTED_SRB(ha)) {
! EL(ha, "QL_ABORTED_SRB handle=%xh\n",
! resp_identifier);
! sp = NULL;
! ha->outstanding_cmds[index] = NULL;
! } else if (sp->handle == resp_identifier) {
/* Neo, you're the one... */
ha->outstanding_cmds[index] = NULL;
sp->handle = 0;
sp->flags &= ~SRB_IN_TOKEN_ARRAY;
} else {
*** 2994,3006 ****
EL(ha, "IOCB handle mismatch pkt=%xh, sp=%xh\n",
resp_identifier, sp->handle);
sp = NULL;
ql_signal_abort(ha, set_flags);
}
- } else {
- sp = ql_verify_preprocessed_cmd(ha,
- (uint32_t *)&pkt23->handle, set_flags, reset_flags);
}
} else {
EL(ha, "osc index out of range, index=%xh, handle=%xh\n",
index, resp_identifier);
ql_signal_abort(ha, set_flags);
--- 3160,3169 ----
*** 3015,3030 ****
}
tq = sp->lun_queue->target_queue;
/* Set ISP completion status */
! if (CFG_IST(ha, CFG_CTRL_24258081)) {
sp->pkt->pkt_reason = ddi_get16(
! ha->hba_buf.acc_handle, &pkt24->status);
} else {
sp->pkt->pkt_reason = ddi_get16(
! ha->hba_buf.acc_handle, &pkt23->comp_status);
}
if (sp->pkt->pkt_reason == CS_RESOUCE_UNAVAILABLE &&
sp->retry_count) {
EL(ha, "Resouce Unavailable Retry = %d\n",
--- 3178,3193 ----
}
tq = sp->lun_queue->target_queue;
/* Set ISP completion status */
! if (CFG_IST(ha, CFG_ISP_FW_TYPE_2)) {
sp->pkt->pkt_reason = ddi_get16(
! rsp_q->rsp_ring.acc_handle, &pkt24->status);
} else {
sp->pkt->pkt_reason = ddi_get16(
! rsp_q->rsp_ring.acc_handle, &pkt23->comp_status);
}
if (sp->pkt->pkt_reason == CS_RESOUCE_UNAVAILABLE &&
sp->retry_count) {
EL(ha, "Resouce Unavailable Retry = %d\n",
*** 3083,3117 ****
EL(ha, "Reset Retry\n");
/* Set retry status. */
sp->flags |= SRB_RETRY;
! } else if (CFG_IST(ha, CFG_CTRL_24258081) &&
sp->pkt->pkt_reason == CS_DATA_UNDERRUN) {
! cnt = ddi_get32(ha->hba_buf.acc_handle,
&pkt24->resp_byte_count);
if (cnt < sizeof (fc_ct_header_t)) {
EL(ha, "Data underrun\n");
} else {
sp->pkt->pkt_reason = CS_COMPLETE;
}
} else if (sp->pkt->pkt_reason != CS_COMPLETE) {
EL(ha, "status err=%xh\n", sp->pkt->pkt_reason);
}
if (sp->pkt->pkt_reason == CS_COMPLETE) {
/*EMPTY*/
! QL_PRINT_3(CE_CONT, "(%d): ct_cmdrsp=%x%02xh resp\n",
! ha->instance, sp->pkt->pkt_cmd[8],
! sp->pkt->pkt_cmd[9]);
QL_DUMP_3(sp->pkt->pkt_resp, 8, sp->pkt->pkt_rsplen);
}
/* For nameserver restore command, management change header. */
if ((sp->flags & SRB_RETRY) == 0) {
! tq->d_id.b24 == 0xfffffc ?
ql_cthdr_endian(sp->pkt->pkt_cmd_acc,
sp->pkt->pkt_cmd, B_TRUE) :
ql_cthdr_endian(sp->pkt->pkt_resp_acc,
sp->pkt->pkt_resp, B_TRUE);
}
--- 3246,3287 ----
EL(ha, "Reset Retry\n");
/* Set retry status. */
sp->flags |= SRB_RETRY;
! } else if (CFG_IST(ha, CFG_ISP_FW_TYPE_2) &&
sp->pkt->pkt_reason == CS_DATA_UNDERRUN) {
! cnt = ddi_get32(rsp_q->rsp_ring.acc_handle,
&pkt24->resp_byte_count);
if (cnt < sizeof (fc_ct_header_t)) {
EL(ha, "Data underrun\n");
} else {
sp->pkt->pkt_reason = CS_COMPLETE;
}
+ } else if (sp->pkt->pkt_reason == CS_PORT_UNAVAILABLE ||
+ sp->pkt->pkt_reason == CS_PORT_LOGGED_OUT) {
+ EL(ha, "Port unavailable %xh\n", sp->pkt->pkt_reason);
+ DEVICE_QUEUE_LOCK(tq);
+ tq->flags |= TQF_LOGIN_NEEDED;
+ DEVICE_QUEUE_UNLOCK(tq);
+ sp->pkt->pkt_reason = CS_TIMEOUT;
+
} else if (sp->pkt->pkt_reason != CS_COMPLETE) {
EL(ha, "status err=%xh\n", sp->pkt->pkt_reason);
}
if (sp->pkt->pkt_reason == CS_COMPLETE) {
/*EMPTY*/
! QL_PRINT_3(ha, "ct_cmdrsp=%x%02xh resp\n",
! sp->pkt->pkt_cmd[8], sp->pkt->pkt_cmd[9]);
QL_DUMP_3(sp->pkt->pkt_resp, 8, sp->pkt->pkt_rsplen);
}
/* For nameserver restore command, management change header. */
if ((sp->flags & SRB_RETRY) == 0) {
! tq->d_id.b24 == FS_NAME_SERVER ?
ql_cthdr_endian(sp->pkt->pkt_cmd_acc,
sp->pkt->pkt_cmd, B_TRUE) :
ql_cthdr_endian(sp->pkt->pkt_resp_acc,
sp->pkt->pkt_resp, B_TRUE);
}
*** 3121,3139 ****
/* Place command on done queue. */
ql_add_link_b(done_q, &sp->cmd);
}
! QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
}
/*
* ql_report_id_entry
* Processes received Name/Management/CT Pass-Through entry.
*
* Input:
* ha: adapter state pointer.
* pkt: entry pointer.
* done_q: done queue pointer.
* set_flags: task daemon flags to set.
* reset_flags: task daemon flags to reset.
*
--- 3291,3310 ----
/* Place command on done queue. */
ql_add_link_b(done_q, &sp->cmd);
}
! QL_PRINT_3(ha, "done\n");
}
/*
* ql_report_id_entry
* Processes received Name/Management/CT Pass-Through entry.
*
* Input:
* ha: adapter state pointer.
+ * rsp_q: response queue structure pointer.
* pkt: entry pointer.
* done_q: done queue pointer.
* set_flags: task daemon flags to set.
* reset_flags: task daemon flags to reset.
*
*** 3140,3188 ****
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
/* ARGSUSED */
static void
! ql_report_id_entry(ql_adapter_state_t *ha, report_id_1_t *pkt,
! ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags)
{
ql_adapter_state_t *vha;
! QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
! EL(ha, "format=%d, vp=%d, status=%d\n",
! pkt->format, pkt->vp_index, pkt->status);
if (pkt->format == 1) {
/* Locate port state structure. */
for (vha = ha; vha != NULL; vha = vha->vp_next) {
if (vha->vp_index == pkt->vp_index) {
break;
}
}
! if (vha != NULL && vha->vp_index != 0 &&
! (pkt->status == CS_COMPLETE ||
! pkt->status == CS_PORT_ID_CHANGE)) {
*set_flags |= LOOP_RESYNC_NEEDED;
*reset_flags &= ~LOOP_RESYNC_NEEDED;
! vha->loop_down_timer = LOOP_DOWN_TIMER_OFF;
TASK_DAEMON_LOCK(ha);
! vha->task_daemon_flags |= LOOP_RESYNC_NEEDED;
vha->task_daemon_flags &= ~LOOP_DOWN;
TASK_DAEMON_UNLOCK(ha);
}
}
! QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
}
/*
* ql_els_entry
* Processes received ELS Pass-Through entry.
*
* Input:
* ha: adapter state pointer.
* pkt23: entry pointer.
* done_q: done queue pointer.
* set_flags: task daemon flags to set.
* reset_flags: task daemon flags to reset.
*
--- 3311,3390 ----
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
/* ARGSUSED */
static void
! ql_report_id_entry(ql_adapter_state_t *ha, ql_response_q_t *rsp_q,
! report_id_acq_t *pkt, ql_head_t *done_q, uint64_t *set_flags,
! uint64_t *reset_flags)
{
ql_adapter_state_t *vha;
! QL_PRINT_3(ha, "started\n");
! EL(ha, "format=%d, index=%d, status=%d\n",
! pkt->format, pkt->vp_index, pkt->vp_status);
if (pkt->format == 1) {
/* Locate port state structure. */
for (vha = ha; vha != NULL; vha = vha->vp_next) {
if (vha->vp_index == pkt->vp_index) {
break;
}
}
! if (vha != NULL) {
! if (pkt->vp_status == CS_COMPLETE ||
! pkt->vp_status == CS_PORT_ID_CHANGE) {
! if (CFG_IST(ha, CFG_FCOE_SUPPORT)) {
! vha->fcoe_fcf_idx = pkt->fcf_index;
! }
! if (vha->vp_index != 0) {
*set_flags |= LOOP_RESYNC_NEEDED;
*reset_flags &= ~LOOP_RESYNC_NEEDED;
! vha->loop_down_timer =
! LOOP_DOWN_TIMER_OFF;
TASK_DAEMON_LOCK(ha);
! vha->task_daemon_flags |=
! LOOP_RESYNC_NEEDED;
vha->task_daemon_flags &= ~LOOP_DOWN;
TASK_DAEMON_UNLOCK(ha);
}
+ ADAPTER_STATE_LOCK(ha);
+ vha->flags &= ~VP_ID_NOT_ACQUIRED;
+ ADAPTER_STATE_UNLOCK(ha);
+ } else {
+ /* FA-WWPN failure. */
+ if (pkt->vp_status == CS_INCOMPLETE &&
+ pkt->ls_rjt_reason_code == 0xff &&
+ pkt->ls_rjt_explanation == 0x44) {
+ *set_flags |= ISP_ABORT_NEEDED;
}
+ if (CFG_IST(ha, CFG_FCOE_SUPPORT)) {
+ EL(ha, "sts sc=%d, rjt_rea=%xh, "
+ "rjt_exp=%xh, rjt_sc=%xh\n",
+ pkt->status_subcode,
+ pkt->ls_rjt_reason_code,
+ pkt->ls_rjt_explanation,
+ pkt->ls_rjt_subcode);
+ }
+ ADAPTER_STATE_LOCK(ha);
+ vha->flags |= VP_ID_NOT_ACQUIRED;
+ ADAPTER_STATE_UNLOCK(ha);
+ }
+ }
+ }
! QL_PRINT_3(ha, "done\n");
}
/*
* ql_els_entry
* Processes received ELS Pass-Through entry.
*
* Input:
* ha: adapter state pointer.
+ * rsp_q: response queue structure pointer.
* pkt23: entry pointer.
* done_q: done queue pointer.
* set_flags: task daemon flags to set.
* reset_flags: task daemon flags to reset.
*
*** 3189,3216 ****
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
/* ARGSUSED */
static void
! ql_els_passthru_entry(ql_adapter_state_t *ha, els_passthru_entry_rsp_t *rsp,
! ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags)
{
ql_tgt_t *tq;
! port_id_t d_id, s_id;
! ql_srb_t *srb;
uint32_t index, resp_identifier;
! QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
/* Validate the response entry handle. */
! resp_identifier = ddi_get32(ha->hba_buf.acc_handle, &rsp->handle);
index = resp_identifier & OSC_INDEX_MASK;
! if (index < MAX_OUTSTANDING_COMMANDS) {
/* the index seems reasonable */
! srb = ha->outstanding_cmds[index];
if (srb != NULL) {
! if (srb->handle == resp_identifier) {
/* Neo, you're the one... */
ha->outstanding_cmds[index] = NULL;
srb->handle = 0;
srb->flags &= ~SRB_IN_TOKEN_ARRAY;
} else {
--- 3391,3429 ----
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
/* ARGSUSED */
static void
! ql_els_passthru_entry(ql_adapter_state_t *ha, ql_response_q_t *rsp_q,
! els_passthru_entry_rsp_t *rsp, ql_head_t *done_q, uint64_t *set_flags,
! uint64_t *reset_flags)
{
ql_tgt_t *tq;
! port_id_t s_id;
! ql_srb_t *srb = NULL;
uint32_t index, resp_identifier;
! QL_PRINT_3(ha, "started\n");
/* Validate the response entry handle. */
! resp_identifier = ddi_get32(rsp_q->rsp_ring.acc_handle, &rsp->handle);
index = resp_identifier & OSC_INDEX_MASK;
! if (index < ha->osc_max_cnt) {
/* the index seems reasonable */
! if ((srb = ha->outstanding_cmds[index]) == NULL) {
! srb = ql_verify_preprocessed_cmd(ha, rsp_q,
! (uint32_t *)&rsp->handle,
! (uint32_t *)&resp_identifier, set_flags,
! reset_flags);
! }
if (srb != NULL) {
! if (srb == QL_ABORTED_SRB(ha)) {
! EL(ha, "QL_ABORTED_SRB handle=%xh\n",
! resp_identifier);
! srb = NULL;
! ha->outstanding_cmds[index] = NULL;
! } else if (srb->handle == resp_identifier) {
/* Neo, you're the one... */
ha->outstanding_cmds[index] = NULL;
srb->handle = 0;
srb->flags &= ~SRB_IN_TOKEN_ARRAY;
} else {
*** 3217,3255 ****
EL(ha, "IOCB handle mismatch pkt=%xh, sp=%xh\n",
resp_identifier, srb->handle);
srb = NULL;
ql_signal_abort(ha, set_flags);
}
- } else {
- srb = ql_verify_preprocessed_cmd(ha,
- (uint32_t *)&rsp->handle, set_flags, reset_flags);
}
} else {
EL(ha, "osc index out of range, index=%xh, handle=%xh\n",
index, resp_identifier);
ql_signal_abort(ha, set_flags);
}
if (srb != NULL) {
if (!(srb->flags & SRB_ELS_PKT)) {
! EL(ha, "Not SRB_ELS_PKT flags=%xh, isp_abort_needed",
srb->flags);
*set_flags |= ISP_ABORT_NEEDED;
return;
}
(void) ddi_dma_sync(srb->pkt->pkt_resp_dma, 0, 0,
DDI_DMA_SYNC_FORKERNEL);
/* Set ISP completion status */
! srb->pkt->pkt_reason = ddi_get16(
! ha->hba_buf.acc_handle, &rsp->comp_status);
if (srb->pkt->pkt_reason != CS_COMPLETE) {
la_els_rjt_t rjt;
- EL(ha, "status err=%xh\n", srb->pkt->pkt_reason);
if (srb->pkt->pkt_reason == CS_LOGIN_LOGOUT_ERROR) {
EL(ha, "e1=%xh e2=%xh\n",
rsp->error_subcode1, rsp->error_subcode2);
}
--- 3430,3467 ----
EL(ha, "IOCB handle mismatch pkt=%xh, sp=%xh\n",
resp_identifier, srb->handle);
srb = NULL;
ql_signal_abort(ha, set_flags);
}
}
} else {
EL(ha, "osc index out of range, index=%xh, handle=%xh\n",
index, resp_identifier);
ql_signal_abort(ha, set_flags);
}
if (srb != NULL) {
if (!(srb->flags & SRB_ELS_PKT)) {
! EL(ha, "Not SRB_ELS_PKT flags=%xh, isp_abort_needed\n",
srb->flags);
*set_flags |= ISP_ABORT_NEEDED;
return;
}
(void) ddi_dma_sync(srb->pkt->pkt_resp_dma, 0, 0,
DDI_DMA_SYNC_FORKERNEL);
/* Set ISP completion status */
! srb->pkt->pkt_reason = ddi_get16(rsp_q->rsp_ring.acc_handle,
! &rsp->comp_status);
if (srb->pkt->pkt_reason != CS_COMPLETE) {
la_els_rjt_t rjt;
+ EL(ha, "srb=%ph,status err=%xh\n",
+ srb, srb->pkt->pkt_reason);
+
if (srb->pkt->pkt_reason == CS_LOGIN_LOGOUT_ERROR) {
EL(ha, "e1=%xh e2=%xh\n",
rsp->error_subcode1, rsp->error_subcode2);
}
*** 3272,3306 ****
uint16_t loop_id;
/* Indicate ISP completion */
srb->flags |= SRB_ISP_COMPLETED;
! loop_id = ddi_get16(ha->hba_buf.acc_handle,
&rsp->n_port_hdl);
! if (ha->topology & QL_N_PORT) {
! /* create a target Q if there isn't one */
! tq = ql_loop_id_to_queue(ha, loop_id);
! if (tq == NULL) {
! d_id.b.al_pa = rsp->d_id_7_0;
! d_id.b.area = rsp->d_id_15_8;
! d_id.b.domain = rsp->d_id_23_16;
! /* Acquire adapter state lock. */
! ADAPTER_STATE_LOCK(ha);
! tq = ql_dev_init(ha, d_id, loop_id);
! EL(ha, " tq = %x\n", tq);
!
! ADAPTER_STATE_UNLOCK(ha);
! }
!
/* on plogi success assume the chosen s_id */
! opcode = ddi_get8(ha->hba_buf.acc_handle,
&rsp->els_cmd_opcode);
! EL(ha, "els_cmd_opcode=%x srb->pkt=%x\n",
! opcode, srb->pkt);
if (opcode == LA_ELS_PLOGI) {
s_id.b.al_pa = rsp->s_id_7_0;
s_id.b.area = rsp->s_id_15_8;
s_id.b.domain = rsp->s_id_23_16;
--- 3484,3508 ----
uint16_t loop_id;
/* Indicate ISP completion */
srb->flags |= SRB_ISP_COMPLETED;
! loop_id = ddi_get16(rsp_q->rsp_ring.acc_handle,
&rsp->n_port_hdl);
! /* tq is obtained from lun_queue */
! tq = srb->lun_queue->target_queue;
! if (ha->topology & QL_N_PORT) {
/* on plogi success assume the chosen s_id */
! opcode = ddi_get8(rsp_q->rsp_ring.acc_handle,
&rsp->els_cmd_opcode);
! EL(ha, "els opcode=%x srb=%ph,pkt=%ph, tq=%ph"
! ", portid=%xh, tqlpid=%xh, loop_id=%xh\n",
! opcode, srb, srb->pkt, tq, tq->d_id.b24,
! tq->loop_id, loop_id);
if (opcode == LA_ELS_PLOGI) {
s_id.b.al_pa = rsp->s_id_7_0;
s_id.b.area = rsp->s_id_15_8;
s_id.b.domain = rsp->s_id_23_16;
*** 3318,3337 ****
if (tq != NULL) {
tq->logout_sent = 0;
tq->flags &= ~TQF_NEED_AUTHENTICATION;
! if (CFG_IST(ha, CFG_CTRL_24258081)) {
tq->flags |= TQF_IIDMA_NEEDED;
}
srb->pkt->pkt_state = FC_PKT_SUCCESS;
}
}
/* invoke the callback */
! ql_awaken_task_daemon(ha, srb, 0, 0);
}
! QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
}
/*
* ql_signal_abort
* Signal to the task daemon that a condition warranting an
--- 3520,3550 ----
if (tq != NULL) {
tq->logout_sent = 0;
tq->flags &= ~TQF_NEED_AUTHENTICATION;
! if (CFG_IST(ha, CFG_ISP_FW_TYPE_2)) {
tq->flags |= TQF_IIDMA_NEEDED;
}
srb->pkt->pkt_state = FC_PKT_SUCCESS;
}
}
+
+ /* Remove command from watchdog queue. */
+ if (srb->flags & SRB_WATCHDOG_ENABLED) {
+ tq = srb->lun_queue->target_queue;
+
+ DEVICE_QUEUE_LOCK(tq);
+ ql_remove_link(&tq->wdg, &srb->wdg);
+ srb->flags &= ~SRB_WATCHDOG_ENABLED;
+ DEVICE_QUEUE_UNLOCK(tq);
+ }
+
/* invoke the callback */
! ql_io_comp(srb);
}
! QL_PRINT_3(ha, "done\n");
}
/*
* ql_signal_abort
* Signal to the task daemon that a condition warranting an
*** 3343,3354 ****
*
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
static void
! ql_signal_abort(ql_adapter_state_t *ha, uint32_t *set_flags)
{
! if (!CFG_IST(ha, CFG_CTRL_8021) &&
!(ha->task_daemon_flags & (ISP_ABORT_NEEDED | ABORT_ISP_ACTIVE))) {
*set_flags |= ISP_ABORT_NEEDED;
}
}
--- 3556,3567 ----
*
* Context:
* Interrupt or Kernel context, no mailbox commands allowed.
*/
static void
! ql_signal_abort(ql_adapter_state_t *ha, uint64_t *set_flags)
{
! if (!CFG_IST(ha, CFG_CTRL_82XX) &&
!(ha->task_daemon_flags & (ISP_ABORT_NEEDED | ABORT_ISP_ACTIVE))) {
*set_flags |= ISP_ABORT_NEEDED;
}
}