block.c revision 3550ccdb9d8d350e526b809bf3dd92b550a74fe1
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/uaccess.h> 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4698ac2162699f7e9880683cb954891817f20b607cPierre Ossman#include "queue.h" 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 486b0b62853b2553be375033776902640320970846Andy WhitcroftMODULE_ALIAS("mmc:block"); 495e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson#ifdef MODULE_PARAM_PREFIX 505e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson#undef MODULE_PARAM_PREFIX 515e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson#endif 525e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson#define MODULE_PARAM_PREFIX "mmcblk." 535e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson 546a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin#define INAND_CMD38_ARG_EXT_CSD 113 556a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin#define INAND_CMD38_ARG_ERASE 0x00 566a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin#define INAND_CMD38_ARG_TRIM 0x01 576a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin#define INAND_CMD38_ARG_SECERASE 0x80 586a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin#define INAND_CMD38_ARG_SECTRIM1 0x81 596a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin#define INAND_CMD38_ARG_SECTRIM2 0x88 606a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin 615e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johanssonstatic DEFINE_MUTEX(block_mutex); 626b0b62853b2553be375033776902640320970846Andy Whitcroft 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 645e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson * The defaults come from config options but can be overriden by module 655e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson * or bootarg options. 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 675e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johanssonstatic int perdev_minors = CONFIG_MMC_BLOCK_MINORS; 681dff314451fa24d6b107aa05393d3169e56a7e0aDavid Woodhouse 695e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson/* 705e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson * We've only got one major, so number of mmcblk devices is 715e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson * limited to 256 / number of minors per device. 725e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson */ 735e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johanssonstatic int max_devices; 745e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson 755e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson/* 256 minors, so at most 256 separate devices */ 765e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johanssonstatic DECLARE_BITMAP(dev_use, 256); 77f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentinstatic DECLARE_BITMAP(name_use, 256); 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * There is one mmc_blk_data per slot. 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct mmc_blk_data { 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spinlock_t lock; 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct gendisk *disk; 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_queue queue; 86371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct list_head part; 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 88d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin unsigned int flags; 89d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin#define MMC_BLK_CMD23 (1 << 0) /* Can do SET_BLOCK_COUNT for multiblock */ 90d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin#define MMC_BLK_REL_WR (1 << 1) /* MMC Reliable write support */ 91d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int usage; 93a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King unsigned int read_only; 94371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin unsigned int part_type; 95f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin unsigned int name_idx; 9667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter unsigned int reset_done; 9767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter#define MMC_BLK_READ BIT(0) 9867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter#define MMC_BLK_WRITE BIT(1) 9967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter#define MMC_BLK_DISCARD BIT(2) 10067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter#define MMC_BLK_SECDISCARD BIT(3) 101371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 102371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin /* 103371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin * Only set in main mmc_blk_data associated 104371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin * with mmc_card with mmc_set_drvdata, and keeps 105371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin * track of the current selected device partition. 106371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin */ 107371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin unsigned int part_curr; 108371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct device_attribute force_ro; 109add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm struct device_attribute power_ro_lock; 110add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm int area_type; 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 113a621aaed690b9439141c555941b6af53873f6ff1Arjan van de Venstatic DEFINE_MUTEX(open_lock); 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 115d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlinenum mmc_blk_status { 116d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin MMC_BLK_SUCCESS = 0, 117d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin MMC_BLK_PARTIAL, 118d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin MMC_BLK_CMD_ERR, 11967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter MMC_BLK_RETRY, 120d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin MMC_BLK_ABORT, 12167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter MMC_BLK_DATA_ERR, 12267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter MMC_BLK_ECC_ERR, 123a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma MMC_BLK_NOMEDIUM, 124d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin}; 125d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin 1265e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johanssonmodule_param(perdev_minors, int, 0444); 1275e71b7a64cb4c6cff75ca42b535d8227526ec592Olof JohanssonMODULE_PARM_DESC(perdev_minors, "Minors numbers to allocate per device"); 1285e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct mmc_blk_data *mmc_blk_get(struct gendisk *disk) 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_blk_data *md; 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 133a621aaed690b9439141c555941b6af53873f6ff1Arjan van de Ven mutex_lock(&open_lock); 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds md = disk->private_data; 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (md && md->usage == 0) 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds md = NULL; 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (md) 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds md->usage++; 139a621aaed690b9439141c555941b6af53873f6ff1Arjan van de Ven mutex_unlock(&open_lock); 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return md; 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 144371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic inline int mmc_get_devidx(struct gendisk *disk) 145371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{ 146371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin int devmaj = MAJOR(disk_devt(disk)); 147371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin int devidx = MINOR(disk_devt(disk)) / perdev_minors; 148371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 149371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin if (!devmaj) 150371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin devidx = disk->first_minor / perdev_minors; 151371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin return devidx; 152371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin} 153371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mmc_blk_put(struct mmc_blk_data *md) 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 156a621aaed690b9439141c555941b6af53873f6ff1Arjan van de Ven mutex_lock(&open_lock); 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds md->usage--; 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (md->usage == 0) { 159371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin int devidx = mmc_get_devidx(md->disk); 1605fa83ce284a4b7cd9dcfadd01500b0ed4ab9b740Adrian Hunter blk_cleanup_queue(md->queue.queue); 1615fa83ce284a4b7cd9dcfadd01500b0ed4ab9b740Adrian Hunter 1621dff314451fa24d6b107aa05393d3169e56a7e0aDavid Woodhouse __clear_bit(devidx, dev_use); 1631dff314451fa24d6b107aa05393d3169e56a7e0aDavid Woodhouse 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds put_disk(md->disk); 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(md); 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 167a621aaed690b9439141c555941b6af53873f6ff1Arjan van de Ven mutex_unlock(&open_lock); 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 170add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholmstatic ssize_t power_ro_lock_show(struct device *dev, 171add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm struct device_attribute *attr, char *buf) 172add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm{ 173add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm int ret; 174add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev)); 175add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm struct mmc_card *card = md->queue.card; 176add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm int locked = 0; 177add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm 178add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm if (card->ext_csd.boot_ro_lock & EXT_CSD_BOOT_WP_B_PERM_WP_EN) 179add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm locked = 2; 180add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm else if (card->ext_csd.boot_ro_lock & EXT_CSD_BOOT_WP_B_PWR_WP_EN) 181add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm locked = 1; 182add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm 183add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm ret = snprintf(buf, PAGE_SIZE, "%d\n", locked); 184add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm 185add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm return ret; 186add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm} 187add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm 188add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholmstatic ssize_t power_ro_lock_store(struct device *dev, 189add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm struct device_attribute *attr, const char *buf, size_t count) 190add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm{ 191add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm int ret; 192add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm struct mmc_blk_data *md, *part_md; 193add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm struct mmc_card *card; 194add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm unsigned long set; 195add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm 196add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm if (kstrtoul(buf, 0, &set)) 197add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm return -EINVAL; 198add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm 199add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm if (set != 1) 200add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm return count; 201add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm 202add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm md = mmc_blk_get(dev_to_disk(dev)); 203add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm card = md->queue.card; 204add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm 205add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm mmc_claim_host(card->host); 206add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm 207add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_WP, 208add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm card->ext_csd.boot_ro_lock | 209add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm EXT_CSD_BOOT_WP_B_PWR_WP_EN, 210add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm card->ext_csd.part_time); 211add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm if (ret) 212add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm pr_err("%s: Locking boot partition ro until next power on failed: %d\n", md->disk->disk_name, ret); 213add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm else 214add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm card->ext_csd.boot_ro_lock |= EXT_CSD_BOOT_WP_B_PWR_WP_EN; 215add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm 216add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm mmc_release_host(card->host); 217add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm 218add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm if (!ret) { 219add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm pr_info("%s: Locking boot partition ro until next power on\n", 220add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm md->disk->disk_name); 221add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm set_disk_ro(md->disk, 1); 222add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm 223add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm list_for_each_entry(part_md, &md->part, part) 224add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm if (part_md->area_type == MMC_BLK_DATA_AREA_BOOT) { 225add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm pr_info("%s: Locking boot partition ro until next power on\n", part_md->disk->disk_name); 226add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm set_disk_ro(part_md->disk, 1); 227add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm } 228add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm } 229add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm 230add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm mmc_blk_put(md); 231add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm return count; 232add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm} 233add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm 234371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic ssize_t force_ro_show(struct device *dev, struct device_attribute *attr, 235371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin char *buf) 236371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{ 237371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin int ret; 238371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev)); 239371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 240371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin ret = snprintf(buf, PAGE_SIZE, "%d", 241371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin get_disk_ro(dev_to_disk(dev)) ^ 242371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin md->read_only); 243371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin mmc_blk_put(md); 244371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin return ret; 245371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin} 246371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 247371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic ssize_t force_ro_store(struct device *dev, struct device_attribute *attr, 248371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin const char *buf, size_t count) 249371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{ 250371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin int ret; 251371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin char *end; 252371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev)); 253371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin unsigned long set = simple_strtoul(buf, &end, 0); 254371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin if (end == buf) { 255371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin ret = -EINVAL; 256371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin goto out; 257371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin } 258371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 259371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin set_disk_ro(dev_to_disk(dev), set || md->read_only); 260371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin ret = count; 261371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinout: 262371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin mmc_blk_put(md); 263371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin return ret; 264371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin} 265371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 266a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Virostatic int mmc_blk_open(struct block_device *bdev, fmode_t mode) 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 268a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Viro struct mmc_blk_data *md = mmc_blk_get(bdev->bd_disk); 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = -ENXIO; 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2712a48fc0ab24241755dc93bfd4f01d68efab47f5aArnd Bergmann mutex_lock(&block_mutex); 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (md) { 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (md->usage == 2) 274a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Viro check_disk_change(bdev); 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = 0; 276a00fc09029f02ca833cf90e5d5625f08c4ac4f51Pierre Ossman 277a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Viro if ((mode & FMODE_WRITE) && md->read_only) { 27870bb08962ea9bd50797ae9f16b2493f5f7c65053Andrew Morton mmc_blk_put(md); 279a00fc09029f02ca833cf90e5d5625f08c4ac4f51Pierre Ossman ret = -EROFS; 28070bb08962ea9bd50797ae9f16b2493f5f7c65053Andrew Morton } 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2822a48fc0ab24241755dc93bfd4f01d68efab47f5aArnd Bergmann mutex_unlock(&block_mutex); 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 287a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Virostatic int mmc_blk_release(struct gendisk *disk, fmode_t mode) 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 289a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Viro struct mmc_blk_data *md = disk->private_data; 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2912a48fc0ab24241755dc93bfd4f01d68efab47f5aArnd Bergmann mutex_lock(&block_mutex); 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_blk_put(md); 2932a48fc0ab24241755dc93bfd4f01d68efab47f5aArnd Bergmann mutex_unlock(&block_mutex); 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 298a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwigmmc_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo) 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 300a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig geo->cylinders = get_capacity(bdev->bd_disk) / (4 * 16); 301a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig geo->heads = 4; 302a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig geo->sectors = 16; 303a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig return 0; 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 306cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtostruct mmc_blk_ioc_data { 307cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto struct mmc_ioc_cmd ic; 308cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto unsigned char *buf; 309cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto u64 buf_bytes; 310cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto}; 311cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 312cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtostatic struct mmc_blk_ioc_data *mmc_blk_ioctl_copy_from_user( 313cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto struct mmc_ioc_cmd __user *user) 314cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto{ 315cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto struct mmc_blk_ioc_data *idata; 316cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto int err; 317cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 318cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto idata = kzalloc(sizeof(*idata), GFP_KERNEL); 319cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (!idata) { 320cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto err = -ENOMEM; 321aea253ecffecd38b5ab97edd73fbe2842a7de371Vladimir Motyka goto out; 322cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto } 323cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 324cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (copy_from_user(&idata->ic, user, sizeof(idata->ic))) { 325cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto err = -EFAULT; 326aea253ecffecd38b5ab97edd73fbe2842a7de371Vladimir Motyka goto idata_err; 327cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto } 328cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 329cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto idata->buf_bytes = (u64) idata->ic.blksz * idata->ic.blocks; 330cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (idata->buf_bytes > MMC_IOC_MAX_BYTES) { 331cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto err = -EOVERFLOW; 332aea253ecffecd38b5ab97edd73fbe2842a7de371Vladimir Motyka goto idata_err; 333cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto } 334cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 3354d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm if (!idata->buf_bytes) 3364d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm return idata; 3374d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm 338cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto idata->buf = kzalloc(idata->buf_bytes, GFP_KERNEL); 339cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (!idata->buf) { 340cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto err = -ENOMEM; 341aea253ecffecd38b5ab97edd73fbe2842a7de371Vladimir Motyka goto idata_err; 342cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto } 343cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 344cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (copy_from_user(idata->buf, (void __user *)(unsigned long) 345cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto idata->ic.data_ptr, idata->buf_bytes)) { 346cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto err = -EFAULT; 347cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto goto copy_err; 348cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto } 349cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 350cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto return idata; 351cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 352cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtocopy_err: 353cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto kfree(idata->buf); 354aea253ecffecd38b5ab97edd73fbe2842a7de371Vladimir Motykaidata_err: 355cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto kfree(idata); 356aea253ecffecd38b5ab97edd73fbe2842a7de371Vladimir Motykaout: 357cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto return ERR_PTR(err); 358cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto} 359cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 360cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtostatic int mmc_blk_ioctl_cmd(struct block_device *bdev, 361cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto struct mmc_ioc_cmd __user *ic_ptr) 362cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto{ 363cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto struct mmc_blk_ioc_data *idata; 364cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto struct mmc_blk_data *md; 365cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto struct mmc_card *card; 366cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto struct mmc_command cmd = {0}; 367cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto struct mmc_data data = {0}; 368ad5fd97288655b5628052c1fa906419417c86100Venkatraman S struct mmc_request mrq = {NULL}; 369cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto struct scatterlist sg; 370cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto int err; 371cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 372cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto /* 373cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto * The caller must have CAP_SYS_RAWIO, and must be calling this on the 374cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto * whole block device, not on a partition. This prevents overspray 375cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto * between sibling partitions. 376cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto */ 377cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if ((!capable(CAP_SYS_RAWIO)) || (bdev != bdev->bd_contains)) 378cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto return -EPERM; 379cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 380cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto idata = mmc_blk_ioctl_copy_from_user(ic_ptr); 381cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (IS_ERR(idata)) 382cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto return PTR_ERR(idata); 383cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 384cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto md = mmc_blk_get(bdev->bd_disk); 385cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (!md) { 386cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto err = -EINVAL; 3871c02f000e78347aa51822feb189fcb0d90273958Philippe De Swert goto cmd_err; 388cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto } 389cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 390cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto card = md->queue.card; 391cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (IS_ERR(card)) { 392cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto err = PTR_ERR(card); 393cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto goto cmd_done; 394cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto } 395cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 3964d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm cmd.opcode = idata->ic.opcode; 3974d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm cmd.arg = idata->ic.arg; 3984d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm cmd.flags = idata->ic.flags; 3994d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm 4004d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm if (idata->buf_bytes) { 4014d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm data.sg = &sg; 4024d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm data.sg_len = 1; 4034d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm data.blksz = idata->ic.blksz; 4044d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm data.blocks = idata->ic.blocks; 4054d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm 4064d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm sg_init_one(data.sg, idata->buf, idata->buf_bytes); 4074d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm 4084d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm if (idata->ic.write_flag) 4094d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm data.flags = MMC_DATA_WRITE; 4104d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm else 4114d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm data.flags = MMC_DATA_READ; 4124d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm 4134d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm /* data.flags must already be set before doing this. */ 4144d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm mmc_set_data_timeout(&data, card); 4154d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm 4164d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm /* Allow overriding the timeout_ns for empirical tuning. */ 4174d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm if (idata->ic.data_timeout_ns) 4184d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm data.timeout_ns = idata->ic.data_timeout_ns; 4194d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm 4204d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm if ((cmd.flags & MMC_RSP_R1B) == MMC_RSP_R1B) { 4214d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm /* 4224d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm * Pretend this is a data transfer and rely on the 4234d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm * host driver to compute timeout. When all host 4244d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm * drivers support cmd.cmd_timeout for R1B, this 4254d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm * can be changed to: 4264d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm * 4274d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm * mrq.data = NULL; 4284d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm * cmd.cmd_timeout = idata->ic.cmd_timeout_ms; 4294d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm */ 4304d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm data.timeout_ns = idata->ic.cmd_timeout_ms * 1000000; 4314d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm } 4324d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm 4334d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm mrq.data = &data; 4344d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm } 4354d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm 4364d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm mrq.cmd = &cmd; 4374d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm 438cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto mmc_claim_host(card->host); 439cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 440cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (idata->ic.is_acmd) { 441cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto err = mmc_app_cmd(card->host, card); 442cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (err) 443cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto goto cmd_rel_host; 444cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto } 445cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 446cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto mmc_wait_for_req(card->host, &mrq); 447cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 448cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (cmd.error) { 449cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto dev_err(mmc_dev(card->host), "%s: cmd error %d\n", 450cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto __func__, cmd.error); 451cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto err = cmd.error; 452cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto goto cmd_rel_host; 453cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto } 454cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (data.error) { 455cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto dev_err(mmc_dev(card->host), "%s: data error %d\n", 456cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto __func__, data.error); 457cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto err = data.error; 458cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto goto cmd_rel_host; 459cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto } 460cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 461cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto /* 462cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto * According to the SD specs, some commands require a delay after 463cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto * issuing the command. 464cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto */ 465cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (idata->ic.postsleep_min_us) 466cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto usleep_range(idata->ic.postsleep_min_us, idata->ic.postsleep_max_us); 467cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 468cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (copy_to_user(&(ic_ptr->response), cmd.resp, sizeof(cmd.resp))) { 469cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto err = -EFAULT; 470cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto goto cmd_rel_host; 471cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto } 472cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 473cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (!idata->ic.write_flag) { 474cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (copy_to_user((void __user *)(unsigned long) idata->ic.data_ptr, 475cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto idata->buf, idata->buf_bytes)) { 476cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto err = -EFAULT; 477cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto goto cmd_rel_host; 478cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto } 479cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto } 480cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 481cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtocmd_rel_host: 482cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto mmc_release_host(card->host); 483cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 484cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtocmd_done: 485cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto mmc_blk_put(md); 4861c02f000e78347aa51822feb189fcb0d90273958Philippe De Swertcmd_err: 487cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto kfree(idata->buf); 488cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto kfree(idata); 489cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto return err; 490cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto} 491cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 492cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtostatic int mmc_blk_ioctl(struct block_device *bdev, fmode_t mode, 493cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto unsigned int cmd, unsigned long arg) 494cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto{ 495cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto int ret = -EINVAL; 496cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (cmd == MMC_IOC_CMD) 497cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto ret = mmc_blk_ioctl_cmd(bdev, (struct mmc_ioc_cmd __user *)arg); 498cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto return ret; 499cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto} 500cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 501cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto#ifdef CONFIG_COMPAT 502cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtostatic int mmc_blk_compat_ioctl(struct block_device *bdev, fmode_t mode, 503cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto unsigned int cmd, unsigned long arg) 504cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto{ 505cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto return mmc_blk_ioctl(bdev, mode, cmd, (unsigned long) compat_ptr(arg)); 506cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto} 507cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto#endif 508cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 50983d5cde47dedf01b6a4a4331882cbc0a7eea3c2eAlexey Dobriyanstatic const struct block_device_operations mmc_bdops = { 510a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Viro .open = mmc_blk_open, 511a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Viro .release = mmc_blk_release, 512a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig .getgeo = mmc_blk_getgeo, 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .owner = THIS_MODULE, 514cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto .ioctl = mmc_blk_ioctl, 515cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto#ifdef CONFIG_COMPAT 516cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto .compat_ioctl = mmc_blk_compat_ioctl, 517cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto#endif 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 520371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic inline int mmc_blk_part_switch(struct mmc_card *card, 521371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct mmc_blk_data *md) 522371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{ 523371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin int ret; 524371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct mmc_blk_data *main_md = mmc_get_drvdata(card); 5250d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter 526371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin if (main_md->part_curr == md->part_type) 527371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin return 0; 528371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 529371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin if (mmc_card_mmc(card)) { 5300d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter u8 part_config = card->ext_csd.part_config; 5310d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter 5320d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter part_config &= ~EXT_CSD_PART_CONFIG_ACC_MASK; 5330d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter part_config |= md->part_type; 534371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 535371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, 5360d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter EXT_CSD_PART_CONFIG, part_config, 537371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin card->ext_csd.part_time); 538371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin if (ret) 539371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin return ret; 5400d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter 5410d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter card->ext_csd.part_config = part_config; 54267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter } 543371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 544371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin main_md->part_curr = md->part_type; 545371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin return 0; 546371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin} 547371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 548ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossmanstatic u32 mmc_sd_num_wr_blocks(struct mmc_card *card) 549ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman{ 550ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman int err; 551051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks u32 result; 552051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks __be32 *blocks; 553ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 554ad5fd97288655b5628052c1fa906419417c86100Venkatraman S struct mmc_request mrq = {NULL}; 5551278dba167f01bb3c6626d16450d31129d041087Chris Ball struct mmc_command cmd = {0}; 556a61ad2b49bfce94dfddce828cd9222e4b9e7825bChris Ball struct mmc_data data = {0}; 557ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 558ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman struct scatterlist sg; 559ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 560ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman cmd.opcode = MMC_APP_CMD; 561ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman cmd.arg = card->rca << 16; 5627213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; 563ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 564ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman err = mmc_wait_for_cmd(card->host, &cmd, 0); 5657213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell if (err) 5667213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell return (u32)-1; 5677213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell if (!mmc_host_is_spi(card->host) && !(cmd.resp[0] & R1_APP_CMD)) 568ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman return (u32)-1; 569ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 570ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman memset(&cmd, 0, sizeof(struct mmc_command)); 571ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 572ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman cmd.opcode = SD_APP_SEND_NUM_WR_BLKS; 573ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman cmd.arg = 0; 5747213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; 575ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 576ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman data.blksz = 4; 577ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman data.blocks = 1; 578ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman data.flags = MMC_DATA_READ; 579ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman data.sg = &sg; 580ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman data.sg_len = 1; 581d380443cd0271903bf9516bc04cead81676be034Subhash Jadavani mmc_set_data_timeout(&data, card); 582ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 583ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman mrq.cmd = &cmd; 584ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman mrq.data = &data; 585ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 586051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks blocks = kmalloc(4, GFP_KERNEL); 587051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks if (!blocks) 588051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks return (u32)-1; 589051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks 590051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks sg_init_one(&sg, blocks, 4); 591ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 592ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman mmc_wait_for_req(card->host, &mrq); 593ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 594051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks result = ntohl(*blocks); 595051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks kfree(blocks); 596051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks 59717b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman if (cmd.error || data.error) 598051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks result = (u32)-1; 599ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 600051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks return result; 601ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman} 602ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 603a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linuxstatic int send_stop(struct mmc_card *card, u32 *status) 604a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux{ 605a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux struct mmc_command cmd = {0}; 606a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux int err; 607a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 608a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux cmd.opcode = MMC_STOP_TRANSMISSION; 609a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; 610a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux err = mmc_wait_for_cmd(card->host, &cmd, 5); 611a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux if (err == 0) 612a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux *status = cmd.resp[0]; 613a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux return err; 614a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux} 615a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 6160a2d4048a22079d7e79d6654bbacbef57bd5728aRussell King - ARM Linuxstatic int get_card_status(struct mmc_card *card, u32 *status, int retries) 617504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter{ 6181278dba167f01bb3c6626d16450d31129d041087Chris Ball struct mmc_command cmd = {0}; 619504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter int err; 620504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter 621504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter cmd.opcode = MMC_SEND_STATUS; 622504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter if (!mmc_host_is_spi(card->host)) 623504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter cmd.arg = card->rca << 16; 624504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC; 6250a2d4048a22079d7e79d6654bbacbef57bd5728aRussell King - ARM Linux err = mmc_wait_for_cmd(card->host, &cmd, retries); 6260a2d4048a22079d7e79d6654bbacbef57bd5728aRussell King - ARM Linux if (err == 0) 6270a2d4048a22079d7e79d6654bbacbef57bd5728aRussell King - ARM Linux *status = cmd.resp[0]; 6280a2d4048a22079d7e79d6654bbacbef57bd5728aRussell King - ARM Linux return err; 629504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter} 630504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter 631a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma#define ERR_NOMEDIUM 3 632a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux#define ERR_RETRY 2 633a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux#define ERR_ABORT 1 634a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux#define ERR_CONTINUE 0 635a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 636a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linuxstatic int mmc_blk_cmd_error(struct request *req, const char *name, int error, 637a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux bool status_valid, u32 status) 638a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux{ 639a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux switch (error) { 640a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux case -EILSEQ: 641a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux /* response crc error, retry the r/w cmd */ 642a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux pr_err("%s: %s sending %s command, card status %#x\n", 643a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux req->rq_disk->disk_name, "response CRC error", 644a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux name, status); 645a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux return ERR_RETRY; 646a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 647a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux case -ETIMEDOUT: 648a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux pr_err("%s: %s sending %s command, card status %#x\n", 649a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux req->rq_disk->disk_name, "timed out", name, status); 650a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 651a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux /* If the status cmd initially failed, retry the r/w cmd */ 652a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux if (!status_valid) 653a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux return ERR_RETRY; 654a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 655a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux /* 656a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * If it was a r/w cmd crc error, or illegal command 657a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * (eg, issued in wrong state) then retry - we should 658a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * have corrected the state problem above. 659a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux */ 660a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux if (status & (R1_COM_CRC_ERROR | R1_ILLEGAL_COMMAND)) 661a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux return ERR_RETRY; 662a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 663a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux /* Otherwise abort the command */ 664a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux return ERR_ABORT; 665a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 666a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux default: 667a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux /* We don't understand the error code the driver gave us */ 668a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux pr_err("%s: unknown error %d sending read/write command, card status %#x\n", 669a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux req->rq_disk->disk_name, error, status); 670a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux return ERR_ABORT; 671a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux } 672a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux} 673a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 674a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux/* 675a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * Initial r/w and stop cmd error recovery. 676a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * We don't know whether the card received the r/w cmd or not, so try to 677a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * restore things back to a sane state. Essentially, we do this as follows: 678a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * - Obtain card status. If the first attempt to obtain card status fails, 679a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * the status word will reflect the failed status cmd, not the failed 680a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * r/w cmd. If we fail to obtain card status, it suggests we can no 681a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * longer communicate with the card. 682a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * - Check the card state. If the card received the cmd but there was a 683a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * transient problem with the response, it might still be in a data transfer 684a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * mode. Try to send it a stop command. If this fails, we can't recover. 685a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * - If the r/w cmd failed due to a response CRC error, it was probably 686a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * transient, so retry the cmd. 687a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * - If the r/w cmd timed out, but we didn't get the r/w cmd status, retry. 688a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * - If the r/w cmd timed out, and the r/w cmd failed due to CRC error or 689a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * illegal cmd, retry. 690a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * Otherwise we don't understand what happened, so abort. 691a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux */ 692a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linuxstatic int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req, 69367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter struct mmc_blk_request *brq, int *ecc_err) 694a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux{ 695a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux bool prev_cmd_status_valid = true; 696a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux u32 status, stop_status = 0; 697a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux int err, retry; 698a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 699a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma if (mmc_card_removed(card)) 700a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma return ERR_NOMEDIUM; 701a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma 702a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux /* 703a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * Try to get card status which indicates both the card state 704a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * and why there was no response. If the first attempt fails, 705a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * we can't be sure the returned status is for the r/w command. 706a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux */ 707a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux for (retry = 2; retry >= 0; retry--) { 708a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux err = get_card_status(card, &status, 0); 709a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux if (!err) 710a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux break; 711a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 712a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux prev_cmd_status_valid = false; 713a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux pr_err("%s: error %d sending status command, %sing\n", 714a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux req->rq_disk->disk_name, err, retry ? "retry" : "abort"); 715a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux } 716a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 717a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux /* We couldn't get a response from the card. Give up. */ 718a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma if (err) { 719a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma /* Check if the card is removed */ 720a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma if (mmc_detect_card_removed(card->host)) 721a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma return ERR_NOMEDIUM; 722a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux return ERR_ABORT; 723a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma } 724a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 72567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter /* Flag ECC errors */ 72667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if ((status & R1_CARD_ECC_FAILED) || 72767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter (brq->stop.resp[0] & R1_CARD_ECC_FAILED) || 72867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter (brq->cmd.resp[0] & R1_CARD_ECC_FAILED)) 72967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter *ecc_err = 1; 73067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter 731a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux /* 732a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * Check the current card state. If it is in some data transfer 733a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * mode, tell it to stop (and hopefully transition back to TRAN.) 734a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux */ 735a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux if (R1_CURRENT_STATE(status) == R1_STATE_DATA || 736a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux R1_CURRENT_STATE(status) == R1_STATE_RCV) { 737a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux err = send_stop(card, &stop_status); 738a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux if (err) 739a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux pr_err("%s: error %d sending stop command\n", 740a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux req->rq_disk->disk_name, err); 741a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 742a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux /* 743a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * If the stop cmd also timed out, the card is probably 744a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * not present, so abort. Other errors are bad news too. 745a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux */ 746a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux if (err) 747a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux return ERR_ABORT; 74867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (stop_status & R1_CARD_ECC_FAILED) 74967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter *ecc_err = 1; 750a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux } 751a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 752a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux /* Check for set block count errors */ 753a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux if (brq->sbc.error) 754a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux return mmc_blk_cmd_error(req, "SET_BLOCK_COUNT", brq->sbc.error, 755a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux prev_cmd_status_valid, status); 756a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 757a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux /* Check for r/w command errors */ 758a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux if (brq->cmd.error) 759a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux return mmc_blk_cmd_error(req, "r/w cmd", brq->cmd.error, 760a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux prev_cmd_status_valid, status); 761a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 76267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter /* Data errors */ 76367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (!brq->stop.error) 76467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter return ERR_CONTINUE; 76567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter 766a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux /* Now for stop errors. These aren't fatal to the transfer. */ 767a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux pr_err("%s: error %d sending stop command, original cmd response %#x, card status %#x\n", 768a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux req->rq_disk->disk_name, brq->stop.error, 769a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux brq->cmd.resp[0], status); 770a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 771a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux /* 772a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * Subsitute in our own stop status as this will give the error 773a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * state which happened during the execution of the r/w command. 774a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux */ 775a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux if (stop_status) { 776a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux brq->stop.resp[0] = stop_status; 777a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux brq->stop.error = 0; 778a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux } 779a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux return ERR_CONTINUE; 780a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux} 781a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 78267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunterstatic int mmc_blk_reset(struct mmc_blk_data *md, struct mmc_host *host, 78367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter int type) 78467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter{ 78567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter int err; 78667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter 78767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (md->reset_done & type) 78867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter return -EEXIST; 78967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter 79067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter md->reset_done |= type; 79167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter err = mmc_hw_reset(host); 79267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter /* Ensure we switch back to the correct partition */ 79367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (err != -EOPNOTSUPP) { 79467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter struct mmc_blk_data *main_md = mmc_get_drvdata(host->card); 79567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter int part_err; 79667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter 79767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter main_md->part_curr = main_md->part_type; 79867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter part_err = mmc_blk_part_switch(host->card, md); 79967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (part_err) { 80067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter /* 80167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter * We have failed to get back into the correct 80267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter * partition, so we need to abort the whole request. 80367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter */ 80467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter return -ENODEV; 80567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter } 80667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter } 80767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter return err; 80867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter} 80967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter 81067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunterstatic inline void mmc_blk_reset_success(struct mmc_blk_data *md, int type) 81167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter{ 81267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter md->reset_done &= ~type; 81367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter} 81467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter 815bd788c9665fb7c543aac21317059375632343337Adrian Hunterstatic int mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req) 816bd788c9665fb7c543aac21317059375632343337Adrian Hunter{ 817bd788c9665fb7c543aac21317059375632343337Adrian Hunter struct mmc_blk_data *md = mq->data; 818bd788c9665fb7c543aac21317059375632343337Adrian Hunter struct mmc_card *card = md->queue.card; 819bd788c9665fb7c543aac21317059375632343337Adrian Hunter unsigned int from, nr, arg; 82067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter int err = 0, type = MMC_BLK_DISCARD; 821bd788c9665fb7c543aac21317059375632343337Adrian Hunter 822bd788c9665fb7c543aac21317059375632343337Adrian Hunter if (!mmc_can_erase(card)) { 823bd788c9665fb7c543aac21317059375632343337Adrian Hunter err = -EOPNOTSUPP; 824bd788c9665fb7c543aac21317059375632343337Adrian Hunter goto out; 825bd788c9665fb7c543aac21317059375632343337Adrian Hunter } 826bd788c9665fb7c543aac21317059375632343337Adrian Hunter 827bd788c9665fb7c543aac21317059375632343337Adrian Hunter from = blk_rq_pos(req); 828bd788c9665fb7c543aac21317059375632343337Adrian Hunter nr = blk_rq_sectors(req); 829bd788c9665fb7c543aac21317059375632343337Adrian Hunter 830b3bf915308ca2b50f3beec6cc824083870f0f4b5Kyungmin Park if (mmc_can_discard(card)) 831b3bf915308ca2b50f3beec6cc824083870f0f4b5Kyungmin Park arg = MMC_DISCARD_ARG; 832b3bf915308ca2b50f3beec6cc824083870f0f4b5Kyungmin Park else if (mmc_can_trim(card)) 833bd788c9665fb7c543aac21317059375632343337Adrian Hunter arg = MMC_TRIM_ARG; 834bd788c9665fb7c543aac21317059375632343337Adrian Hunter else 835bd788c9665fb7c543aac21317059375632343337Adrian Hunter arg = MMC_ERASE_ARG; 83667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunterretry: 8376a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin if (card->quirks & MMC_QUIRK_INAND_CMD38) { 8386a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, 8396a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin INAND_CMD38_ARG_EXT_CSD, 8406a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin arg == MMC_TRIM_ARG ? 8416a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin INAND_CMD38_ARG_TRIM : 8426a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin INAND_CMD38_ARG_ERASE, 8436a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin 0); 8446a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin if (err) 8456a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin goto out; 8466a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin } 847bd788c9665fb7c543aac21317059375632343337Adrian Hunter err = mmc_erase(card, from, nr, arg); 848bd788c9665fb7c543aac21317059375632343337Adrian Hunterout: 84967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (err == -EIO && !mmc_blk_reset(md, card->host, type)) 85067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter goto retry; 85167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (!err) 85267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter mmc_blk_reset_success(md, type); 853ecf8b5d0a378a0f922ffca27bd0a9101f246fa11Subhash Jadavani blk_end_request(req, err, blk_rq_bytes(req)); 854bd788c9665fb7c543aac21317059375632343337Adrian Hunter 855bd788c9665fb7c543aac21317059375632343337Adrian Hunter return err ? 0 : 1; 856bd788c9665fb7c543aac21317059375632343337Adrian Hunter} 857bd788c9665fb7c543aac21317059375632343337Adrian Hunter 8584980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunterstatic int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq, 8594980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter struct request *req) 8604980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter{ 8614980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter struct mmc_blk_data *md = mq->data; 8624980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter struct mmc_card *card = md->queue.card; 863283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter unsigned int from, nr, arg, trim_arg, erase_arg; 86467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter int err = 0, type = MMC_BLK_SECDISCARD; 8654980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter 866d9ddd62943ee07a75d0428ffcf52f1a747a28c39Kyungmin Park if (!(mmc_can_secure_erase_trim(card) || mmc_can_sanitize(card))) { 8674980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter err = -EOPNOTSUPP; 8684980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter goto out; 8694980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter } 8704980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter 871283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter from = blk_rq_pos(req); 872283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter nr = blk_rq_sectors(req); 873283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter 874d9ddd62943ee07a75d0428ffcf52f1a747a28c39Kyungmin Park /* The sanitize operation is supported at v4.5 only */ 875d9ddd62943ee07a75d0428ffcf52f1a747a28c39Kyungmin Park if (mmc_can_sanitize(card)) { 876283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter erase_arg = MMC_ERASE_ARG; 877283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter trim_arg = MMC_TRIM_ARG; 878283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter } else { 879283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter erase_arg = MMC_SECURE_ERASE_ARG; 880283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter trim_arg = MMC_SECURE_TRIM1_ARG; 881d9ddd62943ee07a75d0428ffcf52f1a747a28c39Kyungmin Park } 882d9ddd62943ee07a75d0428ffcf52f1a747a28c39Kyungmin Park 883283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter if (mmc_erase_group_aligned(card, from, nr)) 884283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter arg = erase_arg; 885283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter else if (mmc_can_trim(card)) 886283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter arg = trim_arg; 887283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter else { 888283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter err = -EINVAL; 889283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter goto out; 890283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter } 89167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunterretry: 8926a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin if (card->quirks & MMC_QUIRK_INAND_CMD38) { 8936a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, 8946a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin INAND_CMD38_ARG_EXT_CSD, 8956a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin arg == MMC_SECURE_TRIM1_ARG ? 8966a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin INAND_CMD38_ARG_SECTRIM1 : 8976a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin INAND_CMD38_ARG_SECERASE, 8986a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin 0); 8996a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin if (err) 900283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter goto out_retry; 9016a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin } 902283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter 9034980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter err = mmc_erase(card, from, nr, arg); 904283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter if (err == -EIO) 905283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter goto out_retry; 906283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter if (err) 907283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter goto out; 908283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter 909283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter if (arg == MMC_SECURE_TRIM1_ARG) { 9106a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin if (card->quirks & MMC_QUIRK_INAND_CMD38) { 9116a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, 9126a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin INAND_CMD38_ARG_EXT_CSD, 9136a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin INAND_CMD38_ARG_SECTRIM2, 9146a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin 0); 9156a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin if (err) 916283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter goto out_retry; 9176a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin } 918283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter 9194980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter err = mmc_erase(card, from, nr, MMC_SECURE_TRIM2_ARG); 920283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter if (err == -EIO) 921283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter goto out_retry; 922283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter if (err) 923283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter goto out; 9246a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin } 925283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter 926283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter if (mmc_can_sanitize(card)) 927283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, 928283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter EXT_CSD_SANITIZE_START, 1, 0); 929283028122db37621b124f079ca8eae5b64807ad4Adrian Hunterout_retry: 930283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter if (err && !mmc_blk_reset(md, card->host, type)) 93167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter goto retry; 93267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (!err) 93367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter mmc_blk_reset_success(md, type); 934283028122db37621b124f079ca8eae5b64807ad4Adrian Hunterout: 935ecf8b5d0a378a0f922ffca27bd0a9101f246fa11Subhash Jadavani blk_end_request(req, err, blk_rq_bytes(req)); 9364980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter 9374980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter return err ? 0 : 1; 9384980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter} 9394980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter 940f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentinstatic int mmc_blk_issue_flush(struct mmc_queue *mq, struct request *req) 941f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin{ 942f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin struct mmc_blk_data *md = mq->data; 943881d1c25f765938a95def5afe39486ce39f9fc96Seungwon Jeon struct mmc_card *card = md->queue.card; 944881d1c25f765938a95def5afe39486ce39f9fc96Seungwon Jeon int ret = 0; 945881d1c25f765938a95def5afe39486ce39f9fc96Seungwon Jeon 946881d1c25f765938a95def5afe39486ce39f9fc96Seungwon Jeon ret = mmc_flush_cache(card); 947881d1c25f765938a95def5afe39486ce39f9fc96Seungwon Jeon if (ret) 948881d1c25f765938a95def5afe39486ce39f9fc96Seungwon Jeon ret = -EIO; 949f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin 950ecf8b5d0a378a0f922ffca27bd0a9101f246fa11Subhash Jadavani blk_end_request_all(req, ret); 951f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin 952881d1c25f765938a95def5afe39486ce39f9fc96Seungwon Jeon return ret ? 0 : 1; 953f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin} 954f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin 955f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin/* 956f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin * Reformat current write as a reliable write, supporting 957f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin * both legacy and the enhanced reliable write MMC cards. 958f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin * In each transfer we'll handle only as much as a single 959f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin * reliable write can handle, thus finish the request in 960f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin * partial completions. 961f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin */ 962d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentinstatic inline void mmc_apply_rel_rw(struct mmc_blk_request *brq, 963d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin struct mmc_card *card, 964d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin struct request *req) 965f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin{ 966f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin if (!(card->ext_csd.rel_param & EXT_CSD_WR_REL_PARAM_EN)) { 967f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin /* Legacy mode imposes restrictions on transfers. */ 968f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin if (!IS_ALIGNED(brq->cmd.arg, card->ext_csd.rel_sectors)) 969f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin brq->data.blocks = 1; 970f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin 971f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin if (brq->data.blocks > card->ext_csd.rel_sectors) 972f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin brq->data.blocks = card->ext_csd.rel_sectors; 973f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin else if (brq->data.blocks < card->ext_csd.rel_sectors) 974f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin brq->data.blocks = 1; 975f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin } 976f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin} 977f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin 9784c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux#define CMD_ERRORS \ 9794c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux (R1_OUT_OF_RANGE | /* Command argument out of range */ \ 9804c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux R1_ADDRESS_ERROR | /* Misaligned address */ \ 9814c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux R1_BLOCK_LEN_ERROR | /* Transferred block length incorrect */\ 9824c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux R1_WP_VIOLATION | /* Tried to write to protected block */ \ 9834c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux R1_CC_ERROR | /* Card controller error */ \ 9844c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux R1_ERROR) /* General/unknown error */ 9854c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux 986ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlinstatic int mmc_blk_err_check(struct mmc_card *card, 987ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin struct mmc_async_req *areq) 988d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin{ 989ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin struct mmc_queue_req *mq_mrq = container_of(areq, struct mmc_queue_req, 990ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin mmc_active); 991ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin struct mmc_blk_request *brq = &mq_mrq->brq; 992ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin struct request *req = mq_mrq->req; 99367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter int ecc_err = 0; 994d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin 995d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin /* 996d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * sbc.error indicates a problem with the set block count 997d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * command. No data will have been transferred. 998d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * 999d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * cmd.error indicates a problem with the r/w command. No 1000d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * data will have been transferred. 1001d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * 1002d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * stop.error indicates a problem with the stop command. Data 1003d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * may have been transferred, or may still be transferring. 1004d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin */ 100567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (brq->sbc.error || brq->cmd.error || brq->stop.error || 100667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter brq->data.error) { 100767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter switch (mmc_blk_cmd_recovery(card, req, brq, &ecc_err)) { 1008d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin case ERR_RETRY: 1009d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin return MMC_BLK_RETRY; 1010d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin case ERR_ABORT: 1011d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin return MMC_BLK_ABORT; 1012a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma case ERR_NOMEDIUM: 1013a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma return MMC_BLK_NOMEDIUM; 1014d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin case ERR_CONTINUE: 1015d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin break; 1016d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin } 1017d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin } 1018d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin 1019d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin /* 1020d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * Check for errors relating to the execution of the 1021d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * initial command - such as address errors. No data 1022d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * has been transferred. 1023d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin */ 1024d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin if (brq->cmd.resp[0] & CMD_ERRORS) { 1025d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin pr_err("%s: r/w command failed, status = %#x\n", 1026d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin req->rq_disk->disk_name, brq->cmd.resp[0]); 1027d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin return MMC_BLK_ABORT; 1028d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin } 1029d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin 1030d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin /* 1031d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * Everything else is either success, or a data error of some 1032d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * kind. If it was a write, we may have transitioned to 1033d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * program mode, which we have to wait for it to complete. 1034d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin */ 1035d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) { 1036d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin u32 status; 1037d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin do { 1038d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin int err = get_card_status(card, &status, 5); 1039d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin if (err) { 1040a3c76eb9d4a1e68a69dd880cf0bcb8a52418b993Girish K S pr_err("%s: error %d requesting status\n", 1041d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin req->rq_disk->disk_name, err); 1042d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin return MMC_BLK_CMD_ERR; 1043d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin } 1044d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin /* 1045d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * Some cards mishandle the status bits, 1046d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * so make sure to check both the busy 1047d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * indication and the card state. 1048d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin */ 1049d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin } while (!(status & R1_READY_FOR_DATA) || 1050d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin (R1_CURRENT_STATE(status) == R1_STATE_PRG)); 1051d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin } 1052d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin 1053d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin if (brq->data.error) { 1054d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin pr_err("%s: error %d transferring data, sector %u, nr %u, cmd response %#x, card status %#x\n", 1055d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin req->rq_disk->disk_name, brq->data.error, 1056d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin (unsigned)blk_rq_pos(req), 1057d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin (unsigned)blk_rq_sectors(req), 1058d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin brq->cmd.resp[0], brq->stop.resp[0]); 1059d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin 1060d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin if (rq_data_dir(req) == READ) { 106167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (ecc_err) 106267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter return MMC_BLK_ECC_ERR; 1063d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin return MMC_BLK_DATA_ERR; 1064d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin } else { 1065d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin return MMC_BLK_CMD_ERR; 1066d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin } 1067d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin } 1068d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin 106967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (!brq->data.bytes_xfered) 107067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter return MMC_BLK_RETRY; 1071d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin 107267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (blk_rq_bytes(req) != brq->data.bytes_xfered) 107367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter return MMC_BLK_PARTIAL; 107467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter 107567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter return MMC_BLK_SUCCESS; 1076d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin} 1077d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin 107854d49d77628bed77e5491b8a2a1158a492843a19Per Forlinstatic void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, 107954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin struct mmc_card *card, 108054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin int disable_multi, 108154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin struct mmc_queue *mq) 10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 108354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin u32 readcmd, writecmd; 108454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin struct mmc_blk_request *brq = &mqrq->brq; 108554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin struct request *req = mqrq->req; 10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_blk_data *md = mq->data; 10874265900e0be653f5b78baf2816857ef57cf1332fSaugata Das bool do_data_tag; 10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1089f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin /* 1090f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin * Reliable writes are used to implement Forced Unit Access and 1091f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin * REQ_META accesses, and are supported only on MMCs. 109265299a3b788bd274bed92f9fa3232082c9f3ea70Christoph Hellwig * 109365299a3b788bd274bed92f9fa3232082c9f3ea70Christoph Hellwig * XXX: this really needs a good explanation of why REQ_META 109465299a3b788bd274bed92f9fa3232082c9f3ea70Christoph Hellwig * is treated special. 1095f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin */ 1096f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin bool do_rel_wr = ((req->cmd_flags & REQ_FUA) || 1097f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin (req->cmd_flags & REQ_META)) && 1098f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin (rq_data_dir(req) == WRITE) && 1099d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin (md->flags & MMC_BLK_REL_WR); 1100f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin 110154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin memset(brq, 0, sizeof(struct mmc_blk_request)); 110254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->mrq.cmd = &brq->cmd; 110354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->mrq.data = &brq->data; 11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 110554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->cmd.arg = blk_rq_pos(req); 110654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin if (!mmc_card_blockaddr(card)) 110754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->cmd.arg <<= 9; 110854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; 110954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->data.blksz = 512; 111054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->stop.opcode = MMC_STOP_TRANSMISSION; 111154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->stop.arg = 0; 111254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; 111354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->data.blocks = blk_rq_sectors(req); 11146a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter 111554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin /* 111654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * The block layer doesn't support all sector count 111754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * restrictions, so we need to be prepared for too big 111854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * requests. 111954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin */ 112054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin if (brq->data.blocks > card->host->max_blk_count) 112154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->data.blocks = card->host->max_blk_count; 11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11232bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley if (brq->data.blocks > 1) { 11242bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley /* 11252bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley * After a read error, we redo the request one sector 11262bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley * at a time in order to accurately determine which 11272bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley * sectors can be read successfully. 11282bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley */ 11292bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley if (disable_multi) 11302bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley brq->data.blocks = 1; 11312bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley 11322bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley /* Some controllers can't do multiblock reads due to hw bugs */ 11332bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley if (card->host->caps2 & MMC_CAP2_NO_MULTI_READ && 11342bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley rq_data_dir(req) == READ) 11352bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley brq->data.blocks = 1; 11362bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley } 1137d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin 113854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin if (brq->data.blocks > 1 || do_rel_wr) { 113954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin /* SPI multiblock writes terminate using a special 114054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * token, not a STOP_TRANSMISSION request. 1141d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin */ 114254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin if (!mmc_host_is_spi(card->host) || 114354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin rq_data_dir(req) == READ) 114454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->mrq.stop = &brq->stop; 114554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin readcmd = MMC_READ_MULTIPLE_BLOCK; 114654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin writecmd = MMC_WRITE_MULTIPLE_BLOCK; 114754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin } else { 114854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->mrq.stop = NULL; 114954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin readcmd = MMC_READ_SINGLE_BLOCK; 115054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin writecmd = MMC_WRITE_BLOCK; 115154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin } 115254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin if (rq_data_dir(req) == READ) { 115354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->cmd.opcode = readcmd; 115454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->data.flags |= MMC_DATA_READ; 115554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin } else { 115654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->cmd.opcode = writecmd; 115754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->data.flags |= MMC_DATA_WRITE; 115854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin } 1159d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin 116054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin if (do_rel_wr) 116154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin mmc_apply_rel_rw(brq, card, req); 1162f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin 116354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin /* 11644265900e0be653f5b78baf2816857ef57cf1332fSaugata Das * Data tag is used only during writing meta data to speed 11654265900e0be653f5b78baf2816857ef57cf1332fSaugata Das * up write and any subsequent read of this meta data 11664265900e0be653f5b78baf2816857ef57cf1332fSaugata Das */ 11674265900e0be653f5b78baf2816857ef57cf1332fSaugata Das do_data_tag = (card->ext_csd.data_tag_unit_size) && 11684265900e0be653f5b78baf2816857ef57cf1332fSaugata Das (req->cmd_flags & REQ_META) && 11694265900e0be653f5b78baf2816857ef57cf1332fSaugata Das (rq_data_dir(req) == WRITE) && 11704265900e0be653f5b78baf2816857ef57cf1332fSaugata Das ((brq->data.blocks * brq->data.blksz) >= 11714265900e0be653f5b78baf2816857ef57cf1332fSaugata Das card->ext_csd.data_tag_unit_size); 11724265900e0be653f5b78baf2816857ef57cf1332fSaugata Das 11734265900e0be653f5b78baf2816857ef57cf1332fSaugata Das /* 117454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * Pre-defined multi-block transfers are preferable to 117554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * open ended-ones (and necessary for reliable writes). 117654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * However, it is not sufficient to just send CMD23, 117754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * and avoid the final CMD12, as on an error condition 117854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * CMD12 (stop) needs to be sent anyway. This, coupled 117954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * with Auto-CMD23 enhancements provided by some 118054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * hosts, means that the complexity of dealing 118154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * with this is best left to the host. If CMD23 is 118254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * supported by card and host, we'll fill sbc in and let 118354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * the host deal with handling it correctly. This means 118454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * that for hosts that don't expose MMC_CAP_CMD23, no 118554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * change of behavior will be observed. 118654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * 118754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * N.B: Some MMC cards experience perf degradation. 118854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * We'll avoid using CMD23-bounded multiblock writes for 118954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * these, while retaining features like reliable writes. 119054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin */ 11914265900e0be653f5b78baf2816857ef57cf1332fSaugata Das if ((md->flags & MMC_BLK_CMD23) && mmc_op_multi(brq->cmd.opcode) && 11924265900e0be653f5b78baf2816857ef57cf1332fSaugata Das (do_rel_wr || !(card->quirks & MMC_QUIRK_BLK_NO_CMD23) || 11934265900e0be653f5b78baf2816857ef57cf1332fSaugata Das do_data_tag)) { 119454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->sbc.opcode = MMC_SET_BLOCK_COUNT; 119554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->sbc.arg = brq->data.blocks | 11964265900e0be653f5b78baf2816857ef57cf1332fSaugata Das (do_rel_wr ? (1 << 31) : 0) | 11974265900e0be653f5b78baf2816857ef57cf1332fSaugata Das (do_data_tag ? (1 << 29) : 0); 119854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->sbc.flags = MMC_RSP_R1 | MMC_CMD_AC; 119954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->mrq.sbc = &brq->sbc; 120054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin } 120198ccf14909ba02a41c5925b0b2c92aeeef23d3b9Pierre Ossman 120254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin mmc_set_data_timeout(&brq->data, card); 120354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin 120454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->data.sg = mqrq->sg; 120554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->data.sg_len = mmc_queue_map_sg(mq, mqrq); 120654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin 120754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin /* 120854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * Adjust the sg list so it is the same size as the 120954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * request. 121054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin */ 121154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin if (brq->data.blocks != blk_rq_sectors(req)) { 121254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin int i, data_size = brq->data.blocks << 9; 121354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin struct scatterlist *sg; 121454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin 121554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin for_each_sg(brq->data.sg, sg, brq->data.sg_len, i) { 121654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin data_size -= sg->length; 121754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin if (data_size <= 0) { 121854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin sg->length += data_size; 121954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin i++; 122054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin break; 12216a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter } 12226a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter } 122354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->data.sg_len = i; 122454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin } 122554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin 1226ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin mqrq->mmc_active.mrq = &brq->mrq; 1227ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin mqrq->mmc_active.err_check = mmc_blk_err_check; 1228ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin 122954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin mmc_queue_bounce_pre(mqrq); 123054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin} 12316a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter 123267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunterstatic int mmc_blk_cmd_err(struct mmc_blk_data *md, struct mmc_card *card, 123367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter struct mmc_blk_request *brq, struct request *req, 123467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter int ret) 123567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter{ 123667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter /* 123767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter * If this is an SD card and we're writing, we can first 123867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter * mark the known good sectors as ok. 123967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter * 124067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter * If the card is not SD, we can still ok written sectors 124167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter * as reported by the controller (which might be less than 124267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter * the real number of written sectors, but never more). 124367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter */ 124467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (mmc_card_sd(card)) { 124567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter u32 blocks; 124667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter 124767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter blocks = mmc_sd_num_wr_blocks(card); 124867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (blocks != (u32)-1) { 1249ecf8b5d0a378a0f922ffca27bd0a9101f246fa11Subhash Jadavani ret = blk_end_request(req, 0, blocks << 9); 125067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter } 125167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter } else { 1252ecf8b5d0a378a0f922ffca27bd0a9101f246fa11Subhash Jadavani ret = blk_end_request(req, 0, brq->data.bytes_xfered); 125367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter } 125467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter return ret; 125567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter} 125667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter 1257ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlinstatic int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc) 125854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin{ 125954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin struct mmc_blk_data *md = mq->data; 126054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin struct mmc_card *card = md->queue.card; 126154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin struct mmc_blk_request *brq = &mq->mqrq_cur->brq; 126267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter int ret = 1, disable_multi = 0, retry = 0, type; 1263d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin enum mmc_blk_status status; 1264ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin struct mmc_queue_req *mq_rq; 1265a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das struct request *req = rqc; 1266ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin struct mmc_async_req *areq; 12671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1268ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin if (!rqc && !mq->mqrq_prev->req) 1269ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin return 0; 127098ccf14909ba02a41c5925b0b2c92aeeef23d3b9Pierre Ossman 1271ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin do { 1272ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin if (rqc) { 1273a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das /* 1274a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das * When 4KB native sector is enabled, only 8 blocks 1275a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das * multiple read or write is allowed 1276a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das */ 1277a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das if ((brq->data.blocks & 0x07) && 1278a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das (card->ext_csd.data_sector_size == 4096)) { 1279a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das pr_err("%s: Transfer size is not 4KB sector size aligned\n", 1280a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das req->rq_disk->disk_name); 1281a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das goto cmd_abort; 1282a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das } 1283ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin mmc_blk_rw_rq_prep(mq->mqrq_cur, card, 0, mq); 1284ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin areq = &mq->mqrq_cur->mmc_active; 1285ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin } else 1286ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin areq = NULL; 1287ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin areq = mmc_start_req(card->host, areq, (int *) &status); 1288ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin if (!areq) 1289ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin return 0; 1290ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin 1291ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin mq_rq = container_of(areq, struct mmc_queue_req, mmc_active); 1292ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin brq = &mq_rq->brq; 1293ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin req = mq_rq->req; 129467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter type = rq_data_dir(req) == READ ? MMC_BLK_READ : MMC_BLK_WRITE; 1295ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin mmc_queue_bounce_post(mq_rq); 129698ccf14909ba02a41c5925b0b2c92aeeef23d3b9Pierre Ossman 1297d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin switch (status) { 1298d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin case MMC_BLK_SUCCESS: 1299d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin case MMC_BLK_PARTIAL: 1300d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin /* 1301d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * A block was successfully transferred. 1302d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin */ 130367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter mmc_blk_reset_success(md, type); 1304ecf8b5d0a378a0f922ffca27bd0a9101f246fa11Subhash Jadavani ret = blk_end_request(req, 0, 1305d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin brq->data.bytes_xfered); 130667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter /* 130767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter * If the blk_end_request function returns non-zero even 130867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter * though all data has been transferred and no errors 130967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter * were returned by the host controller, it's a bug. 131067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter */ 1311ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin if (status == MMC_BLK_SUCCESS && ret) { 1312a3c76eb9d4a1e68a69dd880cf0bcb8a52418b993Girish K S pr_err("%s BUG rq_tot %d d_xfer %d\n", 1313ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin __func__, blk_rq_bytes(req), 1314ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin brq->data.bytes_xfered); 1315ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin rqc = NULL; 1316ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin goto cmd_abort; 1317ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin } 1318d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin break; 1319d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin case MMC_BLK_CMD_ERR: 132067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter ret = mmc_blk_cmd_err(md, card, brq, req, ret); 132167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (!mmc_blk_reset(md, card->host, type)) 132267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter break; 132367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter goto cmd_abort; 1324d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin case MMC_BLK_RETRY: 1325d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin if (retry++ < 5) 1326a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux break; 132767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter /* Fall through */ 1328d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin case MMC_BLK_ABORT: 132967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (!mmc_blk_reset(md, card->host, type)) 133067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter break; 13314c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux goto cmd_abort; 133267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter case MMC_BLK_DATA_ERR: { 133367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter int err; 133467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter 133567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter err = mmc_blk_reset(md, card->host, type); 133667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (!err) 133767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter break; 133867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (err == -ENODEV) 133967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter goto cmd_abort; 134067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter /* Fall through */ 134167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter } 134267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter case MMC_BLK_ECC_ERR: 134367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (brq->data.blocks > 1) { 134467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter /* Redo read one sector at a time */ 134567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter pr_warning("%s: retrying using single block read\n", 134667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter req->rq_disk->disk_name); 134767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter disable_multi = 1; 134867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter break; 134967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter } 1350d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin /* 1351d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * After an error, we redo I/O one sector at a 1352d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * time, so we only reach here after trying to 1353d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * read a single sector. 1354d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin */ 1355ecf8b5d0a378a0f922ffca27bd0a9101f246fa11Subhash Jadavani ret = blk_end_request(req, -EIO, 1356d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin brq->data.blksz); 1357ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin if (!ret) 1358ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin goto start_new_req; 1359d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin break; 1360a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma case MMC_BLK_NOMEDIUM: 1361a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma goto cmd_abort; 13624c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux } 13634c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux 1364ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin if (ret) { 1365ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin /* 136667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter * In case of a incomplete request 1367ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin * prepare it again and resend. 1368ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin */ 1369ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin mmc_blk_rw_rq_prep(mq_rq, card, disable_multi, mq); 1370ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin mmc_start_req(card->host, &mq_rq->mmc_active, NULL); 1371ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin } 13721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } while (ret); 13731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 13751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1376a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux cmd_abort: 1377a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma if (mmc_card_removed(card)) 1378a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma req->cmd_flags |= REQ_QUIET; 1379fd539832c7d3a242269374dbcae2cd54da150930Kiyoshi Ueda while (ret) 1380ecf8b5d0a378a0f922ffca27bd0a9101f246fa11Subhash Jadavani ret = blk_end_request(req, -EIO, blk_rq_cur_bytes(req)); 13811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1382ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin start_new_req: 1383ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin if (rqc) { 1384ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin mmc_blk_rw_rq_prep(mq->mqrq_cur, card, 0, mq); 1385ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin mmc_start_req(card->host, &mq->mqrq_cur->mmc_active, NULL); 1386ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin } 1387ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin 13881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 13891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1391bd788c9665fb7c543aac21317059375632343337Adrian Hunterstatic int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) 1392bd788c9665fb7c543aac21317059375632343337Adrian Hunter{ 13931a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin int ret; 13941a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin struct mmc_blk_data *md = mq->data; 13951a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin struct mmc_card *card = md->queue.card; 13961a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin 1397ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin if (req && !mq->mqrq_prev->req) 1398ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin /* claim host only for the first request */ 1399ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin mmc_claim_host(card->host); 1400ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin 1401371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin ret = mmc_blk_part_switch(card, md); 1402371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin if (ret) { 14030d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter if (req) { 1404ecf8b5d0a378a0f922ffca27bd0a9101f246fa11Subhash Jadavani blk_end_request_all(req, -EIO); 14050d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter } 1406371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin ret = 0; 1407371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin goto out; 1408371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin } 14091a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin 1410ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin if (req && req->cmd_flags & REQ_DISCARD) { 1411ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin /* complete ongoing async transfer before issuing discard */ 1412ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin if (card->host->areq) 1413ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin mmc_blk_issue_rw_rq(mq, NULL); 14143550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen if (req->cmd_flags & REQ_SECURE && 14153550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen !(card->quirks & MMC_QUIRK_SEC_ERASE_TRIM_BROKEN)) 14161a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin ret = mmc_blk_issue_secdiscard_rq(mq, req); 14174980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter else 14181a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin ret = mmc_blk_issue_discard_rq(mq, req); 1419ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin } else if (req && req->cmd_flags & REQ_FLUSH) { 1420393f9a08e2ee72e42379489a5781feaf9c406d5fJaehoon Chung /* complete ongoing async transfer before issuing flush */ 1421393f9a08e2ee72e42379489a5781feaf9c406d5fJaehoon Chung if (card->host->areq) 1422393f9a08e2ee72e42379489a5781feaf9c406d5fJaehoon Chung mmc_blk_issue_rw_rq(mq, NULL); 14231a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin ret = mmc_blk_issue_flush(mq, req); 14244980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter } else { 14251a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin ret = mmc_blk_issue_rw_rq(mq, req); 14264980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter } 14271a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin 1428371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinout: 1429ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin if (!req) 1430ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin /* release host only when there are no more requests */ 1431ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin mmc_release_host(card->host); 14321a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin return ret; 1433bd788c9665fb7c543aac21317059375632343337Adrian Hunter} 14341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1435a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell Kingstatic inline int mmc_blk_readonly(struct mmc_card *card) 1436a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King{ 1437a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King return mmc_card_readonly(card) || 1438a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King !(card->csd.cmdclass & CCC_BLOCK_WRITE); 1439a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King} 1440a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King 1441371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card, 1442371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct device *parent, 1443371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin sector_t size, 1444371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin bool default_ro, 1445add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm const char *subname, 1446add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm int area_type) 14471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 14481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_blk_data *md; 14491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int devidx, ret; 14501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14515e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson devidx = find_first_zero_bit(dev_use, max_devices); 14525e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson if (devidx >= max_devices) 14531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ERR_PTR(-ENOSPC); 14541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __set_bit(devidx, dev_use); 14551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1456dd00cc486ab1c17049a535413d1751ef3482141cYoann Padioleau md = kzalloc(sizeof(struct mmc_blk_data), GFP_KERNEL); 1457a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King if (!md) { 1458a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King ret = -ENOMEM; 1459a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King goto out; 1460a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King } 14611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1462a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King /* 1463f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin * !subname implies we are creating main mmc_blk_data that will be 1464f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin * associated with mmc_card with mmc_set_drvdata. Due to device 1465f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin * partitions, devidx will not coincide with a per-physical card 1466f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin * index anymore so we keep track of a name index. 1467f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin */ 1468f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin if (!subname) { 1469f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin md->name_idx = find_first_zero_bit(name_use, max_devices); 1470f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin __set_bit(md->name_idx, name_use); 1471add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm } else 1472f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin md->name_idx = ((struct mmc_blk_data *) 1473f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin dev_to_disk(parent)->private_data)->name_idx; 1474f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin 1475add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm md->area_type = area_type; 1476add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm 1477f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin /* 1478a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * Set the read-only status based on the supported commands 1479a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * and the write protect switch. 1480a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King */ 1481a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King md->read_only = mmc_blk_readonly(card); 14821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14835e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson md->disk = alloc_disk(perdev_minors); 1484a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King if (md->disk == NULL) { 1485a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King ret = -ENOMEM; 1486a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King goto err_kfree; 1487a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King } 14881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1489a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King spin_lock_init(&md->lock); 1490371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin INIT_LIST_HEAD(&md->part); 1491a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King md->usage = 1; 14921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1493d09408ade08a08a710a247fb52aa50101e73ebf7Adrian Hunter ret = mmc_init_queue(&md->queue, card, &md->lock, subname); 1494a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King if (ret) 1495a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King goto err_putdisk; 14961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1497a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King md->queue.issue_fn = mmc_blk_issue_rq; 1498a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King md->queue.data = md; 1499d2b18394259ef621fd2a6322aa9934198fd87a6aRussell King 1500fe6b4c8840c5e23fe9b8696450cee8f2e8cebffdPierre Ossman md->disk->major = MMC_BLOCK_MAJOR; 15015e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson md->disk->first_minor = devidx * perdev_minors; 1502a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King md->disk->fops = &mmc_bdops; 1503a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King md->disk->private_data = md; 1504a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King md->disk->queue = md->queue.queue; 1505371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin md->disk->driverfs_dev = parent; 1506371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin set_disk_ro(md->disk, md->read_only || default_ro); 1507a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King 1508a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King /* 1509a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * As discussed on lkml, GENHD_FL_REMOVABLE should: 1510a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * 1511a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * - be set for removable media with permanent block devices 1512a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * - be unset for removable block devices with permanent media 1513a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * 1514a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * Since MMC block devices clearly fall under the second 1515a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * case, we do not set GENHD_FL_REMOVABLE. Userspace 1516a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * should use the block device creation/destruction hotplug 1517a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * messages to tell when the card is present. 1518a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King */ 1519a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King 1520f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin snprintf(md->disk->disk_name, sizeof(md->disk->disk_name), 1521f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin "mmcblk%d%s", md->name_idx, subname ? subname : ""); 1522a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King 1523a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das if (mmc_card_mmc(card)) 1524a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das blk_queue_logical_block_size(md->queue.queue, 1525a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das card->ext_csd.data_sector_size); 1526a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das else 1527a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das blk_queue_logical_block_size(md->queue.queue, 512); 1528a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das 1529371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin set_capacity(md->disk, size); 1530d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin 1531f0d89972b01798cf9d245dfa1cacfa0ee78a3593Andrei Warkentin if (mmc_host_cmd23(card->host)) { 1532f0d89972b01798cf9d245dfa1cacfa0ee78a3593Andrei Warkentin if (mmc_card_mmc(card) || 1533f0d89972b01798cf9d245dfa1cacfa0ee78a3593Andrei Warkentin (mmc_card_sd(card) && 1534f0d89972b01798cf9d245dfa1cacfa0ee78a3593Andrei Warkentin card->scr.cmds & SD_SCR_CMD23_SUPPORT)) 1535f0d89972b01798cf9d245dfa1cacfa0ee78a3593Andrei Warkentin md->flags |= MMC_BLK_CMD23; 1536f0d89972b01798cf9d245dfa1cacfa0ee78a3593Andrei Warkentin } 1537d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin 1538d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin if (mmc_card_mmc(card) && 1539d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin md->flags & MMC_BLK_CMD23 && 1540d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin ((card->ext_csd.rel_param & EXT_CSD_WR_REL_PARAM_EN) || 1541d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin card->ext_csd.rel_sectors)) { 1542d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin md->flags |= MMC_BLK_REL_WR; 1543d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin blk_queue_flush(md->queue.queue, REQ_FLUSH | REQ_FUA); 1544d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin } 1545d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin 1546371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin return md; 1547371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 1548371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin err_putdisk: 1549371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin put_disk(md->disk); 1550371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin err_kfree: 1551371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin kfree(md); 1552371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin out: 1553371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin return ERR_PTR(ret); 1554371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin} 1555371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 1556371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card) 1557371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{ 1558371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin sector_t size; 1559371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct mmc_blk_data *md; 1560a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King 156185a18ad93ec66888d85758630019b10a84257f3cPierre Ossman if (!mmc_card_sd(card) && mmc_card_blockaddr(card)) { 156285a18ad93ec66888d85758630019b10a84257f3cPierre Ossman /* 156385a18ad93ec66888d85758630019b10a84257f3cPierre Ossman * The EXT_CSD sector count is in number or 512 byte 156485a18ad93ec66888d85758630019b10a84257f3cPierre Ossman * sectors. 156585a18ad93ec66888d85758630019b10a84257f3cPierre Ossman */ 1566371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin size = card->ext_csd.sectors; 156785a18ad93ec66888d85758630019b10a84257f3cPierre Ossman } else { 156885a18ad93ec66888d85758630019b10a84257f3cPierre Ossman /* 156985a18ad93ec66888d85758630019b10a84257f3cPierre Ossman * The CSD capacity field is in units of read_blkbits. 157085a18ad93ec66888d85758630019b10a84257f3cPierre Ossman * set_capacity takes units of 512 bytes. 157185a18ad93ec66888d85758630019b10a84257f3cPierre Ossman */ 1572371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin size = card->csd.capacity << (card->csd.read_blkbits - 9); 157385a18ad93ec66888d85758630019b10a84257f3cPierre Ossman } 1574371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 1575add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm md = mmc_blk_alloc_req(card, &card->dev, size, false, NULL, 1576add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm MMC_BLK_DATA_AREA_MAIN); 15771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return md; 1578371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin} 1579a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King 1580371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic int mmc_blk_alloc_part(struct mmc_card *card, 1581371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct mmc_blk_data *md, 1582371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin unsigned int part_type, 1583371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin sector_t size, 1584371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin bool default_ro, 1585add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm const char *subname, 1586add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm int area_type) 1587371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{ 1588371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin char cap_str[10]; 1589371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct mmc_blk_data *part_md; 1590371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 1591371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin part_md = mmc_blk_alloc_req(card, disk_to_dev(md->disk), size, default_ro, 1592add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm subname, area_type); 1593371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin if (IS_ERR(part_md)) 1594371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin return PTR_ERR(part_md); 1595371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin part_md->part_type = part_type; 1596371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin list_add(&part_md->part, &md->part); 1597371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 1598371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin string_get_size((u64)get_capacity(part_md->disk) << 9, STRING_UNITS_2, 1599371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin cap_str, sizeof(cap_str)); 1600a3c76eb9d4a1e68a69dd880cf0bcb8a52418b993Girish K S pr_info("%s: %s %s partition %u %s\n", 1601371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin part_md->disk->disk_name, mmc_card_id(card), 1602371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin mmc_card_name(card), part_md->part_type, cap_str); 1603371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin return 0; 1604371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin} 1605371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 1606e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon/* MMC Physical partitions consist of two boot partitions and 1607e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon * up to four general purpose partitions. 1608e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon * For each partition enabled in EXT_CSD a block device will be allocatedi 1609e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon * to provide access to the partition. 1610e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon */ 1611e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon 1612371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic int mmc_blk_alloc_parts(struct mmc_card *card, struct mmc_blk_data *md) 1613371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{ 1614e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon int idx, ret = 0; 1615371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 1616371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin if (!mmc_card_mmc(card)) 1617371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin return 0; 1618371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 1619e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon for (idx = 0; idx < card->nr_parts; idx++) { 1620e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon if (card->part[idx].size) { 1621e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon ret = mmc_blk_alloc_part(card, md, 1622e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon card->part[idx].part_cfg, 1623e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon card->part[idx].size >> 9, 1624e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon card->part[idx].force_ro, 1625add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm card->part[idx].name, 1626add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm card->part[idx].area_type); 1627e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon if (ret) 1628e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon return ret; 1629e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon } 1630371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin } 1631371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 1632371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin return ret; 16331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1635371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic void mmc_blk_remove_req(struct mmc_blk_data *md) 1636371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{ 1637add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm struct mmc_card *card; 1638add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm 1639371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin if (md) { 1640add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm card = md->queue.card; 1641371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin if (md->disk->flags & GENHD_FL_UP) { 1642371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin device_remove_file(disk_to_dev(md->disk), &md->force_ro); 1643add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm if ((md->area_type & MMC_BLK_DATA_AREA_BOOT) && 1644add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm card->ext_csd.boot_ro_lockable) 1645add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm device_remove_file(disk_to_dev(md->disk), 1646add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm &md->power_ro_lock); 1647371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 1648371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin /* Stop new requests from getting into the queue */ 1649371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin del_gendisk(md->disk); 1650371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin } 1651371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 1652371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin /* Then flush out any already in there */ 1653371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin mmc_cleanup_queue(&md->queue); 1654371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin mmc_blk_put(md); 1655371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin } 1656371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin} 1657371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 1658371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic void mmc_blk_remove_parts(struct mmc_card *card, 1659371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct mmc_blk_data *md) 1660371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{ 1661371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct list_head *pos, *q; 1662371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct mmc_blk_data *part_md; 1663371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 1664f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin __clear_bit(md->name_idx, name_use); 1665371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin list_for_each_safe(pos, q, &md->part) { 1666371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin part_md = list_entry(pos, struct mmc_blk_data, part); 1667371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin list_del(pos); 1668371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin mmc_blk_remove_req(part_md); 1669371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin } 1670371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin} 1671371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 1672371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic int mmc_add_disk(struct mmc_blk_data *md) 1673371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{ 1674371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin int ret; 1675add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm struct mmc_card *card = md->queue.card; 1676371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 1677371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin add_disk(md->disk); 1678371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin md->force_ro.show = force_ro_show; 1679371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin md->force_ro.store = force_ro_store; 1680641c3187b9d53cfd4c23b0ce2ab18a13d5e775e5Rabin Vincent sysfs_attr_init(&md->force_ro.attr); 1681371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin md->force_ro.attr.name = "force_ro"; 1682371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin md->force_ro.attr.mode = S_IRUGO | S_IWUSR; 1683371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin ret = device_create_file(disk_to_dev(md->disk), &md->force_ro); 1684371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin if (ret) 1685add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm goto force_ro_fail; 1686add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm 1687add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm if ((md->area_type & MMC_BLK_DATA_AREA_BOOT) && 1688add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm card->ext_csd.boot_ro_lockable) { 168988187398cc5fa6650f38b9dcd5464667f468888fAl Viro umode_t mode; 1690add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm 1691add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm if (card->ext_csd.boot_ro_lock & EXT_CSD_BOOT_WP_B_PWR_WP_DIS) 1692add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm mode = S_IRUGO; 1693add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm else 1694add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm mode = S_IRUGO | S_IWUSR; 1695add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm 1696add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm md->power_ro_lock.show = power_ro_lock_show; 1697add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm md->power_ro_lock.store = power_ro_lock_store; 169800d9ac08757049f334803b3d4dd202a6b1687dabRabin Vincent sysfs_attr_init(&md->power_ro_lock.attr); 1699add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm md->power_ro_lock.attr.mode = mode; 1700add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm md->power_ro_lock.attr.name = 1701add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm "ro_lock_until_next_power_on"; 1702add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm ret = device_create_file(disk_to_dev(md->disk), 1703add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm &md->power_ro_lock); 1704add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm if (ret) 1705add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm goto power_ro_lock_fail; 1706add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm } 1707add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm return ret; 1708add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm 1709add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholmpower_ro_lock_fail: 1710add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm device_remove_file(disk_to_dev(md->disk), &md->force_ro); 1711add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholmforce_ro_fail: 1712add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm del_gendisk(md->disk); 1713371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 1714371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin return ret; 1715371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin} 1716371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 1717c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball#define CID_MANFID_SANDISK 0x2 1718c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball#define CID_MANFID_TOSHIBA 0x11 1719c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball#define CID_MANFID_MICRON 0x13 17203550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen#define CID_MANFID_SAMSUNG 0x15 1721c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball 17226f60c22252af05df94352240f30f9fc84090d88dAndrei Warkentinstatic const struct mmc_fixup blk_fixups[] = 17236f60c22252af05df94352240f30f9fc84090d88dAndrei Warkentin{ 1724c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball MMC_FIXUP("SEM02G", CID_MANFID_SANDISK, 0x100, add_quirk, 1725c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball MMC_QUIRK_INAND_CMD38), 1726c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball MMC_FIXUP("SEM04G", CID_MANFID_SANDISK, 0x100, add_quirk, 1727c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball MMC_QUIRK_INAND_CMD38), 1728c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball MMC_FIXUP("SEM08G", CID_MANFID_SANDISK, 0x100, add_quirk, 1729c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball MMC_QUIRK_INAND_CMD38), 1730c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball MMC_FIXUP("SEM16G", CID_MANFID_SANDISK, 0x100, add_quirk, 1731c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball MMC_QUIRK_INAND_CMD38), 1732c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball MMC_FIXUP("SEM32G", CID_MANFID_SANDISK, 0x100, add_quirk, 1733c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball MMC_QUIRK_INAND_CMD38), 1734d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin 1735d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin /* 1736d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin * Some MMC cards experience performance degradation with CMD23 1737d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin * instead of CMD12-bounded multiblock transfers. For now we'll 1738d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin * black list what's bad... 1739d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin * - Certain Toshiba cards. 1740d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin * 1741d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin * N.B. This doesn't affect SD cards. 1742d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin */ 1743c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball MMC_FIXUP("MMC08G", CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc, 1744d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin MMC_QUIRK_BLK_NO_CMD23), 1745c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball MMC_FIXUP("MMC16G", CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc, 1746d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin MMC_QUIRK_BLK_NO_CMD23), 1747c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball MMC_FIXUP("MMC32G", CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc, 1748d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin MMC_QUIRK_BLK_NO_CMD23), 17496de5fc9cf7de334912de4cfd2d06eb2d744d2afeStefan Nilsson XK 17506de5fc9cf7de334912de4cfd2d06eb2d744d2afeStefan Nilsson XK /* 17516de5fc9cf7de334912de4cfd2d06eb2d744d2afeStefan Nilsson XK * Some Micron MMC cards needs longer data read timeout than 17526de5fc9cf7de334912de4cfd2d06eb2d744d2afeStefan Nilsson XK * indicated in CSD. 17536de5fc9cf7de334912de4cfd2d06eb2d744d2afeStefan Nilsson XK */ 1754c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball MMC_FIXUP(CID_NAME_ANY, CID_MANFID_MICRON, 0x200, add_quirk_mmc, 17556de5fc9cf7de334912de4cfd2d06eb2d744d2afeStefan Nilsson XK MMC_QUIRK_LONG_READ_TIME), 17566de5fc9cf7de334912de4cfd2d06eb2d744d2afeStefan Nilsson XK 17573550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen /* 17583550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen * On these Samsung MoviNAND parts, performing secure erase or 17593550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen * secure trim can result in unrecoverable corruption due to a 17603550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen * firmware bug. 17613550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen */ 17623550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen MMC_FIXUP("M8G2FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, 17633550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), 17643550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen MMC_FIXUP("MAG4FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, 17653550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), 17663550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen MMC_FIXUP("MBG8FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, 17673550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), 17683550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen MMC_FIXUP("MCGAFA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, 17693550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), 17703550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen MMC_FIXUP("VAL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, 17713550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), 17723550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen MMC_FIXUP("VYL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, 17733550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), 17743550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen MMC_FIXUP("KYL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, 17753550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), 17763550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen MMC_FIXUP("VZL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, 17773550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), 17783550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen 17796f60c22252af05df94352240f30f9fc84090d88dAndrei Warkentin END_FIXUP 17806f60c22252af05df94352240f30f9fc84090d88dAndrei Warkentin}; 17816f60c22252af05df94352240f30f9fc84090d88dAndrei Warkentin 17821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mmc_blk_probe(struct mmc_card *card) 17831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1784371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct mmc_blk_data *md, *part_md; 1785a7bbb57333447d0cf950992653b6b079585f3531Pierre Ossman char cap_str[10]; 1786a7bbb57333447d0cf950992653b6b079585f3531Pierre Ossman 1787912490db699d83cb3d03570b63df7448677a3f56Pierre Ossman /* 1788912490db699d83cb3d03570b63df7448677a3f56Pierre Ossman * Check that the card supports the command class(es) we need. 1789912490db699d83cb3d03570b63df7448677a3f56Pierre Ossman */ 1790912490db699d83cb3d03570b63df7448677a3f56Pierre Ossman if (!(card->csd.cmdclass & CCC_BLOCK_READ)) 17911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 17921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds md = mmc_blk_alloc(card); 17941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (IS_ERR(md)) 17951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return PTR_ERR(md); 17961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1797444122fd58fdc83c96877a92b3f6288cafddb08dYi Li string_get_size((u64)get_capacity(md->disk) << 9, STRING_UNITS_2, 1798a7bbb57333447d0cf950992653b6b079585f3531Pierre Ossman cap_str, sizeof(cap_str)); 1799a3c76eb9d4a1e68a69dd880cf0bcb8a52418b993Girish K S pr_info("%s: %s %s %s %s\n", 18001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds md->disk->disk_name, mmc_card_id(card), mmc_card_name(card), 1801a7bbb57333447d0cf950992653b6b079585f3531Pierre Ossman cap_str, md->read_only ? "(ro)" : ""); 18021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1803371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin if (mmc_blk_alloc_parts(card, md)) 1804371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin goto out; 1805371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 18061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_set_drvdata(card, md); 18076f60c22252af05df94352240f30f9fc84090d88dAndrei Warkentin mmc_fixup_device(card, blk_fixups); 18086f60c22252af05df94352240f30f9fc84090d88dAndrei Warkentin 1809371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin if (mmc_add_disk(md)) 1810371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin goto out; 1811371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 1812371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin list_for_each_entry(part_md, &md->part, part) { 1813371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin if (mmc_add_disk(part_md)) 1814371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin goto out; 1815371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin } 18161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 18171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 1819371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin mmc_blk_remove_parts(card, md); 1820371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin mmc_blk_remove_req(md); 18215865f2876baa5c68fd0d50029dd220ce19f3d2afUlf Hansson return 0; 18221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 18231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mmc_blk_remove(struct mmc_card *card) 18251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 18261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_blk_data *md = mmc_get_drvdata(card); 18271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1828371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin mmc_blk_remove_parts(card, md); 1829ddd6fa7e794e62af3ec3eb4ffdc78489885701f2Adrian Hunter mmc_claim_host(card->host); 1830ddd6fa7e794e62af3ec3eb4ffdc78489885701f2Adrian Hunter mmc_blk_part_switch(card, md); 1831ddd6fa7e794e62af3ec3eb4ffdc78489885701f2Adrian Hunter mmc_release_host(card->host); 1832371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin mmc_blk_remove_req(md); 18331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_set_drvdata(card, NULL); 18341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 18351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PM 183732d317c60e56c2a34463b51fc0336cc96b3e1735Chuanxiao Dongstatic int mmc_blk_suspend(struct mmc_card *card) 18381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1839371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct mmc_blk_data *part_md; 18401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_blk_data *md = mmc_get_drvdata(card); 18411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (md) { 18431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_queue_suspend(&md->queue); 1844371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin list_for_each_entry(part_md, &md->part, part) { 1845371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin mmc_queue_suspend(&part_md->queue); 1846371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin } 18471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 18481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 18491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 18501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mmc_blk_resume(struct mmc_card *card) 18521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1853371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct mmc_blk_data *part_md; 18541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_blk_data *md = mmc_get_drvdata(card); 18551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (md) { 1857371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin /* 1858371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin * Resume involves the card going into idle state, 1859371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin * so current partition is always the main one. 1860371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin */ 1861371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin md->part_curr = md->part_type; 18621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_queue_resume(&md->queue); 1863371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin list_for_each_entry(part_md, &md->part, part) { 1864371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin mmc_queue_resume(&part_md->queue); 1865371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin } 18661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 18671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 18681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 18691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 18701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define mmc_blk_suspend NULL 18711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define mmc_blk_resume NULL 18721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 18731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct mmc_driver mmc_driver = { 18751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .drv = { 18761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "mmcblk", 18771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 18781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .probe = mmc_blk_probe, 18791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .remove = mmc_blk_remove, 18801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .suspend = mmc_blk_suspend, 18811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .resume = mmc_blk_resume, 18821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 18831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init mmc_blk_init(void) 18851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 18869d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita int res; 18871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18885e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson if (perdev_minors != CONFIG_MMC_BLOCK_MINORS) 18895e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson pr_info("mmcblk: using %d minors per device\n", perdev_minors); 18905e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson 18915e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson max_devices = 256 / perdev_minors; 18925e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson 1893fe6b4c8840c5e23fe9b8696450cee8f2e8cebffdPierre Ossman res = register_blkdev(MMC_BLOCK_MAJOR, "mmc"); 1894fe6b4c8840c5e23fe9b8696450cee8f2e8cebffdPierre Ossman if (res) 18951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 18961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18979d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita res = mmc_register_driver(&mmc_driver); 18989d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita if (res) 18999d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita goto out2; 19001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19019d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita return 0; 19029d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita out2: 19039d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita unregister_blkdev(MMC_BLOCK_MAJOR, "mmc"); 19041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 19051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return res; 19061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 19071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit mmc_blk_exit(void) 19091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 19101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_unregister_driver(&mmc_driver); 1911fe6b4c8840c5e23fe9b8696450cee8f2e8cebffdPierre Ossman unregister_blkdev(MMC_BLOCK_MAJOR, "mmc"); 19121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 19131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(mmc_blk_init); 19151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(mmc_blk_exit); 19161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 19181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("Multimedia Card (MMC) block device driver"); 19191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1920