fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * CDDL HEADER START
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The contents of this file are subject to the terms of the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Common Development and Distribution License (the "License").
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * You may not use this file except in compliance with the License.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * or http://www.opensolaris.org/os/licensing.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * See the License for the specific language governing permissions
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * and limitations under the License.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * When distributing Covered Code, include this CDDL HEADER in each
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If applicable, add the following below this CDDL HEADER, with the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner]
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * CDDL HEADER END
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Copyright 2000 by Cisco Systems, Inc. All rights reserved.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Use is subject to license terms.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iSCSI Software Initiator
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include "iscsi.h" /* main header */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic void iscsi_enqueue_cmd_tail(iscsi_cmd_t **head, iscsi_cmd_t **tail,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_cmd_t *icmdp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * +--------------------------------------------------------------------+
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * | public queue functions |
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * +--------------------------------------------------------------------+
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Public queue locking rules. When acquiring multiple queue locks
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * they MUST always be acquired in a forward order. If a lock is
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * aquire in a reverese order it could lead to a deadlock panic.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The forward order of locking is described as shown below.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * pending -> cmdsn -> active -> completion
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If a cmd_mutex is held, it is either held after the pending queue
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * mutex or after the active queue mutex.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_init_queue - used to initialize iscsi queue
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_init_queue(iscsi_queue_t *queue)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(queue != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte queue->head = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte queue->tail = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte queue->count = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_init(&queue->mutex, NULL, MUTEX_DRIVER, NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_destroy_queue - used to terminate iscsi queue
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_destroy_queue(iscsi_queue_t *queue)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(queue != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(queue->count == 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_destroy(&queue->mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_enqueue_pending_cmd - used to add a command in a pending queue
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_enqueue_pending_cmd(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(isp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icmdp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(mutex_owned(&isp->sess_queue_pending.mutex));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_state = ISCSI_CMD_STATE_PENDING;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_enqueue_cmd_tail(&isp->sess_queue_pending.head,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte &isp->sess_queue_pending.tail, icmdp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte isp->sess_queue_pending.count++;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte KSTAT_WAITQ_ENTER(isp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_enqueue_cmd_head(&isp->sess_queue_pending.head,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte &isp->sess_queue_pending.tail, icmdp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte isp->sess_queue_pending.count++;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte KSTAT_WAITQ_ENTER(isp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_sess_redrive_io(isp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_dequeue_pending_cmd - used to remove a command from a pending queue
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_dequeue_pending_cmd(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_status_t rval = ISCSI_STATUS_SUCCESS;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(isp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icmdp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(mutex_owned(&isp->sess_queue_pending.mutex));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte rval = iscsi_dequeue_cmd(&isp->sess_queue_pending.head,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte &isp->sess_queue_pending.tail, icmdp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (ISCSI_SUCCESS(rval)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte isp->sess_queue_pending.count--;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (((kstat_io_t *)(&isp->stats.ks_io_data))->wcnt) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte KSTAT_WAITQ_EXIT(isp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmn_err(CE_WARN,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "kstat wcnt == 0 when exiting waitq,"
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte " please check\n");
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(FALSE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_enqueue_active_cmd - used to add a command in a active queue
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * This interface attempts to keep newer items are on the tail,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * older items are on the head. But, Do not assume that the list
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * is completely sorted. If someone attempts to enqueue an item
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * that already has cmd_lbolt_active assigned and is older than
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the current head, otherwise add to the tail.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_enqueue_active_cmd(iscsi_conn_t *icp, iscsi_cmd_t *icmdp)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_sess_t *isp = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icmdp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte isp = icp->conn_sess;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(isp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * When receiving data associated to a command it
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * is temporarily removed from the active queue.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Then once the data receive is completed it may
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * be returned to the active queue. If this was
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * an aborting command we need to preserve its
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * state.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (icmdp->cmd_state != ISCSI_CMD_STATE_ABORTING) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_state = ISCSI_CMD_STATE_ACTIVE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * It's possible that this is not a newly issued icmdp - we may
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * have tried to abort it but the abort failed or was rejected
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * and we are putting it back on the active list. So if it is older
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * than the head of the active queue, put it at the head to keep
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the CommandTimeout valid.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (icmdp->cmd_lbolt_active == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_lbolt_active = ddi_get_lbolt();
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_enqueue_cmd_tail(&icp->conn_queue_active.head,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte &icp->conn_queue_active.tail, icmdp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if ((icp->conn_queue_active.head != NULL) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (icmdp->cmd_lbolt_active <
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icp->conn_queue_active.head->cmd_lbolt_active)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_enqueue_cmd_head(&icp->conn_queue_active.head,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte &icp->conn_queue_active.tail, icmdp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_enqueue_cmd_tail(&icp->conn_queue_active.head,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte &icp->conn_queue_active.tail, icmdp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icp->conn_queue_active.count++;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte KSTAT_RUNQ_ENTER(isp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_dequeue_active_cmd - used to remove a command from a active queue
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_dequeue_active_cmd(iscsi_conn_t *icp, iscsi_cmd_t *icmdp)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_status_t rval = ISCSI_STATUS_SUCCESS;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_sess_t *isp = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icmdp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte isp = icp->conn_sess;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(isp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(mutex_owned(&icp->conn_queue_active.mutex));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte rval = iscsi_dequeue_cmd(&icp->conn_queue_active.head,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte &icp->conn_queue_active.tail, icmdp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (ISCSI_SUCCESS(rval)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icp->conn_queue_active.count--;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (((kstat_io_t *)(&isp->stats.ks_io_data))->rcnt) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte KSTAT_RUNQ_EXIT(isp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmn_err(CE_WARN,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "kstat rcnt == 0 when exiting runq,"
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte " please check\n");
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(FALSE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap/*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * iscsi_enqueue_idm_aborting_cmd - used to add a command to the queue
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * representing command waiting for a callback from IDM for aborting
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap *
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Not sorted
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapvoid
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiscsi_enqueue_idm_aborting_cmd(iscsi_conn_t *icp, iscsi_cmd_t *icmdp)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_sess_t *isp = NULL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(icp != NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(icmdp != NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap isp = icp->conn_sess;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(isp != NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(mutex_owned(&icp->conn_queue_idm_aborting.mutex));
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icmdp->cmd_state = ISCSI_CMD_STATE_IDM_ABORTING;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icmdp->cmd_lbolt_idm_aborting = ddi_get_lbolt();
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_enqueue_cmd_tail(&icp->conn_queue_idm_aborting.head,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap &icp->conn_queue_idm_aborting.tail, icmdp);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icp->conn_queue_idm_aborting.count++;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap/*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * iscsi_dequeue_idm_aborting_cmd - used to remove a command from the queue
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * representing commands waiting for a callback from IDM for aborting.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapvoid
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiscsi_dequeue_idm_aborting_cmd(iscsi_conn_t *icp, iscsi_cmd_t *icmdp)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_sess_t *isp = NULL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(icp != NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(icmdp != NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap isp = icp->conn_sess;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(isp != NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(mutex_owned(&icp->conn_queue_idm_aborting.mutex));
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (void) iscsi_dequeue_cmd(&icp->conn_queue_idm_aborting.head,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap &icp->conn_queue_idm_aborting.tail, icmdp);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icp->conn_queue_idm_aborting.count--;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_enqueue_completed_cmd - used to add a command in completion queue
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_enqueue_completed_cmd(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(isp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icmdp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&isp->sess_queue_completion.mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (icmdp->cmd_state != ISCSI_CMD_STATE_COMPLETED) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_state = ISCSI_CMD_STATE_COMPLETED;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * This command has already been completed, probably
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * through the abort code path. It should be in
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the process of being returned to to the upper
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * layers, so do nothing.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&isp->sess_queue_completion.mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_enqueue_cmd_tail(&isp->sess_queue_completion.head,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte &isp->sess_queue_completion.tail, icmdp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ++isp->sess_queue_completion.count;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&isp->sess_queue_completion.mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
49311b3511690f5b23558b0fba067bc8067c7a87Jack Meng (void) iscsi_thread_send_wakeup(isp->sess_ic_thread);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_move_queue - used to move the whole contents of a queue
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The source queue has to be initialized. Its mutex is entered before
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * doing the actual move. The destination queue should be initialized.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * This function is intended to move a queue located in a shared location
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * into local space. No mutex is needed for the destination queue.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_move_queue(
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_queue_t *src_queue,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_queue_t *dst_queue
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(src_queue != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(dst_queue != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&src_queue->mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dst_queue->count = src_queue->count;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dst_queue->head = src_queue->head;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dst_queue->tail = src_queue->tail;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte src_queue->count = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte src_queue->head = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte src_queue->tail = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&src_queue->mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * +--------------------------------------------------------------------+
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * | private functions |
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * +--------------------------------------------------------------------+
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_dequeue_cmd - used to remove a command from a queue
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_status_t
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_dequeue_cmd(iscsi_cmd_t **head, iscsi_cmd_t **tail, iscsi_cmd_t *icmdp)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#ifdef DEBUG
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_cmd_t *tp = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#endif
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(head != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(tail != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icmdp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (*head == NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* empty queue, error */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if (*head == *tail) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* one element queue */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (*head == icmdp) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *head = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *tail = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* multi-element queue */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (*head == icmdp) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* at the head */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *head = icmdp->cmd_next;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (*head)->cmd_prev = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if (*tail == icmdp) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *tail = icmdp->cmd_prev;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (*tail)->cmd_next = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#ifdef DEBUG
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* in the middle? */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (tp = (*head)->cmd_next; (tp != NULL) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (tp != icmdp); tp = tp->cmd_next)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (tp == NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* not found */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#endif
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (icmdp->cmd_prev == NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_prev->cmd_next = icmdp->cmd_next;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (icmdp->cmd_next == NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_next->cmd_prev = icmdp->cmd_prev;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* icmdp no longer in the queue */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_prev = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_next = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (ISCSI_STATUS_SUCCESS);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_enqueue_cmd_head - used to add a command to the head of a queue
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_enqueue_cmd_head(iscsi_cmd_t **head, iscsi_cmd_t **tail,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_cmd_t *icmdp)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icmdp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icmdp->cmd_next == NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icmdp->cmd_prev == NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icmdp != *head);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icmdp != *tail);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (*head == NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* empty queue */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *head = *tail = icmdp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_prev = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_next = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* non-empty queue */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_next = *head;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_prev = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (*head)->cmd_prev = icmdp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *head = icmdp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_enqueue_cmd_tail - used to add a command to the tail of a queue
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic void
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_enqueue_cmd_tail(iscsi_cmd_t **head, iscsi_cmd_t **tail,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_cmd_t *icmdp)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icmdp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icmdp->cmd_next == NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icmdp->cmd_prev == NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icmdp != *head);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icmdp != *tail);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (*head == NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* empty queue */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *head = *tail = icmdp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_prev = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_next = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* non-empty queue */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_next = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_prev = *tail;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (*tail)->cmd_next = icmdp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *tail = icmdp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}