/****************************************************************************** * 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); }