summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/block/ll_rw_blk.c107
-rw-r--r--drivers/ide/tcq.c2
-rw-r--r--include/linux/blkdev.h14
-rw-r--r--include/sound/ac97_codec.h2
4 files changed, 77 insertions, 48 deletions
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index c8f098cd45a3..d53122b1ae46 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -49,6 +49,9 @@ extern int mac_floppy_init(void);
*/
static kmem_cache_t *request_cachep;
+/*
+ * plug management
+ */
static struct list_head blk_plug_list;
static spinlock_t blk_plug_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
@@ -297,6 +300,27 @@ void blk_queue_assign_lock(request_queue_t *q, spinlock_t *lock)
}
/**
+ * blk_queue_find_tag - find a request by its tag and queue
+ *
+ * @q: The request queue for the device
+ * @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(request_queue_t *q, int tag)
+{
+ struct blk_queue_tag *bqt = q->queue_tags;
+
+ if(unlikely(bqt == NULL || bqt->max_depth < tag))
+ return NULL;
+
+ return bqt->tag_index[tag];
+}
+/**
* blk_queue_free_tags - release tag maintenance info
* @q: the request queue for the device
*
@@ -429,10 +453,12 @@ void blk_queue_end_tag(request_queue_t *q, struct request *rq)
* Description:
* This can either be used as a stand-alone helper, or possibly be
* assigned as the queue &prep_rq_fn (in which case &struct request
- * automagically gets a tag assigned). Note that this function assumes
- * that only REQ_CMD requests can be queued! The request will also be
- * removed from the request queue, so it's the drivers responsibility to
- * readd it if it should need to be restarted for some reason.
+ * automagically gets a tag assigned). Note that this function
+ * assumes that any type of request can be queued! if this is not
+ * true for your device, you must check the request type before
+ * calling this function. The request will also be removed from
+ * the request queue, so it's the drivers responsibility to readd
+ * it if it should need to be restarted for some reason.
*
* Notes:
* queue lock must be held.
@@ -443,8 +469,12 @@ int blk_queue_start_tag(request_queue_t *q, struct request *rq)
unsigned long *map = bqt->tag_map;
int tag = 0;
- if (unlikely(!(rq->flags & REQ_CMD)))
- return 1;
+ if (unlikely((rq->flags & REQ_QUEUED))) {
+ printk(KERN_ERR
+ "request %p for device [02%x:02%x] already tagged %d",
+ rq, major(rq->rq_dev), minor(rq->rq_dev), rq->tag);
+ BUG();
+ }
for (map = bqt->tag_map; *map == -1UL; map++) {
tag += BLK_TAGS_PER_LONG;
@@ -794,18 +824,12 @@ static int ll_merge_requests_fn(request_queue_t *q, struct request *req,
* force the transfer to start only after we have put all the requests
* on the list.
*
- * This is called with interrupts off and no requests on the queue.
- * (and with the request spinlock acquired)
+ * This is called with interrupts off and no requests on the queue and
+ * with the queue lock held.
*/
void blk_plug_device(request_queue_t *q)
{
- /*
- * common case
- */
- if (!elv_queue_empty(q))
- return;
-
- if (!test_and_set_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags)) {
+ if (!blk_queue_plugged(q)) {
spin_lock(&blk_plug_lock);
list_add_tail(&q->plug_list, &blk_plug_list);
spin_unlock(&blk_plug_lock);
@@ -813,14 +837,27 @@ void blk_plug_device(request_queue_t *q)
}
/*
+ * remove the queue from the plugged list, if present. called with
+ * queue lock held and interrupts disabled.
+ */
+inline int blk_remove_plug(request_queue_t *q)
+{
+ if (blk_queue_plugged(q)) {
+ spin_lock(&blk_plug_lock);
+ list_del_init(&q->plug_list);
+ spin_unlock(&blk_plug_lock);
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
* remove the plug and let it rip..
*/
static inline void __generic_unplug_device(request_queue_t *q)
{
- /*
- * not plugged
- */
- if (!test_and_clear_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags))
+ if (!blk_remove_plug(q))
return;
if (test_bit(QUEUE_FLAG_STOPPED, &q->queue_flags))
@@ -848,11 +885,10 @@ static inline void __generic_unplug_device(request_queue_t *q)
void generic_unplug_device(void *data)
{
request_queue_t *q = data;
- unsigned long flags;
- spin_lock_irqsave(q->queue_lock, flags);
+ spin_lock_irq(q->queue_lock);
__generic_unplug_device(q);
- spin_unlock_irqrestore(q->queue_lock, flags);
+ spin_unlock_irq(q->queue_lock);
}
/**
@@ -895,17 +931,9 @@ void blk_stop_queue(request_queue_t *q)
unsigned long flags;
spin_lock_irqsave(q->queue_lock, flags);
-
- /*
- * remove from the plugged list, queue must not be called.
- */
- if (test_and_clear_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags)) {
- spin_lock(&blk_plug_lock);
- list_del(&q->plug_list);
- spin_unlock(&blk_plug_lock);
- }
-
+ blk_remove_plug(q);
spin_unlock_irqrestore(q->queue_lock, flags);
+
set_bit(QUEUE_FLAG_STOPPED, &q->queue_flags);
}
@@ -941,12 +969,7 @@ void blk_run_queues(void)
while (!list_empty(&local_plug_list)) {
request_queue_t *q = blk_plug_entry(local_plug_list.next);
- BUG_ON(test_bit(QUEUE_FLAG_STOPPED, &q->queue_flags));
-
- spin_lock_irq(q->queue_lock);
- list_del(&q->plug_list);
- __generic_unplug_device(q);
- spin_unlock_irq(q->queue_lock);
+ q->unplug_fn(q);
}
}
@@ -1089,6 +1112,7 @@ int blk_init_queue(request_queue_t *q, request_fn_proc *rfn, spinlock_t *lock)
q->front_merge_fn = ll_front_merge_fn;
q->merge_requests_fn = ll_merge_requests_fn;
q->prep_rq_fn = NULL;
+ q->unplug_fn = generic_unplug_device;
q->queue_flags = (1 << QUEUE_FLAG_CLUSTER);
q->queue_lock = lock;
@@ -1386,10 +1410,12 @@ again:
req = NULL;
insert_here = q->queue_head.prev;
- if (blk_queue_empty(q) || barrier) {
+ if (blk_queue_empty(q)) {
blk_plug_device(q);
goto get_rq;
}
+ if (barrier)
+ goto get_rq;
el_ret = elv_merge(q, &req, bio);
switch (el_ret) {
@@ -2011,6 +2037,8 @@ EXPORT_SYMBOL(blk_queue_bounce_limit);
EXPORT_SYMBOL(generic_make_request);
EXPORT_SYMBOL(blkdev_release_request);
EXPORT_SYMBOL(generic_unplug_device);
+EXPORT_SYMBOL(blk_plug_device);
+EXPORT_SYMBOL(blk_remove_plug);
EXPORT_SYMBOL(blk_attempt_remerge);
EXPORT_SYMBOL(blk_max_low_pfn);
EXPORT_SYMBOL(blk_max_pfn);
@@ -2032,6 +2060,7 @@ EXPORT_SYMBOL(blk_put_request);
EXPORT_SYMBOL(blk_queue_prep_rq);
+EXPORT_SYMBOL(blk_queue_find_tag);
EXPORT_SYMBOL(blk_queue_init_tags);
EXPORT_SYMBOL(blk_queue_free_tags);
EXPORT_SYMBOL(blk_queue_start_tag);
diff --git a/drivers/ide/tcq.c b/drivers/ide/tcq.c
index fc5123a3dce1..dabc6503dce3 100644
--- a/drivers/ide/tcq.c
+++ b/drivers/ide/tcq.c
@@ -291,7 +291,7 @@ static ide_startstop_t service(struct ata_device *drive, struct request *rq)
TCQ_PRINTK("%s: stat %x, feat %x\n", __FUNCTION__, stat, feat);
- rq = blk_queue_tag_request(&drive->queue, tag);
+ rq = blk_queue_find_tag(&drive->queue, tag);
if (!rq) {
printk(KERN_ERR"%s: missing request for tag %d\n", __FUNCTION__, tag);
return ide_stopped;
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index c2645da2d975..ef86a3ed6e64 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -113,7 +113,7 @@ typedef void (request_fn_proc) (request_queue_t *q);
typedef request_queue_t * (queue_proc) (kdev_t dev);
typedef int (make_request_fn) (request_queue_t *q, struct bio *bio);
typedef int (prep_rq_fn) (request_queue_t *, struct request *);
-typedef void (unplug_device_fn) (void *q);
+typedef void (unplug_fn) (void *q);
enum blk_queue_state {
Queue_down,
@@ -157,6 +157,7 @@ struct request_queue
merge_requests_fn *merge_requests_fn;
make_request_fn *make_request_fn;
prep_rq_fn *prep_rq_fn;
+ unplug_fn *unplug_fn;
struct backing_dev_info backing_dev_info;
@@ -206,13 +207,11 @@ struct request_queue
#define RQ_SCSI_DONE 0xfffe
#define RQ_SCSI_DISCONNECTING 0xffe0
-#define QUEUE_FLAG_PLUGGED 0 /* queue is plugged */
-#define QUEUE_FLAG_CLUSTER 1 /* cluster several segments into 1 */
-#define QUEUE_FLAG_QUEUED 2 /* uses generic tag queueing */
-#define QUEUE_FLAG_STOPPED 3 /* queue is stopped */
+#define QUEUE_FLAG_CLUSTER 0 /* cluster several segments into 1 */
+#define QUEUE_FLAG_QUEUED 1 /* uses generic tag queueing */
+#define QUEUE_FLAG_STOPPED 2 /* queue is stopped */
-#define blk_queue_plugged(q) test_bit(QUEUE_FLAG_PLUGGED, &(q)->queue_flags)
-#define blk_mark_plugged(q) set_bit(QUEUE_FLAG_PLUGGED, &(q)->queue_flags)
+#define blk_queue_plugged(q) !list_empty(&(q)->plug_list)
#define blk_queue_tagged(q) test_bit(QUEUE_FLAG_QUEUED, &(q)->queue_flags)
#define blk_queue_empty(q) elv_queue_empty(q)
#define list_entry_rq(ptr) list_entry((ptr), struct request, queuelist)
@@ -292,6 +291,7 @@ extern void blk_attempt_remerge(request_queue_t *, struct request *);
extern struct request *blk_get_request(request_queue_t *, int, int);
extern void blk_put_request(struct request *);
extern void blk_plug_device(request_queue_t *);
+extern int blk_remove_plug(request_queue_t *);
extern void blk_recount_segments(request_queue_t *, struct bio *);
extern inline int blk_phys_contig_segment(request_queue_t *q, struct bio *, struct bio *);
extern inline int blk_hw_contig_segment(request_queue_t *q, struct bio *, struct bio *);
diff --git a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h
index 1f9fbd9a203b..7e93b7abfa55 100644
--- a/include/sound/ac97_codec.h
+++ b/include/sound/ac97_codec.h
@@ -160,7 +160,7 @@ struct _snd_ac97 {
unsigned int rates_mic_adc;
unsigned int spdif_status;
unsigned short regs[0x80]; /* register cache */
- unsigned long reg_accessed[0x80 / BITS_PER_LONG]; /* bit flags */
+ bitmap_member(reg_accessed, 0x80); /* bit flags */
union { /* vendor specific code */
struct {
unsigned short unchained[3]; // 0 = C34, 1 = C79, 2 = C69