Commit ad5fc6bb authored by Jens Axboe's avatar Jens Axboe

gdrom: convert to blk-mq

Ditch the deffered list, lock, and workqueue handling. Just mark the
set as being blocking, so we are invoked from a workqueue already.
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent a9f38e1d
...@@ -31,12 +31,11 @@ ...@@ -31,12 +31,11 @@
#include <linux/cdrom.h> #include <linux/cdrom.h>
#include <linux/genhd.h> #include <linux/genhd.h>
#include <linux/bio.h> #include <linux/bio.h>
#include <linux/blkdev.h> #include <linux/blk-mq.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/workqueue.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <scsi/scsi.h> #include <scsi/scsi.h>
#include <asm/io.h> #include <asm/io.h>
...@@ -102,11 +101,6 @@ static int gdrom_major; ...@@ -102,11 +101,6 @@ static int gdrom_major;
static DECLARE_WAIT_QUEUE_HEAD(command_queue); static DECLARE_WAIT_QUEUE_HEAD(command_queue);
static DECLARE_WAIT_QUEUE_HEAD(request_queue); static DECLARE_WAIT_QUEUE_HEAD(request_queue);
static DEFINE_SPINLOCK(gdrom_lock);
static void gdrom_readdisk_dma(struct work_struct *work);
static DECLARE_WORK(work, gdrom_readdisk_dma);
static LIST_HEAD(gdrom_deferred);
struct gdromtoc { struct gdromtoc {
unsigned int entry[99]; unsigned int entry[99];
unsigned int first, last; unsigned int first, last;
...@@ -122,6 +116,7 @@ static struct gdrom_unit { ...@@ -122,6 +116,7 @@ static struct gdrom_unit {
char disk_type; char disk_type;
struct gdromtoc *toc; struct gdromtoc *toc;
struct request_queue *gdrom_rq; struct request_queue *gdrom_rq;
struct blk_mq_tag_set tag_set;
} gd; } gd;
struct gdrom_id { struct gdrom_id {
...@@ -584,26 +579,19 @@ static int gdrom_set_interrupt_handlers(void) ...@@ -584,26 +579,19 @@ static int gdrom_set_interrupt_handlers(void)
* 9 -> sectors >> 8 * 9 -> sectors >> 8
* 10 -> sectors * 10 -> sectors
*/ */
static void gdrom_readdisk_dma(struct work_struct *work) static blk_status_t gdrom_readdisk_dma(struct request *req)
{ {
int block, block_cnt; int block, block_cnt;
blk_status_t err; blk_status_t err;
struct packet_command *read_command; struct packet_command *read_command;
struct list_head *elem, *next;
struct request *req;
unsigned long timeout; unsigned long timeout;
if (list_empty(&gdrom_deferred))
return;
read_command = kzalloc(sizeof(struct packet_command), GFP_KERNEL); read_command = kzalloc(sizeof(struct packet_command), GFP_KERNEL);
if (!read_command) if (!read_command)
return; /* get more memory later? */ return BLK_STS_RESOURCE;
read_command->cmd[0] = 0x30; read_command->cmd[0] = 0x30;
read_command->cmd[1] = 0x20; read_command->cmd[1] = 0x20;
spin_lock(&gdrom_lock);
list_for_each_safe(elem, next, &gdrom_deferred) {
req = list_entry(elem, struct request, queuelist);
spin_unlock(&gdrom_lock);
block = blk_rq_pos(req)/GD_TO_BLK + GD_SESSION_OFFSET; block = blk_rq_pos(req)/GD_TO_BLK + GD_SESSION_OFFSET;
block_cnt = blk_rq_sectors(req)/GD_TO_BLK; block_cnt = blk_rq_sectors(req)/GD_TO_BLK;
__raw_writel(virt_to_phys(bio_data(req->bio)), GDROM_DMA_STARTADDR_REG); __raw_writel(virt_to_phys(bio_data(req->bio)), GDROM_DMA_STARTADDR_REG);
...@@ -648,39 +636,26 @@ static void gdrom_readdisk_dma(struct work_struct *work) ...@@ -648,39 +636,26 @@ static void gdrom_readdisk_dma(struct work_struct *work)
err = gd.transfer ? BLK_STS_IOERR : BLK_STS_OK; err = gd.transfer ? BLK_STS_IOERR : BLK_STS_OK;
gd.transfer = 0; gd.transfer = 0;
gd.pending = 0; gd.pending = 0;
/* now seek to take the request spinlock
* before handling ending the request */ blk_mq_end_request(req, err);
spin_lock(&gdrom_lock);
list_del_init(&req->queuelist);
__blk_end_request_all(req, err);
}
spin_unlock(&gdrom_lock);
kfree(read_command); kfree(read_command);
return BLK_STS_OK;
} }
static void gdrom_request(struct request_queue *rq) static blk_status_t gdrom_queue_rq(struct blk_mq_hw_ctx *hctx,
const struct blk_mq_queue_data *bd)
{ {
struct request *req; blk_mq_start_request(bd->rq);
while ((req = blk_fetch_request(rq)) != NULL) { switch (req_op(bd->rq)) {
switch (req_op(req)) {
case REQ_OP_READ: case REQ_OP_READ:
/* return gdrom_readdisk_dma(bd->rq);
* Add to list of deferred work and then schedule
* workqueue.
*/
list_add_tail(&req->queuelist, &gdrom_deferred);
schedule_work(&work);
break;
case REQ_OP_WRITE: case REQ_OP_WRITE:
pr_notice("Read only device - write request ignored\n"); pr_notice("Read only device - write request ignored\n");
__blk_end_request_all(req, BLK_STS_IOERR); return BLK_STS_IOERR;
break;
default: default:
printk(KERN_DEBUG "gdrom: Non-fs request ignored\n"); printk(KERN_DEBUG "gdrom: Non-fs request ignored\n");
__blk_end_request_all(req, BLK_STS_IOERR); return BLK_STS_IOERR;
break;
}
} }
} }
...@@ -768,6 +743,10 @@ static int probe_gdrom_setupqueue(void) ...@@ -768,6 +743,10 @@ static int probe_gdrom_setupqueue(void)
return gdrom_init_dma_mode(); return gdrom_init_dma_mode();
} }
static const struct blk_mq_ops gdrom_mq_ops = {
.queue_rq = gdrom_queue_rq,
};
/* /*
* register this as a block device and as compliant with the * register this as a block device and as compliant with the
* universal CD Rom driver interface * universal CD Rom driver interface
...@@ -811,11 +790,15 @@ static int probe_gdrom(struct platform_device *devptr) ...@@ -811,11 +790,15 @@ static int probe_gdrom(struct platform_device *devptr)
err = gdrom_set_interrupt_handlers(); err = gdrom_set_interrupt_handlers();
if (err) if (err)
goto probe_fail_cmdirq_register; goto probe_fail_cmdirq_register;
gd.gdrom_rq = blk_init_queue(gdrom_request, &gdrom_lock);
if (!gd.gdrom_rq) { gd.gdrom_rq = blk_mq_init_sq_queue(&gd.tag_set, &gdrom_mq_ops, 1,
err = -ENOMEM; BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_BLOCKING);
if (IS_ERR(gd.gdrom_rq)) {
rc = PTR_ERR(gd.gdrom_rq);
gd.gdrom_rq = NULL;
goto probe_fail_requestq; goto probe_fail_requestq;
} }
blk_queue_bounce_limit(gd.gdrom_rq, BLK_BOUNCE_HIGH); blk_queue_bounce_limit(gd.gdrom_rq, BLK_BOUNCE_HIGH);
err = probe_gdrom_setupqueue(); err = probe_gdrom_setupqueue();
...@@ -832,6 +815,7 @@ static int probe_gdrom(struct platform_device *devptr) ...@@ -832,6 +815,7 @@ static int probe_gdrom(struct platform_device *devptr)
probe_fail_toc: probe_fail_toc:
blk_cleanup_queue(gd.gdrom_rq); blk_cleanup_queue(gd.gdrom_rq);
blk_mq_free_tag_set(&gd.tag_set);
probe_fail_requestq: probe_fail_requestq:
free_irq(HW_EVENT_GDROM_DMA, &gd); free_irq(HW_EVENT_GDROM_DMA, &gd);
free_irq(HW_EVENT_GDROM_CMD, &gd); free_irq(HW_EVENT_GDROM_CMD, &gd);
...@@ -849,8 +833,8 @@ static int probe_gdrom(struct platform_device *devptr) ...@@ -849,8 +833,8 @@ static int probe_gdrom(struct platform_device *devptr)
static int remove_gdrom(struct platform_device *devptr) static int remove_gdrom(struct platform_device *devptr)
{ {
flush_work(&work);
blk_cleanup_queue(gd.gdrom_rq); blk_cleanup_queue(gd.gdrom_rq);
blk_mq_free_tag_set(&gd.tag_set);
free_irq(HW_EVENT_GDROM_CMD, &gd); free_irq(HW_EVENT_GDROM_CMD, &gd);
free_irq(HW_EVENT_GDROM_DMA, &gd); free_irq(HW_EVENT_GDROM_DMA, &gd);
del_gendisk(gd.disk); del_gendisk(gd.disk);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment