Skip to content

Commit

Permalink
ide: convert to blk-mq
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Jens Axboe committed Nov 7, 2018
1 parent d0be122 commit 6003352
Show file tree
Hide file tree
Showing 8 changed files with 239 additions and 179 deletions.
25 changes: 17 additions & 8 deletions drivers/ide/ide-atapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,8 @@ EXPORT_SYMBOL_GPL(ide_create_request_sense_cmd);
void ide_prep_sense(ide_drive_t *drive, struct request *rq)
{
struct request_sense *sense = &drive->sense_data;
struct request *sense_rq = drive->sense_rq;
struct scsi_request *req = scsi_req(sense_rq);
struct request *sense_rq;
struct scsi_request *req;
unsigned int cmd_len, sense_len;
int err;

Expand All @@ -196,9 +196,16 @@ void ide_prep_sense(ide_drive_t *drive, struct request *rq)
if (ata_sense_request(rq) || drive->sense_rq_armed)
return;

sense_rq = drive->sense_rq;
if (!sense_rq) {
sense_rq = blk_mq_alloc_request(drive->queue, REQ_OP_DRV_IN,
BLK_MQ_REQ_RESERVED | BLK_MQ_REQ_NOWAIT);
drive->sense_rq = sense_rq;
}
req = scsi_req(sense_rq);

memset(sense, 0, sizeof(*sense));

blk_rq_init(rq->q, sense_rq);
scsi_req_init(req);

err = blk_rq_map_kern(drive->queue, sense_rq, sense, sense_len,
Expand All @@ -207,6 +214,8 @@ void ide_prep_sense(ide_drive_t *drive, struct request *rq)
if (printk_ratelimit())
printk(KERN_WARNING PFX "%s: failed to map sense "
"buffer\n", drive->name);
blk_mq_free_request(sense_rq);
drive->sense_rq = NULL;
return;
}

Expand All @@ -226,19 +235,21 @@ EXPORT_SYMBOL_GPL(ide_prep_sense);

int ide_queue_sense_rq(ide_drive_t *drive, void *special)
{
struct request *sense_rq = drive->sense_rq;

/* deferred failure from ide_prep_sense() */
if (!drive->sense_rq_armed) {
printk(KERN_WARNING PFX "%s: error queuing a sense request\n",
drive->name);
return -ENOMEM;
}

drive->sense_rq->special = special;
sense_rq->special = special;
drive->sense_rq_armed = false;

drive->hwif->rq = NULL;

elv_add_request(drive->queue, drive->sense_rq, ELEVATOR_INSERT_FRONT);
ide_insert_request_head(drive, sense_rq);
return 0;
}
EXPORT_SYMBOL_GPL(ide_queue_sense_rq);
Expand Down Expand Up @@ -270,10 +281,8 @@ void ide_retry_pc(ide_drive_t *drive)
*/
drive->hwif->rq = NULL;
ide_requeue_and_plug(drive, failed_rq);
if (ide_queue_sense_rq(drive, pc)) {
blk_start_request(failed_rq);
if (ide_queue_sense_rq(drive, pc))
ide_complete_rq(drive, BLK_STS_IOERR, blk_rq_bytes(failed_rq));
}
}
EXPORT_SYMBOL_GPL(ide_retry_pc);

Expand Down
175 changes: 94 additions & 81 deletions drivers/ide/ide-cd.c
Original file line number Diff line number Diff line change
Expand Up @@ -258,11 +258,22 @@ static int ide_cd_breathe(ide_drive_t *drive, struct request *rq)
/*
* take a breather
*/
blk_delay_queue(drive->queue, 1);
blk_mq_requeue_request(rq, false);
blk_mq_delay_kick_requeue_list(drive->queue, 1);
return 1;
}
}

static void ide_cd_free_sense(ide_drive_t *drive)
{
if (!drive->sense_rq)
return;

blk_mq_free_request(drive->sense_rq);
drive->sense_rq = NULL;
drive->sense_rq_armed = false;
}

/**
* Returns:
* 0: if the request should be continued.
Expand Down Expand Up @@ -516,6 +527,82 @@ static bool ide_cd_error_cmd(ide_drive_t *drive, struct ide_cmd *cmd)
return false;
}

/* standard prep_rq_fn that builds 10 byte cmds */
static int ide_cdrom_prep_fs(struct request_queue *q, struct request *rq)
{
int hard_sect = queue_logical_block_size(q);
long block = (long)blk_rq_pos(rq) / (hard_sect >> 9);
unsigned long blocks = blk_rq_sectors(rq) / (hard_sect >> 9);
struct scsi_request *req = scsi_req(rq);

if (rq_data_dir(rq) == READ)
req->cmd[0] = GPCMD_READ_10;
else
req->cmd[0] = GPCMD_WRITE_10;

/*
* fill in lba
*/
req->cmd[2] = (block >> 24) & 0xff;
req->cmd[3] = (block >> 16) & 0xff;
req->cmd[4] = (block >> 8) & 0xff;
req->cmd[5] = block & 0xff;

/*
* and transfer length
*/
req->cmd[7] = (blocks >> 8) & 0xff;
req->cmd[8] = blocks & 0xff;
req->cmd_len = 10;
return BLKPREP_OK;
}

/*
* Most of the SCSI commands are supported directly by ATAPI devices.
* This transform handles the few exceptions.
*/
static int ide_cdrom_prep_pc(struct request *rq)
{
u8 *c = scsi_req(rq)->cmd;

/* transform 6-byte read/write commands to the 10-byte version */
if (c[0] == READ_6 || c[0] == WRITE_6) {
c[8] = c[4];
c[5] = c[3];
c[4] = c[2];
c[3] = c[1] & 0x1f;
c[2] = 0;
c[1] &= 0xe0;
c[0] += (READ_10 - READ_6);
scsi_req(rq)->cmd_len = 10;
return BLKPREP_OK;
}

/*
* it's silly to pretend we understand 6-byte sense commands, just
* reject with ILLEGAL_REQUEST and the caller should take the
* appropriate action
*/
if (c[0] == MODE_SENSE || c[0] == MODE_SELECT) {
scsi_req(rq)->result = ILLEGAL_REQUEST;
return BLKPREP_KILL;
}

return BLKPREP_OK;
}

static int ide_cdrom_prep_fn(ide_drive_t *drive, struct request *rq)
{
if (!blk_rq_is_passthrough(rq)) {
scsi_req_init(scsi_req(rq));

return ide_cdrom_prep_fs(drive->queue, rq);
} else if (blk_rq_is_scsi(rq))
return ide_cdrom_prep_pc(rq);

return 0;
}

static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
Expand Down Expand Up @@ -675,7 +762,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
out_end:
if (blk_rq_is_scsi(rq) && rc == 0) {
scsi_req(rq)->resid_len = 0;
blk_end_request_all(rq, BLK_STS_OK);
blk_mq_end_request(rq, BLK_STS_OK);
hwif->rq = NULL;
} else {
if (sense && uptodate)
Expand Down Expand Up @@ -705,6 +792,8 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
if (sense && rc == 2)
ide_error(drive, "request sense failure", stat);
}

ide_cd_free_sense(drive);
return ide_stopped;
}

Expand All @@ -729,7 +818,7 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
* We may be retrying this request after an error. Fix up any
* weirdness which might be present in the request packet.
*/
q->prep_rq_fn(q, rq);
ide_cdrom_prep_fn(drive, rq);
}

/* fs requests *must* be hardware frame aligned */
Expand Down Expand Up @@ -1323,82 +1412,6 @@ static int ide_cdrom_probe_capabilities(ide_drive_t *drive)
return nslots;
}

/* standard prep_rq_fn that builds 10 byte cmds */
static int ide_cdrom_prep_fs(struct request_queue *q, struct request *rq)
{
int hard_sect = queue_logical_block_size(q);
long block = (long)blk_rq_pos(rq) / (hard_sect >> 9);
unsigned long blocks = blk_rq_sectors(rq) / (hard_sect >> 9);
struct scsi_request *req = scsi_req(rq);

q->initialize_rq_fn(rq);

if (rq_data_dir(rq) == READ)
req->cmd[0] = GPCMD_READ_10;
else
req->cmd[0] = GPCMD_WRITE_10;

/*
* fill in lba
*/
req->cmd[2] = (block >> 24) & 0xff;
req->cmd[3] = (block >> 16) & 0xff;
req->cmd[4] = (block >> 8) & 0xff;
req->cmd[5] = block & 0xff;

/*
* and transfer length
*/
req->cmd[7] = (blocks >> 8) & 0xff;
req->cmd[8] = blocks & 0xff;
req->cmd_len = 10;
return BLKPREP_OK;
}

/*
* Most of the SCSI commands are supported directly by ATAPI devices.
* This transform handles the few exceptions.
*/
static int ide_cdrom_prep_pc(struct request *rq)
{
u8 *c = scsi_req(rq)->cmd;

/* transform 6-byte read/write commands to the 10-byte version */
if (c[0] == READ_6 || c[0] == WRITE_6) {
c[8] = c[4];
c[5] = c[3];
c[4] = c[2];
c[3] = c[1] & 0x1f;
c[2] = 0;
c[1] &= 0xe0;
c[0] += (READ_10 - READ_6);
scsi_req(rq)->cmd_len = 10;
return BLKPREP_OK;
}

/*
* it's silly to pretend we understand 6-byte sense commands, just
* reject with ILLEGAL_REQUEST and the caller should take the
* appropriate action
*/
if (c[0] == MODE_SENSE || c[0] == MODE_SELECT) {
scsi_req(rq)->result = ILLEGAL_REQUEST;
return BLKPREP_KILL;
}

return BLKPREP_OK;
}

static int ide_cdrom_prep_fn(struct request_queue *q, struct request *rq)
{
if (!blk_rq_is_passthrough(rq))
return ide_cdrom_prep_fs(q, rq);
else if (blk_rq_is_scsi(rq))
return ide_cdrom_prep_pc(rq);

return 0;
}

struct cd_list_entry {
const char *id_model;
const char *id_firmware;
Expand Down Expand Up @@ -1508,7 +1521,7 @@ static int ide_cdrom_setup(ide_drive_t *drive)

ide_debug_log(IDE_DBG_PROBE, "enter");

blk_queue_prep_rq(q, ide_cdrom_prep_fn);
drive->prep_rq = ide_cdrom_prep_fn;
blk_queue_dma_alignment(q, 31);
blk_queue_update_dma_pad(q, 15);

Expand Down Expand Up @@ -1569,7 +1582,7 @@ static void ide_cd_release(struct device *dev)
if (devinfo->handle == drive)
unregister_cdrom(devinfo);
drive->driver_data = NULL;
blk_queue_prep_rq(drive->queue, NULL);
drive->prep_rq = NULL;
g->private_data = NULL;
put_disk(g);
kfree(info);
Expand Down
5 changes: 2 additions & 3 deletions drivers/ide/ide-disk.c
Original file line number Diff line number Diff line change
Expand Up @@ -427,9 +427,8 @@ static void ide_disk_unlock_native_capacity(ide_drive_t *drive)
drive->dev_flags |= IDE_DFLAG_NOHPA; /* disable HPA on resume */
}

static int idedisk_prep_fn(struct request_queue *q, struct request *rq)
static int idedisk_prep_fn(ide_drive_t *drive, struct request *rq)
{
ide_drive_t *drive = q->queuedata;
struct ide_cmd *cmd;

if (req_op(rq) != REQ_OP_FLUSH)
Expand Down Expand Up @@ -548,7 +547,7 @@ static void update_flush(ide_drive_t *drive)

if (barrier) {
wc = true;
blk_queue_prep_rq(drive->queue, idedisk_prep_fn);
drive->prep_rq = idedisk_prep_fn;
}
}

Expand Down
Loading

0 comments on commit 6003352

Please sign in to comment.