ide: convert to blk-mq
ide-disk and ide-cd tested as working just fine, ide-tape and ide-floppy haven't. But the latter don't require changes, so they should work without issue. Add helper function to insert a request from a work queue, since we cannot invoke the blk-mq request insertion from IRQ context. Cc: David Miller <davem@davemloft.net> Reviewed-by: Hannes Reinecke <hare@suse.com> Tested-by: Ming Lei <ming.lei@redhat.com> Reviewed-by: Omar Sandoval <osandov@fb.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
@@ -67,7 +67,15 @@ int ide_end_rq(ide_drive_t *drive, struct request *rq, blk_status_t error,
|
||||
ide_dma_on(drive);
|
||||
}
|
||||
|
||||
return blk_end_request(rq, error, nr_bytes);
|
||||
if (!blk_update_request(rq, error, nr_bytes)) {
|
||||
if (rq == drive->sense_rq)
|
||||
drive->sense_rq = NULL;
|
||||
|
||||
__blk_mq_end_request(rq, error);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ide_end_rq);
|
||||
|
||||
@@ -307,8 +315,6 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
|
||||
{
|
||||
ide_startstop_t startstop;
|
||||
|
||||
BUG_ON(!(rq->rq_flags & RQF_STARTED));
|
||||
|
||||
#ifdef DEBUG
|
||||
printk("%s: start_request: current=0x%08lx\n",
|
||||
drive->hwif->name, (unsigned long) rq);
|
||||
@@ -320,6 +326,9 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
|
||||
goto kill_rq;
|
||||
}
|
||||
|
||||
if (drive->prep_rq && drive->prep_rq(drive, rq))
|
||||
return ide_stopped;
|
||||
|
||||
if (ata_pm_request(rq))
|
||||
ide_check_pm_state(drive, rq);
|
||||
|
||||
@@ -430,44 +439,38 @@ static inline void ide_unlock_host(struct ide_host *host)
|
||||
}
|
||||
}
|
||||
|
||||
static void __ide_requeue_and_plug(struct request_queue *q, struct request *rq)
|
||||
{
|
||||
if (rq)
|
||||
blk_requeue_request(q, rq);
|
||||
if (rq || blk_peek_request(q)) {
|
||||
/* Use 3ms as that was the old plug delay */
|
||||
blk_delay_queue(q, 3);
|
||||
}
|
||||
}
|
||||
|
||||
void ide_requeue_and_plug(ide_drive_t *drive, struct request *rq)
|
||||
{
|
||||
struct request_queue *q = drive->queue;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(q->queue_lock, flags);
|
||||
__ide_requeue_and_plug(q, rq);
|
||||
spin_unlock_irqrestore(q->queue_lock, flags);
|
||||
/* Use 3ms as that was the old plug delay */
|
||||
if (rq) {
|
||||
blk_mq_requeue_request(rq, false);
|
||||
blk_mq_delay_kick_requeue_list(q, 3);
|
||||
} else
|
||||
blk_mq_delay_run_hw_queue(q->queue_hw_ctx[0], 3);
|
||||
}
|
||||
|
||||
/*
|
||||
* Issue a new request to a device.
|
||||
*/
|
||||
void do_ide_request(struct request_queue *q)
|
||||
blk_status_t ide_queue_rq(struct blk_mq_hw_ctx *hctx,
|
||||
const struct blk_mq_queue_data *bd)
|
||||
{
|
||||
ide_drive_t *drive = q->queuedata;
|
||||
ide_drive_t *drive = hctx->queue->queuedata;
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
struct ide_host *host = hwif->host;
|
||||
struct request *rq = NULL;
|
||||
ide_startstop_t startstop;
|
||||
|
||||
spin_unlock_irq(q->queue_lock);
|
||||
|
||||
/* HLD do_request() callback might sleep, make sure it's okay */
|
||||
might_sleep();
|
||||
|
||||
if (ide_lock_host(host, hwif))
|
||||
goto plug_device_2;
|
||||
return BLK_STS_DEV_RESOURCE;
|
||||
|
||||
rq = bd->rq;
|
||||
blk_mq_start_request(rq);
|
||||
|
||||
spin_lock_irq(&hwif->lock);
|
||||
|
||||
@@ -503,21 +506,16 @@ repeat:
|
||||
hwif->cur_dev = drive;
|
||||
drive->dev_flags &= ~(IDE_DFLAG_SLEEPING | IDE_DFLAG_PARKED);
|
||||
|
||||
spin_unlock_irq(&hwif->lock);
|
||||
spin_lock_irq(q->queue_lock);
|
||||
/*
|
||||
* we know that the queue isn't empty, but this can happen
|
||||
* if the q->prep_rq_fn() decides to kill a request
|
||||
*/
|
||||
if (!rq)
|
||||
rq = blk_fetch_request(drive->queue);
|
||||
|
||||
spin_unlock_irq(q->queue_lock);
|
||||
spin_lock_irq(&hwif->lock);
|
||||
|
||||
if (!rq) {
|
||||
ide_unlock_port(hwif);
|
||||
goto out;
|
||||
rq = bd->rq;
|
||||
if (!rq) {
|
||||
ide_unlock_port(hwif);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -551,23 +549,24 @@ repeat:
|
||||
if (startstop == ide_stopped) {
|
||||
rq = hwif->rq;
|
||||
hwif->rq = NULL;
|
||||
goto repeat;
|
||||
if (rq)
|
||||
goto repeat;
|
||||
ide_unlock_port(hwif);
|
||||
goto out;
|
||||
}
|
||||
} else
|
||||
goto plug_device;
|
||||
} else {
|
||||
plug_device:
|
||||
spin_unlock_irq(&hwif->lock);
|
||||
ide_unlock_host(host);
|
||||
ide_requeue_and_plug(drive, rq);
|
||||
return BLK_STS_OK;
|
||||
}
|
||||
|
||||
out:
|
||||
spin_unlock_irq(&hwif->lock);
|
||||
if (rq == NULL)
|
||||
ide_unlock_host(host);
|
||||
spin_lock_irq(q->queue_lock);
|
||||
return;
|
||||
|
||||
plug_device:
|
||||
spin_unlock_irq(&hwif->lock);
|
||||
ide_unlock_host(host);
|
||||
plug_device_2:
|
||||
spin_lock_irq(q->queue_lock);
|
||||
__ide_requeue_and_plug(q, rq);
|
||||
return BLK_STS_OK;
|
||||
}
|
||||
|
||||
static int drive_is_ready(ide_drive_t *drive)
|
||||
@@ -887,3 +886,16 @@ void ide_pad_transfer(ide_drive_t *drive, int write, int len)
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ide_pad_transfer);
|
||||
|
||||
void ide_insert_request_head(ide_drive_t *drive, struct request *rq)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&hwif->lock, flags);
|
||||
list_add_tail(&rq->queuelist, &drive->rq_list);
|
||||
spin_unlock_irqrestore(&hwif->lock, flags);
|
||||
|
||||
kblockd_schedule_work(&drive->rq_work);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ide_insert_request_head);
|
||||
|
Reference in New Issue
Block a user