@@ -771,7 +771,8 @@ irqreturn_t ide_intr (int irq, void *dev
unsigned long flags;
ide_startstop_t startstop;
irqreturn_t irq_ret = IRQ_NONE;
- int plug_device = 0;
+ bool plug_device = false, uninitialized_var(nested);
+ struct request_queue *q;
struct request *uninitialized_var(rq_in_flight);
if (host->host_flags & IDE_HFLAG_SERIALIZE) {
@@ -837,12 +838,31 @@ irqreturn_t ide_intr (int irq, void *dev
if (hwif->port_ops && hwif->port_ops->clear_irq)
hwif->port_ops->clear_irq(drive);
+ /*
+ * At least task_no_data_intr() may cause do_ide_request() to get
+ * called (via blk_end_request() and __blk_run_queue()), and the
+ * latter doesn't tolerate being called in interrupt (atomic)
+ * context (using might_sleep() right at its top).
+ */
+ q = drive->queue;
+ if (q) {
+ spin_lock(q->queue_lock);
+ nested = queue_flag_test_and_set(QUEUE_FLAG_REENTER, q);
+ spin_unlock(q->queue_lock);
+ }
+
if (drive->dev_flags & IDE_DFLAG_UNMASK)
local_irq_enable_in_hardirq();
/* service this interrupt, may set handler for next interrupt */
startstop = handler(drive);
+ if (q && !nested) {
+ spin_lock(q->queue_lock);
+ queue_flag_clear(QUEUE_FLAG_REENTER, q);
+ spin_unlock(q->queue_lock);
+ }
+
spin_lock_irq(&hwif->lock);
/*
* Note that handler() may have set things up for another