1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2baf8532aSAlex Dubov /*
3baf8532aSAlex Dubov  *  Sony MemoryStick Pro storage support
4baf8532aSAlex Dubov  *
5baf8532aSAlex Dubov  *  Copyright (C) 2007 Alex Dubov <oakad@yahoo.com>
6baf8532aSAlex Dubov  *
7baf8532aSAlex Dubov  * Special thanks to Carlos Corbacho for providing various MemoryStick cards
8baf8532aSAlex Dubov  * that made this driver possible.
9baf8532aSAlex Dubov  */
10baf8532aSAlex Dubov 
11d0be1227SJens Axboe #include <linux/blk-mq.h>
12baf8532aSAlex Dubov #include <linux/idr.h>
13baf8532aSAlex Dubov #include <linux/hdreg.h>
14baf8532aSAlex Dubov #include <linux/kthread.h>
1559367258SAlex Dubov #include <linux/delay.h>
165a0e3ad6STejun Heo #include <linux/slab.h>
172a48fc0aSArnd Bergmann #include <linux/mutex.h>
18baf8532aSAlex Dubov #include <linux/memstick.h>
19c47e7893SPaul Gortmaker #include <linux/module.h>
20baf8532aSAlex Dubov 
21baf8532aSAlex Dubov #define DRIVER_NAME "mspro_block"
22baf8532aSAlex Dubov 
23baf8532aSAlex Dubov static int major;
24baf8532aSAlex Dubov module_param(major, int, 0644);
25baf8532aSAlex Dubov 
26baf8532aSAlex Dubov #define MSPRO_BLOCK_MAX_SEGS  32
27baf8532aSAlex Dubov #define MSPRO_BLOCK_MAX_PAGES ((2 << 16) - 1)
28baf8532aSAlex Dubov 
29baf8532aSAlex Dubov #define MSPRO_BLOCK_SIGNATURE        0xa5c3
30baf8532aSAlex Dubov #define MSPRO_BLOCK_MAX_ATTRIBUTES   41
31baf8532aSAlex Dubov 
328e82f8c3SAlex Dubov #define MSPRO_BLOCK_PART_SHIFT 3
338e82f8c3SAlex Dubov 
34baf8532aSAlex Dubov enum {
35baf8532aSAlex Dubov 	MSPRO_BLOCK_ID_SYSINFO         = 0x10,
36baf8532aSAlex Dubov 	MSPRO_BLOCK_ID_MODELNAME       = 0x15,
37baf8532aSAlex Dubov 	MSPRO_BLOCK_ID_MBR             = 0x20,
38baf8532aSAlex Dubov 	MSPRO_BLOCK_ID_PBR16           = 0x21,
39baf8532aSAlex Dubov 	MSPRO_BLOCK_ID_PBR32           = 0x22,
40baf8532aSAlex Dubov 	MSPRO_BLOCK_ID_SPECFILEVALUES1 = 0x25,
41baf8532aSAlex Dubov 	MSPRO_BLOCK_ID_SPECFILEVALUES2 = 0x26,
42baf8532aSAlex Dubov 	MSPRO_BLOCK_ID_DEVINFO         = 0x30
43baf8532aSAlex Dubov };
44baf8532aSAlex Dubov 
45baf8532aSAlex Dubov struct mspro_sys_attr {
46baf8532aSAlex Dubov 	size_t                  size;
47baf8532aSAlex Dubov 	void                    *data;
48baf8532aSAlex Dubov 	unsigned char           id;
49baf8532aSAlex Dubov 	char                    name[32];
50baf8532aSAlex Dubov 	struct device_attribute dev_attr;
51baf8532aSAlex Dubov };
52baf8532aSAlex Dubov 
53baf8532aSAlex Dubov struct mspro_attr_entry {
5469347a23SHarvey Harrison 	__be32 address;
5569347a23SHarvey Harrison 	__be32 size;
56baf8532aSAlex Dubov 	unsigned char id;
57baf8532aSAlex Dubov 	unsigned char reserved[3];
58baf8532aSAlex Dubov } __attribute__((packed));
59baf8532aSAlex Dubov 
60baf8532aSAlex Dubov struct mspro_attribute {
6169347a23SHarvey Harrison 	__be16 signature;
62baf8532aSAlex Dubov 	unsigned short          version;
63baf8532aSAlex Dubov 	unsigned char           count;
64baf8532aSAlex Dubov 	unsigned char           reserved[11];
65baf8532aSAlex Dubov 	struct mspro_attr_entry entries[];
66baf8532aSAlex Dubov } __attribute__((packed));
67baf8532aSAlex Dubov 
68baf8532aSAlex Dubov struct mspro_sys_info {
69baf8532aSAlex Dubov 	unsigned char  class;
70baf8532aSAlex Dubov 	unsigned char  reserved0;
7169347a23SHarvey Harrison 	__be16 block_size;
7269347a23SHarvey Harrison 	__be16 block_count;
7369347a23SHarvey Harrison 	__be16 user_block_count;
7469347a23SHarvey Harrison 	__be16 page_size;
75baf8532aSAlex Dubov 	unsigned char  reserved1[2];
76baf8532aSAlex Dubov 	unsigned char  assembly_date[8];
7769347a23SHarvey Harrison 	__be32 serial_number;
78baf8532aSAlex Dubov 	unsigned char  assembly_maker_code;
79baf8532aSAlex Dubov 	unsigned char  assembly_model_code[3];
8069347a23SHarvey Harrison 	__be16 memory_maker_code;
8169347a23SHarvey Harrison 	__be16 memory_model_code;
82baf8532aSAlex Dubov 	unsigned char  reserved2[4];
83baf8532aSAlex Dubov 	unsigned char  vcc;
84baf8532aSAlex Dubov 	unsigned char  vpp;
8569347a23SHarvey Harrison 	__be16 controller_number;
8669347a23SHarvey Harrison 	__be16 controller_function;
8769347a23SHarvey Harrison 	__be16 start_sector;
8869347a23SHarvey Harrison 	__be16 unit_size;
89baf8532aSAlex Dubov 	unsigned char  ms_sub_class;
90baf8532aSAlex Dubov 	unsigned char  reserved3[4];
91baf8532aSAlex Dubov 	unsigned char  interface_type;
9269347a23SHarvey Harrison 	__be16 controller_code;
93baf8532aSAlex Dubov 	unsigned char  format_type;
94baf8532aSAlex Dubov 	unsigned char  reserved4;
95baf8532aSAlex Dubov 	unsigned char  device_type;
96baf8532aSAlex Dubov 	unsigned char  reserved5[7];
97baf8532aSAlex Dubov 	unsigned char  mspro_id[16];
98baf8532aSAlex Dubov 	unsigned char  reserved6[16];
99baf8532aSAlex Dubov } __attribute__((packed));
100baf8532aSAlex Dubov 
101baf8532aSAlex Dubov struct mspro_mbr {
102baf8532aSAlex Dubov 	unsigned char boot_partition;
103baf8532aSAlex Dubov 	unsigned char start_head;
104baf8532aSAlex Dubov 	unsigned char start_sector;
105baf8532aSAlex Dubov 	unsigned char start_cylinder;
106baf8532aSAlex Dubov 	unsigned char partition_type;
107baf8532aSAlex Dubov 	unsigned char end_head;
108baf8532aSAlex Dubov 	unsigned char end_sector;
109baf8532aSAlex Dubov 	unsigned char end_cylinder;
110baf8532aSAlex Dubov 	unsigned int  start_sectors;
111baf8532aSAlex Dubov 	unsigned int  sectors_per_partition;
112baf8532aSAlex Dubov } __attribute__((packed));
113baf8532aSAlex Dubov 
114efb2742eSAlex Dubov struct mspro_specfile {
115efb2742eSAlex Dubov 	char           name[8];
116efb2742eSAlex Dubov 	char           ext[3];
117efb2742eSAlex Dubov 	unsigned char  attr;
118efb2742eSAlex Dubov 	unsigned char  reserved[10];
119efb2742eSAlex Dubov 	unsigned short time;
120efb2742eSAlex Dubov 	unsigned short date;
121efb2742eSAlex Dubov 	unsigned short cluster;
122efb2742eSAlex Dubov 	unsigned int   size;
123efb2742eSAlex Dubov } __attribute__((packed));
124efb2742eSAlex Dubov 
125baf8532aSAlex Dubov struct mspro_devinfo {
12669347a23SHarvey Harrison 	__be16 cylinders;
12769347a23SHarvey Harrison 	__be16 heads;
12869347a23SHarvey Harrison 	__be16 bytes_per_track;
12969347a23SHarvey Harrison 	__be16 bytes_per_sector;
13069347a23SHarvey Harrison 	__be16 sectors_per_track;
131baf8532aSAlex Dubov 	unsigned char  reserved[6];
132baf8532aSAlex Dubov } __attribute__((packed));
133baf8532aSAlex Dubov 
134baf8532aSAlex Dubov struct mspro_block_data {
135baf8532aSAlex Dubov 	struct memstick_dev   *card;
136ead70773SAlex Dubov 	unsigned int          caps;
137baf8532aSAlex Dubov 	struct gendisk        *disk;
138baf8532aSAlex Dubov 	struct request_queue  *queue;
139f1d82698SAlex Dubov 	struct request        *block_req;
140d0be1227SJens Axboe 	struct blk_mq_tag_set tag_set;
141baf8532aSAlex Dubov 	spinlock_t            q_lock;
142baf8532aSAlex Dubov 
143baf8532aSAlex Dubov 	unsigned short        page_size;
144baf8532aSAlex Dubov 	unsigned short        cylinders;
145baf8532aSAlex Dubov 	unsigned short        heads;
146baf8532aSAlex Dubov 	unsigned short        sectors_per_track;
147baf8532aSAlex Dubov 
148baf8532aSAlex Dubov 	unsigned char         system;
149baf8532aSAlex Dubov 	unsigned char         read_only:1,
150f1d82698SAlex Dubov 			      eject:1,
151f1d82698SAlex Dubov 			      data_dir:1,
152f1d82698SAlex Dubov 			      active:1;
153baf8532aSAlex Dubov 	unsigned char         transfer_cmd;
154baf8532aSAlex Dubov 
155baf8532aSAlex Dubov 	int                   (*mrq_handler)(struct memstick_dev *card,
156baf8532aSAlex Dubov 					     struct memstick_request **mrq);
157baf8532aSAlex Dubov 
158496fc1a6SAlex Dubov 
159496fc1a6SAlex Dubov 	/* Default request setup function for data access method preferred by
160496fc1a6SAlex Dubov 	 * this host instance.
161496fc1a6SAlex Dubov 	 */
162496fc1a6SAlex Dubov 	void                  (*setup_transfer)(struct memstick_dev *card,
163496fc1a6SAlex Dubov 						u64 offset, size_t length);
164496fc1a6SAlex Dubov 
165baf8532aSAlex Dubov 	struct attribute_group attr_group;
166baf8532aSAlex Dubov 
167baf8532aSAlex Dubov 	struct scatterlist    req_sg[MSPRO_BLOCK_MAX_SEGS];
168baf8532aSAlex Dubov 	unsigned int          seg_count;
169baf8532aSAlex Dubov 	unsigned int          current_seg;
170f1d82698SAlex Dubov 	unsigned int          current_page;
171baf8532aSAlex Dubov };
172baf8532aSAlex Dubov 
173baf8532aSAlex Dubov static DEFINE_IDR(mspro_block_disk_idr);
174baf8532aSAlex Dubov static DEFINE_MUTEX(mspro_block_disk_lock);
175baf8532aSAlex Dubov 
176f1d82698SAlex Dubov static int mspro_block_complete_req(struct memstick_dev *card, int error);
177f1d82698SAlex Dubov 
178baf8532aSAlex Dubov /*** Block device ***/
179baf8532aSAlex Dubov 
mspro_block_bd_free_disk(struct gendisk * disk)180185ed423SChristoph Hellwig static void mspro_block_bd_free_disk(struct gendisk *disk)
181baf8532aSAlex Dubov {
182baf8532aSAlex Dubov 	struct mspro_block_data *msb = disk->private_data;
183f331c029STejun Heo 	int disk_id = MINOR(disk_devt(disk)) >> MSPRO_BLOCK_PART_SHIFT;
184baf8532aSAlex Dubov 
185baf8532aSAlex Dubov 	mutex_lock(&mspro_block_disk_lock);
186baf8532aSAlex Dubov 	idr_remove(&mspro_block_disk_idr, disk_id);
187baf8532aSAlex Dubov 	mutex_unlock(&mspro_block_disk_lock);
188baf8532aSAlex Dubov 
189185ed423SChristoph Hellwig 	kfree(msb);
190baf8532aSAlex Dubov }
191baf8532aSAlex Dubov 
mspro_block_bd_getgeo(struct block_device * bdev,struct hd_geometry * geo)192baf8532aSAlex Dubov static int mspro_block_bd_getgeo(struct block_device *bdev,
193baf8532aSAlex Dubov 				 struct hd_geometry *geo)
194baf8532aSAlex Dubov {
195baf8532aSAlex Dubov 	struct mspro_block_data *msb = bdev->bd_disk->private_data;
196baf8532aSAlex Dubov 
197baf8532aSAlex Dubov 	geo->heads = msb->heads;
198baf8532aSAlex Dubov 	geo->sectors = msb->sectors_per_track;
199baf8532aSAlex Dubov 	geo->cylinders = msb->cylinders;
200baf8532aSAlex Dubov 
201baf8532aSAlex Dubov 	return 0;
202baf8532aSAlex Dubov }
203baf8532aSAlex Dubov 
20483d5cde4SAlexey Dobriyan static const struct block_device_operations ms_block_bdops = {
205185ed423SChristoph Hellwig 	.owner		= THIS_MODULE,
206baf8532aSAlex Dubov 	.getgeo		= mspro_block_bd_getgeo,
207185ed423SChristoph Hellwig 	.free_disk	= mspro_block_bd_free_disk,
208baf8532aSAlex Dubov };
209baf8532aSAlex Dubov 
210baf8532aSAlex Dubov /*** Information ***/
211baf8532aSAlex Dubov 
mspro_from_sysfs_attr(struct attribute * attr)212baf8532aSAlex Dubov static struct mspro_sys_attr *mspro_from_sysfs_attr(struct attribute *attr)
213baf8532aSAlex Dubov {
214baf8532aSAlex Dubov 	struct device_attribute *dev_attr
215baf8532aSAlex Dubov 		= container_of(attr, struct device_attribute, attr);
216baf8532aSAlex Dubov 	return container_of(dev_attr, struct mspro_sys_attr, dev_attr);
217baf8532aSAlex Dubov }
218baf8532aSAlex Dubov 
mspro_block_attr_name(unsigned char tag)219baf8532aSAlex Dubov static const char *mspro_block_attr_name(unsigned char tag)
220baf8532aSAlex Dubov {
221baf8532aSAlex Dubov 	switch (tag) {
222baf8532aSAlex Dubov 	case MSPRO_BLOCK_ID_SYSINFO:
223baf8532aSAlex Dubov 		return "attr_sysinfo";
224baf8532aSAlex Dubov 	case MSPRO_BLOCK_ID_MODELNAME:
225baf8532aSAlex Dubov 		return "attr_modelname";
226baf8532aSAlex Dubov 	case MSPRO_BLOCK_ID_MBR:
227baf8532aSAlex Dubov 		return "attr_mbr";
228baf8532aSAlex Dubov 	case MSPRO_BLOCK_ID_PBR16:
229baf8532aSAlex Dubov 		return "attr_pbr16";
230baf8532aSAlex Dubov 	case MSPRO_BLOCK_ID_PBR32:
231baf8532aSAlex Dubov 		return "attr_pbr32";
232baf8532aSAlex Dubov 	case MSPRO_BLOCK_ID_SPECFILEVALUES1:
233baf8532aSAlex Dubov 		return "attr_specfilevalues1";
234baf8532aSAlex Dubov 	case MSPRO_BLOCK_ID_SPECFILEVALUES2:
235baf8532aSAlex Dubov 		return "attr_specfilevalues2";
236baf8532aSAlex Dubov 	case MSPRO_BLOCK_ID_DEVINFO:
237baf8532aSAlex Dubov 		return "attr_devinfo";
238baf8532aSAlex Dubov 	default:
239baf8532aSAlex Dubov 		return NULL;
2408c3c0acaSTom Rix 	}
241baf8532aSAlex Dubov }
242baf8532aSAlex Dubov 
243baf8532aSAlex Dubov typedef ssize_t (*sysfs_show_t)(struct device *dev,
244baf8532aSAlex Dubov 				struct device_attribute *attr,
245baf8532aSAlex Dubov 				char *buffer);
246baf8532aSAlex Dubov 
mspro_block_attr_show_default(struct device * dev,struct device_attribute * attr,char * buffer)247baf8532aSAlex Dubov static ssize_t mspro_block_attr_show_default(struct device *dev,
248baf8532aSAlex Dubov 					     struct device_attribute *attr,
249baf8532aSAlex Dubov 					     char *buffer)
250baf8532aSAlex Dubov {
251baf8532aSAlex Dubov 	struct mspro_sys_attr *s_attr = container_of(attr,
252baf8532aSAlex Dubov 						     struct mspro_sys_attr,
253baf8532aSAlex Dubov 						     dev_attr);
254baf8532aSAlex Dubov 
255baf8532aSAlex Dubov 	ssize_t cnt, rc = 0;
256baf8532aSAlex Dubov 
257baf8532aSAlex Dubov 	for (cnt = 0; cnt < s_attr->size; cnt++) {
258baf8532aSAlex Dubov 		if (cnt && !(cnt % 16)) {
259baf8532aSAlex Dubov 			if (PAGE_SIZE - rc)
260baf8532aSAlex Dubov 				buffer[rc++] = '\n';
261baf8532aSAlex Dubov 		}
262baf8532aSAlex Dubov 
263*0c359970Sye xingchen 		rc += sysfs_emit_at(buffer, rc, "%02x ",
264baf8532aSAlex Dubov 				    ((unsigned char *)s_attr->data)[cnt]);
265baf8532aSAlex Dubov 	}
266baf8532aSAlex Dubov 	return rc;
267baf8532aSAlex Dubov }
268baf8532aSAlex Dubov 
mspro_block_attr_show_sysinfo(struct device * dev,struct device_attribute * attr,char * buffer)269baf8532aSAlex Dubov static ssize_t mspro_block_attr_show_sysinfo(struct device *dev,
270baf8532aSAlex Dubov 					     struct device_attribute *attr,
271baf8532aSAlex Dubov 					     char *buffer)
272baf8532aSAlex Dubov {
273baf8532aSAlex Dubov 	struct mspro_sys_attr *x_attr = container_of(attr,
274baf8532aSAlex Dubov 						     struct mspro_sys_attr,
275baf8532aSAlex Dubov 						     dev_attr);
276baf8532aSAlex Dubov 	struct mspro_sys_info *x_sys = x_attr->data;
277baf8532aSAlex Dubov 	ssize_t rc = 0;
278251cc9b9SAlex Dubov 	int date_tz = 0, date_tz_f = 0;
279251cc9b9SAlex Dubov 
280251cc9b9SAlex Dubov 	if (x_sys->assembly_date[0] > 0x80U) {
281251cc9b9SAlex Dubov 		date_tz = (~x_sys->assembly_date[0]) + 1;
282251cc9b9SAlex Dubov 		date_tz_f = date_tz & 3;
283251cc9b9SAlex Dubov 		date_tz >>= 2;
284251cc9b9SAlex Dubov 		date_tz = -date_tz;
285251cc9b9SAlex Dubov 		date_tz_f *= 15;
286251cc9b9SAlex Dubov 	} else if (x_sys->assembly_date[0] < 0x80U) {
287251cc9b9SAlex Dubov 		date_tz = x_sys->assembly_date[0];
288251cc9b9SAlex Dubov 		date_tz_f = date_tz & 3;
289251cc9b9SAlex Dubov 		date_tz >>= 2;
290251cc9b9SAlex Dubov 		date_tz_f *= 15;
291251cc9b9SAlex Dubov 	}
292baf8532aSAlex Dubov 
293*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "class: %x\n", x_sys->class);
294*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "block size: %x\n", be16_to_cpu(x_sys->block_size));
295*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "block count: %x\n", be16_to_cpu(x_sys->block_count));
296*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "user block count: %x\n",
297baf8532aSAlex Dubov 			    be16_to_cpu(x_sys->user_block_count));
298*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "page size: %x\n", be16_to_cpu(x_sys->page_size));
299*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "assembly date: GMT%+d:%d %04u-%02u-%02u %02u:%02u:%02u\n",
300251cc9b9SAlex Dubov 			    date_tz, date_tz_f,
30169347a23SHarvey Harrison 			    be16_to_cpup((__be16 *)&x_sys->assembly_date[1]),
302baf8532aSAlex Dubov 			    x_sys->assembly_date[3], x_sys->assembly_date[4],
303baf8532aSAlex Dubov 			    x_sys->assembly_date[5], x_sys->assembly_date[6],
304baf8532aSAlex Dubov 			    x_sys->assembly_date[7]);
305*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "serial number: %x\n", be32_to_cpu(x_sys->serial_number));
306*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "assembly maker code: %x\n", x_sys->assembly_maker_code);
307*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "assembly model code: %02x%02x%02x\n",
308*0c359970Sye xingchen 			    x_sys->assembly_model_code[0],
309baf8532aSAlex Dubov 			    x_sys->assembly_model_code[1],
310baf8532aSAlex Dubov 			    x_sys->assembly_model_code[2]);
311*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "memory maker code: %x\n",
312baf8532aSAlex Dubov 			    be16_to_cpu(x_sys->memory_maker_code));
313*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "memory model code: %x\n",
314baf8532aSAlex Dubov 			    be16_to_cpu(x_sys->memory_model_code));
315*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "vcc: %x\n", x_sys->vcc);
316*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "vpp: %x\n", x_sys->vpp);
317*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "controller number: %x\n",
318baf8532aSAlex Dubov 			    be16_to_cpu(x_sys->controller_number));
319*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "controller function: %x\n",
320baf8532aSAlex Dubov 			    be16_to_cpu(x_sys->controller_function));
321*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "start sector: %x\n", be16_to_cpu(x_sys->start_sector));
322*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "unit size: %x\n", be16_to_cpu(x_sys->unit_size));
323*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "sub class: %x\n", x_sys->ms_sub_class);
324*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "interface type: %x\n", x_sys->interface_type);
325*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "controller code: %x\n",
326baf8532aSAlex Dubov 			    be16_to_cpu(x_sys->controller_code));
327*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "format type: %x\n", x_sys->format_type);
328*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "device type: %x\n", x_sys->device_type);
329*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "mspro id: %s\n", x_sys->mspro_id);
330baf8532aSAlex Dubov 	return rc;
331baf8532aSAlex Dubov }
332baf8532aSAlex Dubov 
mspro_block_attr_show_modelname(struct device * dev,struct device_attribute * attr,char * buffer)333baf8532aSAlex Dubov static ssize_t mspro_block_attr_show_modelname(struct device *dev,
334baf8532aSAlex Dubov 					       struct device_attribute *attr,
335baf8532aSAlex Dubov 					       char *buffer)
336baf8532aSAlex Dubov {
337baf8532aSAlex Dubov 	struct mspro_sys_attr *s_attr = container_of(attr,
338baf8532aSAlex Dubov 						     struct mspro_sys_attr,
339baf8532aSAlex Dubov 						     dev_attr);
340baf8532aSAlex Dubov 
341*0c359970Sye xingchen 	return sysfs_emit(buffer, "%s", (char *)s_attr->data);
342baf8532aSAlex Dubov }
343baf8532aSAlex Dubov 
mspro_block_attr_show_mbr(struct device * dev,struct device_attribute * attr,char * buffer)344baf8532aSAlex Dubov static ssize_t mspro_block_attr_show_mbr(struct device *dev,
345baf8532aSAlex Dubov 					 struct device_attribute *attr,
346baf8532aSAlex Dubov 					 char *buffer)
347baf8532aSAlex Dubov {
348baf8532aSAlex Dubov 	struct mspro_sys_attr *x_attr = container_of(attr,
349baf8532aSAlex Dubov 						     struct mspro_sys_attr,
350baf8532aSAlex Dubov 						     dev_attr);
351baf8532aSAlex Dubov 	struct mspro_mbr *x_mbr = x_attr->data;
352baf8532aSAlex Dubov 	ssize_t rc = 0;
353baf8532aSAlex Dubov 
354*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "boot partition: %x\n", x_mbr->boot_partition);
355*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "start head: %x\n", x_mbr->start_head);
356*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "start sector: %x\n", x_mbr->start_sector);
357*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "start cylinder: %x\n", x_mbr->start_cylinder);
358*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "partition type: %x\n", x_mbr->partition_type);
359*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "end head: %x\n", x_mbr->end_head);
360*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "end sector: %x\n", x_mbr->end_sector);
361*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "end cylinder: %x\n", x_mbr->end_cylinder);
362*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "start sectors: %x\n", x_mbr->start_sectors);
363*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "sectors per partition: %x\n",
364baf8532aSAlex Dubov 			    x_mbr->sectors_per_partition);
365baf8532aSAlex Dubov 	return rc;
366baf8532aSAlex Dubov }
367baf8532aSAlex Dubov 
mspro_block_attr_show_specfile(struct device * dev,struct device_attribute * attr,char * buffer)368efb2742eSAlex Dubov static ssize_t mspro_block_attr_show_specfile(struct device *dev,
369efb2742eSAlex Dubov 					      struct device_attribute *attr,
370efb2742eSAlex Dubov 					      char *buffer)
371efb2742eSAlex Dubov {
372efb2742eSAlex Dubov 	struct mspro_sys_attr *x_attr = container_of(attr,
373efb2742eSAlex Dubov 						     struct mspro_sys_attr,
374efb2742eSAlex Dubov 						     dev_attr);
375efb2742eSAlex Dubov 	struct mspro_specfile *x_spfile = x_attr->data;
376efb2742eSAlex Dubov 	char name[9], ext[4];
377efb2742eSAlex Dubov 	ssize_t rc = 0;
378efb2742eSAlex Dubov 
379efb2742eSAlex Dubov 	memcpy(name, x_spfile->name, 8);
380efb2742eSAlex Dubov 	name[8] = 0;
381efb2742eSAlex Dubov 	memcpy(ext, x_spfile->ext, 3);
382efb2742eSAlex Dubov 	ext[3] = 0;
383efb2742eSAlex Dubov 
384*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "name: %s\n", name);
385*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "ext: %s\n", ext);
386*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "attribute: %x\n", x_spfile->attr);
387*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "time: %d:%d:%d\n",
388efb2742eSAlex Dubov 			    x_spfile->time >> 11,
389efb2742eSAlex Dubov 			    (x_spfile->time >> 5) & 0x3f,
390efb2742eSAlex Dubov 			    (x_spfile->time & 0x1f) * 2);
391*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "date: %d-%d-%d\n",
392efb2742eSAlex Dubov 			    (x_spfile->date >> 9) + 1980,
393efb2742eSAlex Dubov 			    (x_spfile->date >> 5) & 0xf,
394efb2742eSAlex Dubov 			    x_spfile->date & 0x1f);
395*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "start cluster: %x\n", x_spfile->cluster);
396*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "size: %x\n", x_spfile->size);
397efb2742eSAlex Dubov 	return rc;
398efb2742eSAlex Dubov }
399efb2742eSAlex Dubov 
mspro_block_attr_show_devinfo(struct device * dev,struct device_attribute * attr,char * buffer)400baf8532aSAlex Dubov static ssize_t mspro_block_attr_show_devinfo(struct device *dev,
401baf8532aSAlex Dubov 					     struct device_attribute *attr,
402baf8532aSAlex Dubov 					     char *buffer)
403baf8532aSAlex Dubov {
404baf8532aSAlex Dubov 	struct mspro_sys_attr *x_attr = container_of(attr,
405baf8532aSAlex Dubov 						     struct mspro_sys_attr,
406baf8532aSAlex Dubov 						     dev_attr);
407baf8532aSAlex Dubov 	struct mspro_devinfo *x_devinfo = x_attr->data;
408baf8532aSAlex Dubov 	ssize_t rc = 0;
409baf8532aSAlex Dubov 
410*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "cylinders: %x\n", be16_to_cpu(x_devinfo->cylinders));
411*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "heads: %x\n", be16_to_cpu(x_devinfo->heads));
412*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "bytes per track: %x\n",
413baf8532aSAlex Dubov 			    be16_to_cpu(x_devinfo->bytes_per_track));
414*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "bytes per sector: %x\n",
415baf8532aSAlex Dubov 			    be16_to_cpu(x_devinfo->bytes_per_sector));
416*0c359970Sye xingchen 	rc += sysfs_emit_at(buffer, rc, "sectors per track: %x\n",
417baf8532aSAlex Dubov 			    be16_to_cpu(x_devinfo->sectors_per_track));
418baf8532aSAlex Dubov 	return rc;
419baf8532aSAlex Dubov }
420baf8532aSAlex Dubov 
mspro_block_attr_show(unsigned char tag)421baf8532aSAlex Dubov static sysfs_show_t mspro_block_attr_show(unsigned char tag)
422baf8532aSAlex Dubov {
423baf8532aSAlex Dubov 	switch (tag) {
424baf8532aSAlex Dubov 	case MSPRO_BLOCK_ID_SYSINFO:
425baf8532aSAlex Dubov 		return mspro_block_attr_show_sysinfo;
426baf8532aSAlex Dubov 	case MSPRO_BLOCK_ID_MODELNAME:
427baf8532aSAlex Dubov 		return mspro_block_attr_show_modelname;
428baf8532aSAlex Dubov 	case MSPRO_BLOCK_ID_MBR:
429baf8532aSAlex Dubov 		return mspro_block_attr_show_mbr;
430efb2742eSAlex Dubov 	case MSPRO_BLOCK_ID_SPECFILEVALUES1:
431efb2742eSAlex Dubov 	case MSPRO_BLOCK_ID_SPECFILEVALUES2:
432efb2742eSAlex Dubov 		return mspro_block_attr_show_specfile;
433baf8532aSAlex Dubov 	case MSPRO_BLOCK_ID_DEVINFO:
434baf8532aSAlex Dubov 		return mspro_block_attr_show_devinfo;
435baf8532aSAlex Dubov 	default:
436baf8532aSAlex Dubov 		return mspro_block_attr_show_default;
437baf8532aSAlex Dubov 	}
438baf8532aSAlex Dubov }
439baf8532aSAlex Dubov 
440baf8532aSAlex Dubov /*** Protocol handlers ***/
441baf8532aSAlex Dubov 
442baf8532aSAlex Dubov /*
443baf8532aSAlex Dubov  * Functions prefixed with "h_" are protocol callbacks. They can be called from
444baf8532aSAlex Dubov  * interrupt context. Return value of 0 means that request processing is still
445baf8532aSAlex Dubov  * ongoing, while special error value of -EAGAIN means that current request is
446baf8532aSAlex Dubov  * finished (and request processor should come back some time later).
447baf8532aSAlex Dubov  */
448baf8532aSAlex Dubov 
h_mspro_block_req_init(struct memstick_dev * card,struct memstick_request ** mrq)449baf8532aSAlex Dubov static int h_mspro_block_req_init(struct memstick_dev *card,
450baf8532aSAlex Dubov 				  struct memstick_request **mrq)
451baf8532aSAlex Dubov {
452baf8532aSAlex Dubov 	struct mspro_block_data *msb = memstick_get_drvdata(card);
453baf8532aSAlex Dubov 
454baf8532aSAlex Dubov 	*mrq = &card->current_mrq;
455baf8532aSAlex Dubov 	card->next_request = msb->mrq_handler;
456baf8532aSAlex Dubov 	return 0;
457baf8532aSAlex Dubov }
458baf8532aSAlex Dubov 
h_mspro_block_default(struct memstick_dev * card,struct memstick_request ** mrq)459baf8532aSAlex Dubov static int h_mspro_block_default(struct memstick_dev *card,
460baf8532aSAlex Dubov 				 struct memstick_request **mrq)
461baf8532aSAlex Dubov {
462f1d82698SAlex Dubov 	return mspro_block_complete_req(card, (*mrq)->error);
463f1d82698SAlex Dubov }
464f1d82698SAlex Dubov 
h_mspro_block_default_bad(struct memstick_dev * card,struct memstick_request ** mrq)465f1d82698SAlex Dubov static int h_mspro_block_default_bad(struct memstick_dev *card,
466f1d82698SAlex Dubov 				     struct memstick_request **mrq)
467f1d82698SAlex Dubov {
468f1d82698SAlex Dubov 	return -ENXIO;
469baf8532aSAlex Dubov }
470baf8532aSAlex Dubov 
h_mspro_block_get_ro(struct memstick_dev * card,struct memstick_request ** mrq)471baf8532aSAlex Dubov static int h_mspro_block_get_ro(struct memstick_dev *card,
472baf8532aSAlex Dubov 				struct memstick_request **mrq)
473baf8532aSAlex Dubov {
474baf8532aSAlex Dubov 	struct mspro_block_data *msb = memstick_get_drvdata(card);
475baf8532aSAlex Dubov 
476f1d82698SAlex Dubov 	if (!(*mrq)->error) {
477baf8532aSAlex Dubov 		if ((*mrq)->data[offsetof(struct ms_status_register, status0)]
478baf8532aSAlex Dubov 		    & MEMSTICK_STATUS0_WP)
479baf8532aSAlex Dubov 			msb->read_only = 1;
480baf8532aSAlex Dubov 		else
481baf8532aSAlex Dubov 			msb->read_only = 0;
482f1d82698SAlex Dubov 	}
483baf8532aSAlex Dubov 
484f1d82698SAlex Dubov 	return mspro_block_complete_req(card, (*mrq)->error);
485baf8532aSAlex Dubov }
486baf8532aSAlex Dubov 
h_mspro_block_wait_for_ced(struct memstick_dev * card,struct memstick_request ** mrq)487baf8532aSAlex Dubov static int h_mspro_block_wait_for_ced(struct memstick_dev *card,
488baf8532aSAlex Dubov 				      struct memstick_request **mrq)
489baf8532aSAlex Dubov {
490baf8532aSAlex Dubov 	dev_dbg(&card->dev, "wait for ced: value %x\n", (*mrq)->data[0]);
491baf8532aSAlex Dubov 
492f1d82698SAlex Dubov 	if (!(*mrq)->error) {
493f1d82698SAlex Dubov 		if ((*mrq)->data[0] & (MEMSTICK_INT_CMDNAK | MEMSTICK_INT_ERR))
494f1d82698SAlex Dubov 			(*mrq)->error = -EFAULT;
495f1d82698SAlex Dubov 		else if (!((*mrq)->data[0] & MEMSTICK_INT_CED))
496f1d82698SAlex Dubov 			return 0;
497baf8532aSAlex Dubov 	}
498baf8532aSAlex Dubov 
499f1d82698SAlex Dubov 	return mspro_block_complete_req(card, (*mrq)->error);
500baf8532aSAlex Dubov }
501baf8532aSAlex Dubov 
h_mspro_block_transfer_data(struct memstick_dev * card,struct memstick_request ** mrq)502baf8532aSAlex Dubov static int h_mspro_block_transfer_data(struct memstick_dev *card,
503baf8532aSAlex Dubov 				       struct memstick_request **mrq)
504baf8532aSAlex Dubov {
505baf8532aSAlex Dubov 	struct mspro_block_data *msb = memstick_get_drvdata(card);
506baf8532aSAlex Dubov 	unsigned char t_val = 0;
507baf8532aSAlex Dubov 	struct scatterlist t_sg = { 0 };
508baf8532aSAlex Dubov 	size_t t_offset;
509baf8532aSAlex Dubov 
510f1d82698SAlex Dubov 	if ((*mrq)->error)
511f1d82698SAlex Dubov 		return mspro_block_complete_req(card, (*mrq)->error);
512baf8532aSAlex Dubov 
513baf8532aSAlex Dubov 	switch ((*mrq)->tpc) {
514baf8532aSAlex Dubov 	case MS_TPC_WRITE_REG:
515baf8532aSAlex Dubov 		memstick_init_req(*mrq, MS_TPC_SET_CMD, &msb->transfer_cmd, 1);
516ead70773SAlex Dubov 		(*mrq)->need_card_int = 1;
517baf8532aSAlex Dubov 		return 0;
518baf8532aSAlex Dubov 	case MS_TPC_SET_CMD:
519baf8532aSAlex Dubov 		t_val = (*mrq)->int_reg;
520baf8532aSAlex Dubov 		memstick_init_req(*mrq, MS_TPC_GET_INT, NULL, 1);
521ead70773SAlex Dubov 		if (msb->caps & MEMSTICK_CAP_AUTO_GET_INT)
522baf8532aSAlex Dubov 			goto has_int_reg;
523baf8532aSAlex Dubov 		return 0;
524baf8532aSAlex Dubov 	case MS_TPC_GET_INT:
525baf8532aSAlex Dubov 		t_val = (*mrq)->data[0];
526baf8532aSAlex Dubov has_int_reg:
527baf8532aSAlex Dubov 		if (t_val & (MEMSTICK_INT_CMDNAK | MEMSTICK_INT_ERR)) {
528baf8532aSAlex Dubov 			t_val = MSPRO_CMD_STOP;
529baf8532aSAlex Dubov 			memstick_init_req(*mrq, MS_TPC_SET_CMD, &t_val, 1);
530baf8532aSAlex Dubov 			card->next_request = h_mspro_block_default;
531baf8532aSAlex Dubov 			return 0;
532baf8532aSAlex Dubov 		}
533baf8532aSAlex Dubov 
534baf8532aSAlex Dubov 		if (msb->current_page
535baf8532aSAlex Dubov 		    == (msb->req_sg[msb->current_seg].length
536baf8532aSAlex Dubov 			/ msb->page_size)) {
537baf8532aSAlex Dubov 			msb->current_page = 0;
538baf8532aSAlex Dubov 			msb->current_seg++;
539baf8532aSAlex Dubov 
540baf8532aSAlex Dubov 			if (msb->current_seg == msb->seg_count) {
541baf8532aSAlex Dubov 				if (t_val & MEMSTICK_INT_CED) {
542f1d82698SAlex Dubov 					return mspro_block_complete_req(card,
543f1d82698SAlex Dubov 									0);
544baf8532aSAlex Dubov 				} else {
545baf8532aSAlex Dubov 					card->next_request
546baf8532aSAlex Dubov 						= h_mspro_block_wait_for_ced;
547baf8532aSAlex Dubov 					memstick_init_req(*mrq, MS_TPC_GET_INT,
548baf8532aSAlex Dubov 							  NULL, 1);
549baf8532aSAlex Dubov 					return 0;
550baf8532aSAlex Dubov 				}
551baf8532aSAlex Dubov 			}
552baf8532aSAlex Dubov 		}
553baf8532aSAlex Dubov 
554baf8532aSAlex Dubov 		if (!(t_val & MEMSTICK_INT_BREQ)) {
555baf8532aSAlex Dubov 			memstick_init_req(*mrq, MS_TPC_GET_INT, NULL, 1);
556baf8532aSAlex Dubov 			return 0;
557baf8532aSAlex Dubov 		}
558baf8532aSAlex Dubov 
559baf8532aSAlex Dubov 		t_offset = msb->req_sg[msb->current_seg].offset;
560baf8532aSAlex Dubov 		t_offset += msb->current_page * msb->page_size;
561baf8532aSAlex Dubov 
562baf8532aSAlex Dubov 		sg_set_page(&t_sg,
563baf8532aSAlex Dubov 			    nth_page(sg_page(&(msb->req_sg[msb->current_seg])),
564baf8532aSAlex Dubov 				     t_offset >> PAGE_SHIFT),
565baf8532aSAlex Dubov 			    msb->page_size, offset_in_page(t_offset));
566baf8532aSAlex Dubov 
567baf8532aSAlex Dubov 		memstick_init_req_sg(*mrq, msb->data_dir == READ
568baf8532aSAlex Dubov 					   ? MS_TPC_READ_LONG_DATA
569baf8532aSAlex Dubov 					   : MS_TPC_WRITE_LONG_DATA,
570baf8532aSAlex Dubov 				     &t_sg);
571ead70773SAlex Dubov 		(*mrq)->need_card_int = 1;
572baf8532aSAlex Dubov 		return 0;
573baf8532aSAlex Dubov 	case MS_TPC_READ_LONG_DATA:
574baf8532aSAlex Dubov 	case MS_TPC_WRITE_LONG_DATA:
575baf8532aSAlex Dubov 		msb->current_page++;
576ead70773SAlex Dubov 		if (msb->caps & MEMSTICK_CAP_AUTO_GET_INT) {
577baf8532aSAlex Dubov 			t_val = (*mrq)->int_reg;
578baf8532aSAlex Dubov 			goto has_int_reg;
579baf8532aSAlex Dubov 		} else {
580baf8532aSAlex Dubov 			memstick_init_req(*mrq, MS_TPC_GET_INT, NULL, 1);
581baf8532aSAlex Dubov 			return 0;
582baf8532aSAlex Dubov 		}
583baf8532aSAlex Dubov 
584baf8532aSAlex Dubov 	default:
585baf8532aSAlex Dubov 		BUG();
586baf8532aSAlex Dubov 	}
587baf8532aSAlex Dubov }
588baf8532aSAlex Dubov 
589496fc1a6SAlex Dubov /*** Transfer setup functions for different access methods. ***/
590496fc1a6SAlex Dubov 
591496fc1a6SAlex Dubov /** Setup data transfer request for SET_CMD TPC with arguments in card
592496fc1a6SAlex Dubov  *  registers.
593496fc1a6SAlex Dubov  *
594496fc1a6SAlex Dubov  *  @card    Current media instance
595496fc1a6SAlex Dubov  *  @offset  Target data offset in bytes
596496fc1a6SAlex Dubov  *  @length  Required transfer length in bytes.
597496fc1a6SAlex Dubov  */
h_mspro_block_setup_cmd(struct memstick_dev * card,u64 offset,size_t length)598496fc1a6SAlex Dubov static void h_mspro_block_setup_cmd(struct memstick_dev *card, u64 offset,
599496fc1a6SAlex Dubov 				    size_t length)
600496fc1a6SAlex Dubov {
601496fc1a6SAlex Dubov 	struct mspro_block_data *msb = memstick_get_drvdata(card);
602496fc1a6SAlex Dubov 	struct mspro_param_register param = {
603496fc1a6SAlex Dubov 		.system = msb->system,
604496fc1a6SAlex Dubov 		.data_count = cpu_to_be16((uint16_t)(length / msb->page_size)),
605496fc1a6SAlex Dubov 		/* ISO C90 warning precludes direct initialization for now. */
606496fc1a6SAlex Dubov 		.data_address = 0,
607496fc1a6SAlex Dubov 		.tpc_param = 0
608496fc1a6SAlex Dubov 	};
609496fc1a6SAlex Dubov 
610496fc1a6SAlex Dubov 	do_div(offset, msb->page_size);
611496fc1a6SAlex Dubov 	param.data_address = cpu_to_be32((uint32_t)offset);
612496fc1a6SAlex Dubov 
613496fc1a6SAlex Dubov 	card->next_request = h_mspro_block_req_init;
614496fc1a6SAlex Dubov 	msb->mrq_handler = h_mspro_block_transfer_data;
615496fc1a6SAlex Dubov 	memstick_init_req(&card->current_mrq, MS_TPC_WRITE_REG,
616496fc1a6SAlex Dubov 			  &param, sizeof(param));
617496fc1a6SAlex Dubov }
618496fc1a6SAlex Dubov 
619baf8532aSAlex Dubov /*** Data transfer ***/
620baf8532aSAlex Dubov 
mspro_block_issue_req(struct memstick_dev * card)62161009f82SDan Carpenter static int mspro_block_issue_req(struct memstick_dev *card)
622baf8532aSAlex Dubov {
623baf8532aSAlex Dubov 	struct mspro_block_data *msb = memstick_get_drvdata(card);
624496fc1a6SAlex Dubov 	u64 t_off;
625f1d82698SAlex Dubov 	unsigned int count;
626baf8532aSAlex Dubov 
62761009f82SDan Carpenter 	while (true) {
628baf8532aSAlex Dubov 		msb->current_page = 0;
629f1d82698SAlex Dubov 		msb->current_seg = 0;
630f1d82698SAlex Dubov 		msb->seg_count = blk_rq_map_sg(msb->block_req->q,
631f1d82698SAlex Dubov 					       msb->block_req,
632f1d82698SAlex Dubov 					       msb->req_sg);
633baf8532aSAlex Dubov 
634f1d82698SAlex Dubov 		if (!msb->seg_count) {
635d0be1227SJens Axboe 			unsigned int bytes = blk_rq_cur_bytes(msb->block_req);
63661009f82SDan Carpenter 			bool chunk;
637d0be1227SJens Axboe 
638d0be1227SJens Axboe 			chunk = blk_update_request(msb->block_req,
639d0be1227SJens Axboe 							BLK_STS_RESOURCE,
640d0be1227SJens Axboe 							bytes);
641d0be1227SJens Axboe 			if (chunk)
642f1d82698SAlex Dubov 				continue;
643d0be1227SJens Axboe 			__blk_mq_end_request(msb->block_req,
644d0be1227SJens Axboe 						BLK_STS_RESOURCE);
645d0be1227SJens Axboe 			msb->block_req = NULL;
64661009f82SDan Carpenter 			return -EAGAIN;
647f1d82698SAlex Dubov 		}
648f1d82698SAlex Dubov 
649496fc1a6SAlex Dubov 		t_off = blk_rq_pos(msb->block_req);
650496fc1a6SAlex Dubov 		t_off <<= 9;
6511011c1b9STejun Heo 		count = blk_rq_bytes(msb->block_req);
652f1d82698SAlex Dubov 
653496fc1a6SAlex Dubov 		msb->setup_transfer(card, t_off, count);
654baf8532aSAlex Dubov 
655f1d82698SAlex Dubov 		msb->data_dir = rq_data_dir(msb->block_req);
656baf8532aSAlex Dubov 		msb->transfer_cmd = msb->data_dir == READ
657baf8532aSAlex Dubov 				    ? MSPRO_CMD_READ_DATA
658baf8532aSAlex Dubov 				    : MSPRO_CMD_WRITE_DATA;
659baf8532aSAlex Dubov 
660baf8532aSAlex Dubov 		memstick_new_req(card->host);
661f1d82698SAlex Dubov 		return 0;
662baf8532aSAlex Dubov 	}
663f1d82698SAlex Dubov }
664f1d82698SAlex Dubov 
mspro_block_complete_req(struct memstick_dev * card,int error)665f1d82698SAlex Dubov static int mspro_block_complete_req(struct memstick_dev *card, int error)
666baf8532aSAlex Dubov {
667f1d82698SAlex Dubov 	struct mspro_block_data *msb = memstick_get_drvdata(card);
668d0be1227SJens Axboe 	int cnt;
669d0be1227SJens Axboe 	bool chunk;
670f1d82698SAlex Dubov 	unsigned int t_len = 0;
671baf8532aSAlex Dubov 	unsigned long flags;
672baf8532aSAlex Dubov 
673baf8532aSAlex Dubov 	spin_lock_irqsave(&msb->q_lock, flags);
674d0be1227SJens Axboe 	dev_dbg(&card->dev, "complete %d, %d\n", msb->block_req ? 1 : 0,
675f1d82698SAlex Dubov 		error);
676f1d82698SAlex Dubov 
677d0be1227SJens Axboe 	if (msb->block_req) {
678f1d82698SAlex Dubov 		/* Nothing to do - not really an error */
679f1d82698SAlex Dubov 		if (error == -EAGAIN)
680f1d82698SAlex Dubov 			error = 0;
681f1d82698SAlex Dubov 
682f1d82698SAlex Dubov 		if (error || (card->current_mrq.tpc == MSPRO_CMD_STOP)) {
683f1d82698SAlex Dubov 			if (msb->data_dir == READ) {
68413f6b191SDan Carpenter 				for (cnt = 0; cnt < msb->current_seg; cnt++) {
685f1d82698SAlex Dubov 					t_len += msb->req_sg[cnt].length
686f1d82698SAlex Dubov 						 / msb->page_size;
687f1d82698SAlex Dubov 
688f1d82698SAlex Dubov 					if (msb->current_page)
689f1d82698SAlex Dubov 						t_len += msb->current_page - 1;
690f1d82698SAlex Dubov 
691f1d82698SAlex Dubov 					t_len *= msb->page_size;
692f1d82698SAlex Dubov 				}
69313f6b191SDan Carpenter 			}
694f1d82698SAlex Dubov 		} else
6951011c1b9STejun Heo 			t_len = blk_rq_bytes(msb->block_req);
696f1d82698SAlex Dubov 
697f1d82698SAlex Dubov 		dev_dbg(&card->dev, "transferred %x (%d)\n", t_len, error);
698f1d82698SAlex Dubov 
699f1d82698SAlex Dubov 		if (error && !t_len)
700f1d82698SAlex Dubov 			t_len = blk_rq_cur_bytes(msb->block_req);
701f1d82698SAlex Dubov 
702d0be1227SJens Axboe 		chunk = blk_update_request(msb->block_req,
7032a842acaSChristoph Hellwig 				errno_to_blk_status(error), t_len);
704d0be1227SJens Axboe 		if (chunk) {
70561009f82SDan Carpenter 			error = mspro_block_issue_req(card);
706f1d82698SAlex Dubov 			if (!error)
707f1d82698SAlex Dubov 				goto out;
708d0be1227SJens Axboe 		} else {
709d0be1227SJens Axboe 			__blk_mq_end_request(msb->block_req,
710d0be1227SJens Axboe 						errno_to_blk_status(error));
711d0be1227SJens Axboe 			msb->block_req = NULL;
712d0be1227SJens Axboe 		}
713f1d82698SAlex Dubov 	} else {
714f1d82698SAlex Dubov 		if (!error)
715f1d82698SAlex Dubov 			error = -EAGAIN;
716f1d82698SAlex Dubov 	}
717f1d82698SAlex Dubov 
718f1d82698SAlex Dubov 	card->next_request = h_mspro_block_default_bad;
719f1d82698SAlex Dubov 	complete_all(&card->mrq_complete);
720f1d82698SAlex Dubov out:
721baf8532aSAlex Dubov 	spin_unlock_irqrestore(&msb->q_lock, flags);
722f1d82698SAlex Dubov 	return error;
723baf8532aSAlex Dubov }
724baf8532aSAlex Dubov 
mspro_block_stop(struct memstick_dev * card)72517017d8dSAlex Dubov static void mspro_block_stop(struct memstick_dev *card)
72617017d8dSAlex Dubov {
72717017d8dSAlex Dubov 	struct mspro_block_data *msb = memstick_get_drvdata(card);
72817017d8dSAlex Dubov 	int rc = 0;
72917017d8dSAlex Dubov 	unsigned long flags;
73017017d8dSAlex Dubov 
73117017d8dSAlex Dubov 	while (1) {
73217017d8dSAlex Dubov 		spin_lock_irqsave(&msb->q_lock, flags);
733d0be1227SJens Axboe 		if (!msb->block_req) {
734d0be1227SJens Axboe 			blk_mq_stop_hw_queues(msb->queue);
73517017d8dSAlex Dubov 			rc = 1;
73617017d8dSAlex Dubov 		}
73717017d8dSAlex Dubov 		spin_unlock_irqrestore(&msb->q_lock, flags);
73817017d8dSAlex Dubov 
73917017d8dSAlex Dubov 		if (rc)
74017017d8dSAlex Dubov 			break;
74117017d8dSAlex Dubov 
74217017d8dSAlex Dubov 		wait_for_completion(&card->mrq_complete);
74317017d8dSAlex Dubov 	}
74417017d8dSAlex Dubov }
74517017d8dSAlex Dubov 
mspro_block_start(struct memstick_dev * card)74617017d8dSAlex Dubov static void mspro_block_start(struct memstick_dev *card)
74717017d8dSAlex Dubov {
74817017d8dSAlex Dubov 	struct mspro_block_data *msb = memstick_get_drvdata(card);
74917017d8dSAlex Dubov 
750d0be1227SJens Axboe 	blk_mq_start_hw_queues(msb->queue);
75117017d8dSAlex Dubov }
75217017d8dSAlex Dubov 
mspro_queue_rq(struct blk_mq_hw_ctx * hctx,const struct blk_mq_queue_data * bd)753d0be1227SJens Axboe static blk_status_t mspro_queue_rq(struct blk_mq_hw_ctx *hctx,
754d0be1227SJens Axboe 				   const struct blk_mq_queue_data *bd)
755baf8532aSAlex Dubov {
756d0be1227SJens Axboe 	struct memstick_dev *card = hctx->queue->queuedata;
757baf8532aSAlex Dubov 	struct mspro_block_data *msb = memstick_get_drvdata(card);
758baf8532aSAlex Dubov 
759d0be1227SJens Axboe 	spin_lock_irq(&msb->q_lock);
760d0be1227SJens Axboe 
761d0be1227SJens Axboe 	if (msb->block_req) {
762d0be1227SJens Axboe 		spin_unlock_irq(&msb->q_lock);
763d0be1227SJens Axboe 		return BLK_STS_DEV_RESOURCE;
764d0be1227SJens Axboe 	}
765f1d82698SAlex Dubov 
766f1d82698SAlex Dubov 	if (msb->eject) {
767d0be1227SJens Axboe 		spin_unlock_irq(&msb->q_lock);
768d0be1227SJens Axboe 		blk_mq_start_request(bd->rq);
769d0be1227SJens Axboe 		return BLK_STS_IOERR;
770baf8532aSAlex Dubov 	}
771f1d82698SAlex Dubov 
772d0be1227SJens Axboe 	msb->block_req = bd->rq;
773d0be1227SJens Axboe 	blk_mq_start_request(bd->rq);
774d0be1227SJens Axboe 
77561009f82SDan Carpenter 	if (mspro_block_issue_req(card))
776d0be1227SJens Axboe 		msb->block_req = NULL;
777d0be1227SJens Axboe 
778d0be1227SJens Axboe 	spin_unlock_irq(&msb->q_lock);
779d0be1227SJens Axboe 	return BLK_STS_OK;
780baf8532aSAlex Dubov }
781baf8532aSAlex Dubov 
782baf8532aSAlex Dubov /*** Initialization ***/
783baf8532aSAlex Dubov 
mspro_block_wait_for_ced(struct memstick_dev * card)784baf8532aSAlex Dubov static int mspro_block_wait_for_ced(struct memstick_dev *card)
785baf8532aSAlex Dubov {
786baf8532aSAlex Dubov 	struct mspro_block_data *msb = memstick_get_drvdata(card);
787baf8532aSAlex Dubov 
788baf8532aSAlex Dubov 	card->next_request = h_mspro_block_req_init;
789baf8532aSAlex Dubov 	msb->mrq_handler = h_mspro_block_wait_for_ced;
790baf8532aSAlex Dubov 	memstick_init_req(&card->current_mrq, MS_TPC_GET_INT, NULL, 1);
791baf8532aSAlex Dubov 	memstick_new_req(card->host);
792baf8532aSAlex Dubov 	wait_for_completion(&card->mrq_complete);
793baf8532aSAlex Dubov 	return card->current_mrq.error;
794baf8532aSAlex Dubov }
795baf8532aSAlex Dubov 
mspro_block_set_interface(struct memstick_dev * card,unsigned char sys_reg)796962ee1b1SAlex Dubov static int mspro_block_set_interface(struct memstick_dev *card,
797962ee1b1SAlex Dubov 				     unsigned char sys_reg)
798baf8532aSAlex Dubov {
799baf8532aSAlex Dubov 	struct memstick_host *host = card->host;
800baf8532aSAlex Dubov 	struct mspro_block_data *msb = memstick_get_drvdata(card);
801baf8532aSAlex Dubov 	struct mspro_param_register param = {
802962ee1b1SAlex Dubov 		.system = sys_reg,
803baf8532aSAlex Dubov 		.data_count = 0,
804baf8532aSAlex Dubov 		.data_address = 0,
805e1f19995SAlex Dubov 		.tpc_param = 0
806baf8532aSAlex Dubov 	};
807baf8532aSAlex Dubov 
808baf8532aSAlex Dubov 	card->next_request = h_mspro_block_req_init;
809baf8532aSAlex Dubov 	msb->mrq_handler = h_mspro_block_default;
810baf8532aSAlex Dubov 	memstick_init_req(&card->current_mrq, MS_TPC_WRITE_REG, &param,
811baf8532aSAlex Dubov 			  sizeof(param));
812baf8532aSAlex Dubov 	memstick_new_req(host);
813baf8532aSAlex Dubov 	wait_for_completion(&card->mrq_complete);
814baf8532aSAlex Dubov 	return card->current_mrq.error;
815962ee1b1SAlex Dubov }
816962ee1b1SAlex Dubov 
mspro_block_switch_interface(struct memstick_dev * card)817962ee1b1SAlex Dubov static int mspro_block_switch_interface(struct memstick_dev *card)
818962ee1b1SAlex Dubov {
819962ee1b1SAlex Dubov 	struct memstick_host *host = card->host;
820962ee1b1SAlex Dubov 	struct mspro_block_data *msb = memstick_get_drvdata(card);
821962ee1b1SAlex Dubov 	int rc = 0;
822962ee1b1SAlex Dubov 
8238e82f8c3SAlex Dubov try_again:
824962ee1b1SAlex Dubov 	if (msb->caps & MEMSTICK_CAP_PAR4)
825962ee1b1SAlex Dubov 		rc = mspro_block_set_interface(card, MEMSTICK_SYS_PAR4);
826962ee1b1SAlex Dubov 	else
827962ee1b1SAlex Dubov 		return 0;
828962ee1b1SAlex Dubov 
829962ee1b1SAlex Dubov 	if (rc) {
830962ee1b1SAlex Dubov 		printk(KERN_WARNING
831962ee1b1SAlex Dubov 		       "%s: could not switch to 4-bit mode, error %d\n",
8320252c3b4SKay Sievers 		       dev_name(&card->dev), rc);
833962ee1b1SAlex Dubov 		return 0;
834962ee1b1SAlex Dubov 	}
835baf8532aSAlex Dubov 
836e1f19995SAlex Dubov 	msb->system = MEMSTICK_SYS_PAR4;
837e1f19995SAlex Dubov 	host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_PAR4);
838962ee1b1SAlex Dubov 	printk(KERN_INFO "%s: switching to 4-bit parallel mode\n",
8390252c3b4SKay Sievers 	       dev_name(&card->dev));
840962ee1b1SAlex Dubov 
841962ee1b1SAlex Dubov 	if (msb->caps & MEMSTICK_CAP_PAR8) {
842962ee1b1SAlex Dubov 		rc = mspro_block_set_interface(card, MEMSTICK_SYS_PAR8);
843962ee1b1SAlex Dubov 
844962ee1b1SAlex Dubov 		if (!rc) {
845962ee1b1SAlex Dubov 			msb->system = MEMSTICK_SYS_PAR8;
846962ee1b1SAlex Dubov 			host->set_param(host, MEMSTICK_INTERFACE,
847962ee1b1SAlex Dubov 					MEMSTICK_PAR8);
848962ee1b1SAlex Dubov 			printk(KERN_INFO
849962ee1b1SAlex Dubov 			       "%s: switching to 8-bit parallel mode\n",
8500252c3b4SKay Sievers 			       dev_name(&card->dev));
851962ee1b1SAlex Dubov 		} else
852962ee1b1SAlex Dubov 			printk(KERN_WARNING
853962ee1b1SAlex Dubov 			       "%s: could not switch to 8-bit mode, error %d\n",
8540252c3b4SKay Sievers 			       dev_name(&card->dev), rc);
855962ee1b1SAlex Dubov 	}
856baf8532aSAlex Dubov 
857baf8532aSAlex Dubov 	card->next_request = h_mspro_block_req_init;
858baf8532aSAlex Dubov 	msb->mrq_handler = h_mspro_block_default;
859baf8532aSAlex Dubov 	memstick_init_req(&card->current_mrq, MS_TPC_GET_INT, NULL, 1);
860baf8532aSAlex Dubov 	memstick_new_req(card->host);
861baf8532aSAlex Dubov 	wait_for_completion(&card->mrq_complete);
862962ee1b1SAlex Dubov 	rc = card->current_mrq.error;
863baf8532aSAlex Dubov 
864962ee1b1SAlex Dubov 	if (rc) {
865962ee1b1SAlex Dubov 		printk(KERN_WARNING
866962ee1b1SAlex Dubov 		       "%s: interface error, trying to fall back to serial\n",
8670252c3b4SKay Sievers 		       dev_name(&card->dev));
86859367258SAlex Dubov 		msb->system = MEMSTICK_SYS_SERIAL;
86959367258SAlex Dubov 		host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_OFF);
870962ee1b1SAlex Dubov 		msleep(10);
87159367258SAlex Dubov 		host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_ON);
872baf8532aSAlex Dubov 		host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_SERIAL);
87359367258SAlex Dubov 
874962ee1b1SAlex Dubov 		rc = memstick_set_rw_addr(card);
875962ee1b1SAlex Dubov 		if (!rc)
876962ee1b1SAlex Dubov 			rc = mspro_block_set_interface(card, msb->system);
8778e82f8c3SAlex Dubov 
8788e82f8c3SAlex Dubov 		if (!rc) {
8798e82f8c3SAlex Dubov 			msleep(150);
8808e82f8c3SAlex Dubov 			rc = mspro_block_wait_for_ced(card);
8818e82f8c3SAlex Dubov 			if (rc)
8828e82f8c3SAlex Dubov 				return rc;
8838e82f8c3SAlex Dubov 
8848e82f8c3SAlex Dubov 			if (msb->caps & MEMSTICK_CAP_PAR8) {
8858e82f8c3SAlex Dubov 				msb->caps &= ~MEMSTICK_CAP_PAR8;
8868e82f8c3SAlex Dubov 				goto try_again;
8878e82f8c3SAlex Dubov 			}
8888e82f8c3SAlex Dubov 		}
889baf8532aSAlex Dubov 	}
890962ee1b1SAlex Dubov 	return rc;
891baf8532aSAlex Dubov }
892baf8532aSAlex Dubov 
893baf8532aSAlex Dubov /* Memory allocated for attributes by this function should be freed by
89425985edcSLucas De Marchi  * mspro_block_data_clear, no matter if the initialization process succeeded
895baf8532aSAlex Dubov  * or failed.
896baf8532aSAlex Dubov  */
mspro_block_read_attributes(struct memstick_dev * card)897baf8532aSAlex Dubov static int mspro_block_read_attributes(struct memstick_dev *card)
898baf8532aSAlex Dubov {
899baf8532aSAlex Dubov 	struct mspro_block_data *msb = memstick_get_drvdata(card);
900baf8532aSAlex Dubov 	struct mspro_attribute *attr = NULL;
901baf8532aSAlex Dubov 	struct mspro_sys_attr *s_attr = NULL;
902baf8532aSAlex Dubov 	unsigned char *buffer = NULL;
903baf8532aSAlex Dubov 	int cnt, rc, attr_count;
904496fc1a6SAlex Dubov 	/* While normally physical device offsets, represented here by
905496fc1a6SAlex Dubov 	 * attr_offset and attr_len will be of large numeric types, we can be
906496fc1a6SAlex Dubov 	 * sure, that attributes are close enough to the beginning of the
907496fc1a6SAlex Dubov 	 * device, to save ourselves some trouble.
908496fc1a6SAlex Dubov 	 */
909496fc1a6SAlex Dubov 	unsigned int addr, attr_offset = 0, attr_len = msb->page_size;
910baf8532aSAlex Dubov 
911baf8532aSAlex Dubov 	attr = kmalloc(msb->page_size, GFP_KERNEL);
912baf8532aSAlex Dubov 	if (!attr)
913baf8532aSAlex Dubov 		return -ENOMEM;
914baf8532aSAlex Dubov 
915baf8532aSAlex Dubov 	sg_init_one(&msb->req_sg[0], attr, msb->page_size);
916baf8532aSAlex Dubov 	msb->seg_count = 1;
917baf8532aSAlex Dubov 	msb->current_seg = 0;
918baf8532aSAlex Dubov 	msb->current_page = 0;
919baf8532aSAlex Dubov 	msb->data_dir = READ;
920baf8532aSAlex Dubov 	msb->transfer_cmd = MSPRO_CMD_READ_ATRB;
921baf8532aSAlex Dubov 
922496fc1a6SAlex Dubov 	msb->setup_transfer(card, attr_offset, attr_len);
923496fc1a6SAlex Dubov 
924baf8532aSAlex Dubov 	memstick_new_req(card->host);
925baf8532aSAlex Dubov 	wait_for_completion(&card->mrq_complete);
926baf8532aSAlex Dubov 	if (card->current_mrq.error) {
927baf8532aSAlex Dubov 		rc = card->current_mrq.error;
928baf8532aSAlex Dubov 		goto out_free_attr;
929baf8532aSAlex Dubov 	}
930baf8532aSAlex Dubov 
931baf8532aSAlex Dubov 	if (be16_to_cpu(attr->signature) != MSPRO_BLOCK_SIGNATURE) {
932baf8532aSAlex Dubov 		printk(KERN_ERR "%s: unrecognized device signature %x\n",
9330252c3b4SKay Sievers 		       dev_name(&card->dev), be16_to_cpu(attr->signature));
934baf8532aSAlex Dubov 		rc = -ENODEV;
935baf8532aSAlex Dubov 		goto out_free_attr;
936baf8532aSAlex Dubov 	}
937baf8532aSAlex Dubov 
938baf8532aSAlex Dubov 	if (attr->count > MSPRO_BLOCK_MAX_ATTRIBUTES) {
939baf8532aSAlex Dubov 		printk(KERN_WARNING "%s: way too many attribute entries\n",
9400252c3b4SKay Sievers 		       dev_name(&card->dev));
941baf8532aSAlex Dubov 		attr_count = MSPRO_BLOCK_MAX_ATTRIBUTES;
942baf8532aSAlex Dubov 	} else
943baf8532aSAlex Dubov 		attr_count = attr->count;
944baf8532aSAlex Dubov 
945be2d3f97SMichal Nazarewicz 	msb->attr_group.attrs = kcalloc(attr_count + 1,
946be2d3f97SMichal Nazarewicz 					sizeof(*msb->attr_group.attrs),
947baf8532aSAlex Dubov 					GFP_KERNEL);
948baf8532aSAlex Dubov 	if (!msb->attr_group.attrs) {
949baf8532aSAlex Dubov 		rc = -ENOMEM;
950baf8532aSAlex Dubov 		goto out_free_attr;
951baf8532aSAlex Dubov 	}
952baf8532aSAlex Dubov 	msb->attr_group.name = "media_attributes";
953baf8532aSAlex Dubov 
954de6cdcb5SMuhammad Falak R Wani 	buffer = kmemdup(attr, attr_len, GFP_KERNEL);
955baf8532aSAlex Dubov 	if (!buffer) {
956baf8532aSAlex Dubov 		rc = -ENOMEM;
957baf8532aSAlex Dubov 		goto out_free_attr;
958baf8532aSAlex Dubov 	}
959baf8532aSAlex Dubov 
960baf8532aSAlex Dubov 	for (cnt = 0; cnt < attr_count; ++cnt) {
961baf8532aSAlex Dubov 		s_attr = kzalloc(sizeof(struct mspro_sys_attr), GFP_KERNEL);
962baf8532aSAlex Dubov 		if (!s_attr) {
963baf8532aSAlex Dubov 			rc = -ENOMEM;
964baf8532aSAlex Dubov 			goto out_free_buffer;
965baf8532aSAlex Dubov 		}
966baf8532aSAlex Dubov 
967baf8532aSAlex Dubov 		msb->attr_group.attrs[cnt] = &s_attr->dev_attr.attr;
968baf8532aSAlex Dubov 		addr = be32_to_cpu(attr->entries[cnt].address);
969496fc1a6SAlex Dubov 		s_attr->size = be32_to_cpu(attr->entries[cnt].size);
970baf8532aSAlex Dubov 		dev_dbg(&card->dev, "adding attribute %d: id %x, address %x, "
971496fc1a6SAlex Dubov 			"size %zx\n", cnt, attr->entries[cnt].id, addr,
972496fc1a6SAlex Dubov 			s_attr->size);
973baf8532aSAlex Dubov 		s_attr->id = attr->entries[cnt].id;
974baf8532aSAlex Dubov 		if (mspro_block_attr_name(s_attr->id))
975baf8532aSAlex Dubov 			snprintf(s_attr->name, sizeof(s_attr->name), "%s",
976baf8532aSAlex Dubov 				 mspro_block_attr_name(attr->entries[cnt].id));
977baf8532aSAlex Dubov 		else
978baf8532aSAlex Dubov 			snprintf(s_attr->name, sizeof(s_attr->name),
979baf8532aSAlex Dubov 				 "attr_x%02x", attr->entries[cnt].id);
980baf8532aSAlex Dubov 
98121fd0495SMaxim Levitsky 		sysfs_attr_init(&s_attr->dev_attr.attr);
982baf8532aSAlex Dubov 		s_attr->dev_attr.attr.name = s_attr->name;
983baf8532aSAlex Dubov 		s_attr->dev_attr.attr.mode = S_IRUGO;
984baf8532aSAlex Dubov 		s_attr->dev_attr.show = mspro_block_attr_show(s_attr->id);
985baf8532aSAlex Dubov 
986496fc1a6SAlex Dubov 		if (!s_attr->size)
987baf8532aSAlex Dubov 			continue;
988baf8532aSAlex Dubov 
989496fc1a6SAlex Dubov 		s_attr->data = kmalloc(s_attr->size, GFP_KERNEL);
990baf8532aSAlex Dubov 		if (!s_attr->data) {
991baf8532aSAlex Dubov 			rc = -ENOMEM;
992baf8532aSAlex Dubov 			goto out_free_buffer;
993baf8532aSAlex Dubov 		}
994baf8532aSAlex Dubov 
995496fc1a6SAlex Dubov 		if (((addr / msb->page_size) == (attr_offset / msb->page_size))
996496fc1a6SAlex Dubov 		    && (((addr + s_attr->size - 1) / msb->page_size)
997496fc1a6SAlex Dubov 			== (attr_offset / msb->page_size))) {
998baf8532aSAlex Dubov 			memcpy(s_attr->data, buffer + addr % msb->page_size,
999496fc1a6SAlex Dubov 			       s_attr->size);
1000baf8532aSAlex Dubov 			continue;
1001baf8532aSAlex Dubov 		}
1002baf8532aSAlex Dubov 
1003496fc1a6SAlex Dubov 		attr_offset = (addr / msb->page_size) * msb->page_size;
1004496fc1a6SAlex Dubov 
1005496fc1a6SAlex Dubov 		if ((attr_offset + attr_len) < (addr + s_attr->size)) {
1006baf8532aSAlex Dubov 			kfree(buffer);
1007496fc1a6SAlex Dubov 			attr_len = (((addr + s_attr->size) / msb->page_size)
1008496fc1a6SAlex Dubov 				    + 1 ) * msb->page_size - attr_offset;
1009496fc1a6SAlex Dubov 			buffer = kmalloc(attr_len, GFP_KERNEL);
1010baf8532aSAlex Dubov 			if (!buffer) {
1011baf8532aSAlex Dubov 				rc = -ENOMEM;
1012baf8532aSAlex Dubov 				goto out_free_attr;
1013baf8532aSAlex Dubov 			}
1014baf8532aSAlex Dubov 		}
1015baf8532aSAlex Dubov 
1016496fc1a6SAlex Dubov 		sg_init_one(&msb->req_sg[0], buffer, attr_len);
1017baf8532aSAlex Dubov 		msb->seg_count = 1;
1018baf8532aSAlex Dubov 		msb->current_seg = 0;
1019baf8532aSAlex Dubov 		msb->current_page = 0;
1020baf8532aSAlex Dubov 		msb->data_dir = READ;
1021baf8532aSAlex Dubov 		msb->transfer_cmd = MSPRO_CMD_READ_ATRB;
1022baf8532aSAlex Dubov 
1023496fc1a6SAlex Dubov 		dev_dbg(&card->dev, "reading attribute range %x, %x\n",
1024496fc1a6SAlex Dubov 			attr_offset, attr_len);
1025baf8532aSAlex Dubov 
1026496fc1a6SAlex Dubov 		msb->setup_transfer(card, attr_offset, attr_len);
1027baf8532aSAlex Dubov 		memstick_new_req(card->host);
1028baf8532aSAlex Dubov 		wait_for_completion(&card->mrq_complete);
1029baf8532aSAlex Dubov 		if (card->current_mrq.error) {
1030baf8532aSAlex Dubov 			rc = card->current_mrq.error;
1031baf8532aSAlex Dubov 			goto out_free_buffer;
1032baf8532aSAlex Dubov 		}
1033baf8532aSAlex Dubov 
1034496fc1a6SAlex Dubov 		memcpy(s_attr->data, buffer + addr % msb->page_size,
1035496fc1a6SAlex Dubov 		       s_attr->size);
1036baf8532aSAlex Dubov 	}
1037baf8532aSAlex Dubov 
1038baf8532aSAlex Dubov 	rc = 0;
1039baf8532aSAlex Dubov out_free_buffer:
1040baf8532aSAlex Dubov 	kfree(buffer);
1041baf8532aSAlex Dubov out_free_attr:
1042baf8532aSAlex Dubov 	kfree(attr);
1043baf8532aSAlex Dubov 	return rc;
1044baf8532aSAlex Dubov }
1045baf8532aSAlex Dubov 
mspro_block_init_card(struct memstick_dev * card)1046baf8532aSAlex Dubov static int mspro_block_init_card(struct memstick_dev *card)
1047baf8532aSAlex Dubov {
1048baf8532aSAlex Dubov 	struct mspro_block_data *msb = memstick_get_drvdata(card);
1049baf8532aSAlex Dubov 	struct memstick_host *host = card->host;
1050baf8532aSAlex Dubov 	int rc = 0;
1051baf8532aSAlex Dubov 
1052e1f19995SAlex Dubov 	msb->system = MEMSTICK_SYS_SERIAL;
1053496fc1a6SAlex Dubov 	msb->setup_transfer = h_mspro_block_setup_cmd;
1054496fc1a6SAlex Dubov 
1055baf8532aSAlex Dubov 	card->reg_addr.r_offset = offsetof(struct mspro_register, status);
1056baf8532aSAlex Dubov 	card->reg_addr.r_length = sizeof(struct ms_status_register);
1057baf8532aSAlex Dubov 	card->reg_addr.w_offset = offsetof(struct mspro_register, param);
1058baf8532aSAlex Dubov 	card->reg_addr.w_length = sizeof(struct mspro_param_register);
1059baf8532aSAlex Dubov 
1060baf8532aSAlex Dubov 	if (memstick_set_rw_addr(card))
1061baf8532aSAlex Dubov 		return -EIO;
1062baf8532aSAlex Dubov 
1063ead70773SAlex Dubov 	msb->caps = host->caps;
10648e82f8c3SAlex Dubov 
10658e82f8c3SAlex Dubov 	msleep(150);
10668e82f8c3SAlex Dubov 	rc = mspro_block_wait_for_ced(card);
10678e82f8c3SAlex Dubov 	if (rc)
10688e82f8c3SAlex Dubov 		return rc;
10698e82f8c3SAlex Dubov 
1070962ee1b1SAlex Dubov 	rc = mspro_block_switch_interface(card);
1071962ee1b1SAlex Dubov 	if (rc)
1072962ee1b1SAlex Dubov 		return rc;
1073baf8532aSAlex Dubov 
1074baf8532aSAlex Dubov 	dev_dbg(&card->dev, "card activated\n");
1075ead70773SAlex Dubov 	if (msb->system != MEMSTICK_SYS_SERIAL)
1076ead70773SAlex Dubov 		msb->caps |= MEMSTICK_CAP_AUTO_GET_INT;
1077baf8532aSAlex Dubov 
1078baf8532aSAlex Dubov 	card->next_request = h_mspro_block_req_init;
1079baf8532aSAlex Dubov 	msb->mrq_handler = h_mspro_block_get_ro;
1080baf8532aSAlex Dubov 	memstick_init_req(&card->current_mrq, MS_TPC_READ_REG, NULL,
1081baf8532aSAlex Dubov 			  sizeof(struct ms_status_register));
1082baf8532aSAlex Dubov 	memstick_new_req(card->host);
1083baf8532aSAlex Dubov 	wait_for_completion(&card->mrq_complete);
1084baf8532aSAlex Dubov 	if (card->current_mrq.error)
1085baf8532aSAlex Dubov 		return card->current_mrq.error;
1086baf8532aSAlex Dubov 
1087baf8532aSAlex Dubov 	dev_dbg(&card->dev, "card r/w status %d\n", msb->read_only ? 0 : 1);
1088baf8532aSAlex Dubov 
1089baf8532aSAlex Dubov 	msb->page_size = 512;
1090baf8532aSAlex Dubov 	rc = mspro_block_read_attributes(card);
1091baf8532aSAlex Dubov 	if (rc)
1092baf8532aSAlex Dubov 		return rc;
1093baf8532aSAlex Dubov 
1094baf8532aSAlex Dubov 	dev_dbg(&card->dev, "attributes loaded\n");
1095baf8532aSAlex Dubov 	return 0;
1096baf8532aSAlex Dubov 
1097baf8532aSAlex Dubov }
1098baf8532aSAlex Dubov 
1099d0be1227SJens Axboe static const struct blk_mq_ops mspro_mq_ops = {
1100d0be1227SJens Axboe 	.queue_rq	= mspro_queue_rq,
1101d0be1227SJens Axboe };
1102d0be1227SJens Axboe 
mspro_block_init_disk(struct memstick_dev * card)1103baf8532aSAlex Dubov static int mspro_block_init_disk(struct memstick_dev *card)
1104baf8532aSAlex Dubov {
1105baf8532aSAlex Dubov 	struct mspro_block_data *msb = memstick_get_drvdata(card);
1106baf8532aSAlex Dubov 	struct mspro_devinfo *dev_info = NULL;
1107baf8532aSAlex Dubov 	struct mspro_sys_info *sys_info = NULL;
1108baf8532aSAlex Dubov 	struct mspro_sys_attr *s_attr = NULL;
1109baf8532aSAlex Dubov 	int rc, disk_id;
1110baf8532aSAlex Dubov 	unsigned long capacity;
1111baf8532aSAlex Dubov 
1112baf8532aSAlex Dubov 	for (rc = 0; msb->attr_group.attrs[rc]; ++rc) {
1113baf8532aSAlex Dubov 		s_attr = mspro_from_sysfs_attr(msb->attr_group.attrs[rc]);
1114baf8532aSAlex Dubov 
1115baf8532aSAlex Dubov 		if (s_attr->id == MSPRO_BLOCK_ID_DEVINFO)
1116baf8532aSAlex Dubov 			dev_info = s_attr->data;
1117baf8532aSAlex Dubov 		else if (s_attr->id == MSPRO_BLOCK_ID_SYSINFO)
1118baf8532aSAlex Dubov 			sys_info = s_attr->data;
1119baf8532aSAlex Dubov 	}
1120baf8532aSAlex Dubov 
1121baf8532aSAlex Dubov 	if (!dev_info || !sys_info)
1122baf8532aSAlex Dubov 		return -ENODEV;
1123baf8532aSAlex Dubov 
1124baf8532aSAlex Dubov 	msb->cylinders = be16_to_cpu(dev_info->cylinders);
1125baf8532aSAlex Dubov 	msb->heads = be16_to_cpu(dev_info->heads);
1126baf8532aSAlex Dubov 	msb->sectors_per_track = be16_to_cpu(dev_info->sectors_per_track);
1127baf8532aSAlex Dubov 
1128baf8532aSAlex Dubov 	msb->page_size = be16_to_cpu(sys_info->unit_size);
1129baf8532aSAlex Dubov 
1130baf8532aSAlex Dubov 	mutex_lock(&mspro_block_disk_lock);
11317b51f478STejun Heo 	disk_id = idr_alloc(&mspro_block_disk_idr, card, 0, 256, GFP_KERNEL);
1132d8256d48SAlex Dubov 	mutex_unlock(&mspro_block_disk_lock);
11337b51f478STejun Heo 	if (disk_id < 0)
11347b51f478STejun Heo 		return disk_id;
1135baf8532aSAlex Dubov 
113651ed5bd5SChristoph Hellwig 	rc = blk_mq_alloc_sq_tag_set(&msb->tag_set, &mspro_mq_ops, 2,
1137d0be1227SJens Axboe 				     BLK_MQ_F_SHOULD_MERGE);
113851ed5bd5SChristoph Hellwig 	if (rc)
113951ed5bd5SChristoph Hellwig 		goto out_release_id;
1140baf8532aSAlex Dubov 
114151ed5bd5SChristoph Hellwig 	msb->disk = blk_mq_alloc_disk(&msb->tag_set, card);
114251ed5bd5SChristoph Hellwig 	if (IS_ERR(msb->disk)) {
114351ed5bd5SChristoph Hellwig 		rc = PTR_ERR(msb->disk);
114451ed5bd5SChristoph Hellwig 		goto out_free_tag_set;
114551ed5bd5SChristoph Hellwig 	}
114651ed5bd5SChristoph Hellwig 	msb->queue = msb->disk->queue;
1147baf8532aSAlex Dubov 
1148086fa5ffSMartin K. Petersen 	blk_queue_max_hw_sectors(msb->queue, MSPRO_BLOCK_MAX_PAGES);
11498a78362cSMartin K. Petersen 	blk_queue_max_segments(msb->queue, MSPRO_BLOCK_MAX_SEGS);
1150baf8532aSAlex Dubov 	blk_queue_max_segment_size(msb->queue,
1151baf8532aSAlex Dubov 				   MSPRO_BLOCK_MAX_PAGES * msb->page_size);
1152baf8532aSAlex Dubov 
1153baf8532aSAlex Dubov 	msb->disk->major = major;
11548e82f8c3SAlex Dubov 	msb->disk->first_minor = disk_id << MSPRO_BLOCK_PART_SHIFT;
115551ed5bd5SChristoph Hellwig 	msb->disk->minors = 1 << MSPRO_BLOCK_PART_SHIFT;
1156baf8532aSAlex Dubov 	msb->disk->fops = &ms_block_bdops;
1157baf8532aSAlex Dubov 	msb->disk->private_data = msb;
1158baf8532aSAlex Dubov 
1159baf8532aSAlex Dubov 	sprintf(msb->disk->disk_name, "mspblk%d", disk_id);
1160baf8532aSAlex Dubov 
1161e1defc4fSMartin K. Petersen 	blk_queue_logical_block_size(msb->queue, msb->page_size);
1162baf8532aSAlex Dubov 
1163baf8532aSAlex Dubov 	capacity = be16_to_cpu(sys_info->user_block_count);
1164baf8532aSAlex Dubov 	capacity *= be16_to_cpu(sys_info->block_size);
1165baf8532aSAlex Dubov 	capacity *= msb->page_size >> 9;
1166baf8532aSAlex Dubov 	set_capacity(msb->disk, capacity);
1167baf8532aSAlex Dubov 	dev_dbg(&card->dev, "capacity set %ld\n", capacity);
1168baf8532aSAlex Dubov 
11696dab421bSChristoph Hellwig 	if (msb->read_only)
11706dab421bSChristoph Hellwig 		set_disk_ro(msb->disk, true);
11716dab421bSChristoph Hellwig 
1172b3f8eb6eSLuis Chamberlain 	rc = device_add_disk(&card->dev, msb->disk, NULL);
1173b3f8eb6eSLuis Chamberlain 	if (rc)
1174b3f8eb6eSLuis Chamberlain 		goto out_cleanup_disk;
1175baf8532aSAlex Dubov 	msb->active = 1;
1176baf8532aSAlex Dubov 	return 0;
1177baf8532aSAlex Dubov 
1178b3f8eb6eSLuis Chamberlain out_cleanup_disk:
11798b9ab626SChristoph Hellwig 	put_disk(msb->disk);
118051ed5bd5SChristoph Hellwig out_free_tag_set:
118151ed5bd5SChristoph Hellwig 	blk_mq_free_tag_set(&msb->tag_set);
1182baf8532aSAlex Dubov out_release_id:
1183baf8532aSAlex Dubov 	mutex_lock(&mspro_block_disk_lock);
1184baf8532aSAlex Dubov 	idr_remove(&mspro_block_disk_idr, disk_id);
1185baf8532aSAlex Dubov 	mutex_unlock(&mspro_block_disk_lock);
1186baf8532aSAlex Dubov 	return rc;
1187baf8532aSAlex Dubov }
1188baf8532aSAlex Dubov 
mspro_block_data_clear(struct mspro_block_data * msb)1189baf8532aSAlex Dubov static void mspro_block_data_clear(struct mspro_block_data *msb)
1190baf8532aSAlex Dubov {
1191baf8532aSAlex Dubov 	int cnt;
1192baf8532aSAlex Dubov 	struct mspro_sys_attr *s_attr;
1193baf8532aSAlex Dubov 
1194baf8532aSAlex Dubov 	if (msb->attr_group.attrs) {
1195baf8532aSAlex Dubov 		for (cnt = 0; msb->attr_group.attrs[cnt]; ++cnt) {
1196baf8532aSAlex Dubov 			s_attr = mspro_from_sysfs_attr(msb->attr_group
1197baf8532aSAlex Dubov 							   .attrs[cnt]);
1198baf8532aSAlex Dubov 			kfree(s_attr->data);
1199baf8532aSAlex Dubov 			kfree(s_attr);
1200baf8532aSAlex Dubov 		}
1201baf8532aSAlex Dubov 		kfree(msb->attr_group.attrs);
1202baf8532aSAlex Dubov 	}
1203baf8532aSAlex Dubov 
1204baf8532aSAlex Dubov 	msb->card = NULL;
1205baf8532aSAlex Dubov }
1206baf8532aSAlex Dubov 
mspro_block_check_card(struct memstick_dev * card)1207baf8532aSAlex Dubov static int mspro_block_check_card(struct memstick_dev *card)
1208baf8532aSAlex Dubov {
1209baf8532aSAlex Dubov 	struct mspro_block_data *msb = memstick_get_drvdata(card);
1210baf8532aSAlex Dubov 
1211baf8532aSAlex Dubov 	return (msb->active == 1);
1212baf8532aSAlex Dubov }
1213baf8532aSAlex Dubov 
mspro_block_probe(struct memstick_dev * card)1214baf8532aSAlex Dubov static int mspro_block_probe(struct memstick_dev *card)
1215baf8532aSAlex Dubov {
1216baf8532aSAlex Dubov 	struct mspro_block_data *msb;
1217baf8532aSAlex Dubov 	int rc = 0;
1218baf8532aSAlex Dubov 
1219baf8532aSAlex Dubov 	msb = kzalloc(sizeof(struct mspro_block_data), GFP_KERNEL);
1220baf8532aSAlex Dubov 	if (!msb)
1221baf8532aSAlex Dubov 		return -ENOMEM;
1222baf8532aSAlex Dubov 	memstick_set_drvdata(card, msb);
1223baf8532aSAlex Dubov 	msb->card = card;
1224f1d82698SAlex Dubov 	spin_lock_init(&msb->q_lock);
1225baf8532aSAlex Dubov 
1226baf8532aSAlex Dubov 	rc = mspro_block_init_card(card);
1227baf8532aSAlex Dubov 
1228baf8532aSAlex Dubov 	if (rc)
1229baf8532aSAlex Dubov 		goto out_free;
1230baf8532aSAlex Dubov 
1231baf8532aSAlex Dubov 	rc = sysfs_create_group(&card->dev.kobj, &msb->attr_group);
1232baf8532aSAlex Dubov 	if (rc)
1233baf8532aSAlex Dubov 		goto out_free;
1234baf8532aSAlex Dubov 
1235baf8532aSAlex Dubov 	rc = mspro_block_init_disk(card);
1236baf8532aSAlex Dubov 	if (!rc) {
1237baf8532aSAlex Dubov 		card->check = mspro_block_check_card;
123817017d8dSAlex Dubov 		card->stop = mspro_block_stop;
123917017d8dSAlex Dubov 		card->start = mspro_block_start;
1240baf8532aSAlex Dubov 		return 0;
1241baf8532aSAlex Dubov 	}
1242baf8532aSAlex Dubov 
1243baf8532aSAlex Dubov 	sysfs_remove_group(&card->dev.kobj, &msb->attr_group);
1244baf8532aSAlex Dubov out_free:
1245baf8532aSAlex Dubov 	memstick_set_drvdata(card, NULL);
1246baf8532aSAlex Dubov 	mspro_block_data_clear(msb);
1247baf8532aSAlex Dubov 	kfree(msb);
1248baf8532aSAlex Dubov 	return rc;
1249baf8532aSAlex Dubov }
1250baf8532aSAlex Dubov 
mspro_block_remove(struct memstick_dev * card)1251baf8532aSAlex Dubov static void mspro_block_remove(struct memstick_dev *card)
1252baf8532aSAlex Dubov {
1253baf8532aSAlex Dubov 	struct mspro_block_data *msb = memstick_get_drvdata(card);
1254baf8532aSAlex Dubov 	unsigned long flags;
1255baf8532aSAlex Dubov 
1256baf8532aSAlex Dubov 	spin_lock_irqsave(&msb->q_lock, flags);
1257f1d82698SAlex Dubov 	msb->eject = 1;
1258baf8532aSAlex Dubov 	spin_unlock_irqrestore(&msb->q_lock, flags);
1259d0be1227SJens Axboe 	blk_mq_start_hw_queues(msb->queue);
1260baf8532aSAlex Dubov 
1261d862b13bSMaxim Levitsky 	del_gendisk(msb->disk);
1262d862b13bSMaxim Levitsky 	dev_dbg(&card->dev, "mspro block remove\n");
1263d862b13bSMaxim Levitsky 
1264d0be1227SJens Axboe 	blk_mq_free_tag_set(&msb->tag_set);
1265f1d82698SAlex Dubov 	msb->queue = NULL;
1266baf8532aSAlex Dubov 
1267baf8532aSAlex Dubov 	sysfs_remove_group(&card->dev.kobj, &msb->attr_group);
1268baf8532aSAlex Dubov 
1269baf8532aSAlex Dubov 	mutex_lock(&mspro_block_disk_lock);
1270baf8532aSAlex Dubov 	mspro_block_data_clear(msb);
1271baf8532aSAlex Dubov 	mutex_unlock(&mspro_block_disk_lock);
1272baf8532aSAlex Dubov 
1273185ed423SChristoph Hellwig 	put_disk(msb->disk);
1274baf8532aSAlex Dubov 	memstick_set_drvdata(card, NULL);
1275baf8532aSAlex Dubov }
1276baf8532aSAlex Dubov 
1277baf8532aSAlex Dubov #ifdef CONFIG_PM
1278baf8532aSAlex Dubov 
mspro_block_suspend(struct memstick_dev * card,pm_message_t state)1279baf8532aSAlex Dubov static int mspro_block_suspend(struct memstick_dev *card, pm_message_t state)
1280baf8532aSAlex Dubov {
1281baf8532aSAlex Dubov 	struct mspro_block_data *msb = memstick_get_drvdata(card);
1282baf8532aSAlex Dubov 	unsigned long flags;
1283baf8532aSAlex Dubov 
1284d0be1227SJens Axboe 	blk_mq_stop_hw_queues(msb->queue);
1285d0be1227SJens Axboe 
1286baf8532aSAlex Dubov 	spin_lock_irqsave(&msb->q_lock, flags);
1287f1d82698SAlex Dubov 	msb->active = 0;
1288baf8532aSAlex Dubov 	spin_unlock_irqrestore(&msb->q_lock, flags);
1289baf8532aSAlex Dubov 
1290baf8532aSAlex Dubov 	return 0;
1291baf8532aSAlex Dubov }
1292baf8532aSAlex Dubov 
mspro_block_resume(struct memstick_dev * card)1293baf8532aSAlex Dubov static int mspro_block_resume(struct memstick_dev *card)
1294baf8532aSAlex Dubov {
1295baf8532aSAlex Dubov 	struct mspro_block_data *msb = memstick_get_drvdata(card);
1296baf8532aSAlex Dubov 	int rc = 0;
1297baf8532aSAlex Dubov 
1298baf8532aSAlex Dubov #ifdef CONFIG_MEMSTICK_UNSAFE_RESUME
1299baf8532aSAlex Dubov 
1300baf8532aSAlex Dubov 	struct mspro_block_data *new_msb;
1301baf8532aSAlex Dubov 	struct memstick_host *host = card->host;
1302baf8532aSAlex Dubov 	struct mspro_sys_attr *s_attr, *r_attr;
1303baf8532aSAlex Dubov 	unsigned char cnt;
1304baf8532aSAlex Dubov 
1305baf8532aSAlex Dubov 	mutex_lock(&host->lock);
1306baf8532aSAlex Dubov 	new_msb = kzalloc(sizeof(struct mspro_block_data), GFP_KERNEL);
1307baf8532aSAlex Dubov 	if (!new_msb) {
1308baf8532aSAlex Dubov 		rc = -ENOMEM;
1309baf8532aSAlex Dubov 		goto out_unlock;
1310baf8532aSAlex Dubov 	}
1311baf8532aSAlex Dubov 
1312baf8532aSAlex Dubov 	new_msb->card = card;
1313baf8532aSAlex Dubov 	memstick_set_drvdata(card, new_msb);
13148c87dab9SJia-Ju Bai 	rc = mspro_block_init_card(card);
13158c87dab9SJia-Ju Bai 	if (rc)
1316baf8532aSAlex Dubov 		goto out_free;
1317baf8532aSAlex Dubov 
1318baf8532aSAlex Dubov 	for (cnt = 0; new_msb->attr_group.attrs[cnt]
1319baf8532aSAlex Dubov 		      && msb->attr_group.attrs[cnt]; ++cnt) {
1320baf8532aSAlex Dubov 		s_attr = mspro_from_sysfs_attr(new_msb->attr_group.attrs[cnt]);
1321baf8532aSAlex Dubov 		r_attr = mspro_from_sysfs_attr(msb->attr_group.attrs[cnt]);
1322baf8532aSAlex Dubov 
1323baf8532aSAlex Dubov 		if (s_attr->id == MSPRO_BLOCK_ID_SYSINFO
1324baf8532aSAlex Dubov 		    && r_attr->id == s_attr->id) {
1325baf8532aSAlex Dubov 			if (memcmp(s_attr->data, r_attr->data, s_attr->size))
1326baf8532aSAlex Dubov 				break;
1327baf8532aSAlex Dubov 
1328baf8532aSAlex Dubov 			msb->active = 1;
1329baf8532aSAlex Dubov 			break;
1330baf8532aSAlex Dubov 		}
1331baf8532aSAlex Dubov 	}
1332baf8532aSAlex Dubov 
1333baf8532aSAlex Dubov out_free:
1334baf8532aSAlex Dubov 	memstick_set_drvdata(card, msb);
1335baf8532aSAlex Dubov 	mspro_block_data_clear(new_msb);
1336baf8532aSAlex Dubov 	kfree(new_msb);
1337baf8532aSAlex Dubov out_unlock:
1338baf8532aSAlex Dubov 	mutex_unlock(&host->lock);
1339baf8532aSAlex Dubov 
1340baf8532aSAlex Dubov #endif /* CONFIG_MEMSTICK_UNSAFE_RESUME */
1341baf8532aSAlex Dubov 
1342d0be1227SJens Axboe 	blk_mq_start_hw_queues(msb->queue);
1343baf8532aSAlex Dubov 	return rc;
1344baf8532aSAlex Dubov }
1345baf8532aSAlex Dubov 
1346baf8532aSAlex Dubov #else
1347baf8532aSAlex Dubov 
1348baf8532aSAlex Dubov #define mspro_block_suspend NULL
1349baf8532aSAlex Dubov #define mspro_block_resume NULL
1350baf8532aSAlex Dubov 
1351baf8532aSAlex Dubov #endif /* CONFIG_PM */
1352baf8532aSAlex Dubov 
1353baf8532aSAlex Dubov static struct memstick_device_id mspro_block_id_tbl[] = {
1354baf8532aSAlex Dubov 	{MEMSTICK_MATCH_ALL, MEMSTICK_TYPE_PRO, MEMSTICK_CATEGORY_STORAGE_DUO,
13558e82f8c3SAlex Dubov 	 MEMSTICK_CLASS_DUO},
1356baf8532aSAlex Dubov 	{}
1357baf8532aSAlex Dubov };
1358baf8532aSAlex Dubov 
1359baf8532aSAlex Dubov 
1360baf8532aSAlex Dubov static struct memstick_driver mspro_block_driver = {
1361baf8532aSAlex Dubov 	.driver = {
1362baf8532aSAlex Dubov 		.name  = DRIVER_NAME,
1363baf8532aSAlex Dubov 		.owner = THIS_MODULE
1364baf8532aSAlex Dubov 	},
1365baf8532aSAlex Dubov 	.id_table = mspro_block_id_tbl,
1366baf8532aSAlex Dubov 	.probe    = mspro_block_probe,
1367baf8532aSAlex Dubov 	.remove   = mspro_block_remove,
1368baf8532aSAlex Dubov 	.suspend  = mspro_block_suspend,
1369baf8532aSAlex Dubov 	.resume   = mspro_block_resume
1370baf8532aSAlex Dubov };
1371baf8532aSAlex Dubov 
mspro_block_init(void)1372baf8532aSAlex Dubov static int __init mspro_block_init(void)
1373baf8532aSAlex Dubov {
1374baf8532aSAlex Dubov 	int rc = -ENOMEM;
1375baf8532aSAlex Dubov 
1376baf8532aSAlex Dubov 	rc = register_blkdev(major, DRIVER_NAME);
1377baf8532aSAlex Dubov 	if (rc < 0) {
1378baf8532aSAlex Dubov 		printk(KERN_ERR DRIVER_NAME ": failed to register "
1379baf8532aSAlex Dubov 		       "major %d, error %d\n", major, rc);
1380baf8532aSAlex Dubov 		return rc;
1381baf8532aSAlex Dubov 	}
1382baf8532aSAlex Dubov 	if (!major)
1383baf8532aSAlex Dubov 		major = rc;
1384baf8532aSAlex Dubov 
1385baf8532aSAlex Dubov 	rc = memstick_register_driver(&mspro_block_driver);
1386baf8532aSAlex Dubov 	if (rc)
1387baf8532aSAlex Dubov 		unregister_blkdev(major, DRIVER_NAME);
1388baf8532aSAlex Dubov 	return rc;
1389baf8532aSAlex Dubov }
1390baf8532aSAlex Dubov 
mspro_block_exit(void)1391baf8532aSAlex Dubov static void __exit mspro_block_exit(void)
1392baf8532aSAlex Dubov {
1393baf8532aSAlex Dubov 	memstick_unregister_driver(&mspro_block_driver);
1394baf8532aSAlex Dubov 	unregister_blkdev(major, DRIVER_NAME);
1395baf8532aSAlex Dubov 	idr_destroy(&mspro_block_disk_idr);
1396baf8532aSAlex Dubov }
1397baf8532aSAlex Dubov 
1398baf8532aSAlex Dubov module_init(mspro_block_init);
1399baf8532aSAlex Dubov module_exit(mspro_block_exit);
1400baf8532aSAlex Dubov 
1401baf8532aSAlex Dubov MODULE_LICENSE("GPL");
1402baf8532aSAlex Dubov MODULE_AUTHOR("Alex Dubov");
1403baf8532aSAlex Dubov MODULE_DESCRIPTION("Sony MemoryStickPro block device driver");
1404baf8532aSAlex Dubov MODULE_DEVICE_TABLE(memstick, mspro_block_id_tbl);
1405