11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * linux/drivers/acorn/scsi/queue.c: queue handling primitives 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1997-2000 Russell King 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License version 2 as 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * published by the Free Software Foundation. 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Changelog: 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 15-Sep-1997 RMK Created. 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 11-Oct-1997 RMK Corrected problem with queue_remove_exclude 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * not updating internal linked list properly 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (was causing commands to go missing). 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 30-Aug-2000 RMK Use Linux list handling and spinlocks 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/blkdev.h> 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h> 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/spinlock.h> 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/list.h> 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "../scsi.h" 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DEBUG 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstypedef struct queue_entry { 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct list_head list; 32ee0ca6bab394fe41a2b4de58c4532b09a41c9165Henrik Kretzschmar struct scsi_cmnd *SCpnt; 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DEBUG 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long magic; 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} QE_t; 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DEBUG 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define QUEUE_MAGIC_FREE 0xf7e1c9a3 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define QUEUE_MAGIC_USED 0xf7e1cc33 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SET_MAGIC(q,m) ((q)->magic = (m)) 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define BAD_MAGIC(q,m) ((q)->magic != (m)) 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SET_MAGIC(q,m) do { } while (0) 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define BAD_MAGIC(q,m) (0) 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "queue.h" 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define NR_QE 32 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function: void queue_initialise (Queue_t *queue) 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Purpose : initialise a queue 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Params : queue - queue to initialise 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint queue_initialise (Queue_t *queue) 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int nqueues = NR_QE; 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds QE_t *q; 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_init(&queue->queue_lock); 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INIT_LIST_HEAD(&queue->head); 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INIT_LIST_HEAD(&queue->free); 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If life was easier, then SCpnt would have a 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * host-available list head, and we wouldn't 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * need to keep free lists or allocate this 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * memory. 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds queue->alloc = q = kmalloc(sizeof(QE_t) * nqueues, GFP_KERNEL); 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (q) { 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (; nqueues; q++, nqueues--) { 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_MAGIC(q, QUEUE_MAGIC_FREE); 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds q->SCpnt = NULL; 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_add(&q->list, &queue->free); 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return queue->alloc != NULL; 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function: void queue_free (Queue_t *queue) 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Purpose : free a queue 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Params : queue - queue to free 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid queue_free (Queue_t *queue) 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!list_empty(&queue->head)) 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "freeing non-empty queue %p\n", queue); 94c9475cb0c358ff0dd473544280d92482df491913Jesper Juhl kfree(queue->alloc); 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 99ee0ca6bab394fe41a2b4de58c4532b09a41c9165Henrik Kretzschmar * Function: int __queue_add(Queue_t *queue, struct scsi_cmnd *SCpnt, int head) 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Purpose : Add a new command onto a queue, adding REQUEST_SENSE to head. 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Params : queue - destination queue 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SCpnt - command to add 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * head - add command to head of queue 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns : 0 on error, !0 on success 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 106ee0ca6bab394fe41a2b4de58c4532b09a41c9165Henrik Kretzschmarint __queue_add(Queue_t *queue, struct scsi_cmnd *SCpnt, int head) 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct list_head *l; 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds QE_t *q; 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = 0; 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&queue->queue_lock, flags); 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (list_empty(&queue->free)) 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto empty; 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds l = queue->free.next; 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_del(l); 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds q = list_entry(l, QE_t, list); 121125e18745f16685f69a34fd6130d47598fc4bf54Eric Sesterhenn BUG_ON(BAD_MAGIC(q, QUEUE_MAGIC_FREE)); 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_MAGIC(q, QUEUE_MAGIC_USED); 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds q->SCpnt = SCpnt; 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (head) 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_add(l, &queue->head); 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_add_tail(l, &queue->head); 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = 1; 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsempty: 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&queue->queue_lock, flags); 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 137ee0ca6bab394fe41a2b4de58c4532b09a41c9165Henrik Kretzschmarstatic struct scsi_cmnd *__queue_remove(Queue_t *queue, struct list_head *ent) 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds QE_t *q; 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Move the entry from the "used" list onto the "free" list 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_del(ent); 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds q = list_entry(ent, QE_t, list); 146125e18745f16685f69a34fd6130d47598fc4bf54Eric Sesterhenn BUG_ON(BAD_MAGIC(q, QUEUE_MAGIC_USED)); 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_MAGIC(q, QUEUE_MAGIC_FREE); 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_add(ent, &queue->free); 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return q->SCpnt; 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 155ee0ca6bab394fe41a2b4de58c4532b09a41c9165Henrik Kretzschmar * Function: struct scsi_cmnd *queue_remove_exclude (queue, exclude) 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Purpose : remove a SCSI command from a queue 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Params : queue - queue to remove command from 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * exclude - bit array of target&lun which is busy 159ee0ca6bab394fe41a2b4de58c4532b09a41c9165Henrik Kretzschmar * Returns : struct scsi_cmnd if successful (and a reference), or NULL if no command available 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 161ee0ca6bab394fe41a2b4de58c4532b09a41c9165Henrik Kretzschmarstruct scsi_cmnd *queue_remove_exclude(Queue_t *queue, unsigned long *exclude) 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct list_head *l; 165ee0ca6bab394fe41a2b4de58c4532b09a41c9165Henrik Kretzschmar struct scsi_cmnd *SCpnt = NULL; 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&queue->queue_lock, flags); 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_for_each(l, &queue->head) { 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds QE_t *q = list_entry(l, QE_t, list); 1709cb78c16f5dadefd8dc5ba0ae5a2f26cd59419b3Hannes Reinecke if (!test_bit(q->SCpnt->device->id * 8 + 1719cb78c16f5dadefd8dc5ba0ae5a2f26cd59419b3Hannes Reinecke (u8)(q->SCpnt->device->lun & 0x7), exclude)) { 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SCpnt = __queue_remove(queue, l); 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&queue->queue_lock, flags); 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return SCpnt; 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 182ee0ca6bab394fe41a2b4de58c4532b09a41c9165Henrik Kretzschmar * Function: struct scsi_cmnd *queue_remove (queue) 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Purpose : removes first SCSI command from a queue 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Params : queue - queue to remove command from 185ee0ca6bab394fe41a2b4de58c4532b09a41c9165Henrik Kretzschmar * Returns : struct scsi_cmnd if successful (and a reference), or NULL if no command available 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 187ee0ca6bab394fe41a2b4de58c4532b09a41c9165Henrik Kretzschmarstruct scsi_cmnd *queue_remove(Queue_t *queue) 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 190ee0ca6bab394fe41a2b4de58c4532b09a41c9165Henrik Kretzschmar struct scsi_cmnd *SCpnt = NULL; 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&queue->queue_lock, flags); 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!list_empty(&queue->head)) 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SCpnt = __queue_remove(queue, queue->head.next); 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&queue->queue_lock, flags); 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return SCpnt; 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 201ee0ca6bab394fe41a2b4de58c4532b09a41c9165Henrik Kretzschmar * Function: struct scsi_cmnd *queue_remove_tgtluntag (queue, target, lun, tag) 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Purpose : remove a SCSI command from the queue for a specified target/lun/tag 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Params : queue - queue to remove command from 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * target - target that we want 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * lun - lun on device 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * tag - tag on device 207ee0ca6bab394fe41a2b4de58c4532b09a41c9165Henrik Kretzschmar * Returns : struct scsi_cmnd if successful, or NULL if no command satisfies requirements 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 209ee0ca6bab394fe41a2b4de58c4532b09a41c9165Henrik Kretzschmarstruct scsi_cmnd *queue_remove_tgtluntag(Queue_t *queue, int target, int lun, 210ee0ca6bab394fe41a2b4de58c4532b09a41c9165Henrik Kretzschmar int tag) 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct list_head *l; 214ee0ca6bab394fe41a2b4de58c4532b09a41c9165Henrik Kretzschmar struct scsi_cmnd *SCpnt = NULL; 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&queue->queue_lock, flags); 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_for_each(l, &queue->head) { 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds QE_t *q = list_entry(l, QE_t, list); 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (q->SCpnt->device->id == target && q->SCpnt->device->lun == lun && 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds q->SCpnt->tag == tag) { 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SCpnt = __queue_remove(queue, l); 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&queue->queue_lock, flags); 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return SCpnt; 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function: queue_remove_all_target(queue, target) 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Purpose : remove all SCSI commands from the queue for a specified target 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Params : queue - queue to remove command from 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * target - target device id 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns : nothing 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid queue_remove_all_target(Queue_t *queue, int target) 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct list_head *l; 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&queue->queue_lock, flags); 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_for_each(l, &queue->head) { 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds QE_t *q = list_entry(l, QE_t, list); 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (q->SCpnt->device->id == target) 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __queue_remove(queue, l); 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&queue->queue_lock, flags); 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function: int queue_probetgtlun (queue, target, lun) 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Purpose : check to see if we have a command in the queue for the specified 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * target/lun. 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Params : queue - queue to look in 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * target - target we want to probe 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * lun - lun on target 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns : 0 if not found, != 0 if found 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint queue_probetgtlun (Queue_t *queue, int target, int lun) 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct list_head *l; 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int found = 0; 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&queue->queue_lock, flags); 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_for_each(l, &queue->head) { 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds QE_t *q = list_entry(l, QE_t, list); 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (q->SCpnt->device->id == target && q->SCpnt->device->lun == lun) { 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds found = 1; 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&queue->queue_lock, flags); 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return found; 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 280ee0ca6bab394fe41a2b4de58c4532b09a41c9165Henrik Kretzschmar * Function: int queue_remove_cmd(Queue_t *queue, struct scsi_cmnd *SCpnt) 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Purpose : remove a specific command from the queues 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Params : queue - queue to look in 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SCpnt - command to find 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns : 0 if not found 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 286ee0ca6bab394fe41a2b4de58c4532b09a41c9165Henrik Kretzschmarint queue_remove_cmd(Queue_t *queue, struct scsi_cmnd *SCpnt) 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct list_head *l; 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int found = 0; 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&queue->queue_lock, flags); 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_for_each(l, &queue->head) { 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds QE_t *q = list_entry(l, QE_t, list); 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (q->SCpnt == SCpnt) { 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __queue_remove(queue, l); 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds found = 1; 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&queue->queue_lock, flags); 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return found; 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(queue_initialise); 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(queue_free); 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(__queue_add); 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(queue_remove); 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(queue_remove_exclude); 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(queue_remove_tgtluntag); 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(queue_remove_cmd); 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(queue_remove_all_target); 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(queue_probetgtlun); 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Russell King"); 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("SCSI command queueing"); 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 319