block.c revision a3c76eb9d4a1e68a69dd880cf0bcb8a52418b993
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> 34cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto#include <linux/delay.h> 35cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto#include <linux/capability.h> 36cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto#include <linux/compat.h> 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 38cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto#include <linux/mmc/ioctl.h> 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mmc/card.h> 40385e3227d4d83ab13d7767c4bb3593b0256bf246Pierre Ossman#include <linux/mmc/host.h> 41da7fbe58d2d347e95af699ddf04d885be6362bbePierre Ossman#include <linux/mmc/mmc.h> 42da7fbe58d2d347e95af699ddf04d885be6362bbePierre Ossman#include <linux/mmc/sd.h> 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/system.h> 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h> 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4798ac2162699f7e9880683cb954891817f20b607cPierre Ossman#include "queue.h" 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 496b0b62853b2553be375033776902640320970846Andy WhitcroftMODULE_ALIAS("mmc:block"); 505e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson#ifdef MODULE_PARAM_PREFIX 515e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson#undef MODULE_PARAM_PREFIX 525e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson#endif 535e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson#define MODULE_PARAM_PREFIX "mmcblk." 545e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson 556a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin#define INAND_CMD38_ARG_EXT_CSD 113 566a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin#define INAND_CMD38_ARG_ERASE 0x00 576a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin#define INAND_CMD38_ARG_TRIM 0x01 586a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin#define INAND_CMD38_ARG_SECERASE 0x80 596a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin#define INAND_CMD38_ARG_SECTRIM1 0x81 606a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin#define INAND_CMD38_ARG_SECTRIM2 0x88 616a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin 625e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johanssonstatic DEFINE_MUTEX(block_mutex); 636b0b62853b2553be375033776902640320970846Andy Whitcroft 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 655e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson * The defaults come from config options but can be overriden by module 665e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson * or bootarg options. 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 685e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johanssonstatic int perdev_minors = CONFIG_MMC_BLOCK_MINORS; 691dff314451fa24d6b107aa05393d3169e56a7e0aDavid Woodhouse 705e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson/* 715e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson * We've only got one major, so number of mmcblk devices is 725e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson * limited to 256 / number of minors per device. 735e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson */ 745e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johanssonstatic int max_devices; 755e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson 765e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson/* 256 minors, so at most 256 separate devices */ 775e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johanssonstatic DECLARE_BITMAP(dev_use, 256); 78f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentinstatic DECLARE_BITMAP(name_use, 256); 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * There is one mmc_blk_data per slot. 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct mmc_blk_data { 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spinlock_t lock; 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct gendisk *disk; 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_queue queue; 87371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct list_head part; 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 89d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin unsigned int flags; 90d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin#define MMC_BLK_CMD23 (1 << 0) /* Can do SET_BLOCK_COUNT for multiblock */ 91d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin#define MMC_BLK_REL_WR (1 << 1) /* MMC Reliable write support */ 92d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int usage; 94a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King unsigned int read_only; 95371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin unsigned int part_type; 96f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin unsigned int name_idx; 9767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter unsigned int reset_done; 9867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter#define MMC_BLK_READ BIT(0) 9967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter#define MMC_BLK_WRITE BIT(1) 10067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter#define MMC_BLK_DISCARD BIT(2) 10167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter#define MMC_BLK_SECDISCARD BIT(3) 102371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 103371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin /* 104371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin * Only set in main mmc_blk_data associated 105371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin * with mmc_card with mmc_set_drvdata, and keeps 106371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin * track of the current selected device partition. 107371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin */ 108371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin unsigned int part_curr; 109371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct device_attribute force_ro; 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 112a621aaed690b9439141c555941b6af53873f6ff1Arjan van de Venstatic DEFINE_MUTEX(open_lock); 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 114d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlinenum mmc_blk_status { 115d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin MMC_BLK_SUCCESS = 0, 116d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin MMC_BLK_PARTIAL, 117d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin MMC_BLK_CMD_ERR, 11867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter MMC_BLK_RETRY, 119d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin MMC_BLK_ABORT, 12067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter MMC_BLK_DATA_ERR, 12167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter MMC_BLK_ECC_ERR, 122d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin}; 123d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin 1245e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johanssonmodule_param(perdev_minors, int, 0444); 1255e71b7a64cb4c6cff75ca42b535d8227526ec592Olof JohanssonMODULE_PARM_DESC(perdev_minors, "Minors numbers to allocate per device"); 1265e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct mmc_blk_data *mmc_blk_get(struct gendisk *disk) 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_blk_data *md; 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 131a621aaed690b9439141c555941b6af53873f6ff1Arjan van de Ven mutex_lock(&open_lock); 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds md = disk->private_data; 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (md && md->usage == 0) 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds md = NULL; 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (md) 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds md->usage++; 137a621aaed690b9439141c555941b6af53873f6ff1Arjan van de Ven mutex_unlock(&open_lock); 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return md; 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 142371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic inline int mmc_get_devidx(struct gendisk *disk) 143371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{ 144371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin int devmaj = MAJOR(disk_devt(disk)); 145371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin int devidx = MINOR(disk_devt(disk)) / perdev_minors; 146371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 147371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin if (!devmaj) 148371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin devidx = disk->first_minor / perdev_minors; 149371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin return devidx; 150371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin} 151371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mmc_blk_put(struct mmc_blk_data *md) 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 154a621aaed690b9439141c555941b6af53873f6ff1Arjan van de Ven mutex_lock(&open_lock); 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds md->usage--; 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (md->usage == 0) { 157371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin int devidx = mmc_get_devidx(md->disk); 1585fa83ce284a4b7cd9dcfadd01500b0ed4ab9b740Adrian Hunter blk_cleanup_queue(md->queue.queue); 1595fa83ce284a4b7cd9dcfadd01500b0ed4ab9b740Adrian Hunter 1601dff314451fa24d6b107aa05393d3169e56a7e0aDavid Woodhouse __clear_bit(devidx, dev_use); 1611dff314451fa24d6b107aa05393d3169e56a7e0aDavid Woodhouse 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds put_disk(md->disk); 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(md); 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 165a621aaed690b9439141c555941b6af53873f6ff1Arjan van de Ven mutex_unlock(&open_lock); 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 168371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic ssize_t force_ro_show(struct device *dev, struct device_attribute *attr, 169371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin char *buf) 170371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{ 171371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin int ret; 172371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev)); 173371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 174371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin ret = snprintf(buf, PAGE_SIZE, "%d", 175371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin get_disk_ro(dev_to_disk(dev)) ^ 176371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin md->read_only); 177371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin mmc_blk_put(md); 178371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin return ret; 179371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin} 180371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 181371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic ssize_t force_ro_store(struct device *dev, struct device_attribute *attr, 182371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin const char *buf, size_t count) 183371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{ 184371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin int ret; 185371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin char *end; 186371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev)); 187371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin unsigned long set = simple_strtoul(buf, &end, 0); 188371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin if (end == buf) { 189371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin ret = -EINVAL; 190371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin goto out; 191371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin } 192371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 193371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin set_disk_ro(dev_to_disk(dev), set || md->read_only); 194371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin ret = count; 195371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinout: 196371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin mmc_blk_put(md); 197371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin return ret; 198371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin} 199371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 200a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Virostatic int mmc_blk_open(struct block_device *bdev, fmode_t mode) 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 202a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Viro struct mmc_blk_data *md = mmc_blk_get(bdev->bd_disk); 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = -ENXIO; 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2052a48fc0ab24241755dc93bfd4f01d68efab47f5aArnd Bergmann mutex_lock(&block_mutex); 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (md) { 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (md->usage == 2) 208a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Viro check_disk_change(bdev); 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = 0; 210a00fc09029f02ca833cf90e5d5625f08c4ac4f51Pierre Ossman 211a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Viro if ((mode & FMODE_WRITE) && md->read_only) { 21270bb08962ea9bd50797ae9f16b2493f5f7c65053Andrew Morton mmc_blk_put(md); 213a00fc09029f02ca833cf90e5d5625f08c4ac4f51Pierre Ossman ret = -EROFS; 21470bb08962ea9bd50797ae9f16b2493f5f7c65053Andrew Morton } 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2162a48fc0ab24241755dc93bfd4f01d68efab47f5aArnd Bergmann mutex_unlock(&block_mutex); 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 221a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Virostatic int mmc_blk_release(struct gendisk *disk, fmode_t mode) 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 223a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Viro struct mmc_blk_data *md = disk->private_data; 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2252a48fc0ab24241755dc93bfd4f01d68efab47f5aArnd Bergmann mutex_lock(&block_mutex); 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_blk_put(md); 2272a48fc0ab24241755dc93bfd4f01d68efab47f5aArnd Bergmann mutex_unlock(&block_mutex); 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 232a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwigmmc_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo) 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 234a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig geo->cylinders = get_capacity(bdev->bd_disk) / (4 * 16); 235a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig geo->heads = 4; 236a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig geo->sectors = 16; 237a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig return 0; 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 240cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtostruct mmc_blk_ioc_data { 241cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto struct mmc_ioc_cmd ic; 242cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto unsigned char *buf; 243cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto u64 buf_bytes; 244cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto}; 245cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 246cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtostatic struct mmc_blk_ioc_data *mmc_blk_ioctl_copy_from_user( 247cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto struct mmc_ioc_cmd __user *user) 248cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto{ 249cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto struct mmc_blk_ioc_data *idata; 250cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto int err; 251cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 252cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto idata = kzalloc(sizeof(*idata), GFP_KERNEL); 253cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (!idata) { 254cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto err = -ENOMEM; 255aea253ecffecd38b5ab97edd73fbe2842a7de371Vladimir Motyka goto out; 256cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto } 257cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 258cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (copy_from_user(&idata->ic, user, sizeof(idata->ic))) { 259cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto err = -EFAULT; 260aea253ecffecd38b5ab97edd73fbe2842a7de371Vladimir Motyka goto idata_err; 261cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto } 262cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 263cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto idata->buf_bytes = (u64) idata->ic.blksz * idata->ic.blocks; 264cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (idata->buf_bytes > MMC_IOC_MAX_BYTES) { 265cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto err = -EOVERFLOW; 266aea253ecffecd38b5ab97edd73fbe2842a7de371Vladimir Motyka goto idata_err; 267cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto } 268cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 269cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto idata->buf = kzalloc(idata->buf_bytes, GFP_KERNEL); 270cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (!idata->buf) { 271cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto err = -ENOMEM; 272aea253ecffecd38b5ab97edd73fbe2842a7de371Vladimir Motyka goto idata_err; 273cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto } 274cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 275cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (copy_from_user(idata->buf, (void __user *)(unsigned long) 276cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto idata->ic.data_ptr, idata->buf_bytes)) { 277cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto err = -EFAULT; 278cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto goto copy_err; 279cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto } 280cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 281cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto return idata; 282cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 283cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtocopy_err: 284cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto kfree(idata->buf); 285aea253ecffecd38b5ab97edd73fbe2842a7de371Vladimir Motykaidata_err: 286cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto kfree(idata); 287aea253ecffecd38b5ab97edd73fbe2842a7de371Vladimir Motykaout: 288cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto return ERR_PTR(err); 289cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto} 290cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 291cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtostatic int mmc_blk_ioctl_cmd(struct block_device *bdev, 292cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto struct mmc_ioc_cmd __user *ic_ptr) 293cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto{ 294cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto struct mmc_blk_ioc_data *idata; 295cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto struct mmc_blk_data *md; 296cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto struct mmc_card *card; 297cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto struct mmc_command cmd = {0}; 298cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto struct mmc_data data = {0}; 299ad5fd97288655b5628052c1fa906419417c86100Venkatraman S struct mmc_request mrq = {NULL}; 300cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto struct scatterlist sg; 301cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto int err; 302cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 303cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto /* 304cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto * The caller must have CAP_SYS_RAWIO, and must be calling this on the 305cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto * whole block device, not on a partition. This prevents overspray 306cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto * between sibling partitions. 307cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto */ 308cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if ((!capable(CAP_SYS_RAWIO)) || (bdev != bdev->bd_contains)) 309cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto return -EPERM; 310cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 311cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto idata = mmc_blk_ioctl_copy_from_user(ic_ptr); 312cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (IS_ERR(idata)) 313cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto return PTR_ERR(idata); 314cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 315cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto cmd.opcode = idata->ic.opcode; 316cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto cmd.arg = idata->ic.arg; 317cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto cmd.flags = idata->ic.flags; 318cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 319cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto data.sg = &sg; 320cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto data.sg_len = 1; 321cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto data.blksz = idata->ic.blksz; 322cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto data.blocks = idata->ic.blocks; 323cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 324cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto sg_init_one(data.sg, idata->buf, idata->buf_bytes); 325cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 326cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (idata->ic.write_flag) 327cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto data.flags = MMC_DATA_WRITE; 328cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto else 329cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto data.flags = MMC_DATA_READ; 330cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 331cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto mrq.cmd = &cmd; 332cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto mrq.data = &data; 333cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 334cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto md = mmc_blk_get(bdev->bd_disk); 335cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (!md) { 336cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto err = -EINVAL; 337cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto goto cmd_done; 338cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto } 339cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 340cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto card = md->queue.card; 341cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (IS_ERR(card)) { 342cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto err = PTR_ERR(card); 343cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto goto cmd_done; 344cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto } 345cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 346cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto mmc_claim_host(card->host); 347cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 348cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (idata->ic.is_acmd) { 349cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto err = mmc_app_cmd(card->host, card); 350cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (err) 351cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto goto cmd_rel_host; 352cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto } 353cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 354cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto /* data.flags must already be set before doing this. */ 355cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto mmc_set_data_timeout(&data, card); 356cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto /* Allow overriding the timeout_ns for empirical tuning. */ 357cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (idata->ic.data_timeout_ns) 358cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto data.timeout_ns = idata->ic.data_timeout_ns; 359cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 360cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if ((cmd.flags & MMC_RSP_R1B) == MMC_RSP_R1B) { 361cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto /* 362cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto * Pretend this is a data transfer and rely on the host driver 363cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto * to compute timeout. When all host drivers support 364cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto * cmd.cmd_timeout for R1B, this can be changed to: 365cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto * 366cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto * mrq.data = NULL; 367cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto * cmd.cmd_timeout = idata->ic.cmd_timeout_ms; 368cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto */ 369cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto data.timeout_ns = idata->ic.cmd_timeout_ms * 1000000; 370cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto } 371cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 372cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto mmc_wait_for_req(card->host, &mrq); 373cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 374cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (cmd.error) { 375cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto dev_err(mmc_dev(card->host), "%s: cmd error %d\n", 376cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto __func__, cmd.error); 377cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto err = cmd.error; 378cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto goto cmd_rel_host; 379cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto } 380cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (data.error) { 381cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto dev_err(mmc_dev(card->host), "%s: data error %d\n", 382cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto __func__, data.error); 383cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto err = data.error; 384cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto goto cmd_rel_host; 385cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto } 386cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 387cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto /* 388cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto * According to the SD specs, some commands require a delay after 389cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto * issuing the command. 390cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto */ 391cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (idata->ic.postsleep_min_us) 392cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto usleep_range(idata->ic.postsleep_min_us, idata->ic.postsleep_max_us); 393cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 394cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (copy_to_user(&(ic_ptr->response), cmd.resp, sizeof(cmd.resp))) { 395cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto err = -EFAULT; 396cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto goto cmd_rel_host; 397cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto } 398cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 399cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (!idata->ic.write_flag) { 400cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (copy_to_user((void __user *)(unsigned long) idata->ic.data_ptr, 401cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto idata->buf, idata->buf_bytes)) { 402cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto err = -EFAULT; 403cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto goto cmd_rel_host; 404cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto } 405cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto } 406cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 407cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtocmd_rel_host: 408cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto mmc_release_host(card->host); 409cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 410cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtocmd_done: 411cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto mmc_blk_put(md); 412cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto kfree(idata->buf); 413cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto kfree(idata); 414cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto return err; 415cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto} 416cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 417cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtostatic int mmc_blk_ioctl(struct block_device *bdev, fmode_t mode, 418cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto unsigned int cmd, unsigned long arg) 419cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto{ 420cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto int ret = -EINVAL; 421cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (cmd == MMC_IOC_CMD) 422cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto ret = mmc_blk_ioctl_cmd(bdev, (struct mmc_ioc_cmd __user *)arg); 423cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto return ret; 424cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto} 425cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 426cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto#ifdef CONFIG_COMPAT 427cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtostatic int mmc_blk_compat_ioctl(struct block_device *bdev, fmode_t mode, 428cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto unsigned int cmd, unsigned long arg) 429cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto{ 430cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto return mmc_blk_ioctl(bdev, mode, cmd, (unsigned long) compat_ptr(arg)); 431cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto} 432cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto#endif 433cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 43483d5cde47dedf01b6a4a4331882cbc0a7eea3c2eAlexey Dobriyanstatic const struct block_device_operations mmc_bdops = { 435a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Viro .open = mmc_blk_open, 436a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Viro .release = mmc_blk_release, 437a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig .getgeo = mmc_blk_getgeo, 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .owner = THIS_MODULE, 439cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto .ioctl = mmc_blk_ioctl, 440cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto#ifdef CONFIG_COMPAT 441cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto .compat_ioctl = mmc_blk_compat_ioctl, 442cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto#endif 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 445371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic inline int mmc_blk_part_switch(struct mmc_card *card, 446371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct mmc_blk_data *md) 447371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{ 448371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin int ret; 449371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct mmc_blk_data *main_md = mmc_get_drvdata(card); 4500d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter 451371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin if (main_md->part_curr == md->part_type) 452371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin return 0; 453371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 454371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin if (mmc_card_mmc(card)) { 4550d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter u8 part_config = card->ext_csd.part_config; 4560d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter 4570d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter part_config &= ~EXT_CSD_PART_CONFIG_ACC_MASK; 4580d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter part_config |= md->part_type; 459371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 460371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, 4610d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter EXT_CSD_PART_CONFIG, part_config, 462371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin card->ext_csd.part_time); 463371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin if (ret) 464371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin return ret; 4650d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter 4660d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter card->ext_csd.part_config = part_config; 46767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter } 468371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 469371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin main_md->part_curr = md->part_type; 470371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin return 0; 471371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin} 472371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 473ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossmanstatic u32 mmc_sd_num_wr_blocks(struct mmc_card *card) 474ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman{ 475ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman int err; 476051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks u32 result; 477051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks __be32 *blocks; 478ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 479ad5fd97288655b5628052c1fa906419417c86100Venkatraman S struct mmc_request mrq = {NULL}; 4801278dba167f01bb3c6626d16450d31129d041087Chris Ball struct mmc_command cmd = {0}; 481a61ad2b49bfce94dfddce828cd9222e4b9e7825bChris Ball struct mmc_data data = {0}; 482ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman unsigned int timeout_us; 483ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 484ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman struct scatterlist sg; 485ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 486ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman cmd.opcode = MMC_APP_CMD; 487ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman cmd.arg = card->rca << 16; 4887213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; 489ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 490ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman err = mmc_wait_for_cmd(card->host, &cmd, 0); 4917213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell if (err) 4927213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell return (u32)-1; 4937213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell if (!mmc_host_is_spi(card->host) && !(cmd.resp[0] & R1_APP_CMD)) 494ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman return (u32)-1; 495ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 496ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman memset(&cmd, 0, sizeof(struct mmc_command)); 497ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 498ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman cmd.opcode = SD_APP_SEND_NUM_WR_BLKS; 499ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman cmd.arg = 0; 5007213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; 501ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 502ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman data.timeout_ns = card->csd.tacc_ns * 100; 503ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman data.timeout_clks = card->csd.tacc_clks * 100; 504ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 505ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman timeout_us = data.timeout_ns / 1000; 506ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman timeout_us += data.timeout_clks * 1000 / 507ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman (card->host->ios.clock / 1000); 508ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 509ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman if (timeout_us > 100000) { 510ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman data.timeout_ns = 100000000; 511ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman data.timeout_clks = 0; 512ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman } 513ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 514ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman data.blksz = 4; 515ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman data.blocks = 1; 516ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman data.flags = MMC_DATA_READ; 517ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman data.sg = &sg; 518ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman data.sg_len = 1; 519ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 520ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman mrq.cmd = &cmd; 521ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman mrq.data = &data; 522ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 523051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks blocks = kmalloc(4, GFP_KERNEL); 524051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks if (!blocks) 525051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks return (u32)-1; 526051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks 527051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks sg_init_one(&sg, blocks, 4); 528ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 529ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman mmc_wait_for_req(card->host, &mrq); 530ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 531051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks result = ntohl(*blocks); 532051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks kfree(blocks); 533051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks 53417b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman if (cmd.error || data.error) 535051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks result = (u32)-1; 536ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 537051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks return result; 538ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman} 539ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 540a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linuxstatic int send_stop(struct mmc_card *card, u32 *status) 541a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux{ 542a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux struct mmc_command cmd = {0}; 543a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux int err; 544a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 545a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux cmd.opcode = MMC_STOP_TRANSMISSION; 546a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; 547a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux err = mmc_wait_for_cmd(card->host, &cmd, 5); 548a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux if (err == 0) 549a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux *status = cmd.resp[0]; 550a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux return err; 551a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux} 552a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 5530a2d4048a22079d7e79d6654bbacbef57bd5728aRussell King - ARM Linuxstatic int get_card_status(struct mmc_card *card, u32 *status, int retries) 554504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter{ 5551278dba167f01bb3c6626d16450d31129d041087Chris Ball struct mmc_command cmd = {0}; 556504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter int err; 557504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter 558504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter cmd.opcode = MMC_SEND_STATUS; 559504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter if (!mmc_host_is_spi(card->host)) 560504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter cmd.arg = card->rca << 16; 561504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC; 5620a2d4048a22079d7e79d6654bbacbef57bd5728aRussell King - ARM Linux err = mmc_wait_for_cmd(card->host, &cmd, retries); 5630a2d4048a22079d7e79d6654bbacbef57bd5728aRussell King - ARM Linux if (err == 0) 5640a2d4048a22079d7e79d6654bbacbef57bd5728aRussell King - ARM Linux *status = cmd.resp[0]; 5650a2d4048a22079d7e79d6654bbacbef57bd5728aRussell King - ARM Linux return err; 566504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter} 567504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter 568a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux#define ERR_RETRY 2 569a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux#define ERR_ABORT 1 570a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux#define ERR_CONTINUE 0 571a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 572a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linuxstatic int mmc_blk_cmd_error(struct request *req, const char *name, int error, 573a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux bool status_valid, u32 status) 574a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux{ 575a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux switch (error) { 576a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux case -EILSEQ: 577a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux /* response crc error, retry the r/w cmd */ 578a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux pr_err("%s: %s sending %s command, card status %#x\n", 579a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux req->rq_disk->disk_name, "response CRC error", 580a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux name, status); 581a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux return ERR_RETRY; 582a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 583a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux case -ETIMEDOUT: 584a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux pr_err("%s: %s sending %s command, card status %#x\n", 585a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux req->rq_disk->disk_name, "timed out", name, status); 586a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 587a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux /* If the status cmd initially failed, retry the r/w cmd */ 588a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux if (!status_valid) 589a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux return ERR_RETRY; 590a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 591a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux /* 592a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * If it was a r/w cmd crc error, or illegal command 593a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * (eg, issued in wrong state) then retry - we should 594a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * have corrected the state problem above. 595a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux */ 596a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux if (status & (R1_COM_CRC_ERROR | R1_ILLEGAL_COMMAND)) 597a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux return ERR_RETRY; 598a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 599a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux /* Otherwise abort the command */ 600a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux return ERR_ABORT; 601a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 602a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux default: 603a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux /* We don't understand the error code the driver gave us */ 604a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux pr_err("%s: unknown error %d sending read/write command, card status %#x\n", 605a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux req->rq_disk->disk_name, error, status); 606a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux return ERR_ABORT; 607a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux } 608a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux} 609a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 610a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux/* 611a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * Initial r/w and stop cmd error recovery. 612a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * We don't know whether the card received the r/w cmd or not, so try to 613a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * restore things back to a sane state. Essentially, we do this as follows: 614a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * - Obtain card status. If the first attempt to obtain card status fails, 615a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * the status word will reflect the failed status cmd, not the failed 616a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * r/w cmd. If we fail to obtain card status, it suggests we can no 617a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * longer communicate with the card. 618a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * - Check the card state. If the card received the cmd but there was a 619a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * transient problem with the response, it might still be in a data transfer 620a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * mode. Try to send it a stop command. If this fails, we can't recover. 621a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * - If the r/w cmd failed due to a response CRC error, it was probably 622a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * transient, so retry the cmd. 623a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * - If the r/w cmd timed out, but we didn't get the r/w cmd status, retry. 624a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * - If the r/w cmd timed out, and the r/w cmd failed due to CRC error or 625a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * illegal cmd, retry. 626a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * Otherwise we don't understand what happened, so abort. 627a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux */ 628a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linuxstatic int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req, 62967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter struct mmc_blk_request *brq, int *ecc_err) 630a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux{ 631a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux bool prev_cmd_status_valid = true; 632a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux u32 status, stop_status = 0; 633a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux int err, retry; 634a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 635a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux /* 636a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * Try to get card status which indicates both the card state 637a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * and why there was no response. If the first attempt fails, 638a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * we can't be sure the returned status is for the r/w command. 639a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux */ 640a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux for (retry = 2; retry >= 0; retry--) { 641a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux err = get_card_status(card, &status, 0); 642a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux if (!err) 643a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux break; 644a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 645a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux prev_cmd_status_valid = false; 646a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux pr_err("%s: error %d sending status command, %sing\n", 647a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux req->rq_disk->disk_name, err, retry ? "retry" : "abort"); 648a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux } 649a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 650a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux /* We couldn't get a response from the card. Give up. */ 651a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux if (err) 652a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux return ERR_ABORT; 653a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 65467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter /* Flag ECC errors */ 65567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if ((status & R1_CARD_ECC_FAILED) || 65667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter (brq->stop.resp[0] & R1_CARD_ECC_FAILED) || 65767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter (brq->cmd.resp[0] & R1_CARD_ECC_FAILED)) 65867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter *ecc_err = 1; 65967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter 660a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux /* 661a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * Check the current card state. If it is in some data transfer 662a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * mode, tell it to stop (and hopefully transition back to TRAN.) 663a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux */ 664a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux if (R1_CURRENT_STATE(status) == R1_STATE_DATA || 665a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux R1_CURRENT_STATE(status) == R1_STATE_RCV) { 666a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux err = send_stop(card, &stop_status); 667a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux if (err) 668a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux pr_err("%s: error %d sending stop command\n", 669a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux req->rq_disk->disk_name, err); 670a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 671a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux /* 672a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * If the stop cmd also timed out, the card is probably 673a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * not present, so abort. Other errors are bad news too. 674a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux */ 675a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux if (err) 676a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux return ERR_ABORT; 67767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (stop_status & R1_CARD_ECC_FAILED) 67867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter *ecc_err = 1; 679a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux } 680a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 681a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux /* Check for set block count errors */ 682a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux if (brq->sbc.error) 683a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux return mmc_blk_cmd_error(req, "SET_BLOCK_COUNT", brq->sbc.error, 684a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux prev_cmd_status_valid, status); 685a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 686a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux /* Check for r/w command errors */ 687a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux if (brq->cmd.error) 688a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux return mmc_blk_cmd_error(req, "r/w cmd", brq->cmd.error, 689a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux prev_cmd_status_valid, status); 690a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 69167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter /* Data errors */ 69267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (!brq->stop.error) 69367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter return ERR_CONTINUE; 69467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter 695a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux /* Now for stop errors. These aren't fatal to the transfer. */ 696a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux pr_err("%s: error %d sending stop command, original cmd response %#x, card status %#x\n", 697a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux req->rq_disk->disk_name, brq->stop.error, 698a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux brq->cmd.resp[0], status); 699a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 700a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux /* 701a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * Subsitute in our own stop status as this will give the error 702a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * state which happened during the execution of the r/w command. 703a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux */ 704a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux if (stop_status) { 705a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux brq->stop.resp[0] = stop_status; 706a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux brq->stop.error = 0; 707a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux } 708a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux return ERR_CONTINUE; 709a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux} 710a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 71167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunterstatic int mmc_blk_reset(struct mmc_blk_data *md, struct mmc_host *host, 71267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter int type) 71367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter{ 71467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter int err; 71567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter 71667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (md->reset_done & type) 71767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter return -EEXIST; 71867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter 71967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter md->reset_done |= type; 72067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter err = mmc_hw_reset(host); 72167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter /* Ensure we switch back to the correct partition */ 72267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (err != -EOPNOTSUPP) { 72367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter struct mmc_blk_data *main_md = mmc_get_drvdata(host->card); 72467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter int part_err; 72567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter 72667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter main_md->part_curr = main_md->part_type; 72767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter part_err = mmc_blk_part_switch(host->card, md); 72867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (part_err) { 72967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter /* 73067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter * We have failed to get back into the correct 73167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter * partition, so we need to abort the whole request. 73267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter */ 73367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter return -ENODEV; 73467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter } 73567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter } 73667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter return err; 73767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter} 73867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter 73967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunterstatic inline void mmc_blk_reset_success(struct mmc_blk_data *md, int type) 74067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter{ 74167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter md->reset_done &= ~type; 74267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter} 74367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter 744bd788c9665fb7c543aac21317059375632343337Adrian Hunterstatic int mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req) 745bd788c9665fb7c543aac21317059375632343337Adrian Hunter{ 746bd788c9665fb7c543aac21317059375632343337Adrian Hunter struct mmc_blk_data *md = mq->data; 747bd788c9665fb7c543aac21317059375632343337Adrian Hunter struct mmc_card *card = md->queue.card; 748bd788c9665fb7c543aac21317059375632343337Adrian Hunter unsigned int from, nr, arg; 74967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter int err = 0, type = MMC_BLK_DISCARD; 750bd788c9665fb7c543aac21317059375632343337Adrian Hunter 751bd788c9665fb7c543aac21317059375632343337Adrian Hunter if (!mmc_can_erase(card)) { 752bd788c9665fb7c543aac21317059375632343337Adrian Hunter err = -EOPNOTSUPP; 753bd788c9665fb7c543aac21317059375632343337Adrian Hunter goto out; 754bd788c9665fb7c543aac21317059375632343337Adrian Hunter } 755bd788c9665fb7c543aac21317059375632343337Adrian Hunter 756bd788c9665fb7c543aac21317059375632343337Adrian Hunter from = blk_rq_pos(req); 757bd788c9665fb7c543aac21317059375632343337Adrian Hunter nr = blk_rq_sectors(req); 758bd788c9665fb7c543aac21317059375632343337Adrian Hunter 759bd788c9665fb7c543aac21317059375632343337Adrian Hunter if (mmc_can_trim(card)) 760bd788c9665fb7c543aac21317059375632343337Adrian Hunter arg = MMC_TRIM_ARG; 761bd788c9665fb7c543aac21317059375632343337Adrian Hunter else 762bd788c9665fb7c543aac21317059375632343337Adrian Hunter arg = MMC_ERASE_ARG; 76367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunterretry: 7646a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin if (card->quirks & MMC_QUIRK_INAND_CMD38) { 7656a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, 7666a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin INAND_CMD38_ARG_EXT_CSD, 7676a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin arg == MMC_TRIM_ARG ? 7686a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin INAND_CMD38_ARG_TRIM : 7696a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin INAND_CMD38_ARG_ERASE, 7706a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin 0); 7716a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin if (err) 7726a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin goto out; 7736a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin } 774bd788c9665fb7c543aac21317059375632343337Adrian Hunter err = mmc_erase(card, from, nr, arg); 775bd788c9665fb7c543aac21317059375632343337Adrian Hunterout: 77667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (err == -EIO && !mmc_blk_reset(md, card->host, type)) 77767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter goto retry; 77867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (!err) 77967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter mmc_blk_reset_success(md, type); 780bd788c9665fb7c543aac21317059375632343337Adrian Hunter spin_lock_irq(&md->lock); 781bd788c9665fb7c543aac21317059375632343337Adrian Hunter __blk_end_request(req, err, blk_rq_bytes(req)); 782bd788c9665fb7c543aac21317059375632343337Adrian Hunter spin_unlock_irq(&md->lock); 783bd788c9665fb7c543aac21317059375632343337Adrian Hunter 784bd788c9665fb7c543aac21317059375632343337Adrian Hunter return err ? 0 : 1; 785bd788c9665fb7c543aac21317059375632343337Adrian Hunter} 786bd788c9665fb7c543aac21317059375632343337Adrian Hunter 7874980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunterstatic int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq, 7884980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter struct request *req) 7894980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter{ 7904980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter struct mmc_blk_data *md = mq->data; 7914980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter struct mmc_card *card = md->queue.card; 7924980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter unsigned int from, nr, arg; 79367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter int err = 0, type = MMC_BLK_SECDISCARD; 7944980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter 7954980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter if (!mmc_can_secure_erase_trim(card)) { 7964980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter err = -EOPNOTSUPP; 7974980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter goto out; 7984980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter } 7994980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter 8004980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter from = blk_rq_pos(req); 8014980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter nr = blk_rq_sectors(req); 8024980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter 8034980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter if (mmc_can_trim(card) && !mmc_erase_group_aligned(card, from, nr)) 8044980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter arg = MMC_SECURE_TRIM1_ARG; 8054980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter else 8064980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter arg = MMC_SECURE_ERASE_ARG; 80767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunterretry: 8086a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin if (card->quirks & MMC_QUIRK_INAND_CMD38) { 8096a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, 8106a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin INAND_CMD38_ARG_EXT_CSD, 8116a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin arg == MMC_SECURE_TRIM1_ARG ? 8126a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin INAND_CMD38_ARG_SECTRIM1 : 8136a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin INAND_CMD38_ARG_SECERASE, 8146a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin 0); 8156a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin if (err) 8166a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin goto out; 8176a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin } 8184980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter err = mmc_erase(card, from, nr, arg); 8196a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin if (!err && arg == MMC_SECURE_TRIM1_ARG) { 8206a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin if (card->quirks & MMC_QUIRK_INAND_CMD38) { 8216a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, 8226a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin INAND_CMD38_ARG_EXT_CSD, 8236a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin INAND_CMD38_ARG_SECTRIM2, 8246a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin 0); 8256a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin if (err) 8266a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin goto out; 8276a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin } 8284980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter err = mmc_erase(card, from, nr, MMC_SECURE_TRIM2_ARG); 8296a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin } 8304980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunterout: 83167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (err == -EIO && !mmc_blk_reset(md, card->host, type)) 83267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter goto retry; 83367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (!err) 83467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter mmc_blk_reset_success(md, type); 8354980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter spin_lock_irq(&md->lock); 8364980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter __blk_end_request(req, err, blk_rq_bytes(req)); 8374980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter spin_unlock_irq(&md->lock); 8384980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter 8394980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter return err ? 0 : 1; 8404980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter} 8414980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter 842f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentinstatic int mmc_blk_issue_flush(struct mmc_queue *mq, struct request *req) 843f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin{ 844f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin struct mmc_blk_data *md = mq->data; 845f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin 846f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin /* 847f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin * No-op, only service this because we need REQ_FUA for reliable 848f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin * writes. 849f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin */ 850f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin spin_lock_irq(&md->lock); 851f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin __blk_end_request_all(req, 0); 852f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin spin_unlock_irq(&md->lock); 853f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin 854f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin return 1; 855f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin} 856f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin 857f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin/* 858f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin * Reformat current write as a reliable write, supporting 859f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin * both legacy and the enhanced reliable write MMC cards. 860f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin * In each transfer we'll handle only as much as a single 861f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin * reliable write can handle, thus finish the request in 862f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin * partial completions. 863f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin */ 864d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentinstatic inline void mmc_apply_rel_rw(struct mmc_blk_request *brq, 865d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin struct mmc_card *card, 866d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin struct request *req) 867f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin{ 868f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin if (!(card->ext_csd.rel_param & EXT_CSD_WR_REL_PARAM_EN)) { 869f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin /* Legacy mode imposes restrictions on transfers. */ 870f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin if (!IS_ALIGNED(brq->cmd.arg, card->ext_csd.rel_sectors)) 871f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin brq->data.blocks = 1; 872f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin 873f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin if (brq->data.blocks > card->ext_csd.rel_sectors) 874f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin brq->data.blocks = card->ext_csd.rel_sectors; 875f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin else if (brq->data.blocks < card->ext_csd.rel_sectors) 876f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin brq->data.blocks = 1; 877f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin } 878f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin} 879f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin 8804c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux#define CMD_ERRORS \ 8814c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux (R1_OUT_OF_RANGE | /* Command argument out of range */ \ 8824c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux R1_ADDRESS_ERROR | /* Misaligned address */ \ 8834c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux R1_BLOCK_LEN_ERROR | /* Transferred block length incorrect */\ 8844c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux R1_WP_VIOLATION | /* Tried to write to protected block */ \ 8854c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux R1_CC_ERROR | /* Card controller error */ \ 8864c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux R1_ERROR) /* General/unknown error */ 8874c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux 888ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlinstatic int mmc_blk_err_check(struct mmc_card *card, 889ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin struct mmc_async_req *areq) 890d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin{ 891ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin struct mmc_queue_req *mq_mrq = container_of(areq, struct mmc_queue_req, 892ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin mmc_active); 893ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin struct mmc_blk_request *brq = &mq_mrq->brq; 894ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin struct request *req = mq_mrq->req; 89567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter int ecc_err = 0; 896d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin 897d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin /* 898d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * sbc.error indicates a problem with the set block count 899d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * command. No data will have been transferred. 900d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * 901d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * cmd.error indicates a problem with the r/w command. No 902d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * data will have been transferred. 903d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * 904d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * stop.error indicates a problem with the stop command. Data 905d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * may have been transferred, or may still be transferring. 906d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin */ 90767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (brq->sbc.error || brq->cmd.error || brq->stop.error || 90867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter brq->data.error) { 90967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter switch (mmc_blk_cmd_recovery(card, req, brq, &ecc_err)) { 910d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin case ERR_RETRY: 911d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin return MMC_BLK_RETRY; 912d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin case ERR_ABORT: 913d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin return MMC_BLK_ABORT; 914d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin case ERR_CONTINUE: 915d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin break; 916d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin } 917d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin } 918d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin 919d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin /* 920d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * Check for errors relating to the execution of the 921d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * initial command - such as address errors. No data 922d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * has been transferred. 923d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin */ 924d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin if (brq->cmd.resp[0] & CMD_ERRORS) { 925d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin pr_err("%s: r/w command failed, status = %#x\n", 926d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin req->rq_disk->disk_name, brq->cmd.resp[0]); 927d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin return MMC_BLK_ABORT; 928d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin } 929d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin 930d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin /* 931d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * Everything else is either success, or a data error of some 932d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * kind. If it was a write, we may have transitioned to 933d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * program mode, which we have to wait for it to complete. 934d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin */ 935d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) { 936d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin u32 status; 937d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin do { 938d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin int err = get_card_status(card, &status, 5); 939d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin if (err) { 940a3c76eb9d4a1e68a69dd880cf0bcb8a52418b993Girish K S pr_err("%s: error %d requesting status\n", 941d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin req->rq_disk->disk_name, err); 942d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin return MMC_BLK_CMD_ERR; 943d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin } 944d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin /* 945d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * Some cards mishandle the status bits, 946d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * so make sure to check both the busy 947d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * indication and the card state. 948d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin */ 949d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin } while (!(status & R1_READY_FOR_DATA) || 950d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin (R1_CURRENT_STATE(status) == R1_STATE_PRG)); 951d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin } 952d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin 953d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin if (brq->data.error) { 954d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin pr_err("%s: error %d transferring data, sector %u, nr %u, cmd response %#x, card status %#x\n", 955d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin req->rq_disk->disk_name, brq->data.error, 956d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin (unsigned)blk_rq_pos(req), 957d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin (unsigned)blk_rq_sectors(req), 958d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin brq->cmd.resp[0], brq->stop.resp[0]); 959d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin 960d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin if (rq_data_dir(req) == READ) { 96167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (ecc_err) 96267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter return MMC_BLK_ECC_ERR; 963d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin return MMC_BLK_DATA_ERR; 964d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin } else { 965d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin return MMC_BLK_CMD_ERR; 966d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin } 967d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin } 968d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin 96967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (!brq->data.bytes_xfered) 97067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter return MMC_BLK_RETRY; 971d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin 97267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (blk_rq_bytes(req) != brq->data.bytes_xfered) 97367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter return MMC_BLK_PARTIAL; 97467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter 97567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter return MMC_BLK_SUCCESS; 976d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin} 977d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin 97854d49d77628bed77e5491b8a2a1158a492843a19Per Forlinstatic void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, 97954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin struct mmc_card *card, 98054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin int disable_multi, 98154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin struct mmc_queue *mq) 9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 98354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin u32 readcmd, writecmd; 98454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin struct mmc_blk_request *brq = &mqrq->brq; 98554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin struct request *req = mqrq->req; 9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_blk_data *md = mq->data; 9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 988f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin /* 989f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin * Reliable writes are used to implement Forced Unit Access and 990f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin * REQ_META accesses, and are supported only on MMCs. 99165299a3b788bd274bed92f9fa3232082c9f3ea70Christoph Hellwig * 99265299a3b788bd274bed92f9fa3232082c9f3ea70Christoph Hellwig * XXX: this really needs a good explanation of why REQ_META 99365299a3b788bd274bed92f9fa3232082c9f3ea70Christoph Hellwig * is treated special. 994f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin */ 995f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin bool do_rel_wr = ((req->cmd_flags & REQ_FUA) || 996f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin (req->cmd_flags & REQ_META)) && 997f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin (rq_data_dir(req) == WRITE) && 998d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin (md->flags & MMC_BLK_REL_WR); 999f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin 100054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin memset(brq, 0, sizeof(struct mmc_blk_request)); 100154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->mrq.cmd = &brq->cmd; 100254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->mrq.data = &brq->data; 10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 100454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->cmd.arg = blk_rq_pos(req); 100554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin if (!mmc_card_blockaddr(card)) 100654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->cmd.arg <<= 9; 100754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; 100854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->data.blksz = 512; 100954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->stop.opcode = MMC_STOP_TRANSMISSION; 101054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->stop.arg = 0; 101154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; 101254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->data.blocks = blk_rq_sectors(req); 10136a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter 101454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin /* 101554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * The block layer doesn't support all sector count 101654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * restrictions, so we need to be prepared for too big 101754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * requests. 101854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin */ 101954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin if (brq->data.blocks > card->host->max_blk_count) 102054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->data.blocks = card->host->max_blk_count; 10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 102254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin /* 102354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * After a read error, we redo the request one sector at a time 102454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * in order to accurately determine which sectors can be read 102554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * successfully. 102654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin */ 102754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin if (disable_multi && brq->data.blocks > 1) 102854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->data.blocks = 1; 1029d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin 103054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin if (brq->data.blocks > 1 || do_rel_wr) { 103154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin /* SPI multiblock writes terminate using a special 103254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * token, not a STOP_TRANSMISSION request. 1033d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin */ 103454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin if (!mmc_host_is_spi(card->host) || 103554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin rq_data_dir(req) == READ) 103654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->mrq.stop = &brq->stop; 103754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin readcmd = MMC_READ_MULTIPLE_BLOCK; 103854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin writecmd = MMC_WRITE_MULTIPLE_BLOCK; 103954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin } else { 104054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->mrq.stop = NULL; 104154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin readcmd = MMC_READ_SINGLE_BLOCK; 104254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin writecmd = MMC_WRITE_BLOCK; 104354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin } 104454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin if (rq_data_dir(req) == READ) { 104554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->cmd.opcode = readcmd; 104654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->data.flags |= MMC_DATA_READ; 104754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin } else { 104854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->cmd.opcode = writecmd; 104954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->data.flags |= MMC_DATA_WRITE; 105054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin } 1051d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin 105254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin if (do_rel_wr) 105354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin mmc_apply_rel_rw(brq, card, req); 1054f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin 105554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin /* 105654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * Pre-defined multi-block transfers are preferable to 105754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * open ended-ones (and necessary for reliable writes). 105854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * However, it is not sufficient to just send CMD23, 105954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * and avoid the final CMD12, as on an error condition 106054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * CMD12 (stop) needs to be sent anyway. This, coupled 106154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * with Auto-CMD23 enhancements provided by some 106254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * hosts, means that the complexity of dealing 106354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * with this is best left to the host. If CMD23 is 106454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * supported by card and host, we'll fill sbc in and let 106554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * the host deal with handling it correctly. This means 106654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * that for hosts that don't expose MMC_CAP_CMD23, no 106754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * change of behavior will be observed. 106854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * 106954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * N.B: Some MMC cards experience perf degradation. 107054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * We'll avoid using CMD23-bounded multiblock writes for 107154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * these, while retaining features like reliable writes. 107254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin */ 1073b146d26a61e0feab2f12a98ae83fd352830899c0Pierre Ossman 107454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin if ((md->flags & MMC_BLK_CMD23) && 107554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin mmc_op_multi(brq->cmd.opcode) && 107654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin (do_rel_wr || !(card->quirks & MMC_QUIRK_BLK_NO_CMD23))) { 107754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->sbc.opcode = MMC_SET_BLOCK_COUNT; 107854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->sbc.arg = brq->data.blocks | 107954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin (do_rel_wr ? (1 << 31) : 0); 108054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->sbc.flags = MMC_RSP_R1 | MMC_CMD_AC; 108154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->mrq.sbc = &brq->sbc; 108254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin } 108398ccf14909ba02a41c5925b0b2c92aeeef23d3b9Pierre Ossman 108454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin mmc_set_data_timeout(&brq->data, card); 108554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin 108654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->data.sg = mqrq->sg; 108754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->data.sg_len = mmc_queue_map_sg(mq, mqrq); 108854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin 108954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin /* 109054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * Adjust the sg list so it is the same size as the 109154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * request. 109254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin */ 109354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin if (brq->data.blocks != blk_rq_sectors(req)) { 109454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin int i, data_size = brq->data.blocks << 9; 109554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin struct scatterlist *sg; 109654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin 109754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin for_each_sg(brq->data.sg, sg, brq->data.sg_len, i) { 109854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin data_size -= sg->length; 109954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin if (data_size <= 0) { 110054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin sg->length += data_size; 110154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin i++; 110254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin break; 11036a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter } 11046a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter } 110554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->data.sg_len = i; 110654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin } 110754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin 1108ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin mqrq->mmc_active.mrq = &brq->mrq; 1109ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin mqrq->mmc_active.err_check = mmc_blk_err_check; 1110ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin 111154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin mmc_queue_bounce_pre(mqrq); 111254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin} 11136a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter 111467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunterstatic int mmc_blk_cmd_err(struct mmc_blk_data *md, struct mmc_card *card, 111567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter struct mmc_blk_request *brq, struct request *req, 111667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter int ret) 111767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter{ 111867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter /* 111967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter * If this is an SD card and we're writing, we can first 112067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter * mark the known good sectors as ok. 112167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter * 112267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter * If the card is not SD, we can still ok written sectors 112367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter * as reported by the controller (which might be less than 112467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter * the real number of written sectors, but never more). 112567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter */ 112667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (mmc_card_sd(card)) { 112767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter u32 blocks; 112867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter 112967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter blocks = mmc_sd_num_wr_blocks(card); 113067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (blocks != (u32)-1) { 113167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter spin_lock_irq(&md->lock); 113267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter ret = __blk_end_request(req, 0, blocks << 9); 113367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter spin_unlock_irq(&md->lock); 113467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter } 113567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter } else { 113667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter spin_lock_irq(&md->lock); 113767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter ret = __blk_end_request(req, 0, brq->data.bytes_xfered); 113867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter spin_unlock_irq(&md->lock); 113967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter } 114067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter return ret; 114167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter} 114267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter 1143ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlinstatic int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc) 114454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin{ 114554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin struct mmc_blk_data *md = mq->data; 114654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin struct mmc_card *card = md->queue.card; 114754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin struct mmc_blk_request *brq = &mq->mqrq_cur->brq; 114867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter int ret = 1, disable_multi = 0, retry = 0, type; 1149d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin enum mmc_blk_status status; 1150ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin struct mmc_queue_req *mq_rq; 1151ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin struct request *req; 1152ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin struct mmc_async_req *areq; 11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1154ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin if (!rqc && !mq->mqrq_prev->req) 1155ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin return 0; 115698ccf14909ba02a41c5925b0b2c92aeeef23d3b9Pierre Ossman 1157ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin do { 1158ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin if (rqc) { 1159ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin mmc_blk_rw_rq_prep(mq->mqrq_cur, card, 0, mq); 1160ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin areq = &mq->mqrq_cur->mmc_active; 1161ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin } else 1162ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin areq = NULL; 1163ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin areq = mmc_start_req(card->host, areq, (int *) &status); 1164ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin if (!areq) 1165ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin return 0; 1166ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin 1167ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin mq_rq = container_of(areq, struct mmc_queue_req, mmc_active); 1168ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin brq = &mq_rq->brq; 1169ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin req = mq_rq->req; 117067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter type = rq_data_dir(req) == READ ? MMC_BLK_READ : MMC_BLK_WRITE; 1171ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin mmc_queue_bounce_post(mq_rq); 117298ccf14909ba02a41c5925b0b2c92aeeef23d3b9Pierre Ossman 1173d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin switch (status) { 1174d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin case MMC_BLK_SUCCESS: 1175d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin case MMC_BLK_PARTIAL: 1176d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin /* 1177d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * A block was successfully transferred. 1178d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin */ 117967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter mmc_blk_reset_success(md, type); 1180d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin spin_lock_irq(&md->lock); 1181d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin ret = __blk_end_request(req, 0, 1182d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin brq->data.bytes_xfered); 1183d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin spin_unlock_irq(&md->lock); 118467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter /* 118567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter * If the blk_end_request function returns non-zero even 118667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter * though all data has been transferred and no errors 118767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter * were returned by the host controller, it's a bug. 118867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter */ 1189ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin if (status == MMC_BLK_SUCCESS && ret) { 1190a3c76eb9d4a1e68a69dd880cf0bcb8a52418b993Girish K S pr_err("%s BUG rq_tot %d d_xfer %d\n", 1191ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin __func__, blk_rq_bytes(req), 1192ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin brq->data.bytes_xfered); 1193ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin rqc = NULL; 1194ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin goto cmd_abort; 1195ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin } 1196d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin break; 1197d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin case MMC_BLK_CMD_ERR: 119867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter ret = mmc_blk_cmd_err(md, card, brq, req, ret); 119967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (!mmc_blk_reset(md, card->host, type)) 120067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter break; 120167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter goto cmd_abort; 1202d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin case MMC_BLK_RETRY: 1203d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin if (retry++ < 5) 1204a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux break; 120567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter /* Fall through */ 1206d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin case MMC_BLK_ABORT: 120767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (!mmc_blk_reset(md, card->host, type)) 120867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter break; 12094c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux goto cmd_abort; 121067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter case MMC_BLK_DATA_ERR: { 121167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter int err; 121267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter 121367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter err = mmc_blk_reset(md, card->host, type); 121467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (!err) 121567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter break; 121667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (err == -ENODEV) 121767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter goto cmd_abort; 121867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter /* Fall through */ 121967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter } 122067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter case MMC_BLK_ECC_ERR: 122167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (brq->data.blocks > 1) { 122267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter /* Redo read one sector at a time */ 122367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter pr_warning("%s: retrying using single block read\n", 122467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter req->rq_disk->disk_name); 122567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter disable_multi = 1; 122667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter break; 122767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter } 1228d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin /* 1229d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * After an error, we redo I/O one sector at a 1230d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * time, so we only reach here after trying to 1231d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * read a single sector. 1232d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin */ 1233d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin spin_lock_irq(&md->lock); 1234d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin ret = __blk_end_request(req, -EIO, 1235d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin brq->data.blksz); 1236d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin spin_unlock_irq(&md->lock); 1237ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin if (!ret) 1238ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin goto start_new_req; 1239d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin break; 12404c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux } 12414c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux 1242ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin if (ret) { 1243ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin /* 124467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter * In case of a incomplete request 1245ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin * prepare it again and resend. 1246ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin */ 1247ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin mmc_blk_rw_rq_prep(mq_rq, card, disable_multi, mq); 1248ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin mmc_start_req(card->host, &mq_rq->mmc_active, NULL); 1249ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin } 12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } while (ret); 12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1254a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux cmd_abort: 12551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irq(&md->lock); 1256fd539832c7d3a242269374dbcae2cd54da150930Kiyoshi Ueda while (ret) 1257fd539832c7d3a242269374dbcae2cd54da150930Kiyoshi Ueda ret = __blk_end_request(req, -EIO, blk_rq_cur_bytes(req)); 12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irq(&md->lock); 12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1260ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin start_new_req: 1261ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin if (rqc) { 1262ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin mmc_blk_rw_rq_prep(mq->mqrq_cur, card, 0, mq); 1263ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin mmc_start_req(card->host, &mq->mqrq_cur->mmc_active, NULL); 1264ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin } 1265ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin 12661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 12671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1269bd788c9665fb7c543aac21317059375632343337Adrian Hunterstatic int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) 1270bd788c9665fb7c543aac21317059375632343337Adrian Hunter{ 12711a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin int ret; 12721a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin struct mmc_blk_data *md = mq->data; 12731a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin struct mmc_card *card = md->queue.card; 12741a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin 1275ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin if (req && !mq->mqrq_prev->req) 1276ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin /* claim host only for the first request */ 1277ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin mmc_claim_host(card->host); 1278ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin 1279371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin ret = mmc_blk_part_switch(card, md); 1280371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin if (ret) { 12810d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter if (req) { 12820d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter spin_lock_irq(&md->lock); 12830d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter __blk_end_request_all(req, -EIO); 12840d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter spin_unlock_irq(&md->lock); 12850d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter } 1286371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin ret = 0; 1287371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin goto out; 1288371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin } 12891a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin 1290ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin if (req && req->cmd_flags & REQ_DISCARD) { 1291ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin /* complete ongoing async transfer before issuing discard */ 1292ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin if (card->host->areq) 1293ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin mmc_blk_issue_rw_rq(mq, NULL); 12944980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter if (req->cmd_flags & REQ_SECURE) 12951a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin ret = mmc_blk_issue_secdiscard_rq(mq, req); 12964980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter else 12971a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin ret = mmc_blk_issue_discard_rq(mq, req); 1298ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin } else if (req && req->cmd_flags & REQ_FLUSH) { 1299393f9a08e2ee72e42379489a5781feaf9c406d5fJaehoon Chung /* complete ongoing async transfer before issuing flush */ 1300393f9a08e2ee72e42379489a5781feaf9c406d5fJaehoon Chung if (card->host->areq) 1301393f9a08e2ee72e42379489a5781feaf9c406d5fJaehoon Chung mmc_blk_issue_rw_rq(mq, NULL); 13021a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin ret = mmc_blk_issue_flush(mq, req); 13034980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter } else { 13041a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin ret = mmc_blk_issue_rw_rq(mq, req); 13054980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter } 13061a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin 1307371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinout: 1308ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin if (!req) 1309ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin /* release host only when there are no more requests */ 1310ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin mmc_release_host(card->host); 13111a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin return ret; 1312bd788c9665fb7c543aac21317059375632343337Adrian Hunter} 13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1314a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell Kingstatic inline int mmc_blk_readonly(struct mmc_card *card) 1315a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King{ 1316a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King return mmc_card_readonly(card) || 1317a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King !(card->csd.cmdclass & CCC_BLOCK_WRITE); 1318a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King} 1319a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King 1320371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card, 1321371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct device *parent, 1322371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin sector_t size, 1323371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin bool default_ro, 1324371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin const char *subname) 13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_blk_data *md; 13271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int devidx, ret; 13281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13295e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson devidx = find_first_zero_bit(dev_use, max_devices); 13305e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson if (devidx >= max_devices) 13311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ERR_PTR(-ENOSPC); 13321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __set_bit(devidx, dev_use); 13331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1334dd00cc486ab1c17049a535413d1751ef3482141cYoann Padioleau md = kzalloc(sizeof(struct mmc_blk_data), GFP_KERNEL); 1335a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King if (!md) { 1336a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King ret = -ENOMEM; 1337a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King goto out; 1338a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King } 13391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1340a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King /* 1341f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin * !subname implies we are creating main mmc_blk_data that will be 1342f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin * associated with mmc_card with mmc_set_drvdata. Due to device 1343f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin * partitions, devidx will not coincide with a per-physical card 1344f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin * index anymore so we keep track of a name index. 1345f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin */ 1346f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin if (!subname) { 1347f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin md->name_idx = find_first_zero_bit(name_use, max_devices); 1348f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin __set_bit(md->name_idx, name_use); 1349f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin } 1350f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin else 1351f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin md->name_idx = ((struct mmc_blk_data *) 1352f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin dev_to_disk(parent)->private_data)->name_idx; 1353f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin 1354f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin /* 1355a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * Set the read-only status based on the supported commands 1356a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * and the write protect switch. 1357a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King */ 1358a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King md->read_only = mmc_blk_readonly(card); 13591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13605e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson md->disk = alloc_disk(perdev_minors); 1361a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King if (md->disk == NULL) { 1362a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King ret = -ENOMEM; 1363a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King goto err_kfree; 1364a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King } 13651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1366a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King spin_lock_init(&md->lock); 1367371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin INIT_LIST_HEAD(&md->part); 1368a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King md->usage = 1; 13691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1370d09408ade08a08a710a247fb52aa50101e73ebf7Adrian Hunter ret = mmc_init_queue(&md->queue, card, &md->lock, subname); 1371a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King if (ret) 1372a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King goto err_putdisk; 13731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1374a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King md->queue.issue_fn = mmc_blk_issue_rq; 1375a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King md->queue.data = md; 1376d2b18394259ef621fd2a6322aa9934198fd87a6aRussell King 1377fe6b4c8840c5e23fe9b8696450cee8f2e8cebffdPierre Ossman md->disk->major = MMC_BLOCK_MAJOR; 13785e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson md->disk->first_minor = devidx * perdev_minors; 1379a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King md->disk->fops = &mmc_bdops; 1380a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King md->disk->private_data = md; 1381a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King md->disk->queue = md->queue.queue; 1382371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin md->disk->driverfs_dev = parent; 1383371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin set_disk_ro(md->disk, md->read_only || default_ro); 1384a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King 1385a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King /* 1386a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * As discussed on lkml, GENHD_FL_REMOVABLE should: 1387a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * 1388a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * - be set for removable media with permanent block devices 1389a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * - be unset for removable block devices with permanent media 1390a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * 1391a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * Since MMC block devices clearly fall under the second 1392a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * case, we do not set GENHD_FL_REMOVABLE. Userspace 1393a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * should use the block device creation/destruction hotplug 1394a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * messages to tell when the card is present. 1395a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King */ 1396a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King 1397f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin snprintf(md->disk->disk_name, sizeof(md->disk->disk_name), 1398f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin "mmcblk%d%s", md->name_idx, subname ? subname : ""); 1399a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King 1400e1defc4ff0cf57aca6c5e3ff99fa503f5943c1f1Martin K. Petersen blk_queue_logical_block_size(md->queue.queue, 512); 1401371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin set_capacity(md->disk, size); 1402d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin 1403f0d89972b01798cf9d245dfa1cacfa0ee78a3593Andrei Warkentin if (mmc_host_cmd23(card->host)) { 1404f0d89972b01798cf9d245dfa1cacfa0ee78a3593Andrei Warkentin if (mmc_card_mmc(card) || 1405f0d89972b01798cf9d245dfa1cacfa0ee78a3593Andrei Warkentin (mmc_card_sd(card) && 1406f0d89972b01798cf9d245dfa1cacfa0ee78a3593Andrei Warkentin card->scr.cmds & SD_SCR_CMD23_SUPPORT)) 1407f0d89972b01798cf9d245dfa1cacfa0ee78a3593Andrei Warkentin md->flags |= MMC_BLK_CMD23; 1408f0d89972b01798cf9d245dfa1cacfa0ee78a3593Andrei Warkentin } 1409d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin 1410d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin if (mmc_card_mmc(card) && 1411d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin md->flags & MMC_BLK_CMD23 && 1412d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin ((card->ext_csd.rel_param & EXT_CSD_WR_REL_PARAM_EN) || 1413d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin card->ext_csd.rel_sectors)) { 1414d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin md->flags |= MMC_BLK_REL_WR; 1415d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin blk_queue_flush(md->queue.queue, REQ_FLUSH | REQ_FUA); 1416d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin } 1417d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin 1418371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin return md; 1419371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 1420371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin err_putdisk: 1421371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin put_disk(md->disk); 1422371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin err_kfree: 1423371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin kfree(md); 1424371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin out: 1425371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin return ERR_PTR(ret); 1426371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin} 1427371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 1428371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card) 1429371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{ 1430371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin sector_t size; 1431371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct mmc_blk_data *md; 1432a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King 143385a18ad93ec66888d85758630019b10a84257f3cPierre Ossman if (!mmc_card_sd(card) && mmc_card_blockaddr(card)) { 143485a18ad93ec66888d85758630019b10a84257f3cPierre Ossman /* 143585a18ad93ec66888d85758630019b10a84257f3cPierre Ossman * The EXT_CSD sector count is in number or 512 byte 143685a18ad93ec66888d85758630019b10a84257f3cPierre Ossman * sectors. 143785a18ad93ec66888d85758630019b10a84257f3cPierre Ossman */ 1438371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin size = card->ext_csd.sectors; 143985a18ad93ec66888d85758630019b10a84257f3cPierre Ossman } else { 144085a18ad93ec66888d85758630019b10a84257f3cPierre Ossman /* 144185a18ad93ec66888d85758630019b10a84257f3cPierre Ossman * The CSD capacity field is in units of read_blkbits. 144285a18ad93ec66888d85758630019b10a84257f3cPierre Ossman * set_capacity takes units of 512 bytes. 144385a18ad93ec66888d85758630019b10a84257f3cPierre Ossman */ 1444371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin size = card->csd.capacity << (card->csd.read_blkbits - 9); 144585a18ad93ec66888d85758630019b10a84257f3cPierre Ossman } 1446371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 1447371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin md = mmc_blk_alloc_req(card, &card->dev, size, false, NULL); 14481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return md; 1449371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin} 1450a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King 1451371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic int mmc_blk_alloc_part(struct mmc_card *card, 1452371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct mmc_blk_data *md, 1453371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin unsigned int part_type, 1454371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin sector_t size, 1455371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin bool default_ro, 1456371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin const char *subname) 1457371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{ 1458371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin char cap_str[10]; 1459371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct mmc_blk_data *part_md; 1460371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 1461371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin part_md = mmc_blk_alloc_req(card, disk_to_dev(md->disk), size, default_ro, 1462371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin subname); 1463371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin if (IS_ERR(part_md)) 1464371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin return PTR_ERR(part_md); 1465371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin part_md->part_type = part_type; 1466371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin list_add(&part_md->part, &md->part); 1467371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 1468371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin string_get_size((u64)get_capacity(part_md->disk) << 9, STRING_UNITS_2, 1469371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin cap_str, sizeof(cap_str)); 1470a3c76eb9d4a1e68a69dd880cf0bcb8a52418b993Girish K S pr_info("%s: %s %s partition %u %s\n", 1471371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin part_md->disk->disk_name, mmc_card_id(card), 1472371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin mmc_card_name(card), part_md->part_type, cap_str); 1473371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin return 0; 1474371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin} 1475371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 1476e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon/* MMC Physical partitions consist of two boot partitions and 1477e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon * up to four general purpose partitions. 1478e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon * For each partition enabled in EXT_CSD a block device will be allocatedi 1479e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon * to provide access to the partition. 1480e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon */ 1481e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon 1482371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic int mmc_blk_alloc_parts(struct mmc_card *card, struct mmc_blk_data *md) 1483371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{ 1484e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon int idx, ret = 0; 1485371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 1486371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin if (!mmc_card_mmc(card)) 1487371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin return 0; 1488371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 1489e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon for (idx = 0; idx < card->nr_parts; idx++) { 1490e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon if (card->part[idx].size) { 1491e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon ret = mmc_blk_alloc_part(card, md, 1492e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon card->part[idx].part_cfg, 1493e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon card->part[idx].size >> 9, 1494e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon card->part[idx].force_ro, 1495e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon card->part[idx].name); 1496e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon if (ret) 1497e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon return ret; 1498e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon } 1499371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin } 1500371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 1501371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin return ret; 15021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 15031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 15051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card) 15061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 15071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err; 15081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1509b855885e3b60cf6f9452848712a62517b94583ebPierre Ossman mmc_claim_host(card->host); 15100f8d8ea64ec7c77ca5beb59534d386fe0235961aAdrian Hunter err = mmc_set_blocklen(card, 512); 1511b855885e3b60cf6f9452848712a62517b94583ebPierre Ossman mmc_release_host(card->host); 15121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err) { 1514a3c76eb9d4a1e68a69dd880cf0bcb8a52418b993Girish K S pr_err("%s: unable to set block size to 512: %d\n", 15150f8d8ea64ec7c77ca5beb59534d386fe0235961aAdrian Hunter md->disk->disk_name, err); 15161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 15171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 15181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 15201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 15211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1522371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic void mmc_blk_remove_req(struct mmc_blk_data *md) 1523371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{ 1524371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin if (md) { 1525371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin if (md->disk->flags & GENHD_FL_UP) { 1526371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin device_remove_file(disk_to_dev(md->disk), &md->force_ro); 1527371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 1528371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin /* Stop new requests from getting into the queue */ 1529371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin del_gendisk(md->disk); 1530371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin } 1531371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 1532371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin /* Then flush out any already in there */ 1533371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin mmc_cleanup_queue(&md->queue); 1534371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin mmc_blk_put(md); 1535371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin } 1536371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin} 1537371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 1538371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic void mmc_blk_remove_parts(struct mmc_card *card, 1539371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct mmc_blk_data *md) 1540371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{ 1541371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct list_head *pos, *q; 1542371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct mmc_blk_data *part_md; 1543371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 1544f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin __clear_bit(md->name_idx, name_use); 1545371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin list_for_each_safe(pos, q, &md->part) { 1546371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin part_md = list_entry(pos, struct mmc_blk_data, part); 1547371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin list_del(pos); 1548371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin mmc_blk_remove_req(part_md); 1549371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin } 1550371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin} 1551371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 1552371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic int mmc_add_disk(struct mmc_blk_data *md) 1553371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{ 1554371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin int ret; 1555371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 1556371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin add_disk(md->disk); 1557371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin md->force_ro.show = force_ro_show; 1558371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin md->force_ro.store = force_ro_store; 1559641c3187b9d53cfd4c23b0ce2ab18a13d5e775e5Rabin Vincent sysfs_attr_init(&md->force_ro.attr); 1560371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin md->force_ro.attr.name = "force_ro"; 1561371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin md->force_ro.attr.mode = S_IRUGO | S_IWUSR; 1562371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin ret = device_create_file(disk_to_dev(md->disk), &md->force_ro); 1563371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin if (ret) 1564371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin del_gendisk(md->disk); 1565371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 1566371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin return ret; 1567371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin} 1568371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 15696f60c22252af05df94352240f30f9fc84090d88dAndrei Warkentinstatic const struct mmc_fixup blk_fixups[] = 15706f60c22252af05df94352240f30f9fc84090d88dAndrei Warkentin{ 15716a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin MMC_FIXUP("SEM02G", 0x2, 0x100, add_quirk, MMC_QUIRK_INAND_CMD38), 15726a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin MMC_FIXUP("SEM04G", 0x2, 0x100, add_quirk, MMC_QUIRK_INAND_CMD38), 15736a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin MMC_FIXUP("SEM08G", 0x2, 0x100, add_quirk, MMC_QUIRK_INAND_CMD38), 15746a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin MMC_FIXUP("SEM16G", 0x2, 0x100, add_quirk, MMC_QUIRK_INAND_CMD38), 15756a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin MMC_FIXUP("SEM32G", 0x2, 0x100, add_quirk, MMC_QUIRK_INAND_CMD38), 1576d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin 1577d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin /* 1578d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin * Some MMC cards experience performance degradation with CMD23 1579d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin * instead of CMD12-bounded multiblock transfers. For now we'll 1580d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin * black list what's bad... 1581d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin * - Certain Toshiba cards. 1582d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin * 1583d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin * N.B. This doesn't affect SD cards. 1584d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin */ 1585d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin MMC_FIXUP("MMC08G", 0x11, CID_OEMID_ANY, add_quirk_mmc, 1586d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin MMC_QUIRK_BLK_NO_CMD23), 1587d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin MMC_FIXUP("MMC16G", 0x11, CID_OEMID_ANY, add_quirk_mmc, 1588d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin MMC_QUIRK_BLK_NO_CMD23), 1589d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin MMC_FIXUP("MMC32G", 0x11, CID_OEMID_ANY, add_quirk_mmc, 1590d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin MMC_QUIRK_BLK_NO_CMD23), 15916f60c22252af05df94352240f30f9fc84090d88dAndrei Warkentin END_FIXUP 15926f60c22252af05df94352240f30f9fc84090d88dAndrei Warkentin}; 15936f60c22252af05df94352240f30f9fc84090d88dAndrei Warkentin 15941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mmc_blk_probe(struct mmc_card *card) 15951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1596371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct mmc_blk_data *md, *part_md; 15971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err; 1598a7bbb57333447d0cf950992653b6b079585f3531Pierre Ossman char cap_str[10]; 1599a7bbb57333447d0cf950992653b6b079585f3531Pierre Ossman 1600912490db699d83cb3d03570b63df7448677a3f56Pierre Ossman /* 1601912490db699d83cb3d03570b63df7448677a3f56Pierre Ossman * Check that the card supports the command class(es) we need. 1602912490db699d83cb3d03570b63df7448677a3f56Pierre Ossman */ 1603912490db699d83cb3d03570b63df7448677a3f56Pierre Ossman if (!(card->csd.cmdclass & CCC_BLOCK_READ)) 16041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 16051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds md = mmc_blk_alloc(card); 16071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (IS_ERR(md)) 16081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return PTR_ERR(md); 16091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = mmc_blk_set_blksize(md, card); 16111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err) 16121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 16131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1614444122fd58fdc83c96877a92b3f6288cafddb08dYi Li string_get_size((u64)get_capacity(md->disk) << 9, STRING_UNITS_2, 1615a7bbb57333447d0cf950992653b6b079585f3531Pierre Ossman cap_str, sizeof(cap_str)); 1616a3c76eb9d4a1e68a69dd880cf0bcb8a52418b993Girish K S pr_info("%s: %s %s %s %s\n", 16171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds md->disk->disk_name, mmc_card_id(card), mmc_card_name(card), 1618a7bbb57333447d0cf950992653b6b079585f3531Pierre Ossman cap_str, md->read_only ? "(ro)" : ""); 16191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1620371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin if (mmc_blk_alloc_parts(card, md)) 1621371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin goto out; 1622371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 16231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_set_drvdata(card, md); 16246f60c22252af05df94352240f30f9fc84090d88dAndrei Warkentin mmc_fixup_device(card, blk_fixups); 16256f60c22252af05df94352240f30f9fc84090d88dAndrei Warkentin 1626371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin if (mmc_add_disk(md)) 1627371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin goto out; 1628371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 1629371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin list_for_each_entry(part_md, &md->part, part) { 1630371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin if (mmc_add_disk(part_md)) 1631371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin goto out; 1632371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin } 16331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 16341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 1636371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin mmc_blk_remove_parts(card, md); 1637371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin mmc_blk_remove_req(md); 16381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 16391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mmc_blk_remove(struct mmc_card *card) 16421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 16431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_blk_data *md = mmc_get_drvdata(card); 16441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1645371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin mmc_blk_remove_parts(card, md); 1646ddd6fa7e794e62af3ec3eb4ffdc78489885701f2Adrian Hunter mmc_claim_host(card->host); 1647ddd6fa7e794e62af3ec3eb4ffdc78489885701f2Adrian Hunter mmc_blk_part_switch(card, md); 1648ddd6fa7e794e62af3ec3eb4ffdc78489885701f2Adrian Hunter mmc_release_host(card->host); 1649371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin mmc_blk_remove_req(md); 16501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_set_drvdata(card, NULL); 16511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PM 16541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mmc_blk_suspend(struct mmc_card *card, pm_message_t state) 16551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1656371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct mmc_blk_data *part_md; 16571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_blk_data *md = mmc_get_drvdata(card); 16581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (md) { 16601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_queue_suspend(&md->queue); 1661371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin list_for_each_entry(part_md, &md->part, part) { 1662371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin mmc_queue_suspend(&part_md->queue); 1663371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin } 16641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 16651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 16661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mmc_blk_resume(struct mmc_card *card) 16691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1670371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct mmc_blk_data *part_md; 16711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_blk_data *md = mmc_get_drvdata(card); 16721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (md) { 16741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_blk_set_blksize(md, card); 1675371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 1676371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin /* 1677371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin * Resume involves the card going into idle state, 1678371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin * so current partition is always the main one. 1679371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin */ 1680371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin md->part_curr = md->part_type; 16811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_queue_resume(&md->queue); 1682371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin list_for_each_entry(part_md, &md->part, part) { 1683371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin mmc_queue_resume(&part_md->queue); 1684371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin } 16851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 16861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 16871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 16891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define mmc_blk_suspend NULL 16901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define mmc_blk_resume NULL 16911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 16921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct mmc_driver mmc_driver = { 16941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .drv = { 16951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "mmcblk", 16961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 16971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .probe = mmc_blk_probe, 16981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .remove = mmc_blk_remove, 16991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .suspend = mmc_blk_suspend, 17001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .resume = mmc_blk_resume, 17011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 17021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init mmc_blk_init(void) 17041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 17059d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita int res; 17061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17075e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson if (perdev_minors != CONFIG_MMC_BLOCK_MINORS) 17085e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson pr_info("mmcblk: using %d minors per device\n", perdev_minors); 17095e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson 17105e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson max_devices = 256 / perdev_minors; 17115e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson 1712fe6b4c8840c5e23fe9b8696450cee8f2e8cebffdPierre Ossman res = register_blkdev(MMC_BLOCK_MAJOR, "mmc"); 1713fe6b4c8840c5e23fe9b8696450cee8f2e8cebffdPierre Ossman if (res) 17141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 17151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17169d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita res = mmc_register_driver(&mmc_driver); 17179d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita if (res) 17189d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita goto out2; 17191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17209d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita return 0; 17219d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita out2: 17229d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita unregister_blkdev(MMC_BLOCK_MAJOR, "mmc"); 17231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 17241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return res; 17251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 17261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit mmc_blk_exit(void) 17281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 17291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_unregister_driver(&mmc_driver); 1730fe6b4c8840c5e23fe9b8696450cee8f2e8cebffdPierre Ossman unregister_blkdev(MMC_BLOCK_MAJOR, "mmc"); 17311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 17321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(mmc_blk_init); 17341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(mmc_blk_exit); 17351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 17371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("Multimedia Card (MMC) block device driver"); 17381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1739