blob: 5da034f61afa69b41659b30eb21050ae42fdc03a [file] [log] [blame]
/******************************************************************************
* QLOGIC LINUX SOFTWARE
*
* QLogic ISP2x00 device driver for Linux 2.6.x
* Copyright (C) 2003-2004 QLogic Corporation
* (www.qlogic.com)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
******************************************************************************/
/* Management functions for various lists */
/* __add_to_done_queue()
*
* Place SRB command on done queue.
*
* Input:
* ha = host pointer
* sp = srb pointer.
* Locking:
* this function assumes the ha->list_lock is already taken
*/
static inline void
__add_to_done_queue(struct scsi_qla_host * ha, srb_t * sp)
{
/*
if (sp->state != SRB_NO_QUEUE_STATE &&
sp->state != SRB_ACTIVE_STATE)
BUG();
*/
/* Place block on done queue */
sp->cmd->host_scribble = (unsigned char *) NULL;
sp->state = SRB_DONE_STATE;
list_add_tail(&sp->list,&ha->done_queue);
ha->done_q_cnt++;
sp->ha = ha;
}
static inline void
__add_to_retry_queue(struct scsi_qla_host * ha, srb_t * sp)
{
/*
if( sp->state != SRB_NO_QUEUE_STATE &&
sp->state != SRB_ACTIVE_STATE)
BUG();
*/
/* Place block on retry queue */
list_add_tail(&sp->list,&ha->retry_queue);
ha->retry_q_cnt++;
sp->flags |= SRB_WATCHDOG;
sp->state = SRB_RETRY_STATE;
sp->ha = ha;
}
static inline void
__add_to_scsi_retry_queue(struct scsi_qla_host * ha, srb_t * sp)
{
/*
if( sp->state != SRB_NO_QUEUE_STATE &&
sp->state != SRB_ACTIVE_STATE)
BUG();
*/
/* Place block on retry queue */
list_add_tail(&sp->list,&ha->scsi_retry_queue);
ha->scsi_retry_q_cnt++;
sp->state = SRB_SCSI_RETRY_STATE;
sp->ha = ha;
}
static inline void
add_to_done_queue(struct scsi_qla_host * ha, srb_t * sp)
{
unsigned long flags;
spin_lock_irqsave(&ha->list_lock, flags);
__add_to_done_queue(ha,sp);
spin_unlock_irqrestore(&ha->list_lock, flags);
}
static inline void
add_to_free_queue(struct scsi_qla_host * ha, srb_t * sp)
{
mempool_free(sp, ha->srb_mempool);
}
static inline void
add_to_retry_queue(struct scsi_qla_host * ha, srb_t * sp)
{
unsigned long flags;
spin_lock_irqsave(&ha->list_lock, flags);
__add_to_retry_queue(ha,sp);
spin_unlock_irqrestore(&ha->list_lock, flags);
}
static inline void
add_to_scsi_retry_queue(struct scsi_qla_host * ha, srb_t * sp)
{
unsigned long flags;
spin_lock_irqsave(&ha->list_lock, flags);
__add_to_scsi_retry_queue(ha,sp);
spin_unlock_irqrestore(&ha->list_lock, flags);
}
/*
* __del_from_retry_queue
* Function used to remove a command block from the
* watchdog timer queue.
*
* Note: Must insure that command is on watchdog
* list before calling del_from_retry_queue
* if (sp->flags & SRB_WATCHDOG)
*
* Input:
* ha = adapter block pointer.
* sp = srb pointer.
* Locking:
* this function assumes the list_lock is already taken
*/
static inline void
__del_from_retry_queue(struct scsi_qla_host * ha, srb_t * sp)
{
list_del_init(&sp->list);
sp->flags &= ~(SRB_WATCHDOG | SRB_BUSY);
sp->state = SRB_NO_QUEUE_STATE;
ha->retry_q_cnt--;
}
/*
* __del_from_scsi_retry_queue
* Function used to remove a command block from the
* scsi retry queue.
*
* Input:
* ha = adapter block pointer.
* sp = srb pointer.
* Locking:
* this function assumes the list_lock is already taken
*/
static inline void
__del_from_scsi_retry_queue(struct scsi_qla_host * ha, srb_t * sp)
{
list_del_init(&sp->list);
ha->scsi_retry_q_cnt--;
sp->state = SRB_NO_QUEUE_STATE;
}
/*
* del_from_retry_queue
* Function used to remove a command block from the
* watchdog timer queue.
*
* Note: Must insure that command is on watchdog
* list before calling del_from_retry_queue
* if (sp->flags & SRB_WATCHDOG)
*
* Input:
* ha = adapter block pointer.
* sp = srb pointer.
* Locking:
* this function takes and releases the list_lock
*/
static inline void
del_from_retry_queue(struct scsi_qla_host * ha, srb_t * sp)
{
unsigned long flags;
/* if (unlikely(!(sp->flags & SRB_WATCHDOG)))
BUG();*/
spin_lock_irqsave(&ha->list_lock, flags);
/* if (unlikely(list_empty(&ha->retry_queue)))
BUG();*/
__del_from_retry_queue(ha,sp);
spin_unlock_irqrestore(&ha->list_lock, flags);
}
/*
* del_from_scsi_retry_queue
* Function used to remove a command block from the
* scsi retry queue.
*
* Input:
* ha = adapter block pointer.
* sp = srb pointer.
* Locking:
* this function takes and releases the list_lock
*/
static inline void
del_from_scsi_retry_queue(struct scsi_qla_host * ha, srb_t * sp)
{
unsigned long flags;
spin_lock_irqsave(&ha->list_lock, flags);
/* if (unlikely(list_empty(&ha->scsi_retry_queue)))
BUG();*/
__del_from_scsi_retry_queue(ha,sp);
spin_unlock_irqrestore(&ha->list_lock, flags);
}
/*
* __add_to_pending_queue
* Add the standard SCB job to the bottom of standard SCB commands.
*
* Input:
* COMPLETE!!!
* q = SCSI LU pointer.
* sp = srb pointer.
* SCSI_LU_Q lock must be already obtained.
*/
static inline int
__add_to_pending_queue(struct scsi_qla_host *ha, srb_t * sp)
{
int empty;
/*
if( sp->state != SRB_NO_QUEUE_STATE &&
sp->state != SRB_FREE_STATE &&
sp->state != SRB_ACTIVE_STATE)
BUG();
*/
empty = list_empty(&ha->pending_queue);
list_add_tail(&sp->list, &ha->pending_queue);
ha->qthreads++;
sp->state = SRB_PENDING_STATE;
return (empty);
}
static inline void
__add_to_pending_queue_head(struct scsi_qla_host *ha, srb_t * sp)
{
/*
if( sp->state != SRB_NO_QUEUE_STATE &&
sp->state != SRB_FREE_STATE &&
sp->state != SRB_ACTIVE_STATE)
BUG();
*/
list_add(&sp->list, &ha->pending_queue);
ha->qthreads++;
sp->state = SRB_PENDING_STATE;
}
static inline int
add_to_pending_queue(struct scsi_qla_host *ha, srb_t *sp)
{
int empty;
unsigned long flags;
spin_lock_irqsave(&ha->list_lock, flags);
empty = __add_to_pending_queue(ha, sp);
spin_unlock_irqrestore(&ha->list_lock, flags);
return (empty);
}
static inline void
add_to_pending_queue_head(struct scsi_qla_host *ha, srb_t *sp)
{
unsigned long flags;
spin_lock_irqsave(&ha->list_lock, flags);
__add_to_pending_queue_head(ha, sp);
spin_unlock_irqrestore(&ha->list_lock, flags);
}
static inline void
__del_from_pending_queue(struct scsi_qla_host *ha, srb_t *sp)
{
list_del_init(&sp->list);
ha->qthreads--;
sp->state = SRB_NO_QUEUE_STATE;
}
/*
* Failover Stuff.
*/
static inline void
__add_to_failover_queue(struct scsi_qla_host * ha, srb_t * sp)
{
/*
if( sp->state != SRB_NO_QUEUE_STATE &&
sp->state != SRB_ACTIVE_STATE)
BUG();
*/
list_add_tail(&sp->list,&ha->failover_queue);
ha->failover_cnt++;
sp->state = SRB_FAILOVER_STATE;
sp->ha = ha;
}
static inline void add_to_failover_queue(struct scsi_qla_host * ha, srb_t * sp)
{
unsigned long flags;
spin_lock_irqsave(&ha->list_lock, flags);
__add_to_failover_queue(ha,sp);
spin_unlock_irqrestore(&ha->list_lock, flags);
}
static inline void __del_from_failover_queue(struct scsi_qla_host * ha, srb_t *
sp)
{
ha->failover_cnt--;
list_del_init(&sp->list);
sp->state = SRB_NO_QUEUE_STATE;
}
static inline void del_from_failover_queue(struct scsi_qla_host * ha, srb_t * sp)
{
unsigned long flags;
spin_lock_irqsave(&ha->list_lock, flags);
__del_from_failover_queue(ha,sp);
spin_unlock_irqrestore(&ha->list_lock, flags);
}
static inline void
del_from_pending_queue(struct scsi_qla_host * ha, srb_t * sp)
{
unsigned long flags;
spin_lock_irqsave(&ha->list_lock, flags);
__del_from_pending_queue(ha,sp);
spin_unlock_irqrestore(&ha->list_lock, flags);
}