update to 2.6.9-rc1
[linux-flexiantxendom0-3.2.10.git] / drivers / mmc / mmc_block.c
1 /*
2  * Block driver for media (i.e., flash cards)
3  *
4  * Copyright 2002 Hewlett-Packard Company
5  *
6  * Use consistent with the GNU GPL is permitted,
7  * provided that this copyright notice is
8  * preserved in its entirety in all copies and derived works.
9  *
10  * HEWLETT-PACKARD COMPANY MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
11  * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
12  * FITNESS FOR ANY PARTICULAR PURPOSE.
13  *
14  * Many thanks to Alessandro Rubini and Jonathan Corbet!
15  *
16  * Author:  Andrew Christian
17  *          28 May 2002
18  */
19 #include <linux/moduleparam.h>
20 #include <linux/module.h>
21 #include <linux/init.h>
22
23 #include <linux/sched.h>
24 #include <linux/kernel.h>
25 #include <linux/fs.h>
26 #include <linux/errno.h>
27 #include <linux/hdreg.h>
28 #include <linux/kdev_t.h>
29 #include <linux/blkdev.h>
30 #include <linux/devfs_fs_kernel.h>
31
32 #include <linux/mmc/card.h>
33 #include <linux/mmc/protocol.h>
34
35 #include <asm/system.h>
36 #include <asm/uaccess.h>
37
38 #include "mmc_queue.h"
39
40 /*
41  * max 8 partitions per card
42  */
43 #define MMC_SHIFT       3
44
45 static int mmc_major;
46 static int maxsectors = 8;
47
48 /*
49  * There is one mmc_blk_data per slot.
50  */
51 struct mmc_blk_data {
52         spinlock_t      lock;
53         struct gendisk  *disk;
54         struct mmc_queue queue;
55
56         unsigned int    usage;
57         unsigned int    block_bits;
58 };
59
60 static DECLARE_MUTEX(open_lock);
61
62 static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk)
63 {
64         struct mmc_blk_data *md;
65
66         down(&open_lock);
67         md = disk->private_data;
68         if (md && md->usage == 0)
69                 md = NULL;
70         if (md)
71                 md->usage++;
72         up(&open_lock);
73
74         return md;
75 }
76
77 static void mmc_blk_put(struct mmc_blk_data *md)
78 {
79         down(&open_lock);
80         md->usage--;
81         if (md->usage == 0) {
82                 put_disk(md->disk);
83                 mmc_cleanup_queue(&md->queue);
84                 kfree(md);
85         }
86         up(&open_lock);
87 }
88
89 static int mmc_blk_open(struct inode *inode, struct file *filp)
90 {
91         struct mmc_blk_data *md;
92         int ret = -ENXIO;
93
94         md = mmc_blk_get(inode->i_bdev->bd_disk);
95         if (md) {
96                 if (md->usage == 2)
97                         check_disk_change(inode->i_bdev);
98                 ret = 0;
99         }
100
101         return ret;
102 }
103
104 static int mmc_blk_release(struct inode *inode, struct file *filp)
105 {
106         struct mmc_blk_data *md = inode->i_bdev->bd_disk->private_data;
107
108         mmc_blk_put(md);
109         return 0;
110 }
111
112 static int
113 mmc_blk_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
114 {
115         struct block_device *bdev = inode->i_bdev;
116
117         if (cmd == HDIO_GETGEO) {
118                 struct hd_geometry geo;
119
120                 memset(&geo, 0, sizeof(struct hd_geometry));
121
122                 geo.cylinders   = get_capacity(bdev->bd_disk) / (4 * 16);
123                 geo.heads       = 4;
124                 geo.sectors     = 16;
125                 geo.start       = get_start_sect(bdev);
126
127                 return copy_to_user((void *)arg, &geo, sizeof(geo))
128                         ? -EFAULT : 0;
129         }
130
131         return -ENOTTY;
132 }
133
134 static struct block_device_operations mmc_bdops = {
135         .open                   = mmc_blk_open,
136         .release                = mmc_blk_release,
137         .ioctl                  = mmc_blk_ioctl,
138         .owner                  = THIS_MODULE,
139 };
140
141 struct mmc_blk_request {
142         struct mmc_request      mrq;
143         struct mmc_command      cmd;
144         struct mmc_command      stop;
145         struct mmc_data         data;
146 };
147
148 static int mmc_blk_prep_rq(struct mmc_queue *mq, struct request *req)
149 {
150         struct mmc_blk_data *md = mq->data;
151         int stat = BLKPREP_OK;
152
153         /*
154          * If we have no device, we haven't finished initialising.
155          */
156         if (!md || !mq->card) {
157                 printk(KERN_ERR "%s: killing request - no device/host\n",
158                        req->rq_disk->disk_name);
159                 stat = BLKPREP_KILL;
160         }
161
162         return stat;
163 }
164
165 static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
166 {
167         struct mmc_blk_data *md = mq->data;
168         struct mmc_card *card = md->queue.card;
169         int ret;
170
171         if (mmc_card_claim_host(card))
172                 goto cmd_err;
173
174         do {
175                 struct mmc_blk_request brq;
176                 struct mmc_command cmd;
177
178                 memset(&brq, 0, sizeof(struct mmc_blk_request));
179                 brq.mrq.cmd = &brq.cmd;
180                 brq.mrq.data = &brq.data;
181
182                 brq.cmd.arg = req->sector << 9;
183                 brq.cmd.flags = MMC_RSP_SHORT | MMC_RSP_CRC;
184                 brq.data.req = req;
185                 brq.data.timeout_ns = card->csd.tacc_ns * 10;
186                 brq.data.timeout_clks = card->csd.tacc_clks * 10;
187                 brq.data.blksz_bits = md->block_bits;
188                 brq.data.blocks = req->current_nr_sectors >> (md->block_bits - 9);
189                 brq.stop.opcode = MMC_STOP_TRANSMISSION;
190                 brq.stop.arg = 0;
191                 brq.stop.flags = MMC_RSP_SHORT | MMC_RSP_CRC | MMC_RSP_BUSY;
192
193                 if (rq_data_dir(req) == READ) {
194                         brq.cmd.opcode = brq.data.blocks > 1 ? MMC_READ_MULTIPLE_BLOCK : MMC_READ_SINGLE_BLOCK;
195                         brq.data.flags |= MMC_DATA_READ;
196                 } else {
197                         brq.cmd.opcode = MMC_WRITE_BLOCK;
198                         brq.cmd.flags |= MMC_RSP_BUSY;
199                         brq.data.flags |= MMC_DATA_WRITE;
200                         brq.data.blocks = 1;
201                 }
202                 brq.mrq.stop = brq.data.blocks > 1 ? &brq.stop : NULL;
203
204                 mmc_wait_for_req(card->host, &brq.mrq);
205                 if (brq.cmd.error) {
206                         printk(KERN_ERR "%s: error %d sending read/write command\n",
207                                req->rq_disk->disk_name, brq.cmd.error);
208                         goto cmd_err;
209                 }
210
211                 if (brq.data.error) {
212                         printk(KERN_ERR "%s: error %d transferring data\n",
213                                req->rq_disk->disk_name, brq.data.error);
214                         goto cmd_err;
215                 }
216
217                 if (brq.stop.error) {
218                         printk(KERN_ERR "%s: error %d sending stop command\n",
219                                req->rq_disk->disk_name, brq.stop.error);
220                         goto cmd_err;
221                 }
222
223                 do {
224                         int err;
225
226                         cmd.opcode = MMC_SEND_STATUS;
227                         cmd.arg = card->rca << 16;
228                         cmd.flags = MMC_RSP_SHORT | MMC_RSP_CRC;
229                         err = mmc_wait_for_cmd(card->host, &cmd, 5);
230                         if (err) {
231                                 printk(KERN_ERR "%s: error %d requesting status\n",
232                                        req->rq_disk->disk_name, err);
233                                 goto cmd_err;
234                         }
235                 } while (!(cmd.resp[0] & R1_READY_FOR_DATA));
236
237 #if 0
238                 if (cmd.resp[0] & ~0x00000900)
239                         printk(KERN_ERR "%s: status = %08x\n",
240                                req->rq_disk->disk_name, cmd.resp[0]);
241                 if (mmc_decode_status(cmd.resp))
242                         goto cmd_err;
243 #endif
244
245                 /*
246                  * A block was successfully transferred.
247                  */
248                 spin_lock_irq(&md->lock);
249                 ret = end_that_request_chunk(req, 1, brq.data.bytes_xfered);
250                 if (!ret) {
251                         /*
252                          * The whole request completed successfully.
253                          */
254                         add_disk_randomness(req->rq_disk);
255                         blkdev_dequeue_request(req);
256                         end_that_request_last(req);
257                 }
258                 spin_unlock_irq(&md->lock);
259         } while (ret);
260
261         mmc_card_release_host(card);
262
263         return 1;
264
265  cmd_err:
266         mmc_card_release_host(card);
267
268         /*
269          * This is a little draconian, but until we get proper
270          * error handling sorted out here, its the best we can
271          * do - especially as some hosts have no idea how much
272          * data was transferred before the error occurred.
273          */
274         spin_lock_irq(&md->lock);
275         do {
276                 ret = end_that_request_chunk(req, 0,
277                                 req->current_nr_sectors << 9);
278         } while (ret);
279
280         add_disk_randomness(req->rq_disk);
281         blkdev_dequeue_request(req);
282         end_that_request_last(req);
283         spin_unlock_irq(&md->lock);
284
285         return 0;
286 }
287
288 #define MMC_NUM_MINORS  (256 >> MMC_SHIFT)
289
290 static unsigned long dev_use[MMC_NUM_MINORS/(8*sizeof(unsigned long))];
291
292 static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
293 {
294         struct mmc_blk_data *md;
295         int devidx, ret;
296
297         devidx = find_first_zero_bit(dev_use, MMC_NUM_MINORS);
298         if (devidx >= MMC_NUM_MINORS)
299                 return ERR_PTR(-ENOSPC);
300         __set_bit(devidx, dev_use);
301
302         md = kmalloc(sizeof(struct mmc_blk_data), GFP_KERNEL);
303         if (md) {
304                 memset(md, 0, sizeof(struct mmc_blk_data));
305
306                 md->disk = alloc_disk(1 << MMC_SHIFT);
307                 if (md->disk == NULL) {
308                         kfree(md);
309                         md = ERR_PTR(-ENOMEM);
310                         goto out;
311                 }
312
313                 spin_lock_init(&md->lock);
314                 md->usage = 1;
315
316                 ret = mmc_init_queue(&md->queue, card, &md->lock);
317                 if (ret) {
318                         put_disk(md->disk);
319                         kfree(md);
320                         md = ERR_PTR(ret);
321                         goto out;
322                 }
323                 md->queue.prep_fn = mmc_blk_prep_rq;
324                 md->queue.issue_fn = mmc_blk_issue_rq;
325                 md->queue.data = md;
326
327                 md->disk->major = mmc_major;
328                 md->disk->first_minor = devidx << MMC_SHIFT;
329                 md->disk->fops = &mmc_bdops;
330                 md->disk->private_data = md;
331                 md->disk->queue = md->queue.queue;
332                 md->disk->driverfs_dev = &card->dev;
333
334                 sprintf(md->disk->disk_name, "mmcblk%d", devidx);
335                 sprintf(md->disk->devfs_name, "mmc/blk%d", devidx);
336
337                 md->block_bits = md->queue.card->csd.read_blkbits;
338
339                 blk_queue_max_sectors(md->queue.queue, maxsectors);
340                 blk_queue_hardsect_size(md->queue.queue, 1 << md->block_bits);
341                 set_capacity(md->disk, md->queue.card->csd.capacity);
342         }
343  out:
344         return md;
345 }
346
347 static int
348 mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card)
349 {
350         struct mmc_command cmd;
351         int err;
352
353         mmc_card_claim_host(card);
354         cmd.opcode = MMC_SET_BLOCKLEN;
355         cmd.arg = 1 << card->csd.read_blkbits;
356         cmd.flags = MMC_RSP_SHORT | MMC_RSP_CRC;
357         err = mmc_wait_for_cmd(card->host, &cmd, 5);
358         mmc_card_release_host(card);
359
360         if (err) {
361                 printk(KERN_ERR "%s: unable to set block size to %d: %d\n",
362                         md->disk->disk_name, cmd.arg, err);
363                 return -EINVAL;
364         }
365
366         return 0;
367 }
368
369 static int mmc_blk_probe(struct mmc_card *card)
370 {
371         struct mmc_blk_data *md;
372         int err;
373
374         if (card->csd.cmdclass & ~0x1ff)
375                 return -ENODEV;
376
377         if (card->csd.read_blkbits < 9) {
378                 printk(KERN_WARNING "%s: read blocksize too small (%u)\n",
379                         mmc_card_id(card), 1 << card->csd.read_blkbits);
380                 return -ENODEV;
381         }
382
383         md = mmc_blk_alloc(card);
384         if (IS_ERR(md))
385                 return PTR_ERR(md);
386
387         err = mmc_blk_set_blksize(md, card);
388         if (err)
389                 goto out;
390
391         printk(KERN_INFO "%s: %s %s %dKiB\n",
392                 md->disk->disk_name, mmc_card_id(card), mmc_card_name(card),
393                 (card->csd.capacity << card->csd.read_blkbits) / 1024);
394
395         mmc_set_drvdata(card, md);
396         add_disk(md->disk);
397         return 0;
398
399  out:
400         mmc_blk_put(md);
401
402         return err;
403 }
404
405 static void mmc_blk_remove(struct mmc_card *card)
406 {
407         struct mmc_blk_data *md = mmc_get_drvdata(card);
408
409         if (md) {
410                 int devidx;
411
412                 del_gendisk(md->disk);
413
414                 /*
415                  * I think this is needed.
416                  */
417                 md->disk->queue = NULL;
418
419                 devidx = md->disk->first_minor >> MMC_SHIFT;
420                 __clear_bit(devidx, dev_use);
421
422                 mmc_blk_put(md);
423         }
424         mmc_set_drvdata(card, NULL);
425 }
426
427 #ifdef CONFIG_PM
428 static int mmc_blk_suspend(struct mmc_card *card, u32 state)
429 {
430         struct mmc_blk_data *md = mmc_get_drvdata(card);
431
432         if (md) {
433                 blk_stop_queue(md->queue.queue);
434         }
435         return 0;
436 }
437
438 static int mmc_blk_resume(struct mmc_card *card)
439 {
440         struct mmc_blk_data *md = mmc_get_drvdata(card);
441
442         if (md) {
443                 mmc_blk_set_blksize(md, md->queue.card);
444                 blk_start_queue(md->queue.queue);
445         }
446         return 0;
447 }
448 #else
449 #define mmc_blk_suspend NULL
450 #define mmc_blk_resume  NULL
451 #endif
452
453 static struct mmc_driver mmc_driver = {
454         .drv            = {
455                 .name   = "mmcblk",
456         },
457         .probe          = mmc_blk_probe,
458         .remove         = mmc_blk_remove,
459         .suspend        = mmc_blk_suspend,
460         .resume         = mmc_blk_resume,
461 };
462
463 static int __init mmc_blk_init(void)
464 {
465         int res = -ENOMEM;
466
467         res = register_blkdev(mmc_major, "mmc");
468         if (res < 0) {
469                 printk(KERN_WARNING "Unable to get major %d for MMC media: %d\n",
470                        mmc_major, res);
471                 goto out;
472         }
473         if (mmc_major == 0)
474                 mmc_major = res;
475
476         devfs_mk_dir("mmc");
477         return mmc_register_driver(&mmc_driver);
478
479  out:
480         return res;
481 }
482
483 static void __exit mmc_blk_exit(void)
484 {
485         mmc_unregister_driver(&mmc_driver);
486         devfs_remove("mmc");
487         unregister_blkdev(mmc_major, "mmc");
488 }
489
490 module_init(mmc_blk_init);
491 module_exit(mmc_blk_exit);
492 module_param(maxsectors, int, 0444);
493
494 MODULE_PARM_DESC(maxsectors, "Maximum number of sectors for a single request");
495
496 MODULE_LICENSE("GPL");
497 MODULE_DESCRIPTION("Multimedia Card (MMC) block device driver");