|
@@ -13,3 +13,64 @@
|
|
* blk_queue_find_tag - find a request by its tag and queue
|
|
* blk_queue_find_tag - find a request by its tag and queue
|
|
* @q: The request queue for the device
|
|
* @q: The request queue for the device
|
|
* @tag: The tag of the request
|
|
* @tag: The tag of the request
|
|
|
|
+ *
|
|
|
|
+ * Notes:
|
|
|
|
+ * Should be used when a device returns a tag and you want to match
|
|
|
|
+ * it with a request.
|
|
|
|
+ *
|
|
|
|
+ * no locks need be held.
|
|
|
|
+ **/
|
|
|
|
+struct request *blk_queue_find_tag(struct request_queue *q, int tag)
|
|
|
|
+{
|
|
|
|
+ return blk_map_queue_find_tag(q->queue_tags, tag);
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL(blk_queue_find_tag);
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * __blk_free_tags - release a given set of tag maintenance info
|
|
|
|
+ * @bqt: the tag map to free
|
|
|
|
+ *
|
|
|
|
+ * Tries to free the specified @bqt. Returns true if it was
|
|
|
|
+ * actually freed and false if there are still references using it
|
|
|
|
+ */
|
|
|
|
+static int __blk_free_tags(struct blk_queue_tag *bqt)
|
|
|
|
+{
|
|
|
|
+ int retval;
|
|
|
|
+
|
|
|
|
+ retval = atomic_dec_and_test(&bqt->refcnt);
|
|
|
|
+ if (retval) {
|
|
|
|
+ BUG_ON(find_first_bit(bqt->tag_map, bqt->max_depth) <
|
|
|
|
+ bqt->max_depth);
|
|
|
|
+
|
|
|
|
+ kfree(bqt->tag_index);
|
|
|
|
+ bqt->tag_index = NULL;
|
|
|
|
+
|
|
|
|
+ kfree(bqt->tag_map);
|
|
|
|
+ bqt->tag_map = NULL;
|
|
|
|
+
|
|
|
|
+ kfree(bqt);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return retval;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * __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 no need to call this directly.
|
|
|
|
+ **/
|
|
|
|
+void __blk_queue_free_tags(struct request_queue *q)
|
|
|
|
+{
|
|
|
|
+ struct blk_queue_tag *bqt = q->queue_tags;
|
|
|
|
+
|
|
|
|
+ if (!bqt)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ __blk_free_tags(bqt);
|
|
|
|
+
|
|
|
|
+ q->queue_tags = NULL;
|
|
|
|
+ queue_flag_clear_unlocked(QUEUE_FLAG_QUEUED, q);
|
|
|
|
+}
|