507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * CDDL HEADER START
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * The contents of this file are subject to the terms of the
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Common Development and Distribution License (the "License").
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * You may not use this file except in compliance with the License.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * or http://www.opensolaris.org/os/licensing.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * See the License for the specific language governing permissions
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * and limitations under the License.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * When distributing Covered Code, include this CDDL HEADER in each
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * If applicable, add the following below this CDDL HEADER, with the
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * fields enclosed by brackets "[]" replaced with your own identifying
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * information: Portions Copyright [yyyy] [name of copyright owner]
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * CDDL HEADER END
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
14e0668fa5c67fe3c44f2abd39f29a6f18272f11zhongyan gu - Sun Microsystems - Beijing China * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Use is subject to license terms.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#include <sys/types.h>
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#include <sys/kmem.h>
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#include <sys/debug.h>
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#include <sys/scsi/scsi.h>
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#include "ghd.h"
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/* ghd_poll() function codes: */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlftypedef enum {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf GHD_POLL_REQUEST, /* wait for a specific request */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf GHD_POLL_DEVICE, /* wait for a specific device to idle */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf GHD_POLL_ALL /* wait for the whole bus to idle */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf} gpoll_t;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Local functions:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic gcmd_t *ghd_doneq_get(ccc_t *cccp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic void ghd_doneq_pollmode_enter(ccc_t *cccp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic void ghd_doneq_pollmode_exit(ccc_t *cccp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic uint_t ghd_doneq_process(caddr_t arg);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic void ghd_do_reset_notify_callbacks(ccc_t *cccp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int ghd_poll(ccc_t *cccp, gpoll_t polltype, ulong_t polltime,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gcmd_t *poll_gcmdp, gtgt_t *gtgtp, void *intr_status);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Local configuration variables
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
14e0668fa5c67fe3c44f2abd39f29a6f18272f11zhongyan gu - Sun Microsystems - Beijing China#define DEFAULT_GHD_TIMEOUT 50000 /* Amount of time to poll(50ms) */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
14e0668fa5c67fe3c44f2abd39f29a6f18272f11zhongyan gu - Sun Microsystems - Beijing Chinaulong_t ghd_tran_abort_timeout = DEFAULT_GHD_TIMEOUT;
14e0668fa5c67fe3c44f2abd39f29a6f18272f11zhongyan gu - Sun Microsystems - Beijing Chinaulong_t ghd_tran_abort_lun_timeout = DEFAULT_GHD_TIMEOUT;
14e0668fa5c67fe3c44f2abd39f29a6f18272f11zhongyan gu - Sun Microsystems - Beijing Chinaulong_t ghd_tran_reset_target_timeout = DEFAULT_GHD_TIMEOUT;
14e0668fa5c67fe3c44f2abd39f29a6f18272f11zhongyan gu - Sun Microsystems - Beijing Chinaulong_t ghd_tran_reset_bus_timeout = DEFAULT_GHD_TIMEOUT;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfghd_doneq_init(ccc_t *cccp)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_iblock_cookie_t iblock;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf L2_INIT(&cccp->ccc_doneq);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf cccp->ccc_hba_pollmode = TRUE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ddi_add_softintr(cccp->ccc_hba_dip, DDI_SOFTINT_LOW,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf &cccp->ccc_doneq_softid, &iblock, NULL,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ghd_doneq_process, (caddr_t)cccp) != DDI_SUCCESS) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf GDBG_ERROR(("ghd_doneq_init: add softintr failed cccp 0x%p\n",
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf (void *)cccp));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_init(&cccp->ccc_doneq_mutex, NULL, MUTEX_DRIVER, iblock);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ghd_doneq_pollmode_exit(cccp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (TRUE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * ghd_complete():
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * The HBA driver calls this entry point when it's completely
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * done processing a request.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * See the GHD_COMPLETE_INLINE() macro in ghd.h for the actual code.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfvoid
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfghd_complete(ccc_t *cccp, gcmd_t *gcmdp)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ASSERT(mutex_owned(&cccp->ccc_hba_mutex));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf GHD_COMPLETE_INLINE(cccp, gcmdp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * ghd_doneq_put_head():
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Mark the request done and prepend it to the doneq.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * See the GHD_DONEQ_PUT_HEAD_INLINE() macros in ghd.h for
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * the actual code.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfvoid
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfghd_doneq_put_head(ccc_t *cccp, gcmd_t *gcmdp)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf GHD_DONEQ_PUT_HEAD_INLINE(cccp, gcmdp)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * ghd_doneq_put_tail():
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Mark the request done and append it to the doneq.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * See the GHD_DONEQ_PUT_TAIL_INLINE() macros in ghd.h for
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * the actual code.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfvoid
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfghd_doneq_put_tail(ccc_t *cccp, gcmd_t *gcmdp)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf GHD_DONEQ_PUT_TAIL_INLINE(cccp, gcmdp)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic gcmd_t *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfghd_doneq_get(ccc_t *cccp)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf kmutex_t *doneq_mutexp = &cccp->ccc_doneq_mutex;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gcmd_t *gcmdp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_enter(doneq_mutexp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if ((gcmdp = L2_next(&cccp->ccc_doneq)) != NULL)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf L2_delete(&gcmdp->cmd_q);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_exit(doneq_mutexp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (gcmdp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic void
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfghd_doneq_pollmode_enter(ccc_t *cccp)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf kmutex_t *doneq_mutexp = &cccp->ccc_doneq_mutex;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_enter(doneq_mutexp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf cccp->ccc_hba_pollmode = TRUE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_exit(doneq_mutexp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic void
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfghd_doneq_pollmode_exit(ccc_t *cccp)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf kmutex_t *doneq_mutexp = &cccp->ccc_doneq_mutex;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_enter(doneq_mutexp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf cccp->ccc_hba_pollmode = FALSE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_exit(doneq_mutexp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* trigger software interrupt for the completion callbacks */
1dc8bc23152a02d4586ec1fd8612f7e8f57ceb42zk if (!L2_EMPTY(&cccp->ccc_doneq)) {
1dc8bc23152a02d4586ec1fd8612f7e8f57ceb42zk /*
1dc8bc23152a02d4586ec1fd8612f7e8f57ceb42zk * If we are panicking we should just call the completion
1dc8bc23152a02d4586ec1fd8612f7e8f57ceb42zk * function directly as we can not use soft interrupts
1dc8bc23152a02d4586ec1fd8612f7e8f57ceb42zk * or timeouts during panic.
1dc8bc23152a02d4586ec1fd8612f7e8f57ceb42zk */
1dc8bc23152a02d4586ec1fd8612f7e8f57ceb42zk if (!ddi_in_panic())
1dc8bc23152a02d4586ec1fd8612f7e8f57ceb42zk ddi_trigger_softintr(cccp->ccc_doneq_softid);
1dc8bc23152a02d4586ec1fd8612f7e8f57ceb42zk else
1dc8bc23152a02d4586ec1fd8612f7e8f57ceb42zk (void) ghd_doneq_process((caddr_t)cccp);
1dc8bc23152a02d4586ec1fd8612f7e8f57ceb42zk }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/* ***************************************************************** */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * ghd_doneq_process()
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * This function is called directly from the software interrupt
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * handler.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * The doneq is protected by a separate mutex than the
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * HBA mutex in order to avoid mutex contention on MP systems.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic uint_t
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfghd_doneq_process(caddr_t arg)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ccc_t *cccp = (ccc_t *)arg;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf kmutex_t *doneq_mutexp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gcmd_t *gcmdp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int rc = DDI_INTR_UNCLAIMED;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf doneq_mutexp = &cccp->ccc_doneq_mutex;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf for (;;) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_enter(doneq_mutexp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* skip if FLAG_NOINTR request in progress */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (cccp->ccc_hba_pollmode)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* pop the first one from the done Q */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if ((gcmdp = L2_next(&cccp->ccc_doneq)) == NULL)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf L2_delete(&gcmdp->cmd_q);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (gcmdp->cmd_flags & GCMDFLG_RESET_NOTIFY) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* special request; processed here and discarded */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ghd_do_reset_notify_callbacks(cccp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ghd_gcmd_free(gcmdp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_exit(doneq_mutexp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf continue;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * drop the mutex since completion
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * function can re-enter the top half via
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * ghd_transport()
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_exit(doneq_mutexp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gcmdp->cmd_state = GCMD_STATE_IDLE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf (*cccp->ccc_hba_complete)(cccp->ccc_hba_handle, gcmdp, TRUE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#ifdef notyet
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* I don't think this is ever necessary */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rc = DDI_INTR_CLAIMED;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#endif
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_exit(doneq_mutexp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (rc);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic void
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfghd_do_reset_notify_callbacks(ccc_t *cccp)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ghd_reset_notify_list_t *rnp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf L2el_t *rnl = &cccp->ccc_reset_notify_list;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ASSERT(mutex_owned(&cccp->ccc_doneq_mutex));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* lock the reset notify list while we operate on it */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_enter(&cccp->ccc_reset_notify_mutex);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf for (rnp = (ghd_reset_notify_list_t *)L2_next(rnl);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rnp != NULL;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rnp = (ghd_reset_notify_list_t *)L2_next(&rnp->l2_link)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* don't call if HBA driver didn't set it */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (cccp->ccc_hba_reset_notify_callback) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf (*cccp->ccc_hba_reset_notify_callback)(rnp->gtgtp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rnp->callback, rnp->arg);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_exit(&cccp->ccc_reset_notify_mutex);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/* ***************************************************************** */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * ghd_register()
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Do the usual interrupt handler setup stuff.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Also, set up three mutexes: the wait queue mutex, the HBA
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * mutex, and the done queue mutex. The permitted locking
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * orders are:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * 1. enter(waitq)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * 2. enter(activel)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * 3. enter(doneq)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * 4. enter(HBA) then enter(activel)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * 5. enter(HBA) then enter(doneq)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * 6. enter(HBA) then enter(waitq)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * 7. enter(waitq) then tryenter(HBA)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Note: cases 6 and 7 won't deadlock because case 7 is always
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * mutex_tryenter() call.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfint
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfghd_register(char *labelp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ccc_t *cccp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf dev_info_t *dip,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int inumber,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf void *hba_handle,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int (*ccballoc)(gtgt_t *, gcmd_t *, int, int, int, int),
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf void (*ccbfree)(gcmd_t *),
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf void (*sg_func)(gcmd_t *, ddi_dma_cookie_t *, int, int),
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int (*hba_start)(void *, gcmd_t *),
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf void (*hba_complete)(void *, gcmd_t *, int),
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uint_t (*int_handler)(caddr_t),
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int (*get_status)(void *, void *),
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf void (*process_intr)(void *, void *),
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int (*timeout_func)(void *, gcmd_t *, gtgt_t *, gact_t, int),
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf tmr_t *tmrp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf void (*hba_reset_notify_callback)(gtgt_t *,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf void (*)(caddr_t), caddr_t))
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf cccp->ccc_label = labelp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf cccp->ccc_hba_dip = dip;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf cccp->ccc_ccballoc = ccballoc;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf cccp->ccc_ccbfree = ccbfree;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf cccp->ccc_sg_func = sg_func;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf cccp->ccc_hba_start = hba_start;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf cccp->ccc_hba_complete = hba_complete;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf cccp->ccc_process_intr = process_intr;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf cccp->ccc_get_status = get_status;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf cccp->ccc_hba_handle = hba_handle;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf cccp->ccc_hba_reset_notify_callback = hba_reset_notify_callback;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* initialize the HBA's list headers */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf CCCP_INIT(cccp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
9f49ae270d37efd5c5270cb8046b4229b5380021mlf if (ddi_get_iblock_cookie(dip, inumber, &cccp->ccc_iblock)
9f49ae270d37efd5c5270cb8046b4229b5380021mlf != DDI_SUCCESS) {
9f49ae270d37efd5c5270cb8046b4229b5380021mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
9f49ae270d37efd5c5270cb8046b4229b5380021mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_init(&cccp->ccc_hba_mutex, NULL, MUTEX_DRIVER, cccp->ccc_iblock);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
9f49ae270d37efd5c5270cb8046b4229b5380021mlf mutex_init(&cccp->ccc_waitq_mutex, NULL, MUTEX_DRIVER,
9f49ae270d37efd5c5270cb8046b4229b5380021mlf cccp->ccc_iblock);
9f49ae270d37efd5c5270cb8046b4229b5380021mlf
9f49ae270d37efd5c5270cb8046b4229b5380021mlf mutex_init(&cccp->ccc_reset_notify_mutex, NULL, MUTEX_DRIVER,
9f49ae270d37efd5c5270cb8046b4229b5380021mlf cccp->ccc_iblock);
9f49ae270d37efd5c5270cb8046b4229b5380021mlf
9f49ae270d37efd5c5270cb8046b4229b5380021mlf /* Establish interrupt handler */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ddi_add_intr(dip, inumber, &cccp->ccc_iblock, NULL,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int_handler, (caddr_t)hba_handle) != DDI_SUCCESS) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_destroy(&cccp->ccc_hba_mutex);
9f49ae270d37efd5c5270cb8046b4229b5380021mlf mutex_destroy(&cccp->ccc_waitq_mutex);
9f49ae270d37efd5c5270cb8046b4229b5380021mlf mutex_destroy(&cccp->ccc_reset_notify_mutex);
9f49ae270d37efd5c5270cb8046b4229b5380021mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ghd_timer_attach(cccp, tmrp, timeout_func) == FALSE) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_remove_intr(cccp->ccc_hba_dip, 0, cccp->ccc_iblock);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_destroy(&cccp->ccc_hba_mutex);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_destroy(&cccp->ccc_waitq_mutex);
9f49ae270d37efd5c5270cb8046b4229b5380021mlf mutex_destroy(&cccp->ccc_reset_notify_mutex);
9f49ae270d37efd5c5270cb8046b4229b5380021mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ghd_doneq_init(cccp)) {
9f49ae270d37efd5c5270cb8046b4229b5380021mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (TRUE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
9f49ae270d37efd5c5270cb8046b4229b5380021mlf /*
9f49ae270d37efd5c5270cb8046b4229b5380021mlf * ghd_doneq_init() returned error:
9f49ae270d37efd5c5270cb8046b4229b5380021mlf */
9f49ae270d37efd5c5270cb8046b4229b5380021mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ghd_timer_detach(cccp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_remove_intr(cccp->ccc_hba_dip, 0, cccp->ccc_iblock);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_destroy(&cccp->ccc_hba_mutex);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_destroy(&cccp->ccc_waitq_mutex);
9f49ae270d37efd5c5270cb8046b4229b5380021mlf mutex_destroy(&cccp->ccc_reset_notify_mutex);
9f49ae270d37efd5c5270cb8046b4229b5380021mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfvoid
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfghd_unregister(ccc_t *cccp)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ghd_timer_detach(cccp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_remove_intr(cccp->ccc_hba_dip, 0, cccp->ccc_iblock);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_remove_softintr(cccp->ccc_doneq_softid);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_destroy(&cccp->ccc_hba_mutex);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_destroy(&cccp->ccc_waitq_mutex);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_destroy(&cccp->ccc_doneq_mutex);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfint
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfghd_intr(ccc_t *cccp, void *intr_status)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int (*statfunc)(void *, void *) = cccp->ccc_get_status;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf void (*processfunc)(void *, void *) = cccp->ccc_process_intr;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf kmutex_t *waitq_mutexp = &cccp->ccc_waitq_mutex;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf kmutex_t *hba_mutexp = &cccp->ccc_hba_mutex;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf void *handle = cccp->ccc_hba_handle;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int rc = DDI_INTR_UNCLAIMED;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int more;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_enter(hba_mutexp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf GDBG_INTR(("ghd_intr(): cccp=0x%p status=0x%p\n",
903a11ebdc8df157c4700150f41f1f262f4a8ae8rh (void *)cccp, intr_status));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf for (;;) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf more = FALSE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* process the interrupt status */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf while ((*statfunc)(handle, intr_status)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf (*processfunc)(handle, intr_status);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rc = DDI_INTR_CLAIMED;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf more = TRUE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_enter(waitq_mutexp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ghd_waitq_process_and_mutex_hold(cccp)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ASSERT(mutex_owned(hba_mutexp));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_exit(waitq_mutexp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf continue;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (more) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_exit(waitq_mutexp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf continue;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf GDBG_INTR(("ghd_intr(): done cccp=0x%p status=0x%p rc %d\n",
903a11ebdc8df157c4700150f41f1f262f4a8ae8rh (void *)cccp, intr_status, rc));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Release the mutexes in the opposite order that they
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * were acquired to prevent requests queued by
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * ghd_transport() from getting hung up in the wait queue.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_exit(hba_mutexp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_exit(waitq_mutexp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (rc);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfstatic int
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfghd_poll(ccc_t *cccp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gpoll_t polltype,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ulong_t polltime,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gcmd_t *poll_gcmdp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gtgt_t *gtgtp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf void *intr_status)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gcmd_t *gcmdp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf L2el_t gcmd_hold_queue;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int got_it = FALSE;
14e0668fa5c67fe3c44f2abd39f29a6f18272f11zhongyan gu - Sun Microsystems - Beijing China clock_t poll_lbolt;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf clock_t start_lbolt;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf clock_t current_lbolt;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ASSERT(mutex_owned(&cccp->ccc_hba_mutex));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf L2_INIT(&gcmd_hold_queue);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* Que hora es? */
14e0668fa5c67fe3c44f2abd39f29a6f18272f11zhongyan gu - Sun Microsystems - Beijing China poll_lbolt = drv_usectohz((clock_t)polltime);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf start_lbolt = ddi_get_lbolt();
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* unqueue and save all CMD/CCBs until I find the right one */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf while (!got_it) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* Give up yet? */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf current_lbolt = ddi_get_lbolt();
14e0668fa5c67fe3c44f2abd39f29a6f18272f11zhongyan gu - Sun Microsystems - Beijing China if (poll_lbolt && (current_lbolt - start_lbolt >= poll_lbolt))
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * delay 1 msec each time around the loop (this is an
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * arbitrary delay value, any value should work) except
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * zero because some devices don't like being polled too
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * fast and it saturates the bus on an MP system.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf drv_usecwait(1000);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * check for any new device status
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if ((*cccp->ccc_get_status)(cccp->ccc_hba_handle, intr_status))
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf (*cccp->ccc_process_intr)(cccp->ccc_hba_handle,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf intr_status);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * If something completed then try to start the
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * next request from the wait queue. Don't release
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * the HBA mutex because I don't know whether my
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * request(s) is/are on the done queue yet.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_enter(&cccp->ccc_waitq_mutex);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf (void) ghd_waitq_process_and_mutex_hold(cccp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_exit(&cccp->ccc_waitq_mutex);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Process the first of any timed-out requests.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ghd_timer_poll(cccp, GHD_TIMER_POLL_ONE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Unqueue all the completed requests, look for mine
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf while (gcmdp = ghd_doneq_get(cccp)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * If we got one and it's my request, then
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * we're done.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (gcmdp == poll_gcmdp) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf poll_gcmdp->cmd_state = GCMD_STATE_IDLE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf got_it = TRUE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf continue;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* fifo queue the other cmds on my local list */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf L2_add(&gcmd_hold_queue, &gcmdp->cmd_q, gcmdp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Check whether we're done yet.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf switch (polltype) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case GHD_POLL_DEVICE:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * wait for everything queued on a specific device
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (GDEV_NACTIVE(gtgtp->gt_gdevp) == 0)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf got_it = TRUE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case GHD_POLL_ALL:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * if waiting for all outstanding requests and
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * if active list is now empty then exit
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (GHBA_NACTIVE(cccp) == 0)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf got_it = TRUE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case GHD_POLL_REQUEST:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (L2_EMPTY(&gcmd_hold_queue)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ASSERT(!mutex_owned(&cccp->ccc_waitq_mutex));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ASSERT(mutex_owned(&cccp->ccc_hba_mutex));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (got_it);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * copy the local gcmd_hold_queue back to the doneq so
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * that the order of completion callbacks is preserved
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf while (gcmdp = L2_next(&gcmd_hold_queue)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf L2_delete(&gcmdp->cmd_q);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf GHD_DONEQ_PUT_TAIL(cccp, gcmdp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ASSERT(!mutex_owned(&cccp->ccc_waitq_mutex));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ASSERT(mutex_owned(&cccp->ccc_hba_mutex));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (got_it);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * ghd_tran_abort()
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Abort specific command on a target.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfint
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfghd_tran_abort(ccc_t *cccp, gcmd_t *gcmdp, gtgt_t *gtgtp, void *intr_status)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gact_t action;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int rc;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * call the driver's abort_cmd function
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_enter(&cccp->ccc_hba_mutex);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ghd_doneq_pollmode_enter(cccp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf switch (gcmdp->cmd_state) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case GCMD_STATE_WAITQ:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* not yet started */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf action = GACTION_EARLY_ABORT;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case GCMD_STATE_ACTIVE:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* in progress */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf action = GACTION_ABORT_CMD;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf default:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* everything else, probably already being aborted */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rc = FALSE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf goto exit;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* stop the timer and remove it from the active list */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf GHD_TIMER_STOP(cccp, gcmdp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* start a new timer and send out the abort command */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ghd_timer_newstate(cccp, gcmdp, gtgtp, action, GHD_TGTREQ);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* wait for the abort to complete */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (rc = ghd_poll(cccp, GHD_POLL_REQUEST, ghd_tran_abort_timeout,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gcmdp, gtgtp, intr_status)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gcmdp->cmd_state = GCMD_STATE_DONEQ;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf GHD_DONEQ_PUT_TAIL(cccp, gcmdp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfexit:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ghd_doneq_pollmode_exit(cccp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_enter(&cccp->ccc_waitq_mutex);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ghd_waitq_process_and_mutex_exit(cccp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (rc);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * ghd_tran_abort_lun()
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Abort all commands on a specific target.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfint
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfghd_tran_abort_lun(ccc_t *cccp, gtgt_t *gtgtp, void *intr_status)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int rc;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * call the HBA driver's abort_device function
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_enter(&cccp->ccc_hba_mutex);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ghd_doneq_pollmode_enter(cccp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* send out the abort device request */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ghd_timer_newstate(cccp, NULL, gtgtp, GACTION_ABORT_DEV, GHD_TGTREQ);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* wait for the device to go idle */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rc = ghd_poll(cccp, GHD_POLL_DEVICE, ghd_tran_abort_lun_timeout,
1dc8bc23152a02d4586ec1fd8612f7e8f57ceb42zk NULL, gtgtp, intr_status);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ghd_doneq_pollmode_exit(cccp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_enter(&cccp->ccc_waitq_mutex);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ghd_waitq_process_and_mutex_exit(cccp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (rc);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * ghd_tran_reset_target()
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * reset the target device
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfint
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfghd_tran_reset_target(ccc_t *cccp, gtgt_t *gtgtp, void *intr_status)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int rc = TRUE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_enter(&cccp->ccc_hba_mutex);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ghd_doneq_pollmode_enter(cccp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* send out the device reset request */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ghd_timer_newstate(cccp, NULL, gtgtp, GACTION_RESET_TARGET, GHD_TGTREQ);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* wait for the device to reset */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rc = ghd_poll(cccp, GHD_POLL_DEVICE, ghd_tran_reset_target_timeout,
1dc8bc23152a02d4586ec1fd8612f7e8f57ceb42zk NULL, gtgtp, intr_status);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ghd_doneq_pollmode_exit(cccp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_enter(&cccp->ccc_waitq_mutex);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ghd_waitq_process_and_mutex_exit(cccp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (rc);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * ghd_tran_reset_bus()
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * reset the scsi bus
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfint
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfghd_tran_reset_bus(ccc_t *cccp, gtgt_t *gtgtp, void *intr_status)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int rc;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_enter(&cccp->ccc_hba_mutex);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ghd_doneq_pollmode_enter(cccp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* send out the bus reset request */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ghd_timer_newstate(cccp, NULL, gtgtp, GACTION_RESET_BUS, GHD_TGTREQ);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Wait for all active requests on this HBA to complete
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rc = ghd_poll(cccp, GHD_POLL_ALL, ghd_tran_reset_bus_timeout,
1dc8bc23152a02d4586ec1fd8612f7e8f57ceb42zk NULL, NULL, intr_status);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ghd_doneq_pollmode_exit(cccp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_enter(&cccp->ccc_waitq_mutex);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ghd_waitq_process_and_mutex_exit(cccp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (rc);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfint
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfghd_transport(ccc_t *cccp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gcmd_t *gcmdp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gtgt_t *gtgtp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ulong_t timeout,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int polled,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf void *intr_status)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gdev_t *gdevp = gtgtp->gt_gdevp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ASSERT(!mutex_owned(&cccp->ccc_hba_mutex));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ASSERT(!mutex_owned(&cccp->ccc_waitq_mutex));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (polled) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Grab the HBA mutex so no other requests are started
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * until after this one completes.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_enter(&cccp->ccc_hba_mutex);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf GDBG_START(("ghd_transport: polled"
1dc8bc23152a02d4586ec1fd8612f7e8f57ceb42zk " cccp 0x%p gdevp 0x%p gtgtp 0x%p gcmdp 0x%p\n",
903a11ebdc8df157c4700150f41f1f262f4a8ae8rh (void *)cccp, (void *)gdevp, (void *)gtgtp, (void *)gcmdp));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Lock the doneq so no other thread flushes the Q.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ghd_doneq_pollmode_enter(cccp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#if defined(GHD_DEBUG) || defined(__lint)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf else {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf GDBG_START(("ghd_transport: non-polled"
1dc8bc23152a02d4586ec1fd8612f7e8f57ceb42zk " cccp 0x%p gdevp 0x%p gtgtp 0x%p gcmdp 0x%p\n",
903a11ebdc8df157c4700150f41f1f262f4a8ae8rh (void *)cccp, (void *)gdevp, (void *)gtgtp, (void *)gcmdp));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#endif
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * add this request to the tail of the waitq
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gcmdp->cmd_waitq_level = 1;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_enter(&cccp->ccc_waitq_mutex);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf L2_add(&GDEV_QHEAD(gdevp), &gcmdp->cmd_q, gcmdp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Add this request to the packet timer active list and start its
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * abort timer.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gcmdp->cmd_state = GCMD_STATE_WAITQ;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ghd_timer_start(cccp, gcmdp, timeout);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Check the device wait queue throttle and perhaps move
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * some requests to the end of the HBA wait queue.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ghd_waitq_shuffle_up(cccp, gdevp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (!polled) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * See if the HBA mutex is available but use the
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * tryenter so I don't deadlock.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (!mutex_tryenter(&cccp->ccc_hba_mutex)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* The HBA mutex isn't available */
903a11ebdc8df157c4700150f41f1f262f4a8ae8rh GDBG_START(("ghd_transport: !mutex cccp 0x%p\n",
903a11ebdc8df157c4700150f41f1f262f4a8ae8rh (void *)cccp));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_exit(&cccp->ccc_waitq_mutex);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (TRAN_ACCEPT);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
903a11ebdc8df157c4700150f41f1f262f4a8ae8rh GDBG_START(("ghd_transport: got mutex cccp 0x%p\n",
903a11ebdc8df157c4700150f41f1f262f4a8ae8rh (void *)cccp));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * start as many requests as possible from the head
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * of the HBA wait queue
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ghd_waitq_process_and_mutex_exit(cccp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ASSERT(!mutex_owned(&cccp->ccc_hba_mutex));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ASSERT(!mutex_owned(&cccp->ccc_waitq_mutex));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (TRAN_ACCEPT);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * If polled mode (FLAG_NOINTR specified in scsi_pkt flags),
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * then ghd_poll() waits until the request completes or times out
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * before returning.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_exit(&cccp->ccc_waitq_mutex);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf (void) ghd_poll(cccp, GHD_POLL_REQUEST, 0, gcmdp, gtgtp, intr_status);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ghd_doneq_pollmode_exit(cccp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_enter(&cccp->ccc_waitq_mutex);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ghd_waitq_process_and_mutex_exit(cccp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* call HBA's completion function but don't do callback to target */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf (*cccp->ccc_hba_complete)(cccp->ccc_hba_handle, gcmdp, FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
903a11ebdc8df157c4700150f41f1f262f4a8ae8rh GDBG_START(("ghd_transport: polled done cccp 0x%p\n", (void *)cccp));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (TRAN_ACCEPT);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfint ghd_reset_notify(ccc_t *cccp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gtgt_t *gtgtp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int flag,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf void (*callback)(caddr_t),
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf caddr_t arg)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ghd_reset_notify_list_t *rnp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int rc = FALSE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf switch (flag) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case SCSI_RESET_NOTIFY:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rnp = (ghd_reset_notify_list_t *)kmem_zalloc(sizeof (*rnp),
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf KM_SLEEP);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rnp->gtgtp = gtgtp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rnp->callback = callback;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rnp->arg = arg;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_enter(&cccp->ccc_reset_notify_mutex);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf L2_add(&cccp->ccc_reset_notify_list, &rnp->l2_link,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf (void *)rnp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_exit(&cccp->ccc_reset_notify_mutex);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rc = TRUE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case SCSI_RESET_CANCEL:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_enter(&cccp->ccc_reset_notify_mutex);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf for (rnp = (ghd_reset_notify_list_t *)
1dc8bc23152a02d4586ec1fd8612f7e8f57ceb42zk L2_next(&cccp->ccc_reset_notify_list);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rnp != NULL;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rnp = (ghd_reset_notify_list_t *)L2_next(&rnp->l2_link)) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (rnp->gtgtp == gtgtp &&
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rnp->callback == callback &&
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rnp->arg == arg) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf L2_delete(&rnp->l2_link);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf kmem_free(rnp, sizeof (*rnp));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rc = TRUE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_exit(&cccp->ccc_reset_notify_mutex);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf default:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf rc = FALSE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (rc);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * freeze the HBA waitq output (see ghd_waitq_process_and_mutex_hold),
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * presumably because of a SCSI reset, for delay milliseconds.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfvoid
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfghd_freeze_waitq(ccc_t *cccp, int delay)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ASSERT(mutex_owned(&cccp->ccc_hba_mutex));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* freeze the waitq for delay milliseconds */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_enter(&cccp->ccc_waitq_mutex);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf cccp->ccc_waitq_freezetime = ddi_get_lbolt();
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf cccp->ccc_waitq_freezedelay = delay;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf cccp->ccc_waitq_frozen = 1;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_exit(&cccp->ccc_waitq_mutex);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfvoid
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfghd_queue_hold(ccc_t *cccp)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ASSERT(mutex_owned(&cccp->ccc_hba_mutex));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_enter(&cccp->ccc_waitq_mutex);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf cccp->ccc_waitq_held = 1;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_exit(&cccp->ccc_waitq_mutex);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfvoid
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfghd_queue_unhold(ccc_t *cccp)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ASSERT(mutex_owned(&cccp->ccc_hba_mutex));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_enter(&cccp->ccc_waitq_mutex);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf cccp->ccc_waitq_held = 0;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf mutex_exit(&cccp->ccc_waitq_mutex);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Trigger previously-registered reset notifications
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfvoid
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfghd_trigger_reset_notify(ccc_t *cccp)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gcmd_t *gcmdp;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ASSERT(mutex_owned(&cccp->ccc_hba_mutex));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* create magic doneq entry */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gcmdp = ghd_gcmd_alloc((gtgt_t *)NULL, 0, TRUE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gcmdp->cmd_flags = GCMDFLG_RESET_NOTIFY;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* put at head of doneq so it's processed ASAP */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf GHD_DONEQ_PUT_HEAD(cccp, gcmdp);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}