block.c revision 5e71b7a64cb4c6cff75ca42b535d8227526ec592
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Block driver for media (i.e., flash cards) 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright 2002 Hewlett-Packard Company 5979ce7208a679b8d012450610d5d5aa75aab3af9Pierre Ossman * Copyright 2005-2008 Pierre Ossman 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Use consistent with the GNU GPL is permitted, 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * provided that this copyright notice is 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * preserved in its entirety in all copies and derived works. 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * HEWLETT-PACKARD COMPANY MAKES NO WARRANTIES, EXPRESSED OR IMPLIED, 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FITNESS FOR ANY PARTICULAR PURPOSE. 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Many thanks to Alessandro Rubini and Jonathan Corbet! 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Author: Andrew Christian 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 28 May 2002 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/moduleparam.h> 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/fs.h> 265a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/hdreg.h> 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kdev_t.h> 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/blkdev.h> 31a621aaed690b9439141c555941b6af53873f6ff1Arjan van de Ven#include <linux/mutex.h> 32ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman#include <linux/scatterlist.h> 33a7bbb57333447d0cf950992653b6b079585f3531Pierre Ossman#include <linux/string_helpers.h> 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mmc/card.h> 36385e3227d4d83ab13d7767c4bb3593b0256bf246Pierre Ossman#include <linux/mmc/host.h> 37da7fbe58d2d347e95af699ddf04d885be6362bbePierre Ossman#include <linux/mmc/mmc.h> 38da7fbe58d2d347e95af699ddf04d885be6362bbePierre Ossman#include <linux/mmc/sd.h> 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/system.h> 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h> 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4398ac2162699f7e9880683cb954891817f20b607cPierre Ossman#include "queue.h" 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 456b0b62853b2553be375033776902640320970846Andy WhitcroftMODULE_ALIAS("mmc:block"); 465e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson#ifdef MODULE_PARAM_PREFIX 475e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson#undef MODULE_PARAM_PREFIX 485e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson#endif 495e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson#define MODULE_PARAM_PREFIX "mmcblk." 505e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson 515e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johanssonstatic DEFINE_MUTEX(block_mutex); 526b0b62853b2553be375033776902640320970846Andy Whitcroft 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 545e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson * The defaults come from config options but can be overriden by module 555e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson * or bootarg options. 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 575e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johanssonstatic int perdev_minors = CONFIG_MMC_BLOCK_MINORS; 581dff314451fa24d6b107aa05393d3169e56a7e0aDavid Woodhouse 595e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson/* 605e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson * We've only got one major, so number of mmcblk devices is 615e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson * limited to 256 / number of minors per device. 625e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson */ 635e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johanssonstatic int max_devices; 645e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson 655e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson/* 256 minors, so at most 256 separate devices */ 665e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johanssonstatic DECLARE_BITMAP(dev_use, 256); 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * There is one mmc_blk_data per slot. 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct mmc_blk_data { 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spinlock_t lock; 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct gendisk *disk; 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_queue queue; 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int usage; 77a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King unsigned int read_only; 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 80a621aaed690b9439141c555941b6af53873f6ff1Arjan van de Venstatic DEFINE_MUTEX(open_lock); 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 825e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johanssonmodule_param(perdev_minors, int, 0444); 835e71b7a64cb4c6cff75ca42b535d8227526ec592Olof JohanssonMODULE_PARM_DESC(perdev_minors, "Minors numbers to allocate per device"); 845e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct mmc_blk_data *mmc_blk_get(struct gendisk *disk) 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_blk_data *md; 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 89a621aaed690b9439141c555941b6af53873f6ff1Arjan van de Ven mutex_lock(&open_lock); 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds md = disk->private_data; 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (md && md->usage == 0) 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds md = NULL; 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (md) 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds md->usage++; 95a621aaed690b9439141c555941b6af53873f6ff1Arjan van de Ven mutex_unlock(&open_lock); 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return md; 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mmc_blk_put(struct mmc_blk_data *md) 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 102a621aaed690b9439141c555941b6af53873f6ff1Arjan van de Ven mutex_lock(&open_lock); 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds md->usage--; 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (md->usage == 0) { 1057d92df692994472cab6045bbd9d0e2c4afa4365fAnna Lemehova int devmaj = MAJOR(disk_devt(md->disk)); 1065e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson int devidx = MINOR(disk_devt(md->disk)) / perdev_minors; 1077d92df692994472cab6045bbd9d0e2c4afa4365fAnna Lemehova 1087d92df692994472cab6045bbd9d0e2c4afa4365fAnna Lemehova if (!devmaj) 1095e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson devidx = md->disk->first_minor / perdev_minors; 1107d92df692994472cab6045bbd9d0e2c4afa4365fAnna Lemehova 1115fa83ce284a4b7cd9dcfadd01500b0ed4ab9b740Adrian Hunter blk_cleanup_queue(md->queue.queue); 1125fa83ce284a4b7cd9dcfadd01500b0ed4ab9b740Adrian Hunter 1131dff314451fa24d6b107aa05393d3169e56a7e0aDavid Woodhouse __clear_bit(devidx, dev_use); 1141dff314451fa24d6b107aa05393d3169e56a7e0aDavid Woodhouse 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds put_disk(md->disk); 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(md); 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 118a621aaed690b9439141c555941b6af53873f6ff1Arjan van de Ven mutex_unlock(&open_lock); 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 121a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Virostatic int mmc_blk_open(struct block_device *bdev, fmode_t mode) 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 123a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Viro struct mmc_blk_data *md = mmc_blk_get(bdev->bd_disk); 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = -ENXIO; 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1262a48fc0ab24241755dc93bfd4f01d68efab47f5aArnd Bergmann mutex_lock(&block_mutex); 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (md) { 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (md->usage == 2) 129a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Viro check_disk_change(bdev); 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = 0; 131a00fc09029f02ca833cf90e5d5625f08c4ac4f51Pierre Ossman 132a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Viro if ((mode & FMODE_WRITE) && md->read_only) { 13370bb08962ea9bd50797ae9f16b2493f5f7c65053Andrew Morton mmc_blk_put(md); 134a00fc09029f02ca833cf90e5d5625f08c4ac4f51Pierre Ossman ret = -EROFS; 13570bb08962ea9bd50797ae9f16b2493f5f7c65053Andrew Morton } 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1372a48fc0ab24241755dc93bfd4f01d68efab47f5aArnd Bergmann mutex_unlock(&block_mutex); 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 142a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Virostatic int mmc_blk_release(struct gendisk *disk, fmode_t mode) 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 144a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Viro struct mmc_blk_data *md = disk->private_data; 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1462a48fc0ab24241755dc93bfd4f01d68efab47f5aArnd Bergmann mutex_lock(&block_mutex); 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_blk_put(md); 1482a48fc0ab24241755dc93bfd4f01d68efab47f5aArnd Bergmann mutex_unlock(&block_mutex); 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 153a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwigmmc_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo) 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 155a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig geo->cylinders = get_capacity(bdev->bd_disk) / (4 * 16); 156a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig geo->heads = 4; 157a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig geo->sectors = 16; 158a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig return 0; 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16183d5cde47dedf01b6a4a4331882cbc0a7eea3c2eAlexey Dobriyanstatic const struct block_device_operations mmc_bdops = { 162a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Viro .open = mmc_blk_open, 163a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Viro .release = mmc_blk_release, 164a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig .getgeo = mmc_blk_getgeo, 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .owner = THIS_MODULE, 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct mmc_blk_request { 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_request mrq; 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_command cmd; 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_command stop; 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_data data; 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 175ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossmanstatic u32 mmc_sd_num_wr_blocks(struct mmc_card *card) 176ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman{ 177ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman int err; 178051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks u32 result; 179051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks __be32 *blocks; 180ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 181ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman struct mmc_request mrq; 182ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman struct mmc_command cmd; 183ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman struct mmc_data data; 184ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman unsigned int timeout_us; 185ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 186ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman struct scatterlist sg; 187ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 188ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman memset(&cmd, 0, sizeof(struct mmc_command)); 189ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 190ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman cmd.opcode = MMC_APP_CMD; 191ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman cmd.arg = card->rca << 16; 1927213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; 193ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 194ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman err = mmc_wait_for_cmd(card->host, &cmd, 0); 1957213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell if (err) 1967213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell return (u32)-1; 1977213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell if (!mmc_host_is_spi(card->host) && !(cmd.resp[0] & R1_APP_CMD)) 198ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman return (u32)-1; 199ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 200ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman memset(&cmd, 0, sizeof(struct mmc_command)); 201ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 202ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman cmd.opcode = SD_APP_SEND_NUM_WR_BLKS; 203ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman cmd.arg = 0; 2047213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; 205ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 206ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman memset(&data, 0, sizeof(struct mmc_data)); 207ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 208ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman data.timeout_ns = card->csd.tacc_ns * 100; 209ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman data.timeout_clks = card->csd.tacc_clks * 100; 210ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 211ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman timeout_us = data.timeout_ns / 1000; 212ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman timeout_us += data.timeout_clks * 1000 / 213ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman (card->host->ios.clock / 1000); 214ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 215ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman if (timeout_us > 100000) { 216ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman data.timeout_ns = 100000000; 217ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman data.timeout_clks = 0; 218ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman } 219ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 220ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman data.blksz = 4; 221ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman data.blocks = 1; 222ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman data.flags = MMC_DATA_READ; 223ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman data.sg = &sg; 224ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman data.sg_len = 1; 225ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 226ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman memset(&mrq, 0, sizeof(struct mmc_request)); 227ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 228ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman mrq.cmd = &cmd; 229ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman mrq.data = &data; 230ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 231051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks blocks = kmalloc(4, GFP_KERNEL); 232051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks if (!blocks) 233051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks return (u32)-1; 234051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks 235051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks sg_init_one(&sg, blocks, 4); 236ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 237ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman mmc_wait_for_req(card->host, &mrq); 238ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 239051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks result = ntohl(*blocks); 240051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks kfree(blocks); 241051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks 24217b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman if (cmd.error || data.error) 243051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks result = (u32)-1; 244ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 245051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks return result; 246ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman} 247ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 248504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunterstatic u32 get_card_status(struct mmc_card *card, struct request *req) 249504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter{ 250504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter struct mmc_command cmd; 251504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter int err; 252504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter 253504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter memset(&cmd, 0, sizeof(struct mmc_command)); 254504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter cmd.opcode = MMC_SEND_STATUS; 255504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter if (!mmc_host_is_spi(card->host)) 256504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter cmd.arg = card->rca << 16; 257504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC; 258504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter err = mmc_wait_for_cmd(card->host, &cmd, 0); 259504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter if (err) 260504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter printk(KERN_ERR "%s: error %d sending status comand", 261504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter req->rq_disk->disk_name, err); 262504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter return cmd.resp[0]; 263504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter} 264504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter 265bd788c9665fb7c543aac21317059375632343337Adrian Hunterstatic int mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req) 266bd788c9665fb7c543aac21317059375632343337Adrian Hunter{ 267bd788c9665fb7c543aac21317059375632343337Adrian Hunter struct mmc_blk_data *md = mq->data; 268bd788c9665fb7c543aac21317059375632343337Adrian Hunter struct mmc_card *card = md->queue.card; 269bd788c9665fb7c543aac21317059375632343337Adrian Hunter unsigned int from, nr, arg; 270bd788c9665fb7c543aac21317059375632343337Adrian Hunter int err = 0; 271bd788c9665fb7c543aac21317059375632343337Adrian Hunter 272bd788c9665fb7c543aac21317059375632343337Adrian Hunter mmc_claim_host(card->host); 273bd788c9665fb7c543aac21317059375632343337Adrian Hunter 274bd788c9665fb7c543aac21317059375632343337Adrian Hunter if (!mmc_can_erase(card)) { 275bd788c9665fb7c543aac21317059375632343337Adrian Hunter err = -EOPNOTSUPP; 276bd788c9665fb7c543aac21317059375632343337Adrian Hunter goto out; 277bd788c9665fb7c543aac21317059375632343337Adrian Hunter } 278bd788c9665fb7c543aac21317059375632343337Adrian Hunter 279bd788c9665fb7c543aac21317059375632343337Adrian Hunter from = blk_rq_pos(req); 280bd788c9665fb7c543aac21317059375632343337Adrian Hunter nr = blk_rq_sectors(req); 281bd788c9665fb7c543aac21317059375632343337Adrian Hunter 282bd788c9665fb7c543aac21317059375632343337Adrian Hunter if (mmc_can_trim(card)) 283bd788c9665fb7c543aac21317059375632343337Adrian Hunter arg = MMC_TRIM_ARG; 284bd788c9665fb7c543aac21317059375632343337Adrian Hunter else 285bd788c9665fb7c543aac21317059375632343337Adrian Hunter arg = MMC_ERASE_ARG; 286bd788c9665fb7c543aac21317059375632343337Adrian Hunter 287bd788c9665fb7c543aac21317059375632343337Adrian Hunter err = mmc_erase(card, from, nr, arg); 288bd788c9665fb7c543aac21317059375632343337Adrian Hunterout: 289bd788c9665fb7c543aac21317059375632343337Adrian Hunter spin_lock_irq(&md->lock); 290bd788c9665fb7c543aac21317059375632343337Adrian Hunter __blk_end_request(req, err, blk_rq_bytes(req)); 291bd788c9665fb7c543aac21317059375632343337Adrian Hunter spin_unlock_irq(&md->lock); 292bd788c9665fb7c543aac21317059375632343337Adrian Hunter 293bd788c9665fb7c543aac21317059375632343337Adrian Hunter mmc_release_host(card->host); 294bd788c9665fb7c543aac21317059375632343337Adrian Hunter 295bd788c9665fb7c543aac21317059375632343337Adrian Hunter return err ? 0 : 1; 296bd788c9665fb7c543aac21317059375632343337Adrian Hunter} 297bd788c9665fb7c543aac21317059375632343337Adrian Hunter 2984980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunterstatic int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq, 2994980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter struct request *req) 3004980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter{ 3014980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter struct mmc_blk_data *md = mq->data; 3024980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter struct mmc_card *card = md->queue.card; 3034980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter unsigned int from, nr, arg; 3044980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter int err = 0; 3054980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter 3064980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter mmc_claim_host(card->host); 3074980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter 3084980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter if (!mmc_can_secure_erase_trim(card)) { 3094980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter err = -EOPNOTSUPP; 3104980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter goto out; 3114980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter } 3124980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter 3134980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter from = blk_rq_pos(req); 3144980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter nr = blk_rq_sectors(req); 3154980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter 3164980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter if (mmc_can_trim(card) && !mmc_erase_group_aligned(card, from, nr)) 3174980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter arg = MMC_SECURE_TRIM1_ARG; 3184980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter else 3194980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter arg = MMC_SECURE_ERASE_ARG; 3204980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter 3214980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter err = mmc_erase(card, from, nr, arg); 3224980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter if (!err && arg == MMC_SECURE_TRIM1_ARG) 3234980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter err = mmc_erase(card, from, nr, MMC_SECURE_TRIM2_ARG); 3244980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunterout: 3254980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter spin_lock_irq(&md->lock); 3264980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter __blk_end_request(req, err, blk_rq_bytes(req)); 3274980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter spin_unlock_irq(&md->lock); 3284980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter 3294980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter mmc_release_host(card->host); 3304980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter 3314980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter return err ? 0 : 1; 3324980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter} 3334980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter 334bd788c9665fb7c543aac21317059375632343337Adrian Hunterstatic int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req) 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_blk_data *md = mq->data; 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_card *card = md->queue.card; 338176f00ffed3ef94a198326fbf6a5db64f1cf73adPierre Ossman struct mmc_blk_request brq; 3396a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter int ret = 1, disable_multi = 0; 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 341b855885e3b60cf6f9452848712a62517b94583ebPierre Ossman mmc_claim_host(card->host); 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do { 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_command cmd; 345504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter u32 readcmd, writecmd, status = 0; 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(&brq, 0, sizeof(struct mmc_blk_request)); 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds brq.mrq.cmd = &brq.cmd; 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds brq.mrq.data = &brq.data; 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 35183096ebf1263b2c1ee5e653ba37d993d02e3eb7bTejun Heo brq.cmd.arg = blk_rq_pos(req); 352fba68bd2dab1ac99af3c5a963ec9581cfa9f1725Philip Langdale if (!mmc_card_blockaddr(card)) 353fba68bd2dab1ac99af3c5a963ec9581cfa9f1725Philip Langdale brq.cmd.arg <<= 9; 3547213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell brq.cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; 35508846698703dedae6c6915eb4b4d0a36188c5635Pierre Ossman brq.data.blksz = 512; 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds brq.stop.opcode = MMC_STOP_TRANSMISSION; 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds brq.stop.arg = 0; 3587213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell brq.stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; 35983096ebf1263b2c1ee5e653ba37d993d02e3eb7bTejun Heo brq.data.blocks = blk_rq_sectors(req); 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3616a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter /* 362548d2de9bd978a4d4e941477500f1ab97aade137Pierre Ossman * The block layer doesn't support all sector count 363548d2de9bd978a4d4e941477500f1ab97aade137Pierre Ossman * restrictions, so we need to be prepared for too big 364548d2de9bd978a4d4e941477500f1ab97aade137Pierre Ossman * requests. 365548d2de9bd978a4d4e941477500f1ab97aade137Pierre Ossman */ 366548d2de9bd978a4d4e941477500f1ab97aade137Pierre Ossman if (brq.data.blocks > card->host->max_blk_count) 367548d2de9bd978a4d4e941477500f1ab97aade137Pierre Ossman brq.data.blocks = card->host->max_blk_count; 368548d2de9bd978a4d4e941477500f1ab97aade137Pierre Ossman 369548d2de9bd978a4d4e941477500f1ab97aade137Pierre Ossman /* 3706a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter * After a read error, we redo the request one sector at a time 3716a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter * in order to accurately determine which sectors can be read 3726a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter * successfully. 3736a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter */ 3746a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter if (disable_multi && brq.data.blocks > 1) 3756a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter brq.data.blocks = 1; 3766a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter 377788ee7b09883515f3a72a8f2a980df5e94f37e2cRussell King if (brq.data.blocks > 1) { 3787213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell /* SPI multiblock writes terminate using a special 3797213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell * token, not a STOP_TRANSMISSION request. 3807213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell */ 3817213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell if (!mmc_host_is_spi(card->host) 3827213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell || rq_data_dir(req) == READ) 3837213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell brq.mrq.stop = &brq.stop; 384db53f28b3a6d9338cca1b7e917dc063ac99e1871Russell King readcmd = MMC_READ_MULTIPLE_BLOCK; 385db53f28b3a6d9338cca1b7e917dc063ac99e1871Russell King writecmd = MMC_WRITE_MULTIPLE_BLOCK; 386788ee7b09883515f3a72a8f2a980df5e94f37e2cRussell King } else { 387788ee7b09883515f3a72a8f2a980df5e94f37e2cRussell King brq.mrq.stop = NULL; 388db53f28b3a6d9338cca1b7e917dc063ac99e1871Russell King readcmd = MMC_READ_SINGLE_BLOCK; 389db53f28b3a6d9338cca1b7e917dc063ac99e1871Russell King writecmd = MMC_WRITE_BLOCK; 390db53f28b3a6d9338cca1b7e917dc063ac99e1871Russell King } 391db53f28b3a6d9338cca1b7e917dc063ac99e1871Russell King if (rq_data_dir(req) == READ) { 392db53f28b3a6d9338cca1b7e917dc063ac99e1871Russell King brq.cmd.opcode = readcmd; 393db53f28b3a6d9338cca1b7e917dc063ac99e1871Russell King brq.data.flags |= MMC_DATA_READ; 394db53f28b3a6d9338cca1b7e917dc063ac99e1871Russell King } else { 395db53f28b3a6d9338cca1b7e917dc063ac99e1871Russell King brq.cmd.opcode = writecmd; 396db53f28b3a6d9338cca1b7e917dc063ac99e1871Russell King brq.data.flags |= MMC_DATA_WRITE; 397788ee7b09883515f3a72a8f2a980df5e94f37e2cRussell King } 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 399b146d26a61e0feab2f12a98ae83fd352830899c0Pierre Ossman mmc_set_data_timeout(&brq.data, card); 400b146d26a61e0feab2f12a98ae83fd352830899c0Pierre Ossman 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds brq.data.sg = mq->sg; 40298ccf14909ba02a41c5925b0b2c92aeeef23d3b9Pierre Ossman brq.data.sg_len = mmc_queue_map_sg(mq); 40398ccf14909ba02a41c5925b0b2c92aeeef23d3b9Pierre Ossman 4046a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter /* 4056a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter * Adjust the sg list so it is the same size as the 4066a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter * request. 4076a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter */ 40883096ebf1263b2c1ee5e653ba37d993d02e3eb7bTejun Heo if (brq.data.blocks != blk_rq_sectors(req)) { 4096a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter int i, data_size = brq.data.blocks << 9; 4106a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter struct scatterlist *sg; 4116a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter 4126a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter for_each_sg(brq.data.sg, sg, brq.data.sg_len, i) { 4136a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter data_size -= sg->length; 4146a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter if (data_size <= 0) { 4156a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter sg->length += data_size; 4166a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter i++; 4176a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter break; 4186a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter } 4196a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter } 4206a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter brq.data.sg_len = i; 4216a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter } 4226a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter 42398ccf14909ba02a41c5925b0b2c92aeeef23d3b9Pierre Ossman mmc_queue_bounce_pre(mq); 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_wait_for_req(card->host, &brq.mrq); 42698ccf14909ba02a41c5925b0b2c92aeeef23d3b9Pierre Ossman 42798ccf14909ba02a41c5925b0b2c92aeeef23d3b9Pierre Ossman mmc_queue_bounce_post(mq); 42898ccf14909ba02a41c5925b0b2c92aeeef23d3b9Pierre Ossman 429979ce7208a679b8d012450610d5d5aa75aab3af9Pierre Ossman /* 430979ce7208a679b8d012450610d5d5aa75aab3af9Pierre Ossman * Check for errors here, but don't jump to cmd_err 431979ce7208a679b8d012450610d5d5aa75aab3af9Pierre Ossman * until later as we need to wait for the card to leave 432979ce7208a679b8d012450610d5d5aa75aab3af9Pierre Ossman * programming mode even when things go wrong. 433979ce7208a679b8d012450610d5d5aa75aab3af9Pierre Ossman */ 4346a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter if (brq.cmd.error || brq.data.error || brq.stop.error) { 4356a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter if (brq.data.blocks > 1 && rq_data_dir(req) == READ) { 4366a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter /* Redo read one sector at a time */ 4376a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter printk(KERN_WARNING "%s: retrying using single " 4386a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter "block read\n", req->rq_disk->disk_name); 4396a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter disable_multi = 1; 4406a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter continue; 4416a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter } 442504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter status = get_card_status(card, req); 4436a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter } 444504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (brq.cmd.error) { 446504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter printk(KERN_ERR "%s: error %d sending read/write " 447504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter "command, response %#x, card status %#x\n", 448504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter req->rq_disk->disk_name, brq.cmd.error, 449504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter brq.cmd.resp[0], status); 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (brq.data.error) { 453504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter if (brq.data.error == -ETIMEDOUT && brq.mrq.stop) 454504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter /* 'Stop' response contains card status */ 455504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter status = brq.mrq.stop->resp[0]; 456504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter printk(KERN_ERR "%s: error %d transferring data," 457504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter " sector %u, nr %u, card status %#x\n", 458504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter req->rq_disk->disk_name, brq.data.error, 45983096ebf1263b2c1ee5e653ba37d993d02e3eb7bTejun Heo (unsigned)blk_rq_pos(req), 46083096ebf1263b2c1ee5e653ba37d993d02e3eb7bTejun Heo (unsigned)blk_rq_sectors(req), status); 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (brq.stop.error) { 464504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter printk(KERN_ERR "%s: error %d sending stop command, " 465504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter "response %#x, card status %#x\n", 466504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter req->rq_disk->disk_name, brq.stop.error, 467504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter brq.stop.resp[0], status); 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4707213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) { 4712ed6d22cec37d9a3df4c5bacf1160dee7700106eRussell King do { 4722ed6d22cec37d9a3df4c5bacf1160dee7700106eRussell King int err; 4732ed6d22cec37d9a3df4c5bacf1160dee7700106eRussell King 4742ed6d22cec37d9a3df4c5bacf1160dee7700106eRussell King cmd.opcode = MMC_SEND_STATUS; 4752ed6d22cec37d9a3df4c5bacf1160dee7700106eRussell King cmd.arg = card->rca << 16; 4762ed6d22cec37d9a3df4c5bacf1160dee7700106eRussell King cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; 4772ed6d22cec37d9a3df4c5bacf1160dee7700106eRussell King err = mmc_wait_for_cmd(card->host, &cmd, 5); 4782ed6d22cec37d9a3df4c5bacf1160dee7700106eRussell King if (err) { 4792ed6d22cec37d9a3df4c5bacf1160dee7700106eRussell King printk(KERN_ERR "%s: error %d requesting status\n", 4802ed6d22cec37d9a3df4c5bacf1160dee7700106eRussell King req->rq_disk->disk_name, err); 4812ed6d22cec37d9a3df4c5bacf1160dee7700106eRussell King goto cmd_err; 4822ed6d22cec37d9a3df4c5bacf1160dee7700106eRussell King } 483d198f101989d9bb950327f0d043f6203bb862343Pierre Ossman /* 484d198f101989d9bb950327f0d043f6203bb862343Pierre Ossman * Some cards mishandle the status bits, 485d198f101989d9bb950327f0d043f6203bb862343Pierre Ossman * so make sure to check both the busy 486d198f101989d9bb950327f0d043f6203bb862343Pierre Ossman * indication and the card state. 487d198f101989d9bb950327f0d043f6203bb862343Pierre Ossman */ 488d198f101989d9bb950327f0d043f6203bb862343Pierre Ossman } while (!(cmd.resp[0] & R1_READY_FOR_DATA) || 489d198f101989d9bb950327f0d043f6203bb862343Pierre Ossman (R1_CURRENT_STATE(cmd.resp[0]) == 7)); 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0 4922ed6d22cec37d9a3df4c5bacf1160dee7700106eRussell King if (cmd.resp[0] & ~0x00000900) 4932ed6d22cec37d9a3df4c5bacf1160dee7700106eRussell King printk(KERN_ERR "%s: status = %08x\n", 4942ed6d22cec37d9a3df4c5bacf1160dee7700106eRussell King req->rq_disk->disk_name, cmd.resp[0]); 4952ed6d22cec37d9a3df4c5bacf1160dee7700106eRussell King if (mmc_decode_status(cmd.resp)) 4962ed6d22cec37d9a3df4c5bacf1160dee7700106eRussell King goto cmd_err; 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 4982ed6d22cec37d9a3df4c5bacf1160dee7700106eRussell King } 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5006a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter if (brq.cmd.error || brq.stop.error || brq.data.error) { 5016a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter if (rq_data_dir(req) == READ) { 5026a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter /* 5036a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter * After an error, we redo I/O one sector at a 5046a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter * time, so we only reach here after trying to 5056a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter * read a single sector. 5066a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter */ 5076a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter spin_lock_irq(&md->lock); 5086a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter ret = __blk_end_request(req, -EIO, brq.data.blksz); 5096a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter spin_unlock_irq(&md->lock); 5106a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter continue; 5116a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter } 512979ce7208a679b8d012450610d5d5aa75aab3af9Pierre Ossman goto cmd_err; 5136a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter } 514979ce7208a679b8d012450610d5d5aa75aab3af9Pierre Ossman 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * A block was successfully transferred. 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irq(&md->lock); 519fd539832c7d3a242269374dbcae2cd54da150930Kiyoshi Ueda ret = __blk_end_request(req, 0, brq.data.bytes_xfered); 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irq(&md->lock); 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } while (ret); 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 523b855885e3b60cf6f9452848712a62517b94583ebPierre Ossman mmc_release_host(card->host); 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cmd_err: 528ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman /* 529ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman * If this is an SD card and we're writing, we can first 530ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman * mark the known good sectors as ok. 531ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman * 532ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman * If the card is not SD, we can still ok written sectors 53323af60398af2f5033e2f53665538a09f498dbc03Pierre Ossman * as reported by the controller (which might be less than 53423af60398af2f5033e2f53665538a09f498dbc03Pierre Ossman * the real number of written sectors, but never more). 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5366a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter if (mmc_card_sd(card)) { 5376a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter u32 blocks; 53823af60398af2f5033e2f53665538a09f498dbc03Pierre Ossman 5396a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter blocks = mmc_sd_num_wr_blocks(card); 5406a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter if (blocks != (u32)-1) { 541ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman spin_lock_irq(&md->lock); 5426a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter ret = __blk_end_request(req, 0, blocks << 9); 543ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman spin_unlock_irq(&md->lock); 544ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman } 5456a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter } else { 5466a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter spin_lock_irq(&md->lock); 5476a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter ret = __blk_end_request(req, 0, brq.data.bytes_xfered); 5486a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter spin_unlock_irq(&md->lock); 549176f00ffed3ef94a198326fbf6a5db64f1cf73adPierre Ossman } 550176f00ffed3ef94a198326fbf6a5db64f1cf73adPierre Ossman 551b855885e3b60cf6f9452848712a62517b94583ebPierre Ossman mmc_release_host(card->host); 552ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irq(&md->lock); 554fd539832c7d3a242269374dbcae2cd54da150930Kiyoshi Ueda while (ret) 555fd539832c7d3a242269374dbcae2cd54da150930Kiyoshi Ueda ret = __blk_end_request(req, -EIO, blk_rq_cur_bytes(req)); 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irq(&md->lock); 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 561bd788c9665fb7c543aac21317059375632343337Adrian Hunterstatic int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) 562bd788c9665fb7c543aac21317059375632343337Adrian Hunter{ 5634980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter if (req->cmd_flags & REQ_DISCARD) { 5644980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter if (req->cmd_flags & REQ_SECURE) 5654980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter return mmc_blk_issue_secdiscard_rq(mq, req); 5664980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter else 5674980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter return mmc_blk_issue_discard_rq(mq, req); 5684980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter } else { 569bd788c9665fb7c543aac21317059375632343337Adrian Hunter return mmc_blk_issue_rw_rq(mq, req); 5704980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter } 571bd788c9665fb7c543aac21317059375632343337Adrian Hunter} 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 573a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell Kingstatic inline int mmc_blk_readonly(struct mmc_card *card) 574a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King{ 575a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King return mmc_card_readonly(card) || 576a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King !(card->csd.cmdclass & CCC_BLOCK_WRITE); 577a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King} 578a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card) 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_blk_data *md; 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int devidx, ret; 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5845e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson devidx = find_first_zero_bit(dev_use, max_devices); 5855e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson if (devidx >= max_devices) 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ERR_PTR(-ENOSPC); 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __set_bit(devidx, dev_use); 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 589dd00cc486ab1c17049a535413d1751ef3482141cYoann Padioleau md = kzalloc(sizeof(struct mmc_blk_data), GFP_KERNEL); 590a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King if (!md) { 591a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King ret = -ENOMEM; 592a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King goto out; 593a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King } 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 596a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King /* 597a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * Set the read-only status based on the supported commands 598a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * and the write protect switch. 599a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King */ 600a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King md->read_only = mmc_blk_readonly(card); 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6025e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson md->disk = alloc_disk(perdev_minors); 603a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King if (md->disk == NULL) { 604a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King ret = -ENOMEM; 605a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King goto err_kfree; 606a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King } 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 608a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King spin_lock_init(&md->lock); 609a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King md->usage = 1; 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 611a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King ret = mmc_init_queue(&md->queue, card, &md->lock); 612a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King if (ret) 613a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King goto err_putdisk; 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 615a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King md->queue.issue_fn = mmc_blk_issue_rq; 616a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King md->queue.data = md; 617d2b18394259ef621fd2a6322aa9934198fd87a6aRussell King 618fe6b4c8840c5e23fe9b8696450cee8f2e8cebffdPierre Ossman md->disk->major = MMC_BLOCK_MAJOR; 6195e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson md->disk->first_minor = devidx * perdev_minors; 620a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King md->disk->fops = &mmc_bdops; 621a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King md->disk->private_data = md; 622a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King md->disk->queue = md->queue.queue; 623a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King md->disk->driverfs_dev = &card->dev; 624a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King 625a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King /* 626a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * As discussed on lkml, GENHD_FL_REMOVABLE should: 627a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * 628a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * - be set for removable media with permanent block devices 629a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * - be unset for removable block devices with permanent media 630a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * 631a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * Since MMC block devices clearly fall under the second 632a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * case, we do not set GENHD_FL_REMOVABLE. Userspace 633a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * should use the block device creation/destruction hotplug 634a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * messages to tell when the card is present. 635a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King */ 636a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King 63712578f66b9058e63f193fbfe1552e1d1bfa361bbJiebingLi snprintf(md->disk->disk_name, sizeof(md->disk->disk_name), 63812578f66b9058e63f193fbfe1552e1d1bfa361bbJiebingLi "mmcblk%d", devidx); 639a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King 640e1defc4ff0cf57aca6c5e3ff99fa503f5943c1f1Martin K. Petersen blk_queue_logical_block_size(md->queue.queue, 512); 641a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King 64285a18ad93ec66888d85758630019b10a84257f3cPierre Ossman if (!mmc_card_sd(card) && mmc_card_blockaddr(card)) { 64385a18ad93ec66888d85758630019b10a84257f3cPierre Ossman /* 64485a18ad93ec66888d85758630019b10a84257f3cPierre Ossman * The EXT_CSD sector count is in number or 512 byte 64585a18ad93ec66888d85758630019b10a84257f3cPierre Ossman * sectors. 64685a18ad93ec66888d85758630019b10a84257f3cPierre Ossman */ 64785a18ad93ec66888d85758630019b10a84257f3cPierre Ossman set_capacity(md->disk, card->ext_csd.sectors); 64885a18ad93ec66888d85758630019b10a84257f3cPierre Ossman } else { 64985a18ad93ec66888d85758630019b10a84257f3cPierre Ossman /* 65085a18ad93ec66888d85758630019b10a84257f3cPierre Ossman * The CSD capacity field is in units of read_blkbits. 65185a18ad93ec66888d85758630019b10a84257f3cPierre Ossman * set_capacity takes units of 512 bytes. 65285a18ad93ec66888d85758630019b10a84257f3cPierre Ossman */ 65385a18ad93ec66888d85758630019b10a84257f3cPierre Ossman set_capacity(md->disk, 65485a18ad93ec66888d85758630019b10a84257f3cPierre Ossman card->csd.capacity << (card->csd.read_blkbits - 9)); 65585a18ad93ec66888d85758630019b10a84257f3cPierre Ossman } 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return md; 657a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King 658a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King err_putdisk: 659a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King put_disk(md->disk); 660a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King err_kfree: 661a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King kfree(md); 662a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King out: 663a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King return ERR_PTR(ret); 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card) 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err; 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 671b855885e3b60cf6f9452848712a62517b94583ebPierre Ossman mmc_claim_host(card->host); 6720f8d8ea64ec7c77ca5beb59534d386fe0235961aAdrian Hunter err = mmc_set_blocklen(card, 512); 673b855885e3b60cf6f9452848712a62517b94583ebPierre Ossman mmc_release_host(card->host); 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err) { 6760f8d8ea64ec7c77ca5beb59534d386fe0235961aAdrian Hunter printk(KERN_ERR "%s: unable to set block size to 512: %d\n", 6770f8d8ea64ec7c77ca5beb59534d386fe0235961aAdrian Hunter md->disk->disk_name, err); 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mmc_blk_probe(struct mmc_card *card) 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_blk_data *md; 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err; 688a7bbb57333447d0cf950992653b6b079585f3531Pierre Ossman char cap_str[10]; 689a7bbb57333447d0cf950992653b6b079585f3531Pierre Ossman 690912490db699d83cb3d03570b63df7448677a3f56Pierre Ossman /* 691912490db699d83cb3d03570b63df7448677a3f56Pierre Ossman * Check that the card supports the command class(es) we need. 692912490db699d83cb3d03570b63df7448677a3f56Pierre Ossman */ 693912490db699d83cb3d03570b63df7448677a3f56Pierre Ossman if (!(card->csd.cmdclass & CCC_BLOCK_READ)) 6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds md = mmc_blk_alloc(card); 6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (IS_ERR(md)) 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return PTR_ERR(md); 6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = mmc_blk_set_blksize(md, card); 7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err) 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 704444122fd58fdc83c96877a92b3f6288cafddb08dYi Li string_get_size((u64)get_capacity(md->disk) << 9, STRING_UNITS_2, 705a7bbb57333447d0cf950992653b6b079585f3531Pierre Ossman cap_str, sizeof(cap_str)); 706a7bbb57333447d0cf950992653b6b079585f3531Pierre Ossman printk(KERN_INFO "%s: %s %s %s %s\n", 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds md->disk->disk_name, mmc_card_id(card), mmc_card_name(card), 708a7bbb57333447d0cf950992653b6b079585f3531Pierre Ossman cap_str, md->read_only ? "(ro)" : ""); 7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_set_drvdata(card, md); 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds add_disk(md->disk); 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 7150a74ff29b8dd8b748f8856352f9a9b5c6cc362ccJarkko Lavinen mmc_cleanup_queue(&md->queue); 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_blk_put(md); 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mmc_blk_remove(struct mmc_card *card) 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_blk_data *md = mmc_get_drvdata(card); 7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (md) { 72689b4e133afea9fce333054b94d89953583a55c19Pierre Ossman /* Stop new requests from getting into the queue */ 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds del_gendisk(md->disk); 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 72989b4e133afea9fce333054b94d89953583a55c19Pierre Ossman /* Then flush out any already in there */ 73089b4e133afea9fce333054b94d89953583a55c19Pierre Ossman mmc_cleanup_queue(&md->queue); 7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_blk_put(md); 7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_set_drvdata(card, NULL); 7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PM 7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mmc_blk_suspend(struct mmc_card *card, pm_message_t state) 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_blk_data *md = mmc_get_drvdata(card); 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (md) { 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_queue_suspend(&md->queue); 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mmc_blk_resume(struct mmc_card *card) 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_blk_data *md = mmc_get_drvdata(card); 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (md) { 7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_blk_set_blksize(md, card); 7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_queue_resume(&md->queue); 7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define mmc_blk_suspend NULL 7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define mmc_blk_resume NULL 7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct mmc_driver mmc_driver = { 7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .drv = { 7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "mmcblk", 7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .probe = mmc_blk_probe, 7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .remove = mmc_blk_remove, 7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .suspend = mmc_blk_suspend, 7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .resume = mmc_blk_resume, 7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init mmc_blk_init(void) 7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7759d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita int res; 7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7775e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson if (perdev_minors != CONFIG_MMC_BLOCK_MINORS) 7785e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson pr_info("mmcblk: using %d minors per device\n", perdev_minors); 7795e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson 7805e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson max_devices = 256 / perdev_minors; 7815e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson 782fe6b4c8840c5e23fe9b8696450cee8f2e8cebffdPierre Ossman res = register_blkdev(MMC_BLOCK_MAJOR, "mmc"); 783fe6b4c8840c5e23fe9b8696450cee8f2e8cebffdPierre Ossman if (res) 7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7869d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita res = mmc_register_driver(&mmc_driver); 7879d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita if (res) 7889d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita goto out2; 7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7909d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita return 0; 7919d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita out2: 7929d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita unregister_blkdev(MMC_BLOCK_MAJOR, "mmc"); 7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return res; 7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit mmc_blk_exit(void) 7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_unregister_driver(&mmc_driver); 800fe6b4c8840c5e23fe9b8696450cee8f2e8cebffdPierre Ossman unregister_blkdev(MMC_BLOCK_MAJOR, "mmc"); 8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(mmc_blk_init); 8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(mmc_blk_exit); 8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("Multimedia Card (MMC) block device driver"); 8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 809