aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBrian King <brking@us.ibm.com>2004-08-22 22:39:02 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2004-08-22 22:39:02 -0700
commitff2087ea36342cf593ea7935c90edd30aa99feb5 (patch)
tree129f20410b42f579bfc48afe26cae54ee53be455 /drivers
parenteee1a8c490d985022d284c5fa5ba16dd05b08ee9 (diff)
downloadhistory-ff2087ea36342cf593ea7935c90edd30aa99feb5.tar.gz
[PATCH] blk_queue_free_tags() fix
This is a resend of three ll_rw_blk patches related to tagged queuing. Currently blk_queue_free_tags cannot be called with ops outstanding. The scsi_tcq API defined to LLD scsi drivers allows for scsi_deactivate_tcq to be called (which calls blk_queue_free_tags) with ops outstanding. Change blk_queue_free_tags to no longer free the tags, but rather just disable tagged queuing and also modify blk_queue_init_tags to handle re-enabling tagged queuing after it has been disabled. Signed-off-by: Jens Axboe <axboe@suse.de> Signed-off-by: Brian King <brking@us.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/block/ll_rw_blk.c35
1 files changed, 28 insertions, 7 deletions
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index 33b424c92f8150..28de3f55a89506 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -523,15 +523,14 @@ struct request *blk_queue_find_tag(request_queue_t *q, int tag)
EXPORT_SYMBOL(blk_queue_find_tag);
/**
- * blk_queue_free_tags - release tag maintenance info
+ * __blk_queue_free_tags - release tag maintenance info
* @q: the request queue for the device
*
* Notes:
* blk_cleanup_queue() will take care of calling this function, if tagging
- * has been used. So there's usually no need to call this directly, unless
- * tagging is just being disabled but the queue remains in function.
+ * has been used. So there's no need to call this directly.
**/
-void blk_queue_free_tags(request_queue_t *q)
+static void __blk_queue_free_tags(request_queue_t *q)
{
struct blk_queue_tag *bqt = q->queue_tags;
@@ -555,6 +554,19 @@ void blk_queue_free_tags(request_queue_t *q)
q->queue_flags &= ~(1 << QUEUE_FLAG_QUEUED);
}
+/**
+ * blk_queue_free_tags - release tag maintenance info
+ * @q: the request queue for the device
+ *
+ * Notes:
+ * This is used to disabled tagged queuing to a device, yet leave
+ * queue in function.
+ **/
+void blk_queue_free_tags(request_queue_t *q)
+{
+ clear_bit(QUEUE_FLAG_QUEUED, &q->queue_flags);
+}
+
EXPORT_SYMBOL(blk_queue_free_tags);
static int
@@ -605,13 +617,22 @@ fail:
int blk_queue_init_tags(request_queue_t *q, int depth,
struct blk_queue_tag *tags)
{
- if (!tags) {
+ int rc;
+
+ BUG_ON(tags && q->queue_tags && tags != q->queue_tags);
+
+ if (!tags && !q->queue_tags) {
tags = kmalloc(sizeof(struct blk_queue_tag), GFP_ATOMIC);
if (!tags)
goto fail;
if (init_tag_map(q, tags, depth))
goto fail;
+ } else if (q->queue_tags) {
+ if ((rc = blk_queue_resize_tags(q, depth)))
+ return rc;
+ set_bit(QUEUE_FLAG_QUEUED, &q->queue_flags);
+ return 0;
} else
atomic_inc(&tags->refcnt);
@@ -1376,8 +1397,8 @@ void blk_cleanup_queue(request_queue_t * q)
if (rl->rq_pool)
mempool_destroy(rl->rq_pool);
- if (blk_queue_tagged(q))
- blk_queue_free_tags(q);
+ if (q->queue_tags)
+ __blk_queue_free_tags(q);
kmem_cache_free(requestq_cachep, q);
}