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> 37e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson#include <linux/pm_runtime.h> 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 39c01980e6c9a2bbae4d5881fbe018363df6a908f6Ken Sumrall#define CREATE_TRACE_POINTS 40c01980e6c9a2bbae4d5881fbe018363df6a908f6Ken Sumrall#include <trace/events/mmc.h> 41c01980e6c9a2bbae4d5881fbe018363df6a908f6Ken Sumrall 42cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto#include <linux/mmc/ioctl.h> 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mmc/card.h> 44385e3227d4d83ab13d7767c4bb3593b0256bf246Pierre Ossman#include <linux/mmc/host.h> 45da7fbe58d2d347e95af699ddf04d885be6362bbePierre Ossman#include <linux/mmc/mmc.h> 46da7fbe58d2d347e95af699ddf04d885be6362bbePierre Ossman#include <linux/mmc/sd.h> 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h> 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5098ac2162699f7e9880683cb954891817f20b607cPierre Ossman#include "queue.h" 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 526b0b62853b2553be375033776902640320970846Andy WhitcroftMODULE_ALIAS("mmc:block"); 535e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson#ifdef MODULE_PARAM_PREFIX 545e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson#undef MODULE_PARAM_PREFIX 555e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson#endif 565e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson#define MODULE_PARAM_PREFIX "mmcblk." 575e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson 586a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin#define INAND_CMD38_ARG_EXT_CSD 113 596a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin#define INAND_CMD38_ARG_ERASE 0x00 606a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin#define INAND_CMD38_ARG_TRIM 0x01 616a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin#define INAND_CMD38_ARG_SECERASE 0x80 626a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin#define INAND_CMD38_ARG_SECTRIM1 0x81 636a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin#define INAND_CMD38_ARG_SECTRIM2 0x88 648fee476b219d1869762d9ef5c189a0c85e919a4dTrey Ramsay#define MMC_BLK_TIMEOUT_MS (10 * 60 * 1000) /* 10 minute timeout */ 65775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez#define MMC_SANITIZE_REQ_TIMEOUT 240000 66775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez#define MMC_EXTRACT_INDEX_FROM_ARG(x) ((x & 0x00FF0000) >> 16) 676a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin 68ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon#define mmc_req_rel_wr(req) (((req->cmd_flags & REQ_FUA) || \ 69ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon (req->cmd_flags & REQ_META)) && \ 70ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon (rq_data_dir(req) == WRITE)) 71ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon#define PACKED_CMD_VER 0x01 72ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon#define PACKED_CMD_WR 0x02 73ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 745e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johanssonstatic DEFINE_MUTEX(block_mutex); 756b0b62853b2553be375033776902640320970846Andy Whitcroft 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 775e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson * The defaults come from config options but can be overriden by module 785e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson * or bootarg options. 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 805e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johanssonstatic int perdev_minors = CONFIG_MMC_BLOCK_MINORS; 811dff314451fa24d6b107aa05393d3169e56a7e0aDavid Woodhouse 825e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson/* 835e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson * We've only got one major, so number of mmcblk devices is 845e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson * limited to 256 / number of minors per device. 855e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson */ 865e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johanssonstatic int max_devices; 875e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson 885e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson/* 256 minors, so at most 256 separate devices */ 895e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johanssonstatic DECLARE_BITMAP(dev_use, 256); 90f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentinstatic DECLARE_BITMAP(name_use, 256); 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * There is one mmc_blk_data per slot. 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct mmc_blk_data { 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spinlock_t lock; 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct gendisk *disk; 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_queue queue; 99371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct list_head part; 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 101d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin unsigned int flags; 102d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin#define MMC_BLK_CMD23 (1 << 0) /* Can do SET_BLOCK_COUNT for multiblock */ 103d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin#define MMC_BLK_REL_WR (1 << 1) /* MMC Reliable write support */ 104ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon#define MMC_BLK_PACKED_CMD (1 << 2) /* MMC packed command support */ 105d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int usage; 107a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King unsigned int read_only; 108371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin unsigned int part_type; 109f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin unsigned int name_idx; 11067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter unsigned int reset_done; 11167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter#define MMC_BLK_READ BIT(0) 11267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter#define MMC_BLK_WRITE BIT(1) 11367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter#define MMC_BLK_DISCARD BIT(2) 11467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter#define MMC_BLK_SECDISCARD BIT(3) 115371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 116371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin /* 117371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin * Only set in main mmc_blk_data associated 118371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin * with mmc_card with mmc_set_drvdata, and keeps 119371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin * track of the current selected device partition. 120371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin */ 121371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin unsigned int part_curr; 122371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct device_attribute force_ro; 123add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm struct device_attribute power_ro_lock; 124add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm int area_type; 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 127a621aaed690b9439141c555941b6af53873f6ff1Arjan van de Venstatic DEFINE_MUTEX(open_lock); 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 129ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeonenum { 130ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon MMC_PACKED_NR_IDX = -1, 131ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon MMC_PACKED_NR_ZERO, 132ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon MMC_PACKED_NR_SINGLE, 133ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon}; 134ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1355e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johanssonmodule_param(perdev_minors, int, 0444); 1365e71b7a64cb4c6cff75ca42b535d8227526ec592Olof JohanssonMODULE_PARM_DESC(perdev_minors, "Minors numbers to allocate per device"); 1375e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson 1388d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardystatic inline int mmc_blk_part_switch(struct mmc_card *card, 1398d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy struct mmc_blk_data *md); 1408d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardystatic int get_card_status(struct mmc_card *card, u32 *status, int retries); 1418d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy 142ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeonstatic inline void mmc_blk_clear_packed(struct mmc_queue_req *mqrq) 143ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon{ 144ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon struct mmc_packed *packed = mqrq->packed; 145ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 146ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon BUG_ON(!packed); 147ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 148ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon mqrq->cmd_type = MMC_PACKED_NONE; 149ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon packed->nr_entries = MMC_PACKED_NR_ZERO; 150ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon packed->idx_failure = MMC_PACKED_NR_IDX; 151ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon packed->retries = 0; 152ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon packed->blocks = 0; 153ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon} 154ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct mmc_blk_data *mmc_blk_get(struct gendisk *disk) 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_blk_data *md; 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 159a621aaed690b9439141c555941b6af53873f6ff1Arjan van de Ven mutex_lock(&open_lock); 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds md = disk->private_data; 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (md && md->usage == 0) 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds md = NULL; 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (md) 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds md->usage++; 165a621aaed690b9439141c555941b6af53873f6ff1Arjan van de Ven mutex_unlock(&open_lock); 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return md; 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 170371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic inline int mmc_get_devidx(struct gendisk *disk) 171371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{ 172163a4169f98ef0867312fdf70b9389bea7831a8dColin Cross int devidx = disk->first_minor / perdev_minors; 173371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin return devidx; 174371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin} 175371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mmc_blk_put(struct mmc_blk_data *md) 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 178a621aaed690b9439141c555941b6af53873f6ff1Arjan van de Ven mutex_lock(&open_lock); 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds md->usage--; 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (md->usage == 0) { 181371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin int devidx = mmc_get_devidx(md->disk); 1825fa83ce284a4b7cd9dcfadd01500b0ed4ab9b740Adrian Hunter blk_cleanup_queue(md->queue.queue); 1835fa83ce284a4b7cd9dcfadd01500b0ed4ab9b740Adrian Hunter 1841dff314451fa24d6b107aa05393d3169e56a7e0aDavid Woodhouse __clear_bit(devidx, dev_use); 1851dff314451fa24d6b107aa05393d3169e56a7e0aDavid Woodhouse 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds put_disk(md->disk); 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(md); 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 189a621aaed690b9439141c555941b6af53873f6ff1Arjan van de Ven mutex_unlock(&open_lock); 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 192add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholmstatic ssize_t power_ro_lock_show(struct device *dev, 193add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm struct device_attribute *attr, char *buf) 194add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm{ 195add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm int ret; 196add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev)); 197add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm struct mmc_card *card = md->queue.card; 198add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm int locked = 0; 199add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm 200add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm if (card->ext_csd.boot_ro_lock & EXT_CSD_BOOT_WP_B_PERM_WP_EN) 201add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm locked = 2; 202add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm else if (card->ext_csd.boot_ro_lock & EXT_CSD_BOOT_WP_B_PWR_WP_EN) 203add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm locked = 1; 204add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm 205add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm ret = snprintf(buf, PAGE_SIZE, "%d\n", locked); 206add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm 207add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm return ret; 208add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm} 209add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm 210add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholmstatic ssize_t power_ro_lock_store(struct device *dev, 211add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm struct device_attribute *attr, const char *buf, size_t count) 212add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm{ 213add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm int ret; 214add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm struct mmc_blk_data *md, *part_md; 215add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm struct mmc_card *card; 216add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm unsigned long set; 217add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm 218add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm if (kstrtoul(buf, 0, &set)) 219add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm return -EINVAL; 220add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm 221add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm if (set != 1) 222add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm return count; 223add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm 224add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm md = mmc_blk_get(dev_to_disk(dev)); 225add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm card = md->queue.card; 226add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm 227e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson mmc_get_card(card); 228add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm 229add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_WP, 230add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm card->ext_csd.boot_ro_lock | 231add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm EXT_CSD_BOOT_WP_B_PWR_WP_EN, 232add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm card->ext_csd.part_time); 233add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm if (ret) 234add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm pr_err("%s: Locking boot partition ro until next power on failed: %d\n", md->disk->disk_name, ret); 235add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm else 236add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm card->ext_csd.boot_ro_lock |= EXT_CSD_BOOT_WP_B_PWR_WP_EN; 237add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm 238e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson mmc_put_card(card); 239add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm 240add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm if (!ret) { 241add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm pr_info("%s: Locking boot partition ro until next power on\n", 242add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm md->disk->disk_name); 243add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm set_disk_ro(md->disk, 1); 244add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm 245add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm list_for_each_entry(part_md, &md->part, part) 246add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm if (part_md->area_type == MMC_BLK_DATA_AREA_BOOT) { 247add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm pr_info("%s: Locking boot partition ro until next power on\n", part_md->disk->disk_name); 248add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm set_disk_ro(part_md->disk, 1); 249add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm } 250add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm } 251add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm 252add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm mmc_blk_put(md); 253add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm return count; 254add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm} 255add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm 256371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic ssize_t force_ro_show(struct device *dev, struct device_attribute *attr, 257371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin char *buf) 258371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{ 259371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin int ret; 260371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev)); 261371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 262371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin ret = snprintf(buf, PAGE_SIZE, "%d", 263371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin get_disk_ro(dev_to_disk(dev)) ^ 264371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin md->read_only); 265371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin mmc_blk_put(md); 266371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin return ret; 267371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin} 268371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 269371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic ssize_t force_ro_store(struct device *dev, struct device_attribute *attr, 270371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin const char *buf, size_t count) 271371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{ 272371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin int ret; 273371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin char *end; 274371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev)); 275371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin unsigned long set = simple_strtoul(buf, &end, 0); 276371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin if (end == buf) { 277371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin ret = -EINVAL; 278371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin goto out; 279371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin } 280371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 281371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin set_disk_ro(dev_to_disk(dev), set || md->read_only); 282371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin ret = count; 283371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinout: 284371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin mmc_blk_put(md); 285371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin return ret; 286371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin} 287371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 288a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Virostatic int mmc_blk_open(struct block_device *bdev, fmode_t mode) 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 290a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Viro struct mmc_blk_data *md = mmc_blk_get(bdev->bd_disk); 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = -ENXIO; 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2932a48fc0ab24241755dc93bfd4f01d68efab47f5aArnd Bergmann mutex_lock(&block_mutex); 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (md) { 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (md->usage == 2) 296a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Viro check_disk_change(bdev); 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = 0; 298a00fc09029f02ca833cf90e5d5625f08c4ac4f51Pierre Ossman 299a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Viro if ((mode & FMODE_WRITE) && md->read_only) { 30070bb08962ea9bd50797ae9f16b2493f5f7c65053Andrew Morton mmc_blk_put(md); 301a00fc09029f02ca833cf90e5d5625f08c4ac4f51Pierre Ossman ret = -EROFS; 30270bb08962ea9bd50797ae9f16b2493f5f7c65053Andrew Morton } 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3042a48fc0ab24241755dc93bfd4f01d68efab47f5aArnd Bergmann mutex_unlock(&block_mutex); 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 309db2a144bedd58b3dcf19950c2f476c58c9f39d18Al Virostatic void mmc_blk_release(struct gendisk *disk, fmode_t mode) 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 311a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Viro struct mmc_blk_data *md = disk->private_data; 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3132a48fc0ab24241755dc93bfd4f01d68efab47f5aArnd Bergmann mutex_lock(&block_mutex); 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_blk_put(md); 3152a48fc0ab24241755dc93bfd4f01d68efab47f5aArnd Bergmann mutex_unlock(&block_mutex); 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 319a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwigmmc_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo) 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 321a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig geo->cylinders = get_capacity(bdev->bd_disk) / (4 * 16); 322a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig geo->heads = 4; 323a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig geo->sectors = 16; 324a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig return 0; 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 327cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtostruct mmc_blk_ioc_data { 328cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto struct mmc_ioc_cmd ic; 329cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto unsigned char *buf; 330cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto u64 buf_bytes; 331cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto}; 332cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 333cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtostatic struct mmc_blk_ioc_data *mmc_blk_ioctl_copy_from_user( 334cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto struct mmc_ioc_cmd __user *user) 335cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto{ 336cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto struct mmc_blk_ioc_data *idata; 337cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto int err; 338cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 339cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto idata = kzalloc(sizeof(*idata), GFP_KERNEL); 340cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (!idata) { 341cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto err = -ENOMEM; 342aea253ecffecd38b5ab97edd73fbe2842a7de371Vladimir Motyka goto out; 343cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto } 344cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 345cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (copy_from_user(&idata->ic, user, sizeof(idata->ic))) { 346cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto err = -EFAULT; 347aea253ecffecd38b5ab97edd73fbe2842a7de371Vladimir Motyka goto idata_err; 348cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto } 349cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 350cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto idata->buf_bytes = (u64) idata->ic.blksz * idata->ic.blocks; 351cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (idata->buf_bytes > MMC_IOC_MAX_BYTES) { 352cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto err = -EOVERFLOW; 353aea253ecffecd38b5ab97edd73fbe2842a7de371Vladimir Motyka goto idata_err; 354cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto } 355cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 3564d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm if (!idata->buf_bytes) 3574d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm return idata; 3584d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm 359cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto idata->buf = kzalloc(idata->buf_bytes, GFP_KERNEL); 360cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (!idata->buf) { 361cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto err = -ENOMEM; 362aea253ecffecd38b5ab97edd73fbe2842a7de371Vladimir Motyka goto idata_err; 363cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto } 364cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 365cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (copy_from_user(idata->buf, (void __user *)(unsigned long) 366cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto idata->ic.data_ptr, idata->buf_bytes)) { 367cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto err = -EFAULT; 368cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto goto copy_err; 369cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto } 370cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 371cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto return idata; 372cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 373cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtocopy_err: 374cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto kfree(idata->buf); 375aea253ecffecd38b5ab97edd73fbe2842a7de371Vladimir Motykaidata_err: 376cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto kfree(idata); 377aea253ecffecd38b5ab97edd73fbe2842a7de371Vladimir Motykaout: 378cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto return ERR_PTR(err); 379cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto} 380cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 3818d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardystatic int ioctl_rpmb_card_status_poll(struct mmc_card *card, u32 *status, 3828d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy u32 retries_max) 3838d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy{ 3848d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy int err; 3858d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy u32 retry_count = 0; 3868d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy 3878d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy if (!status || !retries_max) 3888d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy return -EINVAL; 3898d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy 3908d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy do { 3918d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy err = get_card_status(card, status, 5); 3928d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy if (err) 3938d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy break; 3948d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy 3958d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy if (!R1_STATUS(*status) && 3968d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy (R1_CURRENT_STATE(*status) != R1_STATE_PRG)) 3978d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy break; /* RPMB programming operation complete */ 3988d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy 3998d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy /* 4008d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy * Rechedule to give the MMC device a chance to continue 4018d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy * processing the previous command without being polled too 4028d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy * frequently. 4038d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy */ 4048d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy usleep_range(1000, 5000); 4058d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy } while (++retry_count < retries_max); 4068d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy 4078d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy if (retry_count == retries_max) 4088d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy err = -EPERM; 4098d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy 4108d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy return err; 4118d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy} 4128d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy 413775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erezstatic int ioctl_do_sanitize(struct mmc_card *card) 414775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez{ 415775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez int err; 416775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez 417a2d1086de6cc3ae2378d9db8b92712911c9e5fefUlf Hansson if (!mmc_can_sanitize(card)) { 418775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez pr_warn("%s: %s - SANITIZE is not supported\n", 419775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez mmc_hostname(card->host), __func__); 420775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez err = -EOPNOTSUPP; 421775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez goto out; 422775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez } 423775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez 424775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez pr_debug("%s: %s - SANITIZE IN PROGRESS...\n", 425775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez mmc_hostname(card->host), __func__); 426775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez 427c01980e6c9a2bbae4d5881fbe018363df6a908f6Ken Sumrall trace_mmc_blk_erase_start(EXT_CSD_SANITIZE_START, 0, 0); 428775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, 429775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez EXT_CSD_SANITIZE_START, 1, 430775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez MMC_SANITIZE_REQ_TIMEOUT); 431c01980e6c9a2bbae4d5881fbe018363df6a908f6Ken Sumrall trace_mmc_blk_erase_end(EXT_CSD_SANITIZE_START, 0, 0); 432775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez 433775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez if (err) 434775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez pr_err("%s: %s - EXT_CSD_SANITIZE_START failed. err=%d\n", 435775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez mmc_hostname(card->host), __func__, err); 436775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez 437775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez pr_debug("%s: %s - SANITIZE COMPLETED\n", mmc_hostname(card->host), 438775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez __func__); 439775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erezout: 440775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez return err; 441775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez} 442775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez 443cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtostatic int mmc_blk_ioctl_cmd(struct block_device *bdev, 444cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto struct mmc_ioc_cmd __user *ic_ptr) 445cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto{ 446cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto struct mmc_blk_ioc_data *idata; 447cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto struct mmc_blk_data *md; 448cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto struct mmc_card *card; 449cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto struct mmc_command cmd = {0}; 450cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto struct mmc_data data = {0}; 451ad5fd97288655b5628052c1fa906419417c86100Venkatraman S struct mmc_request mrq = {NULL}; 452cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto struct scatterlist sg; 453cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto int err; 4548d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy int is_rpmb = false; 4558d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy u32 status = 0; 456cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 457cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto /* 458cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto * The caller must have CAP_SYS_RAWIO, and must be calling this on the 459cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto * whole block device, not on a partition. This prevents overspray 460cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto * between sibling partitions. 461cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto */ 462cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if ((!capable(CAP_SYS_RAWIO)) || (bdev != bdev->bd_contains)) 463cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto return -EPERM; 464cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 465cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto idata = mmc_blk_ioctl_copy_from_user(ic_ptr); 466cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (IS_ERR(idata)) 467cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto return PTR_ERR(idata); 468cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 469cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto md = mmc_blk_get(bdev->bd_disk); 470cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (!md) { 471cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto err = -EINVAL; 4721c02f000e78347aa51822feb189fcb0d90273958Philippe De Swert goto cmd_err; 473cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto } 474cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 4758d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy if (md->area_type & MMC_BLK_DATA_AREA_RPMB) 4768d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy is_rpmb = true; 4778d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy 478cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto card = md->queue.card; 479cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (IS_ERR(card)) { 480cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto err = PTR_ERR(card); 481cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto goto cmd_done; 482cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto } 483cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 4844d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm cmd.opcode = idata->ic.opcode; 4854d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm cmd.arg = idata->ic.arg; 4864d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm cmd.flags = idata->ic.flags; 4874d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm 4884d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm if (idata->buf_bytes) { 4894d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm data.sg = &sg; 4904d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm data.sg_len = 1; 4914d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm data.blksz = idata->ic.blksz; 4924d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm data.blocks = idata->ic.blocks; 4934d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm 4944d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm sg_init_one(data.sg, idata->buf, idata->buf_bytes); 4954d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm 4964d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm if (idata->ic.write_flag) 4974d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm data.flags = MMC_DATA_WRITE; 4984d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm else 4994d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm data.flags = MMC_DATA_READ; 5004d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm 5014d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm /* data.flags must already be set before doing this. */ 5024d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm mmc_set_data_timeout(&data, card); 5034d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm 5044d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm /* Allow overriding the timeout_ns for empirical tuning. */ 5054d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm if (idata->ic.data_timeout_ns) 5064d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm data.timeout_ns = idata->ic.data_timeout_ns; 5074d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm 5084d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm if ((cmd.flags & MMC_RSP_R1B) == MMC_RSP_R1B) { 5094d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm /* 5104d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm * Pretend this is a data transfer and rely on the 5114d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm * host driver to compute timeout. When all host 5124d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm * drivers support cmd.cmd_timeout for R1B, this 5134d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm * can be changed to: 5144d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm * 5154d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm * mrq.data = NULL; 5164d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm * cmd.cmd_timeout = idata->ic.cmd_timeout_ms; 5174d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm */ 5184d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm data.timeout_ns = idata->ic.cmd_timeout_ms * 1000000; 5194d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm } 5204d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm 5214d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm mrq.data = &data; 5224d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm } 5234d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm 5244d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm mrq.cmd = &cmd; 5254d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm 526e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson mmc_get_card(card); 527cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 5288d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy err = mmc_blk_part_switch(card, md); 5298d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy if (err) 5308d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy goto cmd_rel_host; 5318d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy 532cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (idata->ic.is_acmd) { 533cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto err = mmc_app_cmd(card->host, card); 534cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (err) 535cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto goto cmd_rel_host; 536cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto } 537cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 5388d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy if (is_rpmb) { 5398d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy err = mmc_set_blockcount(card, data.blocks, 5408d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy idata->ic.write_flag & (1 << 31)); 5418d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy if (err) 5428d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy goto cmd_rel_host; 5438d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy } 5448d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy 545a82e484e2480583b17be6253b985fa6f582ad20dYaniv Gardi if ((MMC_EXTRACT_INDEX_FROM_ARG(cmd.arg) == EXT_CSD_SANITIZE_START) && 546a82e484e2480583b17be6253b985fa6f582ad20dYaniv Gardi (cmd.opcode == MMC_SWITCH)) { 547775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez err = ioctl_do_sanitize(card); 548775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez 549775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez if (err) 550775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez pr_err("%s: ioctl_do_sanitize() failed. err = %d", 551775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez __func__, err); 552775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez 553775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez goto cmd_rel_host; 554775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez } 555775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez 556cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto mmc_wait_for_req(card->host, &mrq); 557cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 558cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (cmd.error) { 559cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto dev_err(mmc_dev(card->host), "%s: cmd error %d\n", 560cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto __func__, cmd.error); 561cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto err = cmd.error; 562cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto goto cmd_rel_host; 563cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto } 564cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (data.error) { 565cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto dev_err(mmc_dev(card->host), "%s: data error %d\n", 566cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto __func__, data.error); 567cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto err = data.error; 568cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto goto cmd_rel_host; 569cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto } 570cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 571cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto /* 572cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto * According to the SD specs, some commands require a delay after 573cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto * issuing the command. 574cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto */ 575cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (idata->ic.postsleep_min_us) 576cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto usleep_range(idata->ic.postsleep_min_us, idata->ic.postsleep_max_us); 577cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 578cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (copy_to_user(&(ic_ptr->response), cmd.resp, sizeof(cmd.resp))) { 579cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto err = -EFAULT; 580cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto goto cmd_rel_host; 581cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto } 582cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 583cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (!idata->ic.write_flag) { 584cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (copy_to_user((void __user *)(unsigned long) idata->ic.data_ptr, 585cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto idata->buf, idata->buf_bytes)) { 586cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto err = -EFAULT; 587cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto goto cmd_rel_host; 588cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto } 589cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto } 590cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 5918d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy if (is_rpmb) { 5928d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy /* 5938d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy * Ensure RPMB command has completed by polling CMD13 5948d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy * "Send Status". 5958d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy */ 5968d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy err = ioctl_rpmb_card_status_poll(card, &status, 5); 5978d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy if (err) 5988d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy dev_err(mmc_dev(card->host), 5998d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy "%s: Card Status=0x%08X, error %d\n", 6008d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy __func__, status, err); 6018d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy } 6028d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy 603cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtocmd_rel_host: 604e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson mmc_put_card(card); 605cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 606cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtocmd_done: 607cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto mmc_blk_put(md); 6081c02f000e78347aa51822feb189fcb0d90273958Philippe De Swertcmd_err: 609cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto kfree(idata->buf); 610cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto kfree(idata); 611cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto return err; 612cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto} 613cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 614cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtostatic int mmc_blk_ioctl(struct block_device *bdev, fmode_t mode, 615cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto unsigned int cmd, unsigned long arg) 616cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto{ 617cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto int ret = -EINVAL; 618cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto if (cmd == MMC_IOC_CMD) 619cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto ret = mmc_blk_ioctl_cmd(bdev, (struct mmc_ioc_cmd __user *)arg); 620cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto return ret; 621cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto} 622cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 623cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto#ifdef CONFIG_COMPAT 624cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtostatic int mmc_blk_compat_ioctl(struct block_device *bdev, fmode_t mode, 625cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto unsigned int cmd, unsigned long arg) 626cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto{ 627cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto return mmc_blk_ioctl(bdev, mode, cmd, (unsigned long) compat_ptr(arg)); 628cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto} 629cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto#endif 630cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto 63183d5cde47dedf01b6a4a4331882cbc0a7eea3c2eAlexey Dobriyanstatic const struct block_device_operations mmc_bdops = { 632a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Viro .open = mmc_blk_open, 633a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Viro .release = mmc_blk_release, 634a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig .getgeo = mmc_blk_getgeo, 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .owner = THIS_MODULE, 636cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto .ioctl = mmc_blk_ioctl, 637cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto#ifdef CONFIG_COMPAT 638cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto .compat_ioctl = mmc_blk_compat_ioctl, 639cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto#endif 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 642371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic inline int mmc_blk_part_switch(struct mmc_card *card, 643371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct mmc_blk_data *md) 644371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{ 645371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin int ret; 646371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct mmc_blk_data *main_md = mmc_get_drvdata(card); 6470d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter 648371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin if (main_md->part_curr == md->part_type) 649371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin return 0; 650371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 651371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin if (mmc_card_mmc(card)) { 6520d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter u8 part_config = card->ext_csd.part_config; 6530d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter 6540d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter part_config &= ~EXT_CSD_PART_CONFIG_ACC_MASK; 6550d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter part_config |= md->part_type; 656371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 657371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, 6580d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter EXT_CSD_PART_CONFIG, part_config, 659371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin card->ext_csd.part_time); 660371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin if (ret) 661371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin return ret; 6620d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter 6630d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter card->ext_csd.part_config = part_config; 66467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter } 665371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 666371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin main_md->part_curr = md->part_type; 667371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin return 0; 668371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin} 669371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 670ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossmanstatic u32 mmc_sd_num_wr_blocks(struct mmc_card *card) 671ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman{ 672ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman int err; 673051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks u32 result; 674051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks __be32 *blocks; 675ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 676ad5fd97288655b5628052c1fa906419417c86100Venkatraman S struct mmc_request mrq = {NULL}; 6771278dba167f01bb3c6626d16450d31129d041087Chris Ball struct mmc_command cmd = {0}; 678a61ad2b49bfce94dfddce828cd9222e4b9e7825bChris Ball struct mmc_data data = {0}; 679ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 680ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman struct scatterlist sg; 681ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 682ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman cmd.opcode = MMC_APP_CMD; 683ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman cmd.arg = card->rca << 16; 6847213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; 685ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 686ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman err = mmc_wait_for_cmd(card->host, &cmd, 0); 6877213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell if (err) 6887213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell return (u32)-1; 6897213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell if (!mmc_host_is_spi(card->host) && !(cmd.resp[0] & R1_APP_CMD)) 690ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman return (u32)-1; 691ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 692ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman memset(&cmd, 0, sizeof(struct mmc_command)); 693ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 694ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman cmd.opcode = SD_APP_SEND_NUM_WR_BLKS; 695ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman cmd.arg = 0; 6967213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; 697ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 698ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman data.blksz = 4; 699ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman data.blocks = 1; 700ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman data.flags = MMC_DATA_READ; 701ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman data.sg = &sg; 702ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman data.sg_len = 1; 703d380443cd0271903bf9516bc04cead81676be034Subhash Jadavani mmc_set_data_timeout(&data, card); 704ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 705ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman mrq.cmd = &cmd; 706ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman mrq.data = &data; 707ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 708051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks blocks = kmalloc(4, GFP_KERNEL); 709051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks if (!blocks) 710051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks return (u32)-1; 711051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks 712051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks sg_init_one(&sg, blocks, 4); 713ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 714ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman mmc_wait_for_req(card->host, &mrq); 715ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 716051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks result = ntohl(*blocks); 717051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks kfree(blocks); 718051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks 71917b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman if (cmd.error || data.error) 720051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks result = (u32)-1; 721ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 722051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks return result; 723ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman} 724ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman 7250a2d4048a22079d7e79d6654bbacbef57bd5728aRussell King - ARM Linuxstatic int get_card_status(struct mmc_card *card, u32 *status, int retries) 726504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter{ 7271278dba167f01bb3c6626d16450d31129d041087Chris Ball struct mmc_command cmd = {0}; 728504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter int err; 729504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter 730504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter cmd.opcode = MMC_SEND_STATUS; 731504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter if (!mmc_host_is_spi(card->host)) 732504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter cmd.arg = card->rca << 16; 733504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC; 7340a2d4048a22079d7e79d6654bbacbef57bd5728aRussell King - ARM Linux err = mmc_wait_for_cmd(card->host, &cmd, retries); 7350a2d4048a22079d7e79d6654bbacbef57bd5728aRussell King - ARM Linux if (err == 0) 7360a2d4048a22079d7e79d6654bbacbef57bd5728aRussell King - ARM Linux *status = cmd.resp[0]; 7370a2d4048a22079d7e79d6654bbacbef57bd5728aRussell King - ARM Linux return err; 738504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter} 739504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter 740c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hanssonstatic int card_busy_detect(struct mmc_card *card, unsigned int timeout_ms, 74195a91298fc09db0c21193ace96d1934598dd92ddUlf Hansson bool hw_busy_detect, struct request *req, int *gen_err) 742c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson{ 743c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms); 744c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson int err = 0; 745c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson u32 status; 746c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson 747c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson do { 748c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson err = get_card_status(card, &status, 5); 749c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson if (err) { 750c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson pr_err("%s: error %d requesting status\n", 751c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson req->rq_disk->disk_name, err); 752c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson return err; 753c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson } 754c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson 755c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson if (status & R1_ERROR) { 756c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson pr_err("%s: %s: error sending status cmd, status %#x\n", 757c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson req->rq_disk->disk_name, __func__, status); 758c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson *gen_err = 1; 759c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson } 760c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson 76195a91298fc09db0c21193ace96d1934598dd92ddUlf Hansson /* We may rely on the host hw to handle busy detection.*/ 76295a91298fc09db0c21193ace96d1934598dd92ddUlf Hansson if ((card->host->caps & MMC_CAP_WAIT_WHILE_BUSY) && 76395a91298fc09db0c21193ace96d1934598dd92ddUlf Hansson hw_busy_detect) 76495a91298fc09db0c21193ace96d1934598dd92ddUlf Hansson break; 76595a91298fc09db0c21193ace96d1934598dd92ddUlf Hansson 766c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson /* 767c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson * Timeout if the device never becomes ready for data and never 768c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson * leaves the program state. 769c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson */ 770c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson if (time_after(jiffies, timeout)) { 771c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson pr_err("%s: Card stuck in programming state! %s %s\n", 772c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson mmc_hostname(card->host), 773c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson req->rq_disk->disk_name, __func__); 774c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson return -ETIMEDOUT; 775c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson } 776c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson 777c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson /* 778c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson * Some cards mishandle the status bits, 779c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson * so make sure to check both the busy 780c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson * indication and the card state. 781c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson */ 782c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson } while (!(status & R1_READY_FOR_DATA) || 783c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson (R1_CURRENT_STATE(status) == R1_STATE_PRG)); 784c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson 785c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson return err; 786c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson} 787c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson 788bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hanssonstatic int send_stop(struct mmc_card *card, unsigned int timeout_ms, 789bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson struct request *req, int *gen_err, u32 *stop_status) 790bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson{ 791bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson struct mmc_host *host = card->host; 792bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson struct mmc_command cmd = {0}; 793bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson int err; 794bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson bool use_r1b_resp = rq_data_dir(req) == WRITE; 795bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson 796bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson /* 797bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson * Normally we use R1B responses for WRITE, but in cases where the host 798bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson * has specified a max_busy_timeout we need to validate it. A failure 799bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson * means we need to prevent the host from doing hw busy detection, which 800bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson * is done by converting to a R1 response instead. 801bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson */ 802bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson if (host->max_busy_timeout && (timeout_ms > host->max_busy_timeout)) 803bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson use_r1b_resp = false; 804bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson 805bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson cmd.opcode = MMC_STOP_TRANSMISSION; 806bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson if (use_r1b_resp) { 807bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; 808bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson cmd.busy_timeout = timeout_ms; 809bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson } else { 810bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; 811bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson } 812bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson 813bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson err = mmc_wait_for_cmd(host, &cmd, 5); 814bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson if (err) 815bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson return err; 816bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson 817bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson *stop_status = cmd.resp[0]; 818bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson 819bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson /* No need to check card status in case of READ. */ 820bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson if (rq_data_dir(req) == READ) 821bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson return 0; 822bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson 823bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson if (!mmc_host_is_spi(host) && 824bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson (*stop_status & R1_ERROR)) { 825bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson pr_err("%s: %s: general error sending stop command, resp %#x\n", 826bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson req->rq_disk->disk_name, __func__, *stop_status); 827bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson *gen_err = 1; 828bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson } 829bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson 830bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson return card_busy_detect(card, timeout_ms, use_r1b_resp, req, gen_err); 831bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson} 832bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson 833a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma#define ERR_NOMEDIUM 3 834a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux#define ERR_RETRY 2 835a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux#define ERR_ABORT 1 836a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux#define ERR_CONTINUE 0 837a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 838a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linuxstatic int mmc_blk_cmd_error(struct request *req, const char *name, int error, 839a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux bool status_valid, u32 status) 840a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux{ 841a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux switch (error) { 842a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux case -EILSEQ: 843a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux /* response crc error, retry the r/w cmd */ 844a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux pr_err("%s: %s sending %s command, card status %#x\n", 845a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux req->rq_disk->disk_name, "response CRC error", 846a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux name, status); 847a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux return ERR_RETRY; 848a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 849a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux case -ETIMEDOUT: 850a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux pr_err("%s: %s sending %s command, card status %#x\n", 851a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux req->rq_disk->disk_name, "timed out", name, status); 852a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 853a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux /* If the status cmd initially failed, retry the r/w cmd */ 854b794617b30b3bcf2ba48282b19f8906f7e4cd349Ken Sumrall if (!status_valid) { 855b794617b30b3bcf2ba48282b19f8906f7e4cd349Ken Sumrall pr_err("%s: status not valid, retrying timeout\n", req->rq_disk->disk_name); 856a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux return ERR_RETRY; 857b794617b30b3bcf2ba48282b19f8906f7e4cd349Ken Sumrall } 858a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux /* 859a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * If it was a r/w cmd crc error, or illegal command 860a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * (eg, issued in wrong state) then retry - we should 861a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * have corrected the state problem above. 862a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux */ 863b794617b30b3bcf2ba48282b19f8906f7e4cd349Ken Sumrall if (status & (R1_COM_CRC_ERROR | R1_ILLEGAL_COMMAND)) { 864b794617b30b3bcf2ba48282b19f8906f7e4cd349Ken Sumrall pr_err("%s: command error, retrying timeout\n", req->rq_disk->disk_name); 865a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux return ERR_RETRY; 866b794617b30b3bcf2ba48282b19f8906f7e4cd349Ken Sumrall } 867a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 868a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux /* Otherwise abort the command */ 869b794617b30b3bcf2ba48282b19f8906f7e4cd349Ken Sumrall pr_err("%s: not retrying timeout\n", req->rq_disk->disk_name); 870a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux return ERR_ABORT; 871a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 872a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux default: 873a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux /* We don't understand the error code the driver gave us */ 874a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux pr_err("%s: unknown error %d sending read/write command, card status %#x\n", 875a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux req->rq_disk->disk_name, error, status); 876a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux return ERR_ABORT; 877a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux } 878a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux} 879a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 880a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux/* 881a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * Initial r/w and stop cmd error recovery. 882a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * We don't know whether the card received the r/w cmd or not, so try to 883a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * restore things back to a sane state. Essentially, we do this as follows: 884a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * - Obtain card status. If the first attempt to obtain card status fails, 885a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * the status word will reflect the failed status cmd, not the failed 886a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * r/w cmd. If we fail to obtain card status, it suggests we can no 887a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * longer communicate with the card. 888a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * - Check the card state. If the card received the cmd but there was a 889a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * transient problem with the response, it might still be in a data transfer 890a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * mode. Try to send it a stop command. If this fails, we can't recover. 891a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * - If the r/w cmd failed due to a response CRC error, it was probably 892a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * transient, so retry the cmd. 893a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * - If the r/w cmd timed out, but we didn't get the r/w cmd status, retry. 894a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * - If the r/w cmd timed out, and the r/w cmd failed due to CRC error or 895a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * illegal cmd, retry. 896a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * Otherwise we don't understand what happened, so abort. 897a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux */ 898a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linuxstatic int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req, 899c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake struct mmc_blk_request *brq, int *ecc_err, int *gen_err) 900a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux{ 901a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux bool prev_cmd_status_valid = true; 902a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux u32 status, stop_status = 0; 903a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux int err, retry; 904a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 905a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma if (mmc_card_removed(card)) 906a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma return ERR_NOMEDIUM; 907a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma 908a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux /* 909a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * Try to get card status which indicates both the card state 910a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * and why there was no response. If the first attempt fails, 911a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * we can't be sure the returned status is for the r/w command. 912a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux */ 913a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux for (retry = 2; retry >= 0; retry--) { 914a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux err = get_card_status(card, &status, 0); 915a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux if (!err) 916a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux break; 917a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 918a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux prev_cmd_status_valid = false; 919a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux pr_err("%s: error %d sending status command, %sing\n", 920a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux req->rq_disk->disk_name, err, retry ? "retry" : "abort"); 921a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux } 922a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 923a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux /* We couldn't get a response from the card. Give up. */ 924a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma if (err) { 925a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma /* Check if the card is removed */ 926a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma if (mmc_detect_card_removed(card->host)) 927a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma return ERR_NOMEDIUM; 928a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux return ERR_ABORT; 929a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma } 930a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 93167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter /* Flag ECC errors */ 93267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if ((status & R1_CARD_ECC_FAILED) || 93367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter (brq->stop.resp[0] & R1_CARD_ECC_FAILED) || 93467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter (brq->cmd.resp[0] & R1_CARD_ECC_FAILED)) 93567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter *ecc_err = 1; 93667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter 937c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake /* Flag General errors */ 938c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) 939c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake if ((status & R1_ERROR) || 940c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake (brq->stop.resp[0] & R1_ERROR)) { 941c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake pr_err("%s: %s: general error sending stop or status command, stop cmd response %#x, card status %#x\n", 942c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake req->rq_disk->disk_name, __func__, 943c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake brq->stop.resp[0], status); 944c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake *gen_err = 1; 945c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake } 946c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake 947a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux /* 948a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * Check the current card state. If it is in some data transfer 949a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * mode, tell it to stop (and hopefully transition back to TRAN.) 950a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux */ 951a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux if (R1_CURRENT_STATE(status) == R1_STATE_DATA || 952a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux R1_CURRENT_STATE(status) == R1_STATE_RCV) { 953bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson err = send_stop(card, 954bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson DIV_ROUND_UP(brq->data.timeout_ns, 1000000), 955bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson req, gen_err, &stop_status); 956bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson if (err) { 957a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux pr_err("%s: error %d sending stop command\n", 958a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux req->rq_disk->disk_name, err); 959bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson /* 960bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson * If the stop cmd also timed out, the card is probably 961bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson * not present, so abort. Other errors are bad news too. 962bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson */ 963a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux return ERR_ABORT; 964bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson } 965bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson 96667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (stop_status & R1_CARD_ECC_FAILED) 96767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter *ecc_err = 1; 968a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux } 969a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 970a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux /* Check for set block count errors */ 971a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux if (brq->sbc.error) 972a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux return mmc_blk_cmd_error(req, "SET_BLOCK_COUNT", brq->sbc.error, 973a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux prev_cmd_status_valid, status); 974a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 975a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux /* Check for r/w command errors */ 976a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux if (brq->cmd.error) 977a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux return mmc_blk_cmd_error(req, "r/w cmd", brq->cmd.error, 978a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux prev_cmd_status_valid, status); 979a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 98067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter /* Data errors */ 98167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (!brq->stop.error) 98267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter return ERR_CONTINUE; 98367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter 984a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux /* Now for stop errors. These aren't fatal to the transfer. */ 9855e1344eb3f4804d2d50195e197fcbcdbd60ad049Johan Rudholm pr_info("%s: error %d sending stop command, original cmd response %#x, card status %#x\n", 986a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux req->rq_disk->disk_name, brq->stop.error, 987a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux brq->cmd.resp[0], status); 988a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 989a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux /* 990a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * Subsitute in our own stop status as this will give the error 991a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * state which happened during the execution of the r/w command. 992a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux */ 993a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux if (stop_status) { 994a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux brq->stop.resp[0] = stop_status; 995a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux brq->stop.error = 0; 996a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux } 997a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux return ERR_CONTINUE; 998a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux} 999a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux 100067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunterstatic int mmc_blk_reset(struct mmc_blk_data *md, struct mmc_host *host, 100167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter int type) 100267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter{ 100367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter int err; 100467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter 100567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (md->reset_done & type) 100667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter return -EEXIST; 100767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter 100867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter md->reset_done |= type; 100967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter err = mmc_hw_reset(host); 101067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter /* Ensure we switch back to the correct partition */ 101167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (err != -EOPNOTSUPP) { 101267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter struct mmc_blk_data *main_md = mmc_get_drvdata(host->card); 101367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter int part_err; 101467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter 101567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter main_md->part_curr = main_md->part_type; 101667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter part_err = mmc_blk_part_switch(host->card, md); 101767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (part_err) { 101867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter /* 101967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter * We have failed to get back into the correct 102067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter * partition, so we need to abort the whole request. 102167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter */ 102267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter return -ENODEV; 102367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter } 102467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter } 102567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter return err; 102667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter} 102767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter 102867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunterstatic inline void mmc_blk_reset_success(struct mmc_blk_data *md, int type) 102967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter{ 103067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter md->reset_done &= ~type; 103167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter} 103267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter 1033bd788c9665fb7c543aac21317059375632343337Adrian Hunterstatic int mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req) 1034bd788c9665fb7c543aac21317059375632343337Adrian Hunter{ 1035bd788c9665fb7c543aac21317059375632343337Adrian Hunter struct mmc_blk_data *md = mq->data; 1036bd788c9665fb7c543aac21317059375632343337Adrian Hunter struct mmc_card *card = md->queue.card; 1037bd788c9665fb7c543aac21317059375632343337Adrian Hunter unsigned int from, nr, arg; 103867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter int err = 0, type = MMC_BLK_DISCARD; 1039bd788c9665fb7c543aac21317059375632343337Adrian Hunter 1040bd788c9665fb7c543aac21317059375632343337Adrian Hunter if (!mmc_can_erase(card)) { 1041bd788c9665fb7c543aac21317059375632343337Adrian Hunter err = -EOPNOTSUPP; 1042bd788c9665fb7c543aac21317059375632343337Adrian Hunter goto out; 1043bd788c9665fb7c543aac21317059375632343337Adrian Hunter } 1044bd788c9665fb7c543aac21317059375632343337Adrian Hunter 1045bd788c9665fb7c543aac21317059375632343337Adrian Hunter from = blk_rq_pos(req); 1046bd788c9665fb7c543aac21317059375632343337Adrian Hunter nr = blk_rq_sectors(req); 1047bd788c9665fb7c543aac21317059375632343337Adrian Hunter 1048b3bf915308ca2b50f3beec6cc824083870f0f4b5Kyungmin Park if (mmc_can_discard(card)) 1049b3bf915308ca2b50f3beec6cc824083870f0f4b5Kyungmin Park arg = MMC_DISCARD_ARG; 1050b3bf915308ca2b50f3beec6cc824083870f0f4b5Kyungmin Park else if (mmc_can_trim(card)) 1051bd788c9665fb7c543aac21317059375632343337Adrian Hunter arg = MMC_TRIM_ARG; 1052bd788c9665fb7c543aac21317059375632343337Adrian Hunter else 1053bd788c9665fb7c543aac21317059375632343337Adrian Hunter arg = MMC_ERASE_ARG; 105467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunterretry: 10556a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin if (card->quirks & MMC_QUIRK_INAND_CMD38) { 10566a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, 10576a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin INAND_CMD38_ARG_EXT_CSD, 10586a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin arg == MMC_TRIM_ARG ? 10596a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin INAND_CMD38_ARG_TRIM : 10606a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin INAND_CMD38_ARG_ERASE, 10616a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin 0); 10626a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin if (err) 10636a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin goto out; 10646a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin } 1065bd788c9665fb7c543aac21317059375632343337Adrian Hunter err = mmc_erase(card, from, nr, arg); 1066bd788c9665fb7c543aac21317059375632343337Adrian Hunterout: 106767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (err == -EIO && !mmc_blk_reset(md, card->host, type)) 106867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter goto retry; 106967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (!err) 107067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter mmc_blk_reset_success(md, type); 1071ecf8b5d0a378a0f922ffca27bd0a9101f246fa11Subhash Jadavani blk_end_request(req, err, blk_rq_bytes(req)); 1072bd788c9665fb7c543aac21317059375632343337Adrian Hunter 1073bd788c9665fb7c543aac21317059375632343337Adrian Hunter return err ? 0 : 1; 1074bd788c9665fb7c543aac21317059375632343337Adrian Hunter} 1075bd788c9665fb7c543aac21317059375632343337Adrian Hunter 10764980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunterstatic int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq, 10774980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter struct request *req) 10784980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter{ 10794980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter struct mmc_blk_data *md = mq->data; 10804980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter struct mmc_card *card = md->queue.card; 1081775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez unsigned int from, nr, arg; 108267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter int err = 0, type = MMC_BLK_SECDISCARD; 10834980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter 1084775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez if (!(mmc_can_secure_erase_trim(card))) { 10854980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter err = -EOPNOTSUPP; 10864980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter goto out; 10874980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter } 10884980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter 1089283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter from = blk_rq_pos(req); 1090283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter nr = blk_rq_sectors(req); 1091283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter 1092775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez if (mmc_can_trim(card) && !mmc_erase_group_aligned(card, from, nr)) 1093775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez arg = MMC_SECURE_TRIM1_ARG; 1094775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez else 1095775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez arg = MMC_SECURE_ERASE_ARG; 1096d9ddd62943ee07a75d0428ffcf52f1a747a28c39Kyungmin Park 109767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunterretry: 10986a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin if (card->quirks & MMC_QUIRK_INAND_CMD38) { 10996a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, 11006a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin INAND_CMD38_ARG_EXT_CSD, 11016a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin arg == MMC_SECURE_TRIM1_ARG ? 11026a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin INAND_CMD38_ARG_SECTRIM1 : 11036a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin INAND_CMD38_ARG_SECERASE, 11046a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin 0); 11056a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin if (err) 1106283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter goto out_retry; 11076a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin } 1108283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter 11094980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter err = mmc_erase(card, from, nr, arg); 1110283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter if (err == -EIO) 1111283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter goto out_retry; 1112283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter if (err) 1113283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter goto out; 1114283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter 1115283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter if (arg == MMC_SECURE_TRIM1_ARG) { 11166a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin if (card->quirks & MMC_QUIRK_INAND_CMD38) { 11176a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, 11186a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin INAND_CMD38_ARG_EXT_CSD, 11196a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin INAND_CMD38_ARG_SECTRIM2, 11206a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin 0); 11216a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin if (err) 1122283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter goto out_retry; 11236a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin } 1124283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter 11254980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter err = mmc_erase(card, from, nr, MMC_SECURE_TRIM2_ARG); 1126283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter if (err == -EIO) 1127283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter goto out_retry; 1128283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter if (err) 1129283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter goto out; 11306a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin } 1131283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter 1132283028122db37621b124f079ca8eae5b64807ad4Adrian Hunterout_retry: 1133283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter if (err && !mmc_blk_reset(md, card->host, type)) 113467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter goto retry; 113567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (!err) 113667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter mmc_blk_reset_success(md, type); 1137283028122db37621b124f079ca8eae5b64807ad4Adrian Hunterout: 1138ecf8b5d0a378a0f922ffca27bd0a9101f246fa11Subhash Jadavani blk_end_request(req, err, blk_rq_bytes(req)); 11394980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter 11404980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter return err ? 0 : 1; 11414980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter} 11424980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter 1143f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentinstatic int mmc_blk_issue_flush(struct mmc_queue *mq, struct request *req) 1144f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin{ 1145f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin struct mmc_blk_data *md = mq->data; 1146881d1c25f765938a95def5afe39486ce39f9fc96Seungwon Jeon struct mmc_card *card = md->queue.card; 1147881d1c25f765938a95def5afe39486ce39f9fc96Seungwon Jeon int ret = 0; 1148881d1c25f765938a95def5afe39486ce39f9fc96Seungwon Jeon 1149881d1c25f765938a95def5afe39486ce39f9fc96Seungwon Jeon ret = mmc_flush_cache(card); 1150881d1c25f765938a95def5afe39486ce39f9fc96Seungwon Jeon if (ret) 1151881d1c25f765938a95def5afe39486ce39f9fc96Seungwon Jeon ret = -EIO; 1152f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin 1153ecf8b5d0a378a0f922ffca27bd0a9101f246fa11Subhash Jadavani blk_end_request_all(req, ret); 1154f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin 1155881d1c25f765938a95def5afe39486ce39f9fc96Seungwon Jeon return ret ? 0 : 1; 1156f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin} 1157f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin 1158f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin/* 1159f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin * Reformat current write as a reliable write, supporting 1160f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin * both legacy and the enhanced reliable write MMC cards. 1161f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin * In each transfer we'll handle only as much as a single 1162f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin * reliable write can handle, thus finish the request in 1163f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin * partial completions. 1164f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin */ 1165d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentinstatic inline void mmc_apply_rel_rw(struct mmc_blk_request *brq, 1166d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin struct mmc_card *card, 1167d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin struct request *req) 1168f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin{ 1169f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin if (!(card->ext_csd.rel_param & EXT_CSD_WR_REL_PARAM_EN)) { 1170f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin /* Legacy mode imposes restrictions on transfers. */ 1171f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin if (!IS_ALIGNED(brq->cmd.arg, card->ext_csd.rel_sectors)) 1172f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin brq->data.blocks = 1; 1173f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin 1174f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin if (brq->data.blocks > card->ext_csd.rel_sectors) 1175f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin brq->data.blocks = card->ext_csd.rel_sectors; 1176f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin else if (brq->data.blocks < card->ext_csd.rel_sectors) 1177f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin brq->data.blocks = 1; 1178f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin } 1179f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin} 1180f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin 11814c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux#define CMD_ERRORS \ 11824c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux (R1_OUT_OF_RANGE | /* Command argument out of range */ \ 11834c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux R1_ADDRESS_ERROR | /* Misaligned address */ \ 11844c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux R1_BLOCK_LEN_ERROR | /* Transferred block length incorrect */\ 11854c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux R1_WP_VIOLATION | /* Tried to write to protected block */ \ 11864c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux R1_CC_ERROR | /* Card controller error */ \ 11874c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux R1_ERROR) /* General/unknown error */ 11884c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux 1189ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlinstatic int mmc_blk_err_check(struct mmc_card *card, 1190ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin struct mmc_async_req *areq) 1191d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin{ 1192ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin struct mmc_queue_req *mq_mrq = container_of(areq, struct mmc_queue_req, 1193ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin mmc_active); 1194ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin struct mmc_blk_request *brq = &mq_mrq->brq; 1195ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin struct request *req = mq_mrq->req; 1196c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake int ecc_err = 0, gen_err = 0; 1197d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin 1198d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin /* 1199d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * sbc.error indicates a problem with the set block count 1200d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * command. No data will have been transferred. 1201d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * 1202d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * cmd.error indicates a problem with the r/w command. No 1203d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * data will have been transferred. 1204d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * 1205d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * stop.error indicates a problem with the stop command. Data 1206d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * may have been transferred, or may still be transferring. 1207d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin */ 120867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (brq->sbc.error || brq->cmd.error || brq->stop.error || 120967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter brq->data.error) { 1210c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake switch (mmc_blk_cmd_recovery(card, req, brq, &ecc_err, &gen_err)) { 1211d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin case ERR_RETRY: 1212d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin return MMC_BLK_RETRY; 1213d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin case ERR_ABORT: 1214d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin return MMC_BLK_ABORT; 1215a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma case ERR_NOMEDIUM: 1216a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma return MMC_BLK_NOMEDIUM; 1217d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin case ERR_CONTINUE: 1218d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin break; 1219d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin } 1220d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin } 1221d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin 1222d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin /* 1223d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * Check for errors relating to the execution of the 1224d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * initial command - such as address errors. No data 1225d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * has been transferred. 1226d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin */ 1227d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin if (brq->cmd.resp[0] & CMD_ERRORS) { 1228d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin pr_err("%s: r/w command failed, status = %#x\n", 1229d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin req->rq_disk->disk_name, brq->cmd.resp[0]); 1230d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin return MMC_BLK_ABORT; 1231d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin } 1232d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin 1233d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin /* 1234d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * Everything else is either success, or a data error of some 1235d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * kind. If it was a write, we may have transitioned to 1236d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * program mode, which we have to wait for it to complete. 1237d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin */ 1238d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) { 1239c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson int err; 12408fee476b219d1869762d9ef5c189a0c85e919a4dTrey Ramsay 1241c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake /* Check stop command response */ 1242c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake if (brq->stop.resp[0] & R1_ERROR) { 1243c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake pr_err("%s: %s: general error sending stop command, stop cmd response %#x\n", 1244c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake req->rq_disk->disk_name, __func__, 1245c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake brq->stop.resp[0]); 1246c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake gen_err = 1; 1247c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake } 1248c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake 124995a91298fc09db0c21193ace96d1934598dd92ddUlf Hansson err = card_busy_detect(card, MMC_BLK_TIMEOUT_MS, false, req, 125095a91298fc09db0c21193ace96d1934598dd92ddUlf Hansson &gen_err); 1251c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson if (err) 1252c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson return MMC_BLK_CMD_ERR; 1253d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin } 1254d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin 1255c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake /* if general error occurs, retry the write operation. */ 1256c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake if (gen_err) { 1257c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake pr_warn("%s: retrying write for general error\n", 1258c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake req->rq_disk->disk_name); 1259c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake return MMC_BLK_RETRY; 1260c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake } 1261c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake 1262d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin if (brq->data.error) { 1263d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin pr_err("%s: error %d transferring data, sector %u, nr %u, cmd response %#x, card status %#x\n", 1264d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin req->rq_disk->disk_name, brq->data.error, 1265d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin (unsigned)blk_rq_pos(req), 1266d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin (unsigned)blk_rq_sectors(req), 1267d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin brq->cmd.resp[0], brq->stop.resp[0]); 1268d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin 1269d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin if (rq_data_dir(req) == READ) { 127067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (ecc_err) 127167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter return MMC_BLK_ECC_ERR; 1272d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin return MMC_BLK_DATA_ERR; 1273d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin } else { 1274d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin return MMC_BLK_CMD_ERR; 1275d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin } 1276d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin } 1277d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin 127867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (!brq->data.bytes_xfered) 127967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter return MMC_BLK_RETRY; 1280d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin 1281ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon if (mmc_packed_cmd(mq_mrq->cmd_type)) { 1282ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon if (unlikely(brq->data.blocks << 9 != brq->data.bytes_xfered)) 1283ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon return MMC_BLK_PARTIAL; 1284ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon else 1285ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon return MMC_BLK_SUCCESS; 1286ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon } 1287ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 128867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (blk_rq_bytes(req) != brq->data.bytes_xfered) 128967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter return MMC_BLK_PARTIAL; 129067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter 129167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter return MMC_BLK_SUCCESS; 1292d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin} 1293d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin 1294ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeonstatic int mmc_blk_packed_err_check(struct mmc_card *card, 1295ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon struct mmc_async_req *areq) 1296ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon{ 1297ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon struct mmc_queue_req *mq_rq = container_of(areq, struct mmc_queue_req, 1298ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon mmc_active); 1299ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon struct request *req = mq_rq->req; 1300ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon struct mmc_packed *packed = mq_rq->packed; 1301ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon int err, check, status; 1302ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon u8 *ext_csd; 1303ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1304ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon BUG_ON(!packed); 1305ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1306ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon packed->retries--; 1307ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon check = mmc_blk_err_check(card, areq); 1308ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon err = get_card_status(card, &status, 0); 1309ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon if (err) { 1310ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon pr_err("%s: error %d sending status command\n", 1311ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon req->rq_disk->disk_name, err); 1312ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon return MMC_BLK_ABORT; 1313ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon } 1314ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1315ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon if (status & R1_EXCEPTION_EVENT) { 1316ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon ext_csd = kzalloc(512, GFP_KERNEL); 1317ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon if (!ext_csd) { 1318ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon pr_err("%s: unable to allocate buffer for ext_csd\n", 1319ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon req->rq_disk->disk_name); 1320ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon return -ENOMEM; 1321ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon } 1322ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1323ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon err = mmc_send_ext_csd(card, ext_csd); 1324ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon if (err) { 1325ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon pr_err("%s: error %d sending ext_csd\n", 1326ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon req->rq_disk->disk_name, err); 1327ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon check = MMC_BLK_ABORT; 1328ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon goto free; 1329ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon } 1330ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1331ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon if ((ext_csd[EXT_CSD_EXP_EVENTS_STATUS] & 1332ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon EXT_CSD_PACKED_FAILURE) && 1333ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon (ext_csd[EXT_CSD_PACKED_CMD_STATUS] & 1334ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon EXT_CSD_PACKED_GENERIC_ERROR)) { 1335ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon if (ext_csd[EXT_CSD_PACKED_CMD_STATUS] & 1336ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon EXT_CSD_PACKED_INDEXED_ERROR) { 1337ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon packed->idx_failure = 1338ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon ext_csd[EXT_CSD_PACKED_FAILURE_INDEX] - 1; 1339ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon check = MMC_BLK_PARTIAL; 1340ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon } 1341ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon pr_err("%s: packed cmd failed, nr %u, sectors %u, " 1342ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon "failure index: %d\n", 1343ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon req->rq_disk->disk_name, packed->nr_entries, 1344ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon packed->blocks, packed->idx_failure); 1345ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon } 1346ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeonfree: 1347ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon kfree(ext_csd); 1348ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon } 1349ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1350ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon return check; 1351ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon} 1352ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 135354d49d77628bed77e5491b8a2a1158a492843a19Per Forlinstatic void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, 135454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin struct mmc_card *card, 135554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin int disable_multi, 135654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin struct mmc_queue *mq) 13571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 135854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin u32 readcmd, writecmd; 135954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin struct mmc_blk_request *brq = &mqrq->brq; 136054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin struct request *req = mqrq->req; 13611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_blk_data *md = mq->data; 13624265900e0be653f5b78baf2816857ef57cf1332fSaugata Das bool do_data_tag; 13631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1364f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin /* 1365f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin * Reliable writes are used to implement Forced Unit Access and 1366f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin * REQ_META accesses, and are supported only on MMCs. 136765299a3b788bd274bed92f9fa3232082c9f3ea70Christoph Hellwig * 136865299a3b788bd274bed92f9fa3232082c9f3ea70Christoph Hellwig * XXX: this really needs a good explanation of why REQ_META 136965299a3b788bd274bed92f9fa3232082c9f3ea70Christoph Hellwig * is treated special. 1370f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin */ 1371f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin bool do_rel_wr = ((req->cmd_flags & REQ_FUA) || 1372f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin (req->cmd_flags & REQ_META)) && 1373f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin (rq_data_dir(req) == WRITE) && 1374d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin (md->flags & MMC_BLK_REL_WR); 1375f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin 137654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin memset(brq, 0, sizeof(struct mmc_blk_request)); 137754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->mrq.cmd = &brq->cmd; 137854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->mrq.data = &brq->data; 13791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 138054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->cmd.arg = blk_rq_pos(req); 138154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin if (!mmc_card_blockaddr(card)) 138254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->cmd.arg <<= 9; 138354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; 138454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->data.blksz = 512; 138554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->stop.opcode = MMC_STOP_TRANSMISSION; 138654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->stop.arg = 0; 138754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->data.blocks = blk_rq_sectors(req); 13886a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter 138954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin /* 139054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * The block layer doesn't support all sector count 139154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * restrictions, so we need to be prepared for too big 139254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * requests. 139354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin */ 139454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin if (brq->data.blocks > card->host->max_blk_count) 139554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->data.blocks = card->host->max_blk_count; 13961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13972bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley if (brq->data.blocks > 1) { 13982bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley /* 13992bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley * After a read error, we redo the request one sector 14002bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley * at a time in order to accurately determine which 14012bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley * sectors can be read successfully. 14022bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley */ 14032bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley if (disable_multi) 14042bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley brq->data.blocks = 1; 14052bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley 14062e47e84245adcb1b3872210678b6146f674fb3ffKuninori Morimoto /* 14072e47e84245adcb1b3872210678b6146f674fb3ffKuninori Morimoto * Some controllers have HW issues while operating 14082e47e84245adcb1b3872210678b6146f674fb3ffKuninori Morimoto * in multiple I/O mode 14092e47e84245adcb1b3872210678b6146f674fb3ffKuninori Morimoto */ 14102e47e84245adcb1b3872210678b6146f674fb3ffKuninori Morimoto if (card->host->ops->multi_io_quirk) 14112e47e84245adcb1b3872210678b6146f674fb3ffKuninori Morimoto brq->data.blocks = card->host->ops->multi_io_quirk(card, 14122e47e84245adcb1b3872210678b6146f674fb3ffKuninori Morimoto (rq_data_dir(req) == READ) ? 14132e47e84245adcb1b3872210678b6146f674fb3ffKuninori Morimoto MMC_DATA_READ : MMC_DATA_WRITE, 14142e47e84245adcb1b3872210678b6146f674fb3ffKuninori Morimoto brq->data.blocks); 14152bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley } 1416d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin 141754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin if (brq->data.blocks > 1 || do_rel_wr) { 141854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin /* SPI multiblock writes terminate using a special 141954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * token, not a STOP_TRANSMISSION request. 1420d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin */ 142154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin if (!mmc_host_is_spi(card->host) || 142254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin rq_data_dir(req) == READ) 142354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->mrq.stop = &brq->stop; 142454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin readcmd = MMC_READ_MULTIPLE_BLOCK; 142554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin writecmd = MMC_WRITE_MULTIPLE_BLOCK; 142654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin } else { 142754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->mrq.stop = NULL; 142854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin readcmd = MMC_READ_SINGLE_BLOCK; 142954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin writecmd = MMC_WRITE_BLOCK; 143054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin } 143154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin if (rq_data_dir(req) == READ) { 143254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->cmd.opcode = readcmd; 143354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->data.flags |= MMC_DATA_READ; 1434bcc3e1726d827c2d6f62f0e0e7bbc99eed7ad925Ulf Hansson if (brq->mrq.stop) 1435bcc3e1726d827c2d6f62f0e0e7bbc99eed7ad925Ulf Hansson brq->stop.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | 1436bcc3e1726d827c2d6f62f0e0e7bbc99eed7ad925Ulf Hansson MMC_CMD_AC; 143754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin } else { 143854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->cmd.opcode = writecmd; 143954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->data.flags |= MMC_DATA_WRITE; 1440bcc3e1726d827c2d6f62f0e0e7bbc99eed7ad925Ulf Hansson if (brq->mrq.stop) 1441bcc3e1726d827c2d6f62f0e0e7bbc99eed7ad925Ulf Hansson brq->stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | 1442bcc3e1726d827c2d6f62f0e0e7bbc99eed7ad925Ulf Hansson MMC_CMD_AC; 144354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin } 1444d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin 144554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin if (do_rel_wr) 144654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin mmc_apply_rel_rw(brq, card, req); 1447f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin 144854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin /* 14494265900e0be653f5b78baf2816857ef57cf1332fSaugata Das * Data tag is used only during writing meta data to speed 14504265900e0be653f5b78baf2816857ef57cf1332fSaugata Das * up write and any subsequent read of this meta data 14514265900e0be653f5b78baf2816857ef57cf1332fSaugata Das */ 14524265900e0be653f5b78baf2816857ef57cf1332fSaugata Das do_data_tag = (card->ext_csd.data_tag_unit_size) && 14534265900e0be653f5b78baf2816857ef57cf1332fSaugata Das (req->cmd_flags & REQ_META) && 14544265900e0be653f5b78baf2816857ef57cf1332fSaugata Das (rq_data_dir(req) == WRITE) && 14554265900e0be653f5b78baf2816857ef57cf1332fSaugata Das ((brq->data.blocks * brq->data.blksz) >= 14564265900e0be653f5b78baf2816857ef57cf1332fSaugata Das card->ext_csd.data_tag_unit_size); 14574265900e0be653f5b78baf2816857ef57cf1332fSaugata Das 14584265900e0be653f5b78baf2816857ef57cf1332fSaugata Das /* 145954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * Pre-defined multi-block transfers are preferable to 146054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * open ended-ones (and necessary for reliable writes). 146154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * However, it is not sufficient to just send CMD23, 146254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * and avoid the final CMD12, as on an error condition 146354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * CMD12 (stop) needs to be sent anyway. This, coupled 146454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * with Auto-CMD23 enhancements provided by some 146554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * hosts, means that the complexity of dealing 146654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * with this is best left to the host. If CMD23 is 146754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * supported by card and host, we'll fill sbc in and let 146854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * the host deal with handling it correctly. This means 146954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * that for hosts that don't expose MMC_CAP_CMD23, no 147054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * change of behavior will be observed. 147154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * 147254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * N.B: Some MMC cards experience perf degradation. 147354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * We'll avoid using CMD23-bounded multiblock writes for 147454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * these, while retaining features like reliable writes. 147554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin */ 14764265900e0be653f5b78baf2816857ef57cf1332fSaugata Das if ((md->flags & MMC_BLK_CMD23) && mmc_op_multi(brq->cmd.opcode) && 14774265900e0be653f5b78baf2816857ef57cf1332fSaugata Das (do_rel_wr || !(card->quirks & MMC_QUIRK_BLK_NO_CMD23) || 14784265900e0be653f5b78baf2816857ef57cf1332fSaugata Das do_data_tag)) { 147954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->sbc.opcode = MMC_SET_BLOCK_COUNT; 148054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->sbc.arg = brq->data.blocks | 14814265900e0be653f5b78baf2816857ef57cf1332fSaugata Das (do_rel_wr ? (1 << 31) : 0) | 14824265900e0be653f5b78baf2816857ef57cf1332fSaugata Das (do_data_tag ? (1 << 29) : 0); 148354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->sbc.flags = MMC_RSP_R1 | MMC_CMD_AC; 148454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->mrq.sbc = &brq->sbc; 148554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin } 148698ccf14909ba02a41c5925b0b2c92aeeef23d3b9Pierre Ossman 148754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin mmc_set_data_timeout(&brq->data, card); 148854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin 148954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->data.sg = mqrq->sg; 149054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->data.sg_len = mmc_queue_map_sg(mq, mqrq); 149154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin 149254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin /* 149354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * Adjust the sg list so it is the same size as the 149454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin * request. 149554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin */ 149654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin if (brq->data.blocks != blk_rq_sectors(req)) { 149754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin int i, data_size = brq->data.blocks << 9; 149854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin struct scatterlist *sg; 149954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin 150054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin for_each_sg(brq->data.sg, sg, brq->data.sg_len, i) { 150154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin data_size -= sg->length; 150254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin if (data_size <= 0) { 150354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin sg->length += data_size; 150454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin i++; 150554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin break; 15066a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter } 15076a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter } 150854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin brq->data.sg_len = i; 150954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin } 151054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin 1511ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin mqrq->mmc_active.mrq = &brq->mrq; 1512ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin mqrq->mmc_active.err_check = mmc_blk_err_check; 1513ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin 151454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin mmc_queue_bounce_pre(mqrq); 151554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin} 15166a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter 1517ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeonstatic inline u8 mmc_calc_packed_hdr_segs(struct request_queue *q, 1518ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon struct mmc_card *card) 1519ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon{ 1520ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon unsigned int hdr_sz = mmc_large_sector(card) ? 4096 : 512; 1521ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon unsigned int max_seg_sz = queue_max_segment_size(q); 1522ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon unsigned int len, nr_segs = 0; 1523ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1524ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon do { 1525ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon len = min(hdr_sz, max_seg_sz); 1526ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon hdr_sz -= len; 1527ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon nr_segs++; 1528ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon } while (hdr_sz); 1529ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1530ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon return nr_segs; 1531ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon} 1532ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1533ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeonstatic u8 mmc_blk_prep_packed_list(struct mmc_queue *mq, struct request *req) 1534ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon{ 1535ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon struct request_queue *q = mq->queue; 1536ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon struct mmc_card *card = mq->card; 1537ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon struct request *cur = req, *next = NULL; 1538ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon struct mmc_blk_data *md = mq->data; 1539ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon struct mmc_queue_req *mqrq = mq->mqrq_cur; 1540ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon bool en_rel_wr = card->ext_csd.rel_param & EXT_CSD_WR_REL_PARAM_EN; 1541ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon unsigned int req_sectors = 0, phys_segments = 0; 1542ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon unsigned int max_blk_count, max_phys_segs; 1543ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon bool put_back = true; 1544ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon u8 max_packed_rw = 0; 1545ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon u8 reqs = 0; 1546ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1547ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon if (!(md->flags & MMC_BLK_PACKED_CMD)) 1548ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon goto no_packed; 1549ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1550ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon if ((rq_data_dir(cur) == WRITE) && 1551ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon mmc_host_packed_wr(card->host)) 1552ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon max_packed_rw = card->ext_csd.max_packed_writes; 1553ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1554ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon if (max_packed_rw == 0) 1555ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon goto no_packed; 1556ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1557ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon if (mmc_req_rel_wr(cur) && 1558ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon (md->flags & MMC_BLK_REL_WR) && !en_rel_wr) 1559ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon goto no_packed; 1560ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1561ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon if (mmc_large_sector(card) && 1562ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon !IS_ALIGNED(blk_rq_sectors(cur), 8)) 1563ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon goto no_packed; 1564ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1565ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon mmc_blk_clear_packed(mqrq); 1566ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1567ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon max_blk_count = min(card->host->max_blk_count, 1568ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon card->host->max_req_size >> 9); 1569ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon if (unlikely(max_blk_count > 0xffff)) 1570ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon max_blk_count = 0xffff; 1571ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1572ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon max_phys_segs = queue_max_segments(q); 1573ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon req_sectors += blk_rq_sectors(cur); 1574ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon phys_segments += cur->nr_phys_segments; 1575ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1576ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon if (rq_data_dir(cur) == WRITE) { 1577ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon req_sectors += mmc_large_sector(card) ? 8 : 1; 1578ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon phys_segments += mmc_calc_packed_hdr_segs(q, card); 1579ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon } 1580ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1581ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon do { 1582ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon if (reqs >= max_packed_rw - 1) { 1583ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon put_back = false; 1584ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon break; 1585ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon } 1586ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1587ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon spin_lock_irq(q->queue_lock); 1588ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon next = blk_fetch_request(q); 1589ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon spin_unlock_irq(q->queue_lock); 1590ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon if (!next) { 1591ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon put_back = false; 1592ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon break; 1593ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon } 1594ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1595ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon if (mmc_large_sector(card) && 1596ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon !IS_ALIGNED(blk_rq_sectors(next), 8)) 1597ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon break; 1598ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1599ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon if (next->cmd_flags & REQ_DISCARD || 1600ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon next->cmd_flags & REQ_FLUSH) 1601ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon break; 1602ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1603ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon if (rq_data_dir(cur) != rq_data_dir(next)) 1604ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon break; 1605ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1606ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon if (mmc_req_rel_wr(next) && 1607ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon (md->flags & MMC_BLK_REL_WR) && !en_rel_wr) 1608ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon break; 1609ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1610ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon req_sectors += blk_rq_sectors(next); 1611ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon if (req_sectors > max_blk_count) 1612ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon break; 1613ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1614ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon phys_segments += next->nr_phys_segments; 1615ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon if (phys_segments > max_phys_segs) 1616ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon break; 1617ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1618ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon list_add_tail(&next->queuelist, &mqrq->packed->list); 1619ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon cur = next; 1620ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon reqs++; 1621ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon } while (1); 1622ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1623ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon if (put_back) { 1624ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon spin_lock_irq(q->queue_lock); 1625ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon blk_requeue_request(q, next); 1626ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon spin_unlock_irq(q->queue_lock); 1627ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon } 1628ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1629ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon if (reqs > 0) { 1630ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon list_add(&req->queuelist, &mqrq->packed->list); 1631ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon mqrq->packed->nr_entries = ++reqs; 1632ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon mqrq->packed->retries = reqs; 1633ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon return reqs; 1634ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon } 1635ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1636ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeonno_packed: 1637ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon mqrq->cmd_type = MMC_PACKED_NONE; 1638ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon return 0; 1639ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon} 1640ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1641ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeonstatic void mmc_blk_packed_hdr_wrq_prep(struct mmc_queue_req *mqrq, 1642ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon struct mmc_card *card, 1643ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon struct mmc_queue *mq) 1644ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon{ 1645ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon struct mmc_blk_request *brq = &mqrq->brq; 1646ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon struct request *req = mqrq->req; 1647ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon struct request *prq; 1648ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon struct mmc_blk_data *md = mq->data; 1649ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon struct mmc_packed *packed = mqrq->packed; 1650ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon bool do_rel_wr, do_data_tag; 1651ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon u32 *packed_cmd_hdr; 1652ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon u8 hdr_blocks; 1653ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon u8 i = 1; 1654ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1655ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon BUG_ON(!packed); 1656ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1657ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon mqrq->cmd_type = MMC_PACKED_WRITE; 1658ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon packed->blocks = 0; 1659ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon packed->idx_failure = MMC_PACKED_NR_IDX; 1660ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1661ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon packed_cmd_hdr = packed->cmd_hdr; 1662ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon memset(packed_cmd_hdr, 0, sizeof(packed->cmd_hdr)); 1663ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon packed_cmd_hdr[0] = (packed->nr_entries << 16) | 1664ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon (PACKED_CMD_WR << 8) | PACKED_CMD_VER; 1665ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon hdr_blocks = mmc_large_sector(card) ? 8 : 1; 1666ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1667ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon /* 1668ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon * Argument for each entry of packed group 1669ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon */ 1670ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon list_for_each_entry(prq, &packed->list, queuelist) { 1671ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon do_rel_wr = mmc_req_rel_wr(prq) && (md->flags & MMC_BLK_REL_WR); 1672ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon do_data_tag = (card->ext_csd.data_tag_unit_size) && 1673ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon (prq->cmd_flags & REQ_META) && 1674ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon (rq_data_dir(prq) == WRITE) && 1675ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon ((brq->data.blocks * brq->data.blksz) >= 1676ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon card->ext_csd.data_tag_unit_size); 1677ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon /* Argument of CMD23 */ 1678ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon packed_cmd_hdr[(i * 2)] = 1679ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon (do_rel_wr ? MMC_CMD23_ARG_REL_WR : 0) | 1680ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon (do_data_tag ? MMC_CMD23_ARG_TAG_REQ : 0) | 1681ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon blk_rq_sectors(prq); 1682ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon /* Argument of CMD18 or CMD25 */ 1683ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon packed_cmd_hdr[((i * 2)) + 1] = 1684ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon mmc_card_blockaddr(card) ? 1685ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon blk_rq_pos(prq) : blk_rq_pos(prq) << 9; 1686ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon packed->blocks += blk_rq_sectors(prq); 1687ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon i++; 1688ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon } 1689ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1690ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon memset(brq, 0, sizeof(struct mmc_blk_request)); 1691ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon brq->mrq.cmd = &brq->cmd; 1692ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon brq->mrq.data = &brq->data; 1693ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon brq->mrq.sbc = &brq->sbc; 1694ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon brq->mrq.stop = &brq->stop; 1695ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1696ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon brq->sbc.opcode = MMC_SET_BLOCK_COUNT; 1697ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon brq->sbc.arg = MMC_CMD23_ARG_PACKED | (packed->blocks + hdr_blocks); 1698ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon brq->sbc.flags = MMC_RSP_R1 | MMC_CMD_AC; 1699ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1700ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon brq->cmd.opcode = MMC_WRITE_MULTIPLE_BLOCK; 1701ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon brq->cmd.arg = blk_rq_pos(req); 1702ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon if (!mmc_card_blockaddr(card)) 1703ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon brq->cmd.arg <<= 9; 1704ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon brq->cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; 1705ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1706ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon brq->data.blksz = 512; 1707ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon brq->data.blocks = packed->blocks + hdr_blocks; 1708ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon brq->data.flags |= MMC_DATA_WRITE; 1709ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1710ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon brq->stop.opcode = MMC_STOP_TRANSMISSION; 1711ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon brq->stop.arg = 0; 1712ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon brq->stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; 1713ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1714ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon mmc_set_data_timeout(&brq->data, card); 1715ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1716ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon brq->data.sg = mqrq->sg; 1717ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon brq->data.sg_len = mmc_queue_map_sg(mq, mqrq); 1718ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1719ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon mqrq->mmc_active.mrq = &brq->mrq; 1720ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon mqrq->mmc_active.err_check = mmc_blk_packed_err_check; 1721ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1722ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon mmc_queue_bounce_pre(mqrq); 1723ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon} 1724ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 172567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunterstatic int mmc_blk_cmd_err(struct mmc_blk_data *md, struct mmc_card *card, 172667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter struct mmc_blk_request *brq, struct request *req, 172767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter int ret) 172867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter{ 1729ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon struct mmc_queue_req *mq_rq; 1730ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon mq_rq = container_of(brq, struct mmc_queue_req, brq); 1731ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 173267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter /* 173367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter * If this is an SD card and we're writing, we can first 173467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter * mark the known good sectors as ok. 173567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter * 173667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter * If the card is not SD, we can still ok written sectors 173767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter * as reported by the controller (which might be less than 173867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter * the real number of written sectors, but never more). 173967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter */ 174067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (mmc_card_sd(card)) { 174167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter u32 blocks; 174267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter 174367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter blocks = mmc_sd_num_wr_blocks(card); 174467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (blocks != (u32)-1) { 1745ecf8b5d0a378a0f922ffca27bd0a9101f246fa11Subhash Jadavani ret = blk_end_request(req, 0, blocks << 9); 174667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter } 174767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter } else { 1748ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon if (!mmc_packed_cmd(mq_rq->cmd_type)) 1749ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon ret = blk_end_request(req, 0, brq->data.bytes_xfered); 175067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter } 175167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter return ret; 175267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter} 175367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter 1754ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeonstatic int mmc_blk_end_packed_req(struct mmc_queue_req *mq_rq) 1755ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon{ 1756ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon struct request *prq; 1757ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon struct mmc_packed *packed = mq_rq->packed; 1758ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon int idx = packed->idx_failure, i = 0; 1759ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon int ret = 0; 1760ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1761ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon BUG_ON(!packed); 1762ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1763ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon while (!list_empty(&packed->list)) { 1764ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon prq = list_entry_rq(packed->list.next); 1765ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon if (idx == i) { 1766ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon /* retry from error index */ 1767ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon packed->nr_entries -= idx; 1768ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon mq_rq->req = prq; 1769ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon ret = 1; 1770ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1771ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon if (packed->nr_entries == MMC_PACKED_NR_SINGLE) { 1772ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon list_del_init(&prq->queuelist); 1773ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon mmc_blk_clear_packed(mq_rq); 1774ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon } 1775ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon return ret; 1776ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon } 1777ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon list_del_init(&prq->queuelist); 1778ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon blk_end_request(prq, 0, blk_rq_bytes(prq)); 1779ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon i++; 1780ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon } 1781ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1782ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon mmc_blk_clear_packed(mq_rq); 1783ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon return ret; 1784ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon} 1785ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1786ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeonstatic void mmc_blk_abort_packed_req(struct mmc_queue_req *mq_rq) 1787ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon{ 1788ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon struct request *prq; 1789ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon struct mmc_packed *packed = mq_rq->packed; 1790ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1791ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon BUG_ON(!packed); 1792ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1793ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon while (!list_empty(&packed->list)) { 1794ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon prq = list_entry_rq(packed->list.next); 1795ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon list_del_init(&prq->queuelist); 1796ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon blk_end_request(prq, -EIO, blk_rq_bytes(prq)); 1797ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon } 1798ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1799ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon mmc_blk_clear_packed(mq_rq); 1800ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon} 1801ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1802ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeonstatic void mmc_blk_revert_packed_req(struct mmc_queue *mq, 1803ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon struct mmc_queue_req *mq_rq) 1804ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon{ 1805ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon struct request *prq; 1806ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon struct request_queue *q = mq->queue; 1807ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon struct mmc_packed *packed = mq_rq->packed; 1808ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1809ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon BUG_ON(!packed); 1810ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1811ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon while (!list_empty(&packed->list)) { 1812ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon prq = list_entry_rq(packed->list.prev); 1813ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon if (prq->queuelist.prev != &packed->list) { 1814ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon list_del_init(&prq->queuelist); 1815ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon spin_lock_irq(q->queue_lock); 1816ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon blk_requeue_request(mq->queue, prq); 1817ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon spin_unlock_irq(q->queue_lock); 1818ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon } else { 1819ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon list_del_init(&prq->queuelist); 1820ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon } 1821ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon } 1822ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1823ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon mmc_blk_clear_packed(mq_rq); 1824ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon} 1825ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1826ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlinstatic int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc) 182754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin{ 182854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin struct mmc_blk_data *md = mq->data; 182954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin struct mmc_card *card = md->queue.card; 183054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin struct mmc_blk_request *brq = &mq->mqrq_cur->brq; 183167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter int ret = 1, disable_multi = 0, retry = 0, type; 1832d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin enum mmc_blk_status status; 1833ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin struct mmc_queue_req *mq_rq; 1834a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das struct request *req = rqc; 1835ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin struct mmc_async_req *areq; 1836ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon const u8 packed_nr = 2; 1837ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon u8 reqs = 0; 18381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1839ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin if (!rqc && !mq->mqrq_prev->req) 1840ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin return 0; 184198ccf14909ba02a41c5925b0b2c92aeeef23d3b9Pierre Ossman 1842ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon if (rqc) 1843ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon reqs = mmc_blk_prep_packed_list(mq, rqc); 1844ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1845ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin do { 1846ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin if (rqc) { 1847a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das /* 1848a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das * When 4KB native sector is enabled, only 8 blocks 1849a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das * multiple read or write is allowed 1850a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das */ 1851a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das if ((brq->data.blocks & 0x07) && 1852a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das (card->ext_csd.data_sector_size == 4096)) { 1853a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das pr_err("%s: Transfer size is not 4KB sector size aligned\n", 1854a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das req->rq_disk->disk_name); 1855ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon mq_rq = mq->mqrq_cur; 1856a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das goto cmd_abort; 1857a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das } 1858ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1859ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon if (reqs >= packed_nr) 1860ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon mmc_blk_packed_hdr_wrq_prep(mq->mqrq_cur, 1861ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon card, mq); 1862ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon else 1863ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon mmc_blk_rw_rq_prep(mq->mqrq_cur, card, 0, mq); 1864ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin areq = &mq->mqrq_cur->mmc_active; 1865ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin } else 1866ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin areq = NULL; 1867ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin areq = mmc_start_req(card->host, areq, (int *) &status); 18682220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman if (!areq) { 18692220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman if (status == MMC_BLK_NEW_REQUEST) 18702220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman mq->flags |= MMC_QUEUE_NEW_REQUEST; 1871ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin return 0; 18722220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman } 1873ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin 1874ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin mq_rq = container_of(areq, struct mmc_queue_req, mmc_active); 1875ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin brq = &mq_rq->brq; 1876ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin req = mq_rq->req; 187767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter type = rq_data_dir(req) == READ ? MMC_BLK_READ : MMC_BLK_WRITE; 1878ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin mmc_queue_bounce_post(mq_rq); 187998ccf14909ba02a41c5925b0b2c92aeeef23d3b9Pierre Ossman 1880d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin switch (status) { 1881d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin case MMC_BLK_SUCCESS: 1882d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin case MMC_BLK_PARTIAL: 1883d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin /* 1884d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * A block was successfully transferred. 1885d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin */ 188667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter mmc_blk_reset_success(md, type); 1887ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1888ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon if (mmc_packed_cmd(mq_rq->cmd_type)) { 1889ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon ret = mmc_blk_end_packed_req(mq_rq); 1890ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon break; 1891ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon } else { 1892ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon ret = blk_end_request(req, 0, 1893d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin brq->data.bytes_xfered); 1894ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon } 1895ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 189667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter /* 189767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter * If the blk_end_request function returns non-zero even 189867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter * though all data has been transferred and no errors 189967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter * were returned by the host controller, it's a bug. 190067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter */ 1901ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin if (status == MMC_BLK_SUCCESS && ret) { 1902a3c76eb9d4a1e68a69dd880cf0bcb8a52418b993Girish K S pr_err("%s BUG rq_tot %d d_xfer %d\n", 1903ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin __func__, blk_rq_bytes(req), 1904ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin brq->data.bytes_xfered); 1905ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin rqc = NULL; 1906ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin goto cmd_abort; 1907ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin } 1908d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin break; 1909d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin case MMC_BLK_CMD_ERR: 191067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter ret = mmc_blk_cmd_err(md, card, brq, req, ret); 191167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (!mmc_blk_reset(md, card->host, type)) 191267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter break; 191367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter goto cmd_abort; 1914d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin case MMC_BLK_RETRY: 1915d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin if (retry++ < 5) 1916a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux break; 191767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter /* Fall through */ 1918d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin case MMC_BLK_ABORT: 191967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (!mmc_blk_reset(md, card->host, type)) 192067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter break; 19214c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux goto cmd_abort; 192267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter case MMC_BLK_DATA_ERR: { 192367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter int err; 192467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter 192567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter err = mmc_blk_reset(md, card->host, type); 192667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (!err) 192767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter break; 1928ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon if (err == -ENODEV || 1929ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon mmc_packed_cmd(mq_rq->cmd_type)) 193067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter goto cmd_abort; 193167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter /* Fall through */ 193267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter } 193367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter case MMC_BLK_ECC_ERR: 193467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter if (brq->data.blocks > 1) { 193567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter /* Redo read one sector at a time */ 19366606110d89aefcb21b9e70adfe064987cbd8393aJoe Perches pr_warn("%s: retrying using single block read\n", 19376606110d89aefcb21b9e70adfe064987cbd8393aJoe Perches req->rq_disk->disk_name); 193867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter disable_multi = 1; 193967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter break; 194067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter } 1941d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin /* 1942d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * After an error, we redo I/O one sector at a 1943d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * time, so we only reach here after trying to 1944d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin * read a single sector. 1945d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin */ 1946ecf8b5d0a378a0f922ffca27bd0a9101f246fa11Subhash Jadavani ret = blk_end_request(req, -EIO, 1947d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin brq->data.blksz); 1948ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin if (!ret) 1949ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin goto start_new_req; 1950d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin break; 1951a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma case MMC_BLK_NOMEDIUM: 1952a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma goto cmd_abort; 19532220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman default: 19542220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman pr_err("%s: Unhandled return value (%d)", 19552220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman req->rq_disk->disk_name, status); 19562220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman goto cmd_abort; 19574c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux } 19584c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux 1959ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin if (ret) { 1960ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon if (mmc_packed_cmd(mq_rq->cmd_type)) { 1961ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon if (!mq_rq->packed->retries) 1962ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon goto cmd_abort; 1963ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon mmc_blk_packed_hdr_wrq_prep(mq_rq, card, mq); 1964ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon mmc_start_req(card->host, 1965ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon &mq_rq->mmc_active, NULL); 1966ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon } else { 1967ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 1968ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon /* 1969ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon * In case of a incomplete request 1970ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon * prepare it again and resend. 1971ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon */ 1972ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon mmc_blk_rw_rq_prep(mq_rq, card, 1973ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon disable_multi, mq); 1974ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon mmc_start_req(card->host, 1975ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon &mq_rq->mmc_active, NULL); 1976ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon } 1977ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin } 19781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } while (ret); 19791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 19811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1982a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux cmd_abort: 1983ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon if (mmc_packed_cmd(mq_rq->cmd_type)) { 1984ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon mmc_blk_abort_packed_req(mq_rq); 1985ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon } else { 1986ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon if (mmc_card_removed(card)) 1987ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon req->cmd_flags |= REQ_QUIET; 1988ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon while (ret) 1989ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon ret = blk_end_request(req, -EIO, 1990ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon blk_rq_cur_bytes(req)); 1991ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon } 19921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1993ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin start_new_req: 1994ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin if (rqc) { 19957a81902fa52f2b6f5037e167f74ebb5a41cfc7d1Seungwon Jeon if (mmc_card_removed(card)) { 19967a81902fa52f2b6f5037e167f74ebb5a41cfc7d1Seungwon Jeon rqc->cmd_flags |= REQ_QUIET; 19977a81902fa52f2b6f5037e167f74ebb5a41cfc7d1Seungwon Jeon blk_end_request_all(rqc, -EIO); 19987a81902fa52f2b6f5037e167f74ebb5a41cfc7d1Seungwon Jeon } else { 1999ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon /* 2000ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon * If current request is packed, it needs to put back. 2001ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon */ 2002ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon if (mmc_packed_cmd(mq->mqrq_cur->cmd_type)) 2003ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon mmc_blk_revert_packed_req(mq, mq->mqrq_cur); 2004ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 20057a81902fa52f2b6f5037e167f74ebb5a41cfc7d1Seungwon Jeon mmc_blk_rw_rq_prep(mq->mqrq_cur, card, 0, mq); 20067a81902fa52f2b6f5037e167f74ebb5a41cfc7d1Seungwon Jeon mmc_start_req(card->host, 20077a81902fa52f2b6f5037e167f74ebb5a41cfc7d1Seungwon Jeon &mq->mqrq_cur->mmc_active, NULL); 20087a81902fa52f2b6f5037e167f74ebb5a41cfc7d1Seungwon Jeon } 2009ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin } 2010ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin 20111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 20121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 20131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2014bd788c9665fb7c543aac21317059375632343337Adrian Hunterstatic int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) 2015bd788c9665fb7c543aac21317059375632343337Adrian Hunter{ 20161a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin int ret; 20171a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin struct mmc_blk_data *md = mq->data; 20181a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin struct mmc_card *card = md->queue.card; 20192220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman struct mmc_host *host = card->host; 20202220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman unsigned long flags; 2021f662ae48ae67dfd42739e65750274fe8de46240aRay Jui unsigned int cmd_flags = req ? req->cmd_flags : 0; 20221a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin 20232c84417a1305da892c8a7d0bf8d0bad50d1688b8San Mehat#ifdef CONFIG_MMC_BLOCK_DEFERRED_RESUME 2024627bad809474a8a9b411bd45a71bf971069e507eArve Hjønnevåg if (mmc_bus_needs_resume(card->host)) 20252c84417a1305da892c8a7d0bf8d0bad50d1688b8San Mehat mmc_resume_bus(card->host); 20262c84417a1305da892c8a7d0bf8d0bad50d1688b8San Mehat#endif 20272c84417a1305da892c8a7d0bf8d0bad50d1688b8San Mehat 2028ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin if (req && !mq->mqrq_prev->req) 2029ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin /* claim host only for the first request */ 2030e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson mmc_get_card(card); 2031ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin 2032371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin ret = mmc_blk_part_switch(card, md); 2033371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin if (ret) { 20340d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter if (req) { 2035ecf8b5d0a378a0f922ffca27bd0a9101f246fa11Subhash Jadavani blk_end_request_all(req, -EIO); 20360d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter } 2037371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin ret = 0; 2038371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin goto out; 2039371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin } 20401a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin 20412220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman mq->flags &= ~MMC_QUEUE_NEW_REQUEST; 2042f662ae48ae67dfd42739e65750274fe8de46240aRay Jui if (cmd_flags & REQ_DISCARD) { 2043ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin /* complete ongoing async transfer before issuing discard */ 2044ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin if (card->host->areq) 2045ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin mmc_blk_issue_rw_rq(mq, NULL); 20465204d00f06ac9af4ef9c469cce7f9bbe179739b1Lukas Czerner if (req->cmd_flags & REQ_SECURE) 20471a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin ret = mmc_blk_issue_secdiscard_rq(mq, req); 20484980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter else 20491a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin ret = mmc_blk_issue_discard_rq(mq, req); 2050f662ae48ae67dfd42739e65750274fe8de46240aRay Jui } else if (cmd_flags & REQ_FLUSH) { 2051393f9a08e2ee72e42379489a5781feaf9c406d5fJaehoon Chung /* complete ongoing async transfer before issuing flush */ 2052393f9a08e2ee72e42379489a5781feaf9c406d5fJaehoon Chung if (card->host->areq) 2053393f9a08e2ee72e42379489a5781feaf9c406d5fJaehoon Chung mmc_blk_issue_rw_rq(mq, NULL); 20541a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin ret = mmc_blk_issue_flush(mq, req); 20554980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter } else { 20562220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman if (!req && host->areq) { 20572220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman spin_lock_irqsave(&host->context_info.lock, flags); 20582220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman host->context_info.is_waiting_last_req = true; 20592220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman spin_unlock_irqrestore(&host->context_info.lock, flags); 20602220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman } 20611a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin ret = mmc_blk_issue_rw_rq(mq, req); 20624980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter } 20631a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin 2064371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinout: 2065ef3a69c7a40d5350adeaed7f0f4b4dcf6362dbbdSeungwon Jeon if ((!req && !(mq->flags & MMC_QUEUE_NEW_REQUEST)) || 2066f662ae48ae67dfd42739e65750274fe8de46240aRay Jui (cmd_flags & MMC_REQ_SPECIAL_MASK)) 2067ef3a69c7a40d5350adeaed7f0f4b4dcf6362dbbdSeungwon Jeon /* 2068ef3a69c7a40d5350adeaed7f0f4b4dcf6362dbbdSeungwon Jeon * Release host when there are no more requests 2069ef3a69c7a40d5350adeaed7f0f4b4dcf6362dbbdSeungwon Jeon * and after special request(discard, flush) is done. 2070ef3a69c7a40d5350adeaed7f0f4b4dcf6362dbbdSeungwon Jeon * In case sepecial request, there is no reentry to 2071ef3a69c7a40d5350adeaed7f0f4b4dcf6362dbbdSeungwon Jeon * the 'mmc_blk_issue_rq' with 'mqrq_prev->req'. 2072ef3a69c7a40d5350adeaed7f0f4b4dcf6362dbbdSeungwon Jeon */ 2073e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson mmc_put_card(card); 20741a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin return ret; 2075bd788c9665fb7c543aac21317059375632343337Adrian Hunter} 20761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2077a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell Kingstatic inline int mmc_blk_readonly(struct mmc_card *card) 2078a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King{ 2079a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King return mmc_card_readonly(card) || 2080a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King !(card->csd.cmdclass & CCC_BLOCK_WRITE); 2081a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King} 2082a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King 2083371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card, 2084371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct device *parent, 2085371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin sector_t size, 2086371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin bool default_ro, 2087add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm const char *subname, 2088add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm int area_type) 20891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 20901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_blk_data *md; 20911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int devidx, ret; 20921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20935e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson devidx = find_first_zero_bit(dev_use, max_devices); 20945e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson if (devidx >= max_devices) 20951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ERR_PTR(-ENOSPC); 20961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __set_bit(devidx, dev_use); 20971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2098dd00cc486ab1c17049a535413d1751ef3482141cYoann Padioleau md = kzalloc(sizeof(struct mmc_blk_data), GFP_KERNEL); 2099a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King if (!md) { 2100a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King ret = -ENOMEM; 2101a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King goto out; 2102a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King } 21031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2104a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King /* 2105f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin * !subname implies we are creating main mmc_blk_data that will be 2106f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin * associated with mmc_card with mmc_set_drvdata. Due to device 2107f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin * partitions, devidx will not coincide with a per-physical card 2108f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin * index anymore so we keep track of a name index. 2109f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin */ 2110f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin if (!subname) { 2111f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin md->name_idx = find_first_zero_bit(name_use, max_devices); 2112f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin __set_bit(md->name_idx, name_use); 2113add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm } else 2114f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin md->name_idx = ((struct mmc_blk_data *) 2115f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin dev_to_disk(parent)->private_data)->name_idx; 2116f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin 2117add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm md->area_type = area_type; 2118add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm 2119f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin /* 2120a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * Set the read-only status based on the supported commands 2121a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * and the write protect switch. 2122a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King */ 2123a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King md->read_only = mmc_blk_readonly(card); 21241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21255e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson md->disk = alloc_disk(perdev_minors); 2126a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King if (md->disk == NULL) { 2127a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King ret = -ENOMEM; 2128a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King goto err_kfree; 2129a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King } 21301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2131a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King spin_lock_init(&md->lock); 2132371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin INIT_LIST_HEAD(&md->part); 2133a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King md->usage = 1; 21341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2135d09408ade08a08a710a247fb52aa50101e73ebf7Adrian Hunter ret = mmc_init_queue(&md->queue, card, &md->lock, subname); 2136a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King if (ret) 2137a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King goto err_putdisk; 21381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2139a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King md->queue.issue_fn = mmc_blk_issue_rq; 2140a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King md->queue.data = md; 2141d2b18394259ef621fd2a6322aa9934198fd87a6aRussell King 2142fe6b4c8840c5e23fe9b8696450cee8f2e8cebffdPierre Ossman md->disk->major = MMC_BLOCK_MAJOR; 21435e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson md->disk->first_minor = devidx * perdev_minors; 2144a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King md->disk->fops = &mmc_bdops; 2145a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King md->disk->private_data = md; 2146a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King md->disk->queue = md->queue.queue; 2147371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin md->disk->driverfs_dev = parent; 2148371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin set_disk_ro(md->disk, md->read_only || default_ro); 2149163a4169f98ef0867312fdf70b9389bea7831a8dColin Cross md->disk->flags = GENHD_FL_EXT_DEVT; 2150f5b4d71f72c5f08c2e1d0af68ef881f85537e7a1Ulf Hansson if (area_type & (MMC_BLK_DATA_AREA_RPMB | MMC_BLK_DATA_AREA_BOOT)) 215153d8f97462b0bbb51150f4d6bc2fd45336a008b9Loic Pallardy md->disk->flags |= GENHD_FL_NO_PART_SCAN; 2152a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King 2153a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King /* 2154a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * As discussed on lkml, GENHD_FL_REMOVABLE should: 2155a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * 2156a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * - be set for removable media with permanent block devices 2157a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * - be unset for removable block devices with permanent media 2158a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * 2159a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * Since MMC block devices clearly fall under the second 2160a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * case, we do not set GENHD_FL_REMOVABLE. Userspace 2161a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * should use the block device creation/destruction hotplug 2162a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King * messages to tell when the card is present. 2163a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King */ 2164a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King 2165f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin snprintf(md->disk->disk_name, sizeof(md->disk->disk_name), 2166f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin "mmcblk%d%s", md->name_idx, subname ? subname : ""); 2167a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King 2168a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das if (mmc_card_mmc(card)) 2169a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das blk_queue_logical_block_size(md->queue.queue, 2170a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das card->ext_csd.data_sector_size); 2171a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das else 2172a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das blk_queue_logical_block_size(md->queue.queue, 512); 2173a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das 2174371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin set_capacity(md->disk, size); 2175d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin 2176f0d89972b01798cf9d245dfa1cacfa0ee78a3593Andrei Warkentin if (mmc_host_cmd23(card->host)) { 2177f0d89972b01798cf9d245dfa1cacfa0ee78a3593Andrei Warkentin if (mmc_card_mmc(card) || 2178f0d89972b01798cf9d245dfa1cacfa0ee78a3593Andrei Warkentin (mmc_card_sd(card) && 2179f0d89972b01798cf9d245dfa1cacfa0ee78a3593Andrei Warkentin card->scr.cmds & SD_SCR_CMD23_SUPPORT)) 2180f0d89972b01798cf9d245dfa1cacfa0ee78a3593Andrei Warkentin md->flags |= MMC_BLK_CMD23; 2181f0d89972b01798cf9d245dfa1cacfa0ee78a3593Andrei Warkentin } 2182d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin 2183d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin if (mmc_card_mmc(card) && 2184d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin md->flags & MMC_BLK_CMD23 && 2185d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin ((card->ext_csd.rel_param & EXT_CSD_WR_REL_PARAM_EN) || 2186d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin card->ext_csd.rel_sectors)) { 2187d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin md->flags |= MMC_BLK_REL_WR; 2188d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin blk_queue_flush(md->queue.queue, REQ_FLUSH | REQ_FUA); 2189d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin } 2190d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin 2191ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon if (mmc_card_mmc(card) && 2192ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon (area_type == MMC_BLK_DATA_AREA_MAIN) && 2193ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon (md->flags & MMC_BLK_CMD23) && 2194ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon card->ext_csd.packed_event_en) { 2195ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon if (!mmc_packed_init(&md->queue, card)) 2196ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon md->flags |= MMC_BLK_PACKED_CMD; 2197ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon } 2198ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon 2199371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin return md; 2200371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 2201371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin err_putdisk: 2202371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin put_disk(md->disk); 2203371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin err_kfree: 2204371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin kfree(md); 2205371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin out: 2206371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin return ERR_PTR(ret); 2207371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin} 2208371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 2209371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card) 2210371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{ 2211371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin sector_t size; 2212371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct mmc_blk_data *md; 2213a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King 221485a18ad93ec66888d85758630019b10a84257f3cPierre Ossman if (!mmc_card_sd(card) && mmc_card_blockaddr(card)) { 221585a18ad93ec66888d85758630019b10a84257f3cPierre Ossman /* 221685a18ad93ec66888d85758630019b10a84257f3cPierre Ossman * The EXT_CSD sector count is in number or 512 byte 221785a18ad93ec66888d85758630019b10a84257f3cPierre Ossman * sectors. 221885a18ad93ec66888d85758630019b10a84257f3cPierre Ossman */ 2219371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin size = card->ext_csd.sectors; 222085a18ad93ec66888d85758630019b10a84257f3cPierre Ossman } else { 222185a18ad93ec66888d85758630019b10a84257f3cPierre Ossman /* 222285a18ad93ec66888d85758630019b10a84257f3cPierre Ossman * The CSD capacity field is in units of read_blkbits. 222385a18ad93ec66888d85758630019b10a84257f3cPierre Ossman * set_capacity takes units of 512 bytes. 222485a18ad93ec66888d85758630019b10a84257f3cPierre Ossman */ 2225371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin size = card->csd.capacity << (card->csd.read_blkbits - 9); 222685a18ad93ec66888d85758630019b10a84257f3cPierre Ossman } 2227371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 2228add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm md = mmc_blk_alloc_req(card, &card->dev, size, false, NULL, 2229add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm MMC_BLK_DATA_AREA_MAIN); 22301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return md; 2231371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin} 2232a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King 2233371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic int mmc_blk_alloc_part(struct mmc_card *card, 2234371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct mmc_blk_data *md, 2235371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin unsigned int part_type, 2236371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin sector_t size, 2237371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin bool default_ro, 2238add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm const char *subname, 2239add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm int area_type) 2240371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{ 2241371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin char cap_str[10]; 2242371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct mmc_blk_data *part_md; 2243371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 2244371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin part_md = mmc_blk_alloc_req(card, disk_to_dev(md->disk), size, default_ro, 2245add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm subname, area_type); 2246371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin if (IS_ERR(part_md)) 2247371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin return PTR_ERR(part_md); 2248371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin part_md->part_type = part_type; 2249371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin list_add(&part_md->part, &md->part); 2250371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 2251371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin string_get_size((u64)get_capacity(part_md->disk) << 9, STRING_UNITS_2, 2252371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin cap_str, sizeof(cap_str)); 2253a3c76eb9d4a1e68a69dd880cf0bcb8a52418b993Girish K S pr_info("%s: %s %s partition %u %s\n", 2254371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin part_md->disk->disk_name, mmc_card_id(card), 2255371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin mmc_card_name(card), part_md->part_type, cap_str); 2256371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin return 0; 2257371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin} 2258371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 2259e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon/* MMC Physical partitions consist of two boot partitions and 2260e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon * up to four general purpose partitions. 2261e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon * For each partition enabled in EXT_CSD a block device will be allocatedi 2262e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon * to provide access to the partition. 2263e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon */ 2264e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon 2265371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic int mmc_blk_alloc_parts(struct mmc_card *card, struct mmc_blk_data *md) 2266371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{ 2267e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon int idx, ret = 0; 2268371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 2269371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin if (!mmc_card_mmc(card)) 2270371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin return 0; 2271371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 2272e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon for (idx = 0; idx < card->nr_parts; idx++) { 2273e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon if (card->part[idx].size) { 2274e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon ret = mmc_blk_alloc_part(card, md, 2275e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon card->part[idx].part_cfg, 2276e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon card->part[idx].size >> 9, 2277e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon card->part[idx].force_ro, 2278add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm card->part[idx].name, 2279add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm card->part[idx].area_type); 2280e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon if (ret) 2281e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon return ret; 2282e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon } 2283371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin } 2284371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 2285371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin return ret; 22861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 22871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2288371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic void mmc_blk_remove_req(struct mmc_blk_data *md) 2289371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{ 2290add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm struct mmc_card *card; 2291add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm 2292371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin if (md) { 2293fdfa20c1631210d0ca218689204682ea80e170e3Paul Taysom /* 2294fdfa20c1631210d0ca218689204682ea80e170e3Paul Taysom * Flush remaining requests and free queues. It 2295fdfa20c1631210d0ca218689204682ea80e170e3Paul Taysom * is freeing the queue that stops new requests 2296fdfa20c1631210d0ca218689204682ea80e170e3Paul Taysom * from being accepted. 2297fdfa20c1631210d0ca218689204682ea80e170e3Paul Taysom */ 22988efb83a2f8518a6ffcc074177f8d659c5165ef37Franck Jullien card = md->queue.card; 2299fdfa20c1631210d0ca218689204682ea80e170e3Paul Taysom mmc_cleanup_queue(&md->queue); 2300fdfa20c1631210d0ca218689204682ea80e170e3Paul Taysom if (md->flags & MMC_BLK_PACKED_CMD) 2301fdfa20c1631210d0ca218689204682ea80e170e3Paul Taysom mmc_packed_clean(&md->queue); 2302371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin if (md->disk->flags & GENHD_FL_UP) { 2303371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin device_remove_file(disk_to_dev(md->disk), &md->force_ro); 2304add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm if ((md->area_type & MMC_BLK_DATA_AREA_BOOT) && 2305add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm card->ext_csd.boot_ro_lockable) 2306add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm device_remove_file(disk_to_dev(md->disk), 2307add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm &md->power_ro_lock); 2308371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 2309371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin del_gendisk(md->disk); 2310371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin } 2311371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin mmc_blk_put(md); 2312371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin } 2313371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin} 2314371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 2315371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic void mmc_blk_remove_parts(struct mmc_card *card, 2316371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct mmc_blk_data *md) 2317371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{ 2318371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct list_head *pos, *q; 2319371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct mmc_blk_data *part_md; 2320371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 2321f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin __clear_bit(md->name_idx, name_use); 2322371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin list_for_each_safe(pos, q, &md->part) { 2323371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin part_md = list_entry(pos, struct mmc_blk_data, part); 2324371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin list_del(pos); 2325371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin mmc_blk_remove_req(part_md); 2326371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin } 2327371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin} 2328371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 2329371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic int mmc_add_disk(struct mmc_blk_data *md) 2330371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{ 2331371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin int ret; 2332add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm struct mmc_card *card = md->queue.card; 2333371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 2334371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin add_disk(md->disk); 2335371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin md->force_ro.show = force_ro_show; 2336371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin md->force_ro.store = force_ro_store; 2337641c3187b9d53cfd4c23b0ce2ab18a13d5e775e5Rabin Vincent sysfs_attr_init(&md->force_ro.attr); 2338371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin md->force_ro.attr.name = "force_ro"; 2339371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin md->force_ro.attr.mode = S_IRUGO | S_IWUSR; 2340371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin ret = device_create_file(disk_to_dev(md->disk), &md->force_ro); 2341371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin if (ret) 2342add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm goto force_ro_fail; 2343add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm 2344add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm if ((md->area_type & MMC_BLK_DATA_AREA_BOOT) && 2345add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm card->ext_csd.boot_ro_lockable) { 234688187398cc5fa6650f38b9dcd5464667f468888fAl Viro umode_t mode; 2347add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm 2348add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm if (card->ext_csd.boot_ro_lock & EXT_CSD_BOOT_WP_B_PWR_WP_DIS) 2349add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm mode = S_IRUGO; 2350add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm else 2351add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm mode = S_IRUGO | S_IWUSR; 2352add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm 2353add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm md->power_ro_lock.show = power_ro_lock_show; 2354add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm md->power_ro_lock.store = power_ro_lock_store; 235500d9ac08757049f334803b3d4dd202a6b1687dabRabin Vincent sysfs_attr_init(&md->power_ro_lock.attr); 2356add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm md->power_ro_lock.attr.mode = mode; 2357add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm md->power_ro_lock.attr.name = 2358add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm "ro_lock_until_next_power_on"; 2359add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm ret = device_create_file(disk_to_dev(md->disk), 2360add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm &md->power_ro_lock); 2361add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm if (ret) 2362add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm goto power_ro_lock_fail; 2363add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm } 2364add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm return ret; 2365add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm 2366add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholmpower_ro_lock_fail: 2367add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm device_remove_file(disk_to_dev(md->disk), &md->force_ro); 2368add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholmforce_ro_fail: 2369add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm del_gendisk(md->disk); 2370371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 2371371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin return ret; 2372371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin} 2373371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 2374c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball#define CID_MANFID_SANDISK 0x2 2375c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball#define CID_MANFID_TOSHIBA 0x11 2376c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball#define CID_MANFID_MICRON 0x13 23773550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen#define CID_MANFID_SAMSUNG 0x15 2378c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball 23796f60c22252af05df94352240f30f9fc84090d88dAndrei Warkentinstatic const struct mmc_fixup blk_fixups[] = 23806f60c22252af05df94352240f30f9fc84090d88dAndrei Warkentin{ 2381c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball MMC_FIXUP("SEM02G", CID_MANFID_SANDISK, 0x100, add_quirk, 2382c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball MMC_QUIRK_INAND_CMD38), 2383c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball MMC_FIXUP("SEM04G", CID_MANFID_SANDISK, 0x100, add_quirk, 2384c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball MMC_QUIRK_INAND_CMD38), 2385c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball MMC_FIXUP("SEM08G", CID_MANFID_SANDISK, 0x100, add_quirk, 2386c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball MMC_QUIRK_INAND_CMD38), 2387c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball MMC_FIXUP("SEM16G", CID_MANFID_SANDISK, 0x100, add_quirk, 2388c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball MMC_QUIRK_INAND_CMD38), 2389c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball MMC_FIXUP("SEM32G", CID_MANFID_SANDISK, 0x100, add_quirk, 2390c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball MMC_QUIRK_INAND_CMD38), 2391d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin 2392d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin /* 2393d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin * Some MMC cards experience performance degradation with CMD23 2394d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin * instead of CMD12-bounded multiblock transfers. For now we'll 2395d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin * black list what's bad... 2396d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin * - Certain Toshiba cards. 2397d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin * 2398d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin * N.B. This doesn't affect SD cards. 2399d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin */ 2400c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball MMC_FIXUP("MMC08G", CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc, 2401d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin MMC_QUIRK_BLK_NO_CMD23), 2402c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball MMC_FIXUP("MMC16G", CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc, 2403d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin MMC_QUIRK_BLK_NO_CMD23), 2404c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball MMC_FIXUP("MMC32G", CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc, 2405d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin MMC_QUIRK_BLK_NO_CMD23), 24066de5fc9cf7de334912de4cfd2d06eb2d744d2afeStefan Nilsson XK 24076de5fc9cf7de334912de4cfd2d06eb2d744d2afeStefan Nilsson XK /* 24086de5fc9cf7de334912de4cfd2d06eb2d744d2afeStefan Nilsson XK * Some Micron MMC cards needs longer data read timeout than 24096de5fc9cf7de334912de4cfd2d06eb2d744d2afeStefan Nilsson XK * indicated in CSD. 24106de5fc9cf7de334912de4cfd2d06eb2d744d2afeStefan Nilsson XK */ 2411c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball MMC_FIXUP(CID_NAME_ANY, CID_MANFID_MICRON, 0x200, add_quirk_mmc, 24126de5fc9cf7de334912de4cfd2d06eb2d744d2afeStefan Nilsson XK MMC_QUIRK_LONG_READ_TIME), 24136de5fc9cf7de334912de4cfd2d06eb2d744d2afeStefan Nilsson XK 24143550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen /* 24153550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen * On these Samsung MoviNAND parts, performing secure erase or 24163550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen * secure trim can result in unrecoverable corruption due to a 24173550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen * firmware bug. 24183550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen */ 24193550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen MMC_FIXUP("M8G2FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, 24203550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), 24213550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen MMC_FIXUP("MAG4FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, 24223550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), 24233550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen MMC_FIXUP("MBG8FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, 24243550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), 24253550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen MMC_FIXUP("MCGAFA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, 24263550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), 24273550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen MMC_FIXUP("VAL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, 24283550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), 24293550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen MMC_FIXUP("VYL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, 24303550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), 24313550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen MMC_FIXUP("KYL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, 24323550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), 24333550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen MMC_FIXUP("VZL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, 24343550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), 24353550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen 24366f60c22252af05df94352240f30f9fc84090d88dAndrei Warkentin END_FIXUP 24376f60c22252af05df94352240f30f9fc84090d88dAndrei Warkentin}; 24386f60c22252af05df94352240f30f9fc84090d88dAndrei Warkentin 24391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mmc_blk_probe(struct mmc_card *card) 24401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2441371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct mmc_blk_data *md, *part_md; 2442a7bbb57333447d0cf950992653b6b079585f3531Pierre Ossman char cap_str[10]; 2443a7bbb57333447d0cf950992653b6b079585f3531Pierre Ossman 2444912490db699d83cb3d03570b63df7448677a3f56Pierre Ossman /* 2445912490db699d83cb3d03570b63df7448677a3f56Pierre Ossman * Check that the card supports the command class(es) we need. 2446912490db699d83cb3d03570b63df7448677a3f56Pierre Ossman */ 2447912490db699d83cb3d03570b63df7448677a3f56Pierre Ossman if (!(card->csd.cmdclass & CCC_BLOCK_READ)) 24481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 24491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24505204d00f06ac9af4ef9c469cce7f9bbe179739b1Lukas Czerner mmc_fixup_device(card, blk_fixups); 24515204d00f06ac9af4ef9c469cce7f9bbe179739b1Lukas Czerner 24521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds md = mmc_blk_alloc(card); 24531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (IS_ERR(md)) 24541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return PTR_ERR(md); 24551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2456444122fd58fdc83c96877a92b3f6288cafddb08dYi Li string_get_size((u64)get_capacity(md->disk) << 9, STRING_UNITS_2, 2457a7bbb57333447d0cf950992653b6b079585f3531Pierre Ossman cap_str, sizeof(cap_str)); 2458a3c76eb9d4a1e68a69dd880cf0bcb8a52418b993Girish K S pr_info("%s: %s %s %s %s\n", 24591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds md->disk->disk_name, mmc_card_id(card), mmc_card_name(card), 2460a7bbb57333447d0cf950992653b6b079585f3531Pierre Ossman cap_str, md->read_only ? "(ro)" : ""); 24611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2462371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin if (mmc_blk_alloc_parts(card, md)) 2463371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin goto out; 2464371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 24651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_set_drvdata(card, md); 24666f60c22252af05df94352240f30f9fc84090d88dAndrei Warkentin 24672c84417a1305da892c8a7d0bf8d0bad50d1688b8San Mehat#ifdef CONFIG_MMC_BLOCK_DEFERRED_RESUME 24682c84417a1305da892c8a7d0bf8d0bad50d1688b8San Mehat mmc_set_bus_resume_policy(card->host, 1); 24692c84417a1305da892c8a7d0bf8d0bad50d1688b8San Mehat#endif 2470371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin if (mmc_add_disk(md)) 2471371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin goto out; 2472371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin 2473371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin list_for_each_entry(part_md, &md->part, part) { 2474371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin if (mmc_add_disk(part_md)) 2475371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin goto out; 2476371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin } 2477e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson 2478e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson pm_runtime_set_autosuspend_delay(&card->dev, 3000); 2479e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson pm_runtime_use_autosuspend(&card->dev); 2480e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson 2481e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson /* 2482e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson * Don't enable runtime PM for SD-combo cards here. Leave that 2483e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson * decision to be taken during the SDIO init sequence instead. 2484e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson */ 2485e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson if (card->type != MMC_TYPE_SD_COMBO) { 2486e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson pm_runtime_set_active(&card->dev); 2487e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson pm_runtime_enable(&card->dev); 2488e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson } 2489e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson 24901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 24911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 2493371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin mmc_blk_remove_parts(card, md); 2494371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin mmc_blk_remove_req(md); 24955865f2876baa5c68fd0d50029dd220ce19f3d2afUlf Hansson return 0; 24961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 24971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mmc_blk_remove(struct mmc_card *card) 24991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 25001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_blk_data *md = mmc_get_drvdata(card); 25011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2502371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin mmc_blk_remove_parts(card, md); 2503e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson pm_runtime_get_sync(&card->dev); 2504ddd6fa7e794e62af3ec3eb4ffdc78489885701f2Adrian Hunter mmc_claim_host(card->host); 2505ddd6fa7e794e62af3ec3eb4ffdc78489885701f2Adrian Hunter mmc_blk_part_switch(card, md); 2506ddd6fa7e794e62af3ec3eb4ffdc78489885701f2Adrian Hunter mmc_release_host(card->host); 2507e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson if (card->type != MMC_TYPE_SD_COMBO) 2508e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson pm_runtime_disable(&card->dev); 2509e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson pm_runtime_put_noidle(&card->dev); 2510371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin mmc_blk_remove_req(md); 25111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_set_drvdata(card, NULL); 25122c84417a1305da892c8a7d0bf8d0bad50d1688b8San Mehat#ifdef CONFIG_MMC_BLOCK_DEFERRED_RESUME 25132c84417a1305da892c8a7d0bf8d0bad50d1688b8San Mehat mmc_set_bus_resume_policy(card->host, 0); 25142c84417a1305da892c8a7d0bf8d0bad50d1688b8San Mehat#endif 25151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 25161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25177628774851751e55362ec7d9d57c9334e656a655Ulf Hanssonstatic int _mmc_blk_suspend(struct mmc_card *card) 25181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2519371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct mmc_blk_data *part_md; 25201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_blk_data *md = mmc_get_drvdata(card); 25211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (md) { 25231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_queue_suspend(&md->queue); 2524371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin list_for_each_entry(part_md, &md->part, part) { 2525371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin mmc_queue_suspend(&part_md->queue); 2526371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin } 25271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 25281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 25291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 25301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25317628774851751e55362ec7d9d57c9334e656a655Ulf Hanssonstatic void mmc_blk_shutdown(struct mmc_card *card) 25327628774851751e55362ec7d9d57c9334e656a655Ulf Hansson{ 25337628774851751e55362ec7d9d57c9334e656a655Ulf Hansson _mmc_blk_suspend(card); 25347628774851751e55362ec7d9d57c9334e656a655Ulf Hansson} 25357628774851751e55362ec7d9d57c9334e656a655Ulf Hansson 25367628774851751e55362ec7d9d57c9334e656a655Ulf Hansson#ifdef CONFIG_PM 25377628774851751e55362ec7d9d57c9334e656a655Ulf Hanssonstatic int mmc_blk_suspend(struct mmc_card *card) 25387628774851751e55362ec7d9d57c9334e656a655Ulf Hansson{ 25397628774851751e55362ec7d9d57c9334e656a655Ulf Hansson return _mmc_blk_suspend(card); 25407628774851751e55362ec7d9d57c9334e656a655Ulf Hansson} 25417628774851751e55362ec7d9d57c9334e656a655Ulf Hansson 25421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mmc_blk_resume(struct mmc_card *card) 25431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2544371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin struct mmc_blk_data *part_md; 25451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_blk_data *md = mmc_get_drvdata(card); 25461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (md) { 2548371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin /* 2549371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin * Resume involves the card going into idle state, 2550371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin * so current partition is always the main one. 2551371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin */ 2552371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin md->part_curr = md->part_type; 25531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_queue_resume(&md->queue); 2554371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin list_for_each_entry(part_md, &md->part, part) { 2555371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin mmc_queue_resume(&part_md->queue); 2556371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin } 25571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 25581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 25591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 25601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 25611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define mmc_blk_suspend NULL 25621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define mmc_blk_resume NULL 25631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 25641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct mmc_driver mmc_driver = { 25661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .drv = { 25671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "mmcblk", 25681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 25691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .probe = mmc_blk_probe, 25701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .remove = mmc_blk_remove, 25711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .suspend = mmc_blk_suspend, 25721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .resume = mmc_blk_resume, 25737628774851751e55362ec7d9d57c9334e656a655Ulf Hansson .shutdown = mmc_blk_shutdown, 25741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 25751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init mmc_blk_init(void) 25771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 25789d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita int res; 25791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25805e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson if (perdev_minors != CONFIG_MMC_BLOCK_MINORS) 25815e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson pr_info("mmcblk: using %d minors per device\n", perdev_minors); 25825e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson 25835e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson max_devices = 256 / perdev_minors; 25845e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson 2585fe6b4c8840c5e23fe9b8696450cee8f2e8cebffdPierre Ossman res = register_blkdev(MMC_BLOCK_MAJOR, "mmc"); 2586fe6b4c8840c5e23fe9b8696450cee8f2e8cebffdPierre Ossman if (res) 25871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 25881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25899d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita res = mmc_register_driver(&mmc_driver); 25909d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita if (res) 25919d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita goto out2; 25921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25939d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita return 0; 25949d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita out2: 25959d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita unregister_blkdev(MMC_BLOCK_MAJOR, "mmc"); 25961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 25971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return res; 25981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 25991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit mmc_blk_exit(void) 26011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 26021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_unregister_driver(&mmc_driver); 2603fe6b4c8840c5e23fe9b8696450cee8f2e8cebffdPierre Ossman unregister_blkdev(MMC_BLOCK_MAJOR, "mmc"); 26041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 26051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(mmc_blk_init); 26071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(mmc_blk_exit); 26081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 26101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("Multimedia Card (MMC) block device driver"); 26111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2612