summaryrefslogtreecommitdiff
path: root/drivers/memstick/core/mspro_block.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/memstick/core/mspro_block.c')
-rw-r--r--drivers/memstick/core/mspro_block.c421
1 files changed, 173 insertions, 248 deletions
diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c
index 8897962781bb..e507bb11c802 100644
--- a/drivers/memstick/core/mspro_block.c
+++ b/drivers/memstick/core/mspro_block.c
@@ -1,18 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Sony MemoryStick Pro storage support
*
* Copyright (C) 2007 Alex Dubov <oakad@yahoo.com>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
* Special thanks to Carlos Corbacho for providing various MemoryStick cards
* that made this driver possible.
- *
*/
-#include <linux/blkdev.h>
+#include <linux/blk-mq.h>
#include <linux/idr.h>
#include <linux/hdreg.h>
#include <linux/kthread.h>
@@ -137,11 +133,11 @@ struct mspro_devinfo {
struct mspro_block_data {
struct memstick_dev *card;
- unsigned int usage_count;
unsigned int caps;
struct gendisk *disk;
struct request_queue *queue;
struct request *block_req;
+ struct blk_mq_tag_set tag_set;
spinlock_t q_lock;
unsigned short page_size;
@@ -152,7 +148,6 @@ struct mspro_block_data {
unsigned char system;
unsigned char read_only:1,
eject:1,
- has_request:1,
data_dir:1,
active:1;
unsigned char transfer_cmd;
@@ -182,59 +177,22 @@ static int mspro_block_complete_req(struct memstick_dev *card, int error);
/*** Block device ***/
-static int mspro_block_bd_open(struct block_device *bdev, fmode_t mode)
-{
- struct gendisk *disk = bdev->bd_disk;
- struct mspro_block_data *msb = disk->private_data;
- int rc = -ENXIO;
-
- mutex_lock(&mspro_block_disk_lock);
-
- if (msb && msb->card) {
- msb->usage_count++;
- if ((mode & FMODE_WRITE) && msb->read_only)
- rc = -EROFS;
- else
- rc = 0;
- }
-
- mutex_unlock(&mspro_block_disk_lock);
-
- return rc;
-}
-
-
-static void mspro_block_disk_release(struct gendisk *disk)
+static void mspro_block_bd_free_disk(struct gendisk *disk)
{
struct mspro_block_data *msb = disk->private_data;
int disk_id = MINOR(disk_devt(disk)) >> MSPRO_BLOCK_PART_SHIFT;
mutex_lock(&mspro_block_disk_lock);
-
- if (msb) {
- if (msb->usage_count)
- msb->usage_count--;
-
- if (!msb->usage_count) {
- kfree(msb);
- disk->private_data = NULL;
- idr_remove(&mspro_block_disk_idr, disk_id);
- put_disk(disk);
- }
- }
-
+ idr_remove(&mspro_block_disk_idr, disk_id);
mutex_unlock(&mspro_block_disk_lock);
-}
-static void mspro_block_bd_release(struct gendisk *disk, fmode_t mode)
-{
- mspro_block_disk_release(disk);
+ kfree(msb);
}
-static int mspro_block_bd_getgeo(struct block_device *bdev,
+static int mspro_block_bd_getgeo(struct gendisk *disk,
struct hd_geometry *geo)
{
- struct mspro_block_data *msb = bdev->bd_disk->private_data;
+ struct mspro_block_data *msb = disk->private_data;
geo->heads = msb->heads;
geo->sectors = msb->sectors_per_track;
@@ -244,10 +202,9 @@ static int mspro_block_bd_getgeo(struct block_device *bdev,
}
static const struct block_device_operations ms_block_bdops = {
- .open = mspro_block_bd_open,
- .release = mspro_block_bd_release,
- .getgeo = mspro_block_bd_getgeo,
- .owner = THIS_MODULE
+ .owner = THIS_MODULE,
+ .getgeo = mspro_block_bd_getgeo,
+ .free_disk = mspro_block_bd_free_disk,
};
/*** Information ***/
@@ -280,7 +237,7 @@ static const char *mspro_block_attr_name(unsigned char tag)
return "attr_devinfo";
default:
return NULL;
- };
+ }
}
typedef ssize_t (*sysfs_show_t)(struct device *dev,
@@ -303,8 +260,8 @@ static ssize_t mspro_block_attr_show_default(struct device *dev,
buffer[rc++] = '\n';
}
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "%02x ",
- ((unsigned char *)s_attr->data)[cnt]);
+ rc += sysfs_emit_at(buffer, rc, "%02x ",
+ ((unsigned char *)s_attr->data)[cnt]);
}
return rc;
}
@@ -333,61 +290,43 @@ static ssize_t mspro_block_attr_show_sysinfo(struct device *dev,
date_tz_f *= 15;
}
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "class: %x\n",
- x_sys->class);
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "block size: %x\n",
- be16_to_cpu(x_sys->block_size));
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "block count: %x\n",
- be16_to_cpu(x_sys->block_count));
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "user block count: %x\n",
- be16_to_cpu(x_sys->user_block_count));
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "page size: %x\n",
- be16_to_cpu(x_sys->page_size));
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "assembly date: "
- "GMT%+d:%d %04u-%02u-%02u %02u:%02u:%02u\n",
- date_tz, date_tz_f,
- be16_to_cpup((__be16 *)&x_sys->assembly_date[1]),
- x_sys->assembly_date[3], x_sys->assembly_date[4],
- x_sys->assembly_date[5], x_sys->assembly_date[6],
- x_sys->assembly_date[7]);
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "serial number: %x\n",
- be32_to_cpu(x_sys->serial_number));
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc,
- "assembly maker code: %x\n",
- x_sys->assembly_maker_code);
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "assembly model code: "
- "%02x%02x%02x\n", x_sys->assembly_model_code[0],
- x_sys->assembly_model_code[1],
- x_sys->assembly_model_code[2]);
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "memory maker code: %x\n",
- be16_to_cpu(x_sys->memory_maker_code));
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "memory model code: %x\n",
- be16_to_cpu(x_sys->memory_model_code));
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "vcc: %x\n",
- x_sys->vcc);
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "vpp: %x\n",
- x_sys->vpp);
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "controller number: %x\n",
- be16_to_cpu(x_sys->controller_number));
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc,
- "controller function: %x\n",
- be16_to_cpu(x_sys->controller_function));
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "start sector: %x\n",
- be16_to_cpu(x_sys->start_sector));
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "unit size: %x\n",
- be16_to_cpu(x_sys->unit_size));
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "sub class: %x\n",
- x_sys->ms_sub_class);
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "interface type: %x\n",
- x_sys->interface_type);
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "controller code: %x\n",
- be16_to_cpu(x_sys->controller_code));
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "format type: %x\n",
- x_sys->format_type);
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "device type: %x\n",
- x_sys->device_type);
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "mspro id: %s\n",
- x_sys->mspro_id);
+ rc += sysfs_emit_at(buffer, rc, "class: %x\n", x_sys->class);
+ rc += sysfs_emit_at(buffer, rc, "block size: %x\n", be16_to_cpu(x_sys->block_size));
+ rc += sysfs_emit_at(buffer, rc, "block count: %x\n", be16_to_cpu(x_sys->block_count));
+ rc += sysfs_emit_at(buffer, rc, "user block count: %x\n",
+ be16_to_cpu(x_sys->user_block_count));
+ rc += sysfs_emit_at(buffer, rc, "page size: %x\n", be16_to_cpu(x_sys->page_size));
+ rc += sysfs_emit_at(buffer, rc, "assembly date: GMT%+d:%d %04u-%02u-%02u %02u:%02u:%02u\n",
+ date_tz, date_tz_f,
+ be16_to_cpup((__be16 *)&x_sys->assembly_date[1]),
+ x_sys->assembly_date[3], x_sys->assembly_date[4],
+ x_sys->assembly_date[5], x_sys->assembly_date[6],
+ x_sys->assembly_date[7]);
+ rc += sysfs_emit_at(buffer, rc, "serial number: %x\n", be32_to_cpu(x_sys->serial_number));
+ rc += sysfs_emit_at(buffer, rc, "assembly maker code: %x\n", x_sys->assembly_maker_code);
+ rc += sysfs_emit_at(buffer, rc, "assembly model code: %02x%02x%02x\n",
+ x_sys->assembly_model_code[0],
+ x_sys->assembly_model_code[1],
+ x_sys->assembly_model_code[2]);
+ rc += sysfs_emit_at(buffer, rc, "memory maker code: %x\n",
+ be16_to_cpu(x_sys->memory_maker_code));
+ rc += sysfs_emit_at(buffer, rc, "memory model code: %x\n",
+ be16_to_cpu(x_sys->memory_model_code));
+ rc += sysfs_emit_at(buffer, rc, "vcc: %x\n", x_sys->vcc);
+ rc += sysfs_emit_at(buffer, rc, "vpp: %x\n", x_sys->vpp);
+ rc += sysfs_emit_at(buffer, rc, "controller number: %x\n",
+ be16_to_cpu(x_sys->controller_number));
+ rc += sysfs_emit_at(buffer, rc, "controller function: %x\n",
+ be16_to_cpu(x_sys->controller_function));
+ rc += sysfs_emit_at(buffer, rc, "start sector: %x\n", be16_to_cpu(x_sys->start_sector));
+ rc += sysfs_emit_at(buffer, rc, "unit size: %x\n", be16_to_cpu(x_sys->unit_size));
+ rc += sysfs_emit_at(buffer, rc, "sub class: %x\n", x_sys->ms_sub_class);
+ rc += sysfs_emit_at(buffer, rc, "interface type: %x\n", x_sys->interface_type);
+ rc += sysfs_emit_at(buffer, rc, "controller code: %x\n",
+ be16_to_cpu(x_sys->controller_code));
+ rc += sysfs_emit_at(buffer, rc, "format type: %x\n", x_sys->format_type);
+ rc += sysfs_emit_at(buffer, rc, "device type: %x\n", x_sys->device_type);
+ rc += sysfs_emit_at(buffer, rc, "mspro id: %s\n", x_sys->mspro_id);
return rc;
}
@@ -399,7 +338,7 @@ static ssize_t mspro_block_attr_show_modelname(struct device *dev,
struct mspro_sys_attr,
dev_attr);
- return scnprintf(buffer, PAGE_SIZE, "%s", (char *)s_attr->data);
+ return sysfs_emit(buffer, "%s", (char *)s_attr->data);
}
static ssize_t mspro_block_attr_show_mbr(struct device *dev,
@@ -412,27 +351,17 @@ static ssize_t mspro_block_attr_show_mbr(struct device *dev,
struct mspro_mbr *x_mbr = x_attr->data;
ssize_t rc = 0;
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "boot partition: %x\n",
- x_mbr->boot_partition);
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "start head: %x\n",
- x_mbr->start_head);
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "start sector: %x\n",
- x_mbr->start_sector);
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "start cylinder: %x\n",
- x_mbr->start_cylinder);
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "partition type: %x\n",
- x_mbr->partition_type);
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "end head: %x\n",
- x_mbr->end_head);
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "end sector: %x\n",
- x_mbr->end_sector);
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "end cylinder: %x\n",
- x_mbr->end_cylinder);
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "start sectors: %x\n",
- x_mbr->start_sectors);
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc,
- "sectors per partition: %x\n",
- x_mbr->sectors_per_partition);
+ rc += sysfs_emit_at(buffer, rc, "boot partition: %x\n", x_mbr->boot_partition);
+ rc += sysfs_emit_at(buffer, rc, "start head: %x\n", x_mbr->start_head);
+ rc += sysfs_emit_at(buffer, rc, "start sector: %x\n", x_mbr->start_sector);
+ rc += sysfs_emit_at(buffer, rc, "start cylinder: %x\n", x_mbr->start_cylinder);
+ rc += sysfs_emit_at(buffer, rc, "partition type: %x\n", x_mbr->partition_type);
+ rc += sysfs_emit_at(buffer, rc, "end head: %x\n", x_mbr->end_head);
+ rc += sysfs_emit_at(buffer, rc, "end sector: %x\n", x_mbr->end_sector);
+ rc += sysfs_emit_at(buffer, rc, "end cylinder: %x\n", x_mbr->end_cylinder);
+ rc += sysfs_emit_at(buffer, rc, "start sectors: %x\n", x_mbr->start_sectors);
+ rc += sysfs_emit_at(buffer, rc, "sectors per partition: %x\n",
+ x_mbr->sectors_per_partition);
return rc;
}
@@ -452,22 +381,19 @@ static ssize_t mspro_block_attr_show_specfile(struct device *dev,
memcpy(ext, x_spfile->ext, 3);
ext[3] = 0;
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "name: %s\n", name);
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "ext: %s\n", ext);
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "attribute: %x\n",
- x_spfile->attr);
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "time: %d:%d:%d\n",
- x_spfile->time >> 11,
- (x_spfile->time >> 5) & 0x3f,
- (x_spfile->time & 0x1f) * 2);
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "date: %d-%d-%d\n",
- (x_spfile->date >> 9) + 1980,
- (x_spfile->date >> 5) & 0xf,
- x_spfile->date & 0x1f);
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "start cluster: %x\n",
- x_spfile->cluster);
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "size: %x\n",
- x_spfile->size);
+ rc += sysfs_emit_at(buffer, rc, "name: %s\n", name);
+ rc += sysfs_emit_at(buffer, rc, "ext: %s\n", ext);
+ rc += sysfs_emit_at(buffer, rc, "attribute: %x\n", x_spfile->attr);
+ rc += sysfs_emit_at(buffer, rc, "time: %d:%d:%d\n",
+ x_spfile->time >> 11,
+ (x_spfile->time >> 5) & 0x3f,
+ (x_spfile->time & 0x1f) * 2);
+ rc += sysfs_emit_at(buffer, rc, "date: %d-%d-%d\n",
+ (x_spfile->date >> 9) + 1980,
+ (x_spfile->date >> 5) & 0xf,
+ x_spfile->date & 0x1f);
+ rc += sysfs_emit_at(buffer, rc, "start cluster: %x\n", x_spfile->cluster);
+ rc += sysfs_emit_at(buffer, rc, "size: %x\n", x_spfile->size);
return rc;
}
@@ -481,16 +407,14 @@ static ssize_t mspro_block_attr_show_devinfo(struct device *dev,
struct mspro_devinfo *x_devinfo = x_attr->data;
ssize_t rc = 0;
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "cylinders: %x\n",
- be16_to_cpu(x_devinfo->cylinders));
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "heads: %x\n",
- be16_to_cpu(x_devinfo->heads));
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "bytes per track: %x\n",
- be16_to_cpu(x_devinfo->bytes_per_track));
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "bytes per sector: %x\n",
- be16_to_cpu(x_devinfo->bytes_per_sector));
- rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "sectors per track: %x\n",
- be16_to_cpu(x_devinfo->sectors_per_track));
+ rc += sysfs_emit_at(buffer, rc, "cylinders: %x\n", be16_to_cpu(x_devinfo->cylinders));
+ rc += sysfs_emit_at(buffer, rc, "heads: %x\n", be16_to_cpu(x_devinfo->heads));
+ rc += sysfs_emit_at(buffer, rc, "bytes per track: %x\n",
+ be16_to_cpu(x_devinfo->bytes_per_track));
+ rc += sysfs_emit_at(buffer, rc, "bytes per sector: %x\n",
+ be16_to_cpu(x_devinfo->bytes_per_sector));
+ rc += sysfs_emit_at(buffer, rc, "sectors per track: %x\n",
+ be16_to_cpu(x_devinfo->sectors_per_track));
return rc;
}
@@ -636,8 +560,7 @@ has_int_reg:
t_offset += msb->current_page * msb->page_size;
sg_set_page(&t_sg,
- nth_page(sg_page(&(msb->req_sg[msb->current_seg])),
- t_offset >> PAGE_SHIFT),
+ sg_page(&(msb->req_sg[msb->current_seg])) + (t_offset >> PAGE_SHIFT),
msb->page_size, offset_in_page(t_offset));
memstick_init_req_sg(*mrq, msb->data_dir == READ
@@ -694,24 +617,30 @@ static void h_mspro_block_setup_cmd(struct memstick_dev *card, u64 offset,
/*** Data transfer ***/
-static int mspro_block_issue_req(struct memstick_dev *card, int chunk)
+static int mspro_block_issue_req(struct memstick_dev *card)
{
struct mspro_block_data *msb = memstick_get_drvdata(card);
u64 t_off;
unsigned int count;
-try_again:
- while (chunk) {
+ while (true) {
msb->current_page = 0;
msb->current_seg = 0;
- msb->seg_count = blk_rq_map_sg(msb->block_req->q,
- msb->block_req,
- msb->req_sg);
+ msb->seg_count = blk_rq_map_sg(msb->block_req, msb->req_sg);
if (!msb->seg_count) {
- chunk = __blk_end_request_cur(msb->block_req,
- BLK_STS_RESOURCE);
- continue;
+ unsigned int bytes = blk_rq_cur_bytes(msb->block_req);
+ bool chunk;
+
+ chunk = blk_update_request(msb->block_req,
+ BLK_STS_RESOURCE,
+ bytes);
+ if (chunk)
+ continue;
+ __blk_mq_end_request(msb->block_req,
+ BLK_STS_RESOURCE);
+ msb->block_req = NULL;
+ return -EAGAIN;
}
t_off = blk_rq_pos(msb->block_req);
@@ -728,31 +657,21 @@ try_again:
memstick_new_req(card->host);
return 0;
}
-
- dev_dbg(&card->dev, "blk_fetch\n");
- msb->block_req = blk_fetch_request(msb->queue);
- if (!msb->block_req) {
- dev_dbg(&card->dev, "issue end\n");
- return -EAGAIN;
- }
-
- dev_dbg(&card->dev, "trying again\n");
- chunk = 1;
- goto try_again;
}
static int mspro_block_complete_req(struct memstick_dev *card, int error)
{
struct mspro_block_data *msb = memstick_get_drvdata(card);
- int chunk, cnt;
+ int cnt;
+ bool chunk;
unsigned int t_len = 0;
unsigned long flags;
spin_lock_irqsave(&msb->q_lock, flags);
- dev_dbg(&card->dev, "complete %d, %d\n", msb->has_request ? 1 : 0,
+ dev_dbg(&card->dev, "complete %d, %d\n", msb->block_req ? 1 : 0,
error);
- if (msb->has_request) {
+ if (msb->block_req) {
/* Nothing to do - not really an error */
if (error == -EAGAIN)
error = 0;
@@ -777,15 +696,17 @@ static int mspro_block_complete_req(struct memstick_dev *card, int error)
if (error && !t_len)
t_len = blk_rq_cur_bytes(msb->block_req);
- chunk = __blk_end_request(msb->block_req,
+ chunk = blk_update_request(msb->block_req,
errno_to_blk_status(error), t_len);
-
- error = mspro_block_issue_req(card, chunk);
-
- if (!error)
- goto out;
- else
- msb->has_request = 0;
+ if (chunk) {
+ error = mspro_block_issue_req(card);
+ if (!error)
+ goto out;
+ } else {
+ __blk_mq_end_request(msb->block_req,
+ errno_to_blk_status(error));
+ msb->block_req = NULL;
+ }
} else {
if (!error)
error = -EAGAIN;
@@ -806,8 +727,8 @@ static void mspro_block_stop(struct memstick_dev *card)
while (1) {
spin_lock_irqsave(&msb->q_lock, flags);
- if (!msb->has_request) {
- blk_stop_queue(msb->queue);
+ if (!msb->block_req) {
+ blk_mq_stop_hw_queues(msb->queue);
rc = 1;
}
spin_unlock_irqrestore(&msb->q_lock, flags);
@@ -822,32 +743,37 @@ static void mspro_block_stop(struct memstick_dev *card)
static void mspro_block_start(struct memstick_dev *card)
{
struct mspro_block_data *msb = memstick_get_drvdata(card);
- unsigned long flags;
- spin_lock_irqsave(&msb->q_lock, flags);
- blk_start_queue(msb->queue);
- spin_unlock_irqrestore(&msb->q_lock, flags);
+ blk_mq_start_hw_queues(msb->queue);
}
-static void mspro_block_submit_req(struct request_queue *q)
+static blk_status_t mspro_queue_rq(struct blk_mq_hw_ctx *hctx,
+ const struct blk_mq_queue_data *bd)
{
- struct memstick_dev *card = q->queuedata;
+ struct memstick_dev *card = hctx->queue->queuedata;
struct mspro_block_data *msb = memstick_get_drvdata(card);
- struct request *req = NULL;
- if (msb->has_request)
- return;
+ spin_lock_irq(&msb->q_lock);
- if (msb->eject) {
- while ((req = blk_fetch_request(q)) != NULL)
- __blk_end_request_all(req, BLK_STS_IOERR);
+ if (msb->block_req) {
+ spin_unlock_irq(&msb->q_lock);
+ return BLK_STS_DEV_RESOURCE;
+ }
- return;
+ if (msb->eject) {
+ spin_unlock_irq(&msb->q_lock);
+ blk_mq_start_request(bd->rq);
+ return BLK_STS_IOERR;
}
- msb->has_request = 1;
- if (mspro_block_issue_req(card, 0))
- msb->has_request = 0;
+ msb->block_req = bd->rq;
+ blk_mq_start_request(bd->rq);
+
+ if (mspro_block_issue_req(card))
+ msb->block_req = NULL;
+
+ spin_unlock_irq(&msb->q_lock);
+ return BLK_STS_OK;
}
/*** Initialization ***/
@@ -1167,20 +1093,25 @@ static int mspro_block_init_card(struct memstick_dev *card)
}
+static const struct blk_mq_ops mspro_mq_ops = {
+ .queue_rq = mspro_queue_rq,
+};
+
static int mspro_block_init_disk(struct memstick_dev *card)
{
struct mspro_block_data *msb = memstick_get_drvdata(card);
- struct memstick_host *host = card->host;
+ struct queue_limits lim = {
+ .logical_block_size = msb->page_size,
+ .max_hw_sectors = MSPRO_BLOCK_MAX_PAGES,
+ .max_segments = MSPRO_BLOCK_MAX_SEGS,
+ .max_segment_size = MSPRO_BLOCK_MAX_PAGES * msb->page_size,
+ };
struct mspro_devinfo *dev_info = NULL;
struct mspro_sys_info *sys_info = NULL;
struct mspro_sys_attr *s_attr = NULL;
int rc, disk_id;
- u64 limit = BLK_BOUNCE_HIGH;
unsigned long capacity;
- if (host->dev.dma_mask && *(host->dev.dma_mask))
- limit = *(host->dev.dma_mask);
-
for (rc = 0; msb->attr_group.attrs[rc]; ++rc) {
s_attr = mspro_from_sysfs_attr(msb->attr_group.attrs[rc]);
@@ -1205,49 +1136,44 @@ static int mspro_block_init_disk(struct memstick_dev *card)
if (disk_id < 0)
return disk_id;
- msb->disk = alloc_disk(1 << MSPRO_BLOCK_PART_SHIFT);
- if (!msb->disk) {
- rc = -ENOMEM;
+ rc = blk_mq_alloc_sq_tag_set(&msb->tag_set, &mspro_mq_ops, 2, 0);
+ if (rc)
goto out_release_id;
- }
- msb->queue = blk_init_queue(mspro_block_submit_req, &msb->q_lock);
- if (!msb->queue) {
- rc = -ENOMEM;
- goto out_put_disk;
+ msb->disk = blk_mq_alloc_disk(&msb->tag_set, &lim, card);
+ if (IS_ERR(msb->disk)) {
+ rc = PTR_ERR(msb->disk);
+ goto out_free_tag_set;
}
-
- msb->queue->queuedata = card;
-
- blk_queue_bounce_limit(msb->queue, limit);
- blk_queue_max_hw_sectors(msb->queue, MSPRO_BLOCK_MAX_PAGES);
- blk_queue_max_segments(msb->queue, MSPRO_BLOCK_MAX_SEGS);
- blk_queue_max_segment_size(msb->queue,
- MSPRO_BLOCK_MAX_PAGES * msb->page_size);
+ msb->queue = msb->disk->queue;
msb->disk->major = major;
msb->disk->first_minor = disk_id << MSPRO_BLOCK_PART_SHIFT;
+ msb->disk->minors = 1 << MSPRO_BLOCK_PART_SHIFT;
msb->disk->fops = &ms_block_bdops;
- msb->usage_count = 1;
msb->disk->private_data = msb;
- msb->disk->queue = msb->queue;
sprintf(msb->disk->disk_name, "mspblk%d", disk_id);
- blk_queue_logical_block_size(msb->queue, msb->page_size);
-
capacity = be16_to_cpu(sys_info->user_block_count);
capacity *= be16_to_cpu(sys_info->block_size);
capacity *= msb->page_size >> 9;
set_capacity(msb->disk, capacity);
dev_dbg(&card->dev, "capacity set %ld\n", capacity);
- device_add_disk(&card->dev, msb->disk);
+ if (msb->read_only)
+ set_disk_ro(msb->disk, true);
+
+ rc = device_add_disk(&card->dev, msb->disk, NULL);
+ if (rc)
+ goto out_cleanup_disk;
msb->active = 1;
return 0;
-out_put_disk:
+out_cleanup_disk:
put_disk(msb->disk);
+out_free_tag_set:
+ blk_mq_free_tag_set(&msb->tag_set);
out_release_id:
mutex_lock(&mspro_block_disk_lock);
idr_remove(&mspro_block_disk_idr, disk_id);
@@ -1324,13 +1250,13 @@ static void mspro_block_remove(struct memstick_dev *card)
spin_lock_irqsave(&msb->q_lock, flags);
msb->eject = 1;
- blk_start_queue(msb->queue);
spin_unlock_irqrestore(&msb->q_lock, flags);
+ blk_mq_start_hw_queues(msb->queue);
del_gendisk(msb->disk);
dev_dbg(&card->dev, "mspro block remove\n");
- blk_cleanup_queue(msb->queue);
+ blk_mq_free_tag_set(&msb->tag_set);
msb->queue = NULL;
sysfs_remove_group(&card->dev.kobj, &msb->attr_group);
@@ -1339,7 +1265,7 @@ static void mspro_block_remove(struct memstick_dev *card)
mspro_block_data_clear(msb);
mutex_unlock(&mspro_block_disk_lock);
- mspro_block_disk_release(msb->disk);
+ put_disk(msb->disk);
memstick_set_drvdata(card, NULL);
}
@@ -1350,8 +1276,9 @@ static int mspro_block_suspend(struct memstick_dev *card, pm_message_t state)
struct mspro_block_data *msb = memstick_get_drvdata(card);
unsigned long flags;
+ blk_mq_stop_hw_queues(msb->queue);
+
spin_lock_irqsave(&msb->q_lock, flags);
- blk_stop_queue(msb->queue);
msb->active = 0;
spin_unlock_irqrestore(&msb->q_lock, flags);
@@ -1361,7 +1288,6 @@ static int mspro_block_suspend(struct memstick_dev *card, pm_message_t state)
static int mspro_block_resume(struct memstick_dev *card)
{
struct mspro_block_data *msb = memstick_get_drvdata(card);
- unsigned long flags;
int rc = 0;
#ifdef CONFIG_MEMSTICK_UNSAFE_RESUME
@@ -1380,7 +1306,8 @@ static int mspro_block_resume(struct memstick_dev *card)
new_msb->card = card;
memstick_set_drvdata(card, new_msb);
- if (mspro_block_init_card(card))
+ rc = mspro_block_init_card(card);
+ if (rc)
goto out_free;
for (cnt = 0; new_msb->attr_group.attrs[cnt]
@@ -1407,9 +1334,7 @@ out_unlock:
#endif /* CONFIG_MEMSTICK_UNSAFE_RESUME */
- spin_lock_irqsave(&msb->q_lock, flags);
- blk_start_queue(msb->queue);
- spin_unlock_irqrestore(&msb->q_lock, flags);
+ blk_mq_start_hw_queues(msb->queue);
return rc;
}
@@ -1420,7 +1345,7 @@ out_unlock:
#endif /* CONFIG_PM */
-static struct memstick_device_id mspro_block_id_tbl[] = {
+static const struct memstick_device_id mspro_block_id_tbl[] = {
{MEMSTICK_MATCH_ALL, MEMSTICK_TYPE_PRO, MEMSTICK_CATEGORY_STORAGE_DUO,
MEMSTICK_CLASS_DUO},
{}