2005-04-17 02:20:36 +04:00
/*
* Block driver for media ( i . e . , flash cards )
*
* Copyright 2002 Hewlett - Packard Company
2008-06-29 14:19:47 +04:00
* Copyright 2005 - 2008 Pierre Ossman
2005-04-17 02:20:36 +04:00
*
* Use consistent with the GNU GPL is permitted ,
* provided that this copyright notice is
* preserved in its entirety in all copies and derived works .
*
* HEWLETT - PACKARD COMPANY MAKES NO WARRANTIES , EXPRESSED OR IMPLIED ,
* AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
* FITNESS FOR ANY PARTICULAR PURPOSE .
*
* Many thanks to Alessandro Rubini and Jonathan Corbet !
*
* Author : Andrew Christian
* 28 May 2002
*/
# include <linux/moduleparam.h>
# include <linux/module.h>
# include <linux/init.h>
# include <linux/kernel.h>
# include <linux/fs.h>
# include <linux/errno.h>
# include <linux/hdreg.h>
# include <linux/kdev_t.h>
# include <linux/blkdev.h>
2006-01-12 21:43:35 +03:00
# include <linux/mutex.h>
2006-10-06 11:44:03 +04:00
# include <linux/scatterlist.h>
2005-04-17 02:20:36 +04:00
# include <linux/mmc/card.h>
2006-06-18 16:34:37 +04:00
# include <linux/mmc/host.h>
2006-12-25 00:46:55 +03:00
# include <linux/mmc/mmc.h>
# include <linux/mmc/sd.h>
2005-04-17 02:20:36 +04:00
# include <asm/system.h>
# include <asm/uaccess.h>
2006-12-23 22:03:02 +03:00
# include "queue.h"
2005-04-17 02:20:36 +04:00
/*
* max 8 partitions per card
*/
# define MMC_SHIFT 3
2007-11-21 20:45:12 +03:00
# define MMC_NUM_MINORS (256 >> MMC_SHIFT)
2008-06-06 03:10:21 +04:00
static DECLARE_BITMAP ( dev_use , MMC_NUM_MINORS ) ;
2005-04-17 02:20:36 +04:00
/*
* There is one mmc_blk_data per slot .
*/
struct mmc_blk_data {
spinlock_t lock ;
struct gendisk * disk ;
struct mmc_queue queue ;
unsigned int usage ;
unsigned int block_bits ;
2006-01-04 01:38:44 +03:00
unsigned int read_only ;
2005-04-17 02:20:36 +04:00
} ;
2006-01-12 21:43:35 +03:00
static DEFINE_MUTEX ( open_lock ) ;
2005-04-17 02:20:36 +04:00
static struct mmc_blk_data * mmc_blk_get ( struct gendisk * disk )
{
struct mmc_blk_data * md ;
2006-01-12 21:43:35 +03:00
mutex_lock ( & open_lock ) ;
2005-04-17 02:20:36 +04:00
md = disk - > private_data ;
if ( md & & md - > usage = = 0 )
md = NULL ;
if ( md )
md - > usage + + ;
2006-01-12 21:43:35 +03:00
mutex_unlock ( & open_lock ) ;
2005-04-17 02:20:36 +04:00
return md ;
}
static void mmc_blk_put ( struct mmc_blk_data * md )
{
2006-01-12 21:43:35 +03:00
mutex_lock ( & open_lock ) ;
2005-04-17 02:20:36 +04:00
md - > usage - - ;
if ( md - > usage = = 0 ) {
2007-11-21 20:45:12 +03:00
int devidx = md - > disk - > first_minor > > MMC_SHIFT ;
__clear_bit ( devidx , dev_use ) ;
2005-04-17 02:20:36 +04:00
put_disk ( md - > disk ) ;
kfree ( md ) ;
}
2006-01-12 21:43:35 +03:00
mutex_unlock ( & open_lock ) ;
2005-04-17 02:20:36 +04:00
}
static int mmc_blk_open ( struct inode * inode , struct file * filp )
{
struct mmc_blk_data * md ;
int ret = - ENXIO ;
md = mmc_blk_get ( inode - > i_bdev - > bd_disk ) ;
if ( md ) {
if ( md - > usage = = 2 )
check_disk_change ( inode - > i_bdev ) ;
ret = 0 ;
2005-09-07 02:18:52 +04:00
2006-01-04 01:38:44 +03:00
if ( ( filp - > f_mode & FMODE_WRITE ) & & md - > read_only )
2005-09-07 02:18:52 +04:00
ret = - EROFS ;
2005-04-17 02:20:36 +04:00
}
return ret ;
}
static int mmc_blk_release ( struct inode * inode , struct file * filp )
{
struct mmc_blk_data * md = inode - > i_bdev - > bd_disk - > private_data ;
mmc_blk_put ( md ) ;
return 0 ;
}
static int
2006-01-08 12:02:50 +03:00
mmc_blk_getgeo ( struct block_device * bdev , struct hd_geometry * geo )
2005-04-17 02:20:36 +04:00
{
2006-01-08 12:02:50 +03:00
geo - > cylinders = get_capacity ( bdev - > bd_disk ) / ( 4 * 16 ) ;
geo - > heads = 4 ;
geo - > sectors = 16 ;
return 0 ;
2005-04-17 02:20:36 +04:00
}
static struct block_device_operations mmc_bdops = {
. open = mmc_blk_open ,
. release = mmc_blk_release ,
2006-01-08 12:02:50 +03:00
. getgeo = mmc_blk_getgeo ,
2005-04-17 02:20:36 +04:00
. owner = THIS_MODULE ,
} ;
struct mmc_blk_request {
struct mmc_request mrq ;
struct mmc_command cmd ;
struct mmc_command stop ;
struct mmc_data data ;
} ;
2006-10-06 11:44:03 +04:00
static u32 mmc_sd_num_wr_blocks ( struct mmc_card * card )
{
int err ;
u32 blocks ;
struct mmc_request mrq ;
struct mmc_command cmd ;
struct mmc_data data ;
unsigned int timeout_us ;
struct scatterlist sg ;
memset ( & cmd , 0 , sizeof ( struct mmc_command ) ) ;
cmd . opcode = MMC_APP_CMD ;
cmd . arg = card - > rca < < 16 ;
2007-08-08 20:10:23 +04:00
cmd . flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC ;
2006-10-06 11:44:03 +04:00
err = mmc_wait_for_cmd ( card - > host , & cmd , 0 ) ;
2007-08-08 20:10:23 +04:00
if ( err )
return ( u32 ) - 1 ;
if ( ! mmc_host_is_spi ( card - > host ) & & ! ( cmd . resp [ 0 ] & R1_APP_CMD ) )
2006-10-06 11:44:03 +04:00
return ( u32 ) - 1 ;
memset ( & cmd , 0 , sizeof ( struct mmc_command ) ) ;
cmd . opcode = SD_APP_SEND_NUM_WR_BLKS ;
cmd . arg = 0 ;
2007-08-08 20:10:23 +04:00
cmd . flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC ;
2006-10-06 11:44:03 +04:00
memset ( & data , 0 , sizeof ( struct mmc_data ) ) ;
data . timeout_ns = card - > csd . tacc_ns * 100 ;
data . timeout_clks = card - > csd . tacc_clks * 100 ;
timeout_us = data . timeout_ns / 1000 ;
timeout_us + = data . timeout_clks * 1000 /
( card - > host - > ios . clock / 1000 ) ;
if ( timeout_us > 100000 ) {
data . timeout_ns = 100000000 ;
data . timeout_clks = 0 ;
}
data . blksz = 4 ;
data . blocks = 1 ;
data . flags = MMC_DATA_READ ;
data . sg = & sg ;
data . sg_len = 1 ;
memset ( & mrq , 0 , sizeof ( struct mmc_request ) ) ;
mrq . cmd = & cmd ;
mrq . data = & data ;
sg_init_one ( & sg , & blocks , 4 ) ;
mmc_wait_for_req ( card - > host , & mrq ) ;
2007-07-23 00:18:46 +04:00
if ( cmd . error | | data . error )
2006-10-06 11:44:03 +04:00
return ( u32 ) - 1 ;
blocks = ntohl ( blocks ) ;
return blocks ;
}
2005-04-17 02:20:36 +04:00
static int mmc_blk_issue_rq ( struct mmc_queue * mq , struct request * req )
{
struct mmc_blk_data * md = mq - > data ;
struct mmc_card * card = md - > queue . card ;
2006-10-04 13:15:41 +04:00
struct mmc_blk_request brq ;
2008-07-29 03:23:24 +04:00
int ret = 1 , data_size , i ;
struct scatterlist * sg ;
2005-04-17 02:20:36 +04:00
2007-01-03 21:47:29 +03:00
mmc_claim_host ( card - > host ) ;
2005-04-17 02:20:36 +04:00
do {
struct mmc_command cmd ;
2006-08-30 18:14:56 +04:00
u32 readcmd , writecmd ;
2005-04-17 02:20:36 +04:00
memset ( & brq , 0 , sizeof ( struct mmc_blk_request ) ) ;
brq . mrq . cmd = & brq . cmd ;
brq . mrq . data = & brq . data ;
2007-01-04 17:57:32 +03:00
brq . cmd . arg = req - > sector ;
if ( ! mmc_card_blockaddr ( card ) )
brq . cmd . arg < < = 9 ;
2007-08-08 20:10:23 +04:00
brq . cmd . flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC ;
2006-05-20 00:48:03 +04:00
brq . data . blksz = 1 < < md - > block_bits ;
2005-04-17 02:20:36 +04:00
brq . stop . opcode = MMC_STOP_TRANSMISSION ;
brq . stop . arg = 0 ;
2007-08-08 20:10:23 +04:00
brq . stop . flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC ;
2006-11-21 19:55:45 +03:00
brq . data . blocks = req - > nr_sectors > > ( md - > block_bits - 9 ) ;
if ( brq . data . blocks > card - > host - > max_blk_count )
brq . data . blocks = card - > host - > max_blk_count ;
2005-04-17 02:20:36 +04:00
2006-01-10 00:12:17 +03:00
if ( brq . data . blocks > 1 ) {
2007-08-08 20:10:23 +04:00
/* SPI multiblock writes terminate using a special
* token , not a STOP_TRANSMISSION request .
*/
if ( ! mmc_host_is_spi ( card - > host )
| | rq_data_dir ( req ) = = READ )
brq . mrq . stop = & brq . stop ;
2006-08-30 18:14:56 +04:00
readcmd = MMC_READ_MULTIPLE_BLOCK ;
writecmd = MMC_WRITE_MULTIPLE_BLOCK ;
2006-01-10 00:12:17 +03:00
} else {
brq . mrq . stop = NULL ;
2006-08-30 18:14:56 +04:00
readcmd = MMC_READ_SINGLE_BLOCK ;
writecmd = MMC_WRITE_BLOCK ;
}
if ( rq_data_dir ( req ) = = READ ) {
brq . cmd . opcode = readcmd ;
brq . data . flags | = MMC_DATA_READ ;
} else {
brq . cmd . opcode = writecmd ;
brq . data . flags | = MMC_DATA_WRITE ;
2006-01-10 00:12:17 +03:00
}
2005-04-17 02:20:36 +04:00
2007-07-24 21:16:54 +04:00
mmc_set_data_timeout ( & brq . data , card ) ;
2005-04-17 02:20:36 +04:00
brq . data . sg = mq - > sg ;
2007-05-12 02:26:16 +04:00
brq . data . sg_len = mmc_queue_map_sg ( mq ) ;
mmc_queue_bounce_pre ( mq ) ;
2005-04-17 02:20:36 +04:00
2008-07-29 03:23:24 +04:00
/*
* Adjust the sg list so it is the same size as the
* request .
*/
2007-04-13 21:04:38 +04:00
if ( brq . data . blocks ! =
( req - > nr_sectors > > ( md - > block_bits - 9 ) ) ) {
data_size = brq . data . blocks * brq . data . blksz ;
2008-07-29 03:23:24 +04:00
for_each_sg ( brq . data . sg , sg , brq . data . sg_len , i ) {
data_size - = sg - > length ;
2007-04-13 21:04:38 +04:00
if ( data_size < = 0 ) {
2008-07-29 03:23:24 +04:00
sg - > length + = data_size ;
i + + ;
2007-04-13 21:04:38 +04:00
break ;
}
}
2008-07-29 03:23:24 +04:00
brq . data . sg_len = i ;
2007-04-13 21:04:38 +04:00
}
2005-04-17 02:20:36 +04:00
mmc_wait_for_req ( card - > host , & brq . mrq ) ;
2007-05-12 02:26:16 +04:00
mmc_queue_bounce_post ( mq ) ;
2008-06-29 14:19:47 +04:00
/*
* Check for errors here , but don ' t jump to cmd_err
* until later as we need to wait for the card to leave
* programming mode even when things go wrong .
*/
2005-04-17 02:20:36 +04:00
if ( brq . cmd . error ) {
printk ( KERN_ERR " %s: error %d sending read/write command \n " ,
req - > rq_disk - > disk_name , brq . cmd . error ) ;
}
if ( brq . data . error ) {
printk ( KERN_ERR " %s: error %d transferring data \n " ,
req - > rq_disk - > disk_name , brq . data . error ) ;
}
if ( brq . stop . error ) {
printk ( KERN_ERR " %s: error %d sending stop command \n " ,
req - > rq_disk - > disk_name , brq . stop . error ) ;
}
2007-08-08 20:10:23 +04:00
if ( ! mmc_host_is_spi ( card - > host ) & & rq_data_dir ( req ) ! = READ ) {
2006-09-24 13:46:43 +04:00
do {
int err ;
cmd . opcode = MMC_SEND_STATUS ;
cmd . arg = card - > rca < < 16 ;
cmd . flags = MMC_RSP_R1 | MMC_CMD_AC ;
err = mmc_wait_for_cmd ( card - > host , & cmd , 5 ) ;
if ( err ) {
printk ( KERN_ERR " %s: error %d requesting status \n " ,
req - > rq_disk - > disk_name , err ) ;
goto cmd_err ;
}
2007-11-02 20:21:13 +03:00
/*
* Some cards mishandle the status bits ,
* so make sure to check both the busy
* indication and the card state .
*/
} while ( ! ( cmd . resp [ 0 ] & R1_READY_FOR_DATA ) | |
( R1_CURRENT_STATE ( cmd . resp [ 0 ] ) = = 7 ) ) ;
2005-04-17 02:20:36 +04:00
#if 0
2006-09-24 13:46:43 +04:00
if ( cmd . resp [ 0 ] & ~ 0x00000900 )
printk ( KERN_ERR " %s: status = %08x \n " ,
req - > rq_disk - > disk_name , cmd . resp [ 0 ] ) ;
if ( mmc_decode_status ( cmd . resp ) )
goto cmd_err ;
2005-04-17 02:20:36 +04:00
# endif
2006-09-24 13:46:43 +04:00
}
2005-04-17 02:20:36 +04:00
2008-06-29 14:19:47 +04:00
if ( brq . cmd . error | | brq . data . error | | brq . stop . error )
goto cmd_err ;
2005-04-17 02:20:36 +04:00
/*
* A block was successfully transferred .
*/
spin_lock_irq ( & md - > lock ) ;
2007-12-12 01:48:29 +03:00
ret = __blk_end_request ( req , 0 , brq . data . bytes_xfered ) ;
2005-04-17 02:20:36 +04:00
spin_unlock_irq ( & md - > lock ) ;
} while ( ret ) ;
2007-01-03 21:47:29 +03:00
mmc_release_host ( card - > host ) ;
2005-04-17 02:20:36 +04:00
return 1 ;
cmd_err :
2006-10-06 11:44:03 +04:00
/*
* If this is an SD card and we ' re writing , we can first
* mark the known good sectors as ok .
*
* If the card is not SD , we can still ok written sectors
2008-07-06 03:10:27 +04:00
* as reported by the controller ( which might be less than
* the real number of written sectors , but never more ) .
2006-10-04 13:15:41 +04:00
*
* For reads we just fail the entire chunk as that should
* be safe in all cases .
2005-04-17 02:20:36 +04:00
*/
2008-07-06 03:10:27 +04:00
if ( rq_data_dir ( req ) ! = READ ) {
if ( mmc_card_sd ( card ) ) {
u32 blocks ;
unsigned int bytes ;
blocks = mmc_sd_num_wr_blocks ( card ) ;
if ( blocks ! = ( u32 ) - 1 ) {
if ( card - > csd . write_partial )
bytes = blocks < < md - > block_bits ;
else
bytes = blocks < < 9 ;
spin_lock_irq ( & md - > lock ) ;
ret = __blk_end_request ( req , 0 , bytes ) ;
spin_unlock_irq ( & md - > lock ) ;
}
} else {
2006-10-06 11:44:03 +04:00
spin_lock_irq ( & md - > lock ) ;
2008-07-06 03:10:27 +04:00
ret = __blk_end_request ( req , 0 , brq . data . bytes_xfered ) ;
2006-10-06 11:44:03 +04:00
spin_unlock_irq ( & md - > lock ) ;
}
2006-10-04 13:15:41 +04:00
}
2007-01-03 21:47:29 +03:00
mmc_release_host ( card - > host ) ;
2006-10-06 11:44:03 +04:00
2005-04-17 02:20:36 +04:00
spin_lock_irq ( & md - > lock ) ;
2007-12-12 01:48:29 +03:00
while ( ret )
ret = __blk_end_request ( req , - EIO , blk_rq_cur_bytes ( req ) ) ;
2005-04-17 02:20:36 +04:00
spin_unlock_irq ( & md - > lock ) ;
return 0 ;
}
2006-01-04 01:38:44 +03:00
static inline int mmc_blk_readonly ( struct mmc_card * card )
{
return mmc_card_readonly ( card ) | |
! ( card - > csd . cmdclass & CCC_BLOCK_WRITE ) ;
}
2005-04-17 02:20:36 +04:00
static struct mmc_blk_data * mmc_blk_alloc ( struct mmc_card * card )
{
struct mmc_blk_data * md ;
int devidx , ret ;
devidx = find_first_zero_bit ( dev_use , MMC_NUM_MINORS ) ;
if ( devidx > = MMC_NUM_MINORS )
return ERR_PTR ( - ENOSPC ) ;
__set_bit ( devidx , dev_use ) ;
some kmalloc/memset ->kzalloc (tree wide)
Transform some calls to kmalloc/memset to a single kzalloc (or kcalloc).
Here is a short excerpt of the semantic patch performing
this transformation:
@@
type T2;
expression x;
identifier f,fld;
expression E;
expression E1,E2;
expression e1,e2,e3,y;
statement S;
@@
x =
- kmalloc
+ kzalloc
(E1,E2)
... when != \(x->fld=E;\|y=f(...,x,...);\|f(...,x,...);\|x=E;\|while(...) S\|for(e1;e2;e3) S\)
- memset((T2)x,0,E1);
@@
expression E1,E2,E3;
@@
- kzalloc(E1 * E2,E3)
+ kcalloc(E1,E2,E3)
[akpm@linux-foundation.org: get kcalloc args the right way around]
Signed-off-by: Yoann Padioleau <padator@wanadoo.fr>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Acked-by: Russell King <rmk@arm.linux.org.uk>
Cc: Bryan Wu <bryan.wu@analog.com>
Acked-by: Jiri Slaby <jirislaby@gmail.com>
Cc: Dave Airlie <airlied@linux.ie>
Acked-by: Roland Dreier <rolandd@cisco.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Acked-by: Dmitry Torokhov <dtor@mail.ru>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Acked-by: Pierre Ossman <drzeus-list@drzeus.cx>
Cc: Jeff Garzik <jeff@garzik.org>
Cc: "David S. Miller" <davem@davemloft.net>
Acked-by: Greg KH <greg@kroah.com>
Cc: James Bottomley <James.Bottomley@steeleye.com>
Cc: "Antonino A. Daplas" <adaplas@pol.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-07-19 12:49:03 +04:00
md = kzalloc ( sizeof ( struct mmc_blk_data ) , GFP_KERNEL ) ;
2006-01-04 01:38:44 +03:00
if ( ! md ) {
ret = - ENOMEM ;
goto out ;
}
2005-04-17 02:20:36 +04:00
2006-01-04 01:38:44 +03:00
/*
* Set the read - only status based on the supported commands
* and the write protect switch .
*/
md - > read_only = mmc_blk_readonly ( card ) ;
2005-04-17 02:20:36 +04:00
2006-01-04 01:38:44 +03:00
/*
2006-09-07 19:01:30 +04:00
* Both SD and MMC specifications state ( although a bit
* unclearly in the MMC case ) that a block size of 512
* bytes must always be supported by the card .
2006-01-04 01:38:44 +03:00
*/
2006-09-07 19:01:30 +04:00
md - > block_bits = 9 ;
2005-04-17 02:20:36 +04:00
2006-01-04 01:38:44 +03:00
md - > disk = alloc_disk ( 1 < < MMC_SHIFT ) ;
if ( md - > disk = = NULL ) {
ret = - ENOMEM ;
goto err_kfree ;
}
2005-04-17 02:20:36 +04:00
2006-01-04 01:38:44 +03:00
spin_lock_init ( & md - > lock ) ;
md - > usage = 1 ;
2005-04-17 02:20:36 +04:00
2006-01-04 01:38:44 +03:00
ret = mmc_init_queue ( & md - > queue , card , & md - > lock ) ;
if ( ret )
goto err_putdisk ;
2005-04-17 02:20:36 +04:00
2006-01-04 01:38:44 +03:00
md - > queue . issue_fn = mmc_blk_issue_rq ;
md - > queue . data = md ;
2005-12-23 02:21:38 +03:00
2007-05-14 19:27:29 +04:00
md - > disk - > major = MMC_BLOCK_MAJOR ;
2006-01-04 01:38:44 +03:00
md - > disk - > first_minor = devidx < < MMC_SHIFT ;
md - > disk - > fops = & mmc_bdops ;
md - > disk - > private_data = md ;
md - > disk - > queue = md - > queue . queue ;
md - > disk - > driverfs_dev = & card - > dev ;
/*
* As discussed on lkml , GENHD_FL_REMOVABLE should :
*
* - be set for removable media with permanent block devices
* - be unset for removable block devices with permanent media
*
* Since MMC block devices clearly fall under the second
* case , we do not set GENHD_FL_REMOVABLE . Userspace
* should use the block device creation / destruction hotplug
* messages to tell when the card is present .
*/
sprintf ( md - > disk - > disk_name , " mmcblk%d " , devidx ) ;
blk_queue_hardsect_size ( md - > queue . queue , 1 < < md - > block_bits ) ;
2007-02-18 00:15:27 +03:00
if ( ! mmc_card_sd ( card ) & & mmc_card_blockaddr ( card ) ) {
/*
* The EXT_CSD sector count is in number or 512 byte
* sectors .
*/
set_capacity ( md - > disk , card - > ext_csd . sectors ) ;
} else {
/*
* The CSD capacity field is in units of read_blkbits .
* set_capacity takes units of 512 bytes .
*/
set_capacity ( md - > disk ,
card - > csd . capacity < < ( card - > csd . read_blkbits - 9 ) ) ;
}
2005-04-17 02:20:36 +04:00
return md ;
2006-01-04 01:38:44 +03:00
err_putdisk :
put_disk ( md - > disk ) ;
err_kfree :
kfree ( md ) ;
out :
return ERR_PTR ( ret ) ;
2005-04-17 02:20:36 +04:00
}
static int
mmc_blk_set_blksize ( struct mmc_blk_data * md , struct mmc_card * card )
{
struct mmc_command cmd ;
int err ;
2007-01-04 17:57:32 +03:00
/* Block-addressed cards ignore MMC_SET_BLOCKLEN. */
if ( mmc_card_blockaddr ( card ) )
return 0 ;
2007-01-03 21:47:29 +03:00
mmc_claim_host ( card - > host ) ;
2005-04-17 02:20:36 +04:00
cmd . opcode = MMC_SET_BLOCKLEN ;
2005-12-23 02:21:38 +03:00
cmd . arg = 1 < < md - > block_bits ;
2007-08-08 20:10:23 +04:00
cmd . flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC ;
2005-04-17 02:20:36 +04:00
err = mmc_wait_for_cmd ( card - > host , & cmd , 5 ) ;
2007-01-03 21:47:29 +03:00
mmc_release_host ( card - > host ) ;
2005-04-17 02:20:36 +04:00
if ( err ) {
printk ( KERN_ERR " %s: unable to set block size to %d: %d \n " ,
md - > disk - > disk_name , cmd . arg , err ) ;
return - EINVAL ;
}
return 0 ;
}
static int mmc_blk_probe ( struct mmc_card * card )
{
struct mmc_blk_data * md ;
int err ;
2005-05-21 13:27:02 +04:00
/*
* Check that the card supports the command class ( es ) we need .
*/
if ( ! ( card - > csd . cmdclass & CCC_BLOCK_READ ) )
2005-04-17 02:20:36 +04:00
return - ENODEV ;
md = mmc_blk_alloc ( card ) ;
if ( IS_ERR ( md ) )
return PTR_ERR ( md ) ;
err = mmc_blk_set_blksize ( md , card ) ;
if ( err )
goto out ;
2006-01-14 00:44:18 +03:00
printk ( KERN_INFO " %s: %s %s %lluKiB %s \n " ,
2005-04-17 02:20:36 +04:00
md - > disk - > disk_name , mmc_card_id ( card ) , mmc_card_name ( card ) ,
2006-01-14 00:44:18 +03:00
( unsigned long long ) ( get_capacity ( md - > disk ) > > 1 ) ,
md - > read_only ? " (ro) " : " " ) ;
2005-04-17 02:20:36 +04:00
mmc_set_drvdata ( card , md ) ;
add_disk ( md - > disk ) ;
return 0 ;
out :
mmc_blk_put ( md ) ;
return err ;
}
static void mmc_blk_remove ( struct mmc_card * card )
{
struct mmc_blk_data * md = mmc_get_drvdata ( card ) ;
if ( md ) {
2006-11-15 00:08:16 +03:00
/* Stop new requests from getting into the queue */
2005-04-17 02:20:36 +04:00
del_gendisk ( md - > disk ) ;
2006-11-15 00:08:16 +03:00
/* Then flush out any already in there */
mmc_cleanup_queue ( & md - > queue ) ;
2005-04-17 02:20:36 +04:00
mmc_blk_put ( md ) ;
}
mmc_set_drvdata ( card , NULL ) ;
}
# ifdef CONFIG_PM
static int mmc_blk_suspend ( struct mmc_card * card , pm_message_t state )
{
struct mmc_blk_data * md = mmc_get_drvdata ( card ) ;
if ( md ) {
mmc_queue_suspend ( & md - > queue ) ;
}
return 0 ;
}
static int mmc_blk_resume ( struct mmc_card * card )
{
struct mmc_blk_data * md = mmc_get_drvdata ( card ) ;
if ( md ) {
mmc_blk_set_blksize ( md , card ) ;
mmc_queue_resume ( & md - > queue ) ;
}
return 0 ;
}
# else
# define mmc_blk_suspend NULL
# define mmc_blk_resume NULL
# endif
static struct mmc_driver mmc_driver = {
. drv = {
. name = " mmcblk " ,
} ,
. probe = mmc_blk_probe ,
. remove = mmc_blk_remove ,
. suspend = mmc_blk_suspend ,
. resume = mmc_blk_resume ,
} ;
static int __init mmc_blk_init ( void )
{
int res = - ENOMEM ;
2007-05-14 19:27:29 +04:00
res = register_blkdev ( MMC_BLOCK_MAJOR , " mmc " ) ;
if ( res )
2005-04-17 02:20:36 +04:00
goto out ;
return mmc_register_driver ( & mmc_driver ) ;
out :
return res ;
}
static void __exit mmc_blk_exit ( void )
{
mmc_unregister_driver ( & mmc_driver ) ;
2007-05-14 19:27:29 +04:00
unregister_blkdev ( MMC_BLOCK_MAJOR , " mmc " ) ;
2005-04-17 02:20:36 +04:00
}
module_init ( mmc_blk_init ) ;
module_exit ( mmc_blk_exit ) ;
MODULE_LICENSE ( " GPL " ) ;
MODULE_DESCRIPTION ( " Multimedia Card (MMC) block device driver " ) ;