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 ¶m, 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, ¶m,
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