block.c revision 88187398cc5fa6650f38b9dcd5464667f468888f
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Block driver for media (i.e., flash cards)
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright 2002 Hewlett-Packard Company
5979ce7208a679b8d012450610d5d5aa75aab3af9Pierre Ossman * Copyright 2005-2008 Pierre Ossman
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Use consistent with the GNU GPL is permitted,
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * provided that this copyright notice is
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * preserved in its entirety in all copies and derived works.
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * HEWLETT-PACKARD COMPANY MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FITNESS FOR ANY PARTICULAR PURPOSE.
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Many thanks to Alessandro Rubini and Jonathan Corbet!
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Author:  Andrew Christian
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *          28 May 2002
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/moduleparam.h>
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/fs.h>
265a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h>
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/hdreg.h>
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kdev_t.h>
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/blkdev.h>
31a621aaed690b9439141c555941b6af53873f6ff1Arjan van de Ven#include <linux/mutex.h>
32ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman#include <linux/scatterlist.h>
33a7bbb57333447d0cf950992653b6b079585f3531Pierre Ossman#include <linux/string_helpers.h>
34cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto#include <linux/delay.h>
35cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto#include <linux/capability.h>
36cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto#include <linux/compat.h>
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto#include <linux/mmc/ioctl.h>
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mmc/card.h>
40385e3227d4d83ab13d7767c4bb3593b0256bf246Pierre Ossman#include <linux/mmc/host.h>
41da7fbe58d2d347e95af699ddf04d885be6362bbePierre Ossman#include <linux/mmc/mmc.h>
42da7fbe58d2d347e95af699ddf04d885be6362bbePierre Ossman#include <linux/mmc/sd.h>
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/system.h>
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h>
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4798ac2162699f7e9880683cb954891817f20b607cPierre Ossman#include "queue.h"
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
496b0b62853b2553be375033776902640320970846Andy WhitcroftMODULE_ALIAS("mmc:block");
505e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson#ifdef MODULE_PARAM_PREFIX
515e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson#undef MODULE_PARAM_PREFIX
525e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson#endif
535e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson#define MODULE_PARAM_PREFIX "mmcblk."
545e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson
556a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin#define INAND_CMD38_ARG_EXT_CSD  113
566a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin#define INAND_CMD38_ARG_ERASE    0x00
576a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin#define INAND_CMD38_ARG_TRIM     0x01
586a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin#define INAND_CMD38_ARG_SECERASE 0x80
596a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin#define INAND_CMD38_ARG_SECTRIM1 0x81
606a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin#define INAND_CMD38_ARG_SECTRIM2 0x88
616a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin
625e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johanssonstatic DEFINE_MUTEX(block_mutex);
636b0b62853b2553be375033776902640320970846Andy Whitcroft
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
655e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson * The defaults come from config options but can be overriden by module
665e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson * or bootarg options.
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
685e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johanssonstatic int perdev_minors = CONFIG_MMC_BLOCK_MINORS;
691dff314451fa24d6b107aa05393d3169e56a7e0aDavid Woodhouse
705e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson/*
715e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson * We've only got one major, so number of mmcblk devices is
725e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson * limited to 256 / number of minors per device.
735e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson */
745e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johanssonstatic int max_devices;
755e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson
765e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson/* 256 minors, so at most 256 separate devices */
775e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johanssonstatic DECLARE_BITMAP(dev_use, 256);
78f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentinstatic DECLARE_BITMAP(name_use, 256);
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * There is one mmc_blk_data per slot.
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct mmc_blk_data {
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spinlock_t	lock;
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct gendisk	*disk;
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mmc_queue queue;
87371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	struct list_head part;
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
89d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin	unsigned int	flags;
90d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin#define MMC_BLK_CMD23	(1 << 0)	/* Can do SET_BLOCK_COUNT for multiblock */
91d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin#define MMC_BLK_REL_WR	(1 << 1)	/* MMC Reliable write support */
92d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int	usage;
94a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	unsigned int	read_only;
95371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	unsigned int	part_type;
96f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin	unsigned int	name_idx;
9767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	unsigned int	reset_done;
9867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter#define MMC_BLK_READ		BIT(0)
9967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter#define MMC_BLK_WRITE		BIT(1)
10067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter#define MMC_BLK_DISCARD		BIT(2)
10167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter#define MMC_BLK_SECDISCARD	BIT(3)
102371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
103371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	/*
104371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	 * Only set in main mmc_blk_data associated
105371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	 * with mmc_card with mmc_set_drvdata, and keeps
106371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	 * track of the current selected device partition.
107371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	 */
108371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	unsigned int	part_curr;
109371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	struct device_attribute force_ro;
110add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	struct device_attribute power_ro_lock;
111add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	int	area_type;
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
114a621aaed690b9439141c555941b6af53873f6ff1Arjan van de Venstatic DEFINE_MUTEX(open_lock);
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
116d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlinenum mmc_blk_status {
117d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	MMC_BLK_SUCCESS = 0,
118d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	MMC_BLK_PARTIAL,
119d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	MMC_BLK_CMD_ERR,
12067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	MMC_BLK_RETRY,
121d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	MMC_BLK_ABORT,
12267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	MMC_BLK_DATA_ERR,
12367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	MMC_BLK_ECC_ERR,
124a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma	MMC_BLK_NOMEDIUM,
125d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin};
126d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin
1275e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johanssonmodule_param(perdev_minors, int, 0444);
1285e71b7a64cb4c6cff75ca42b535d8227526ec592Olof JohanssonMODULE_PARM_DESC(perdev_minors, "Minors numbers to allocate per device");
1295e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct mmc_blk_data *mmc_blk_get(struct gendisk *disk)
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mmc_blk_data *md;
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
134a621aaed690b9439141c555941b6af53873f6ff1Arjan van de Ven	mutex_lock(&open_lock);
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	md = disk->private_data;
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (md && md->usage == 0)
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		md = NULL;
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (md)
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		md->usage++;
140a621aaed690b9439141c555941b6af53873f6ff1Arjan van de Ven	mutex_unlock(&open_lock);
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return md;
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
145371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic inline int mmc_get_devidx(struct gendisk *disk)
146371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{
147371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	int devmaj = MAJOR(disk_devt(disk));
148371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	int devidx = MINOR(disk_devt(disk)) / perdev_minors;
149371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
150371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	if (!devmaj)
151371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		devidx = disk->first_minor / perdev_minors;
152371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	return devidx;
153371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin}
154371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mmc_blk_put(struct mmc_blk_data *md)
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
157a621aaed690b9439141c555941b6af53873f6ff1Arjan van de Ven	mutex_lock(&open_lock);
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	md->usage--;
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (md->usage == 0) {
160371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		int devidx = mmc_get_devidx(md->disk);
1615fa83ce284a4b7cd9dcfadd01500b0ed4ab9b740Adrian Hunter		blk_cleanup_queue(md->queue.queue);
1625fa83ce284a4b7cd9dcfadd01500b0ed4ab9b740Adrian Hunter
1631dff314451fa24d6b107aa05393d3169e56a7e0aDavid Woodhouse		__clear_bit(devidx, dev_use);
1641dff314451fa24d6b107aa05393d3169e56a7e0aDavid Woodhouse
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		put_disk(md->disk);
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kfree(md);
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
168a621aaed690b9439141c555941b6af53873f6ff1Arjan van de Ven	mutex_unlock(&open_lock);
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
171add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholmstatic ssize_t power_ro_lock_show(struct device *dev,
172add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		struct device_attribute *attr, char *buf)
173add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm{
174add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	int ret;
175add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
176add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	struct mmc_card *card = md->queue.card;
177add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	int locked = 0;
178add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
179add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	if (card->ext_csd.boot_ro_lock & EXT_CSD_BOOT_WP_B_PERM_WP_EN)
180add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		locked = 2;
181add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	else if (card->ext_csd.boot_ro_lock & EXT_CSD_BOOT_WP_B_PWR_WP_EN)
182add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		locked = 1;
183add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
184add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	ret = snprintf(buf, PAGE_SIZE, "%d\n", locked);
185add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
186add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	return ret;
187add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm}
188add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
189add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholmstatic ssize_t power_ro_lock_store(struct device *dev,
190add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		struct device_attribute *attr, const char *buf, size_t count)
191add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm{
192add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	int ret;
193add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	struct mmc_blk_data *md, *part_md;
194add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	struct mmc_card *card;
195add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	unsigned long set;
196add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
197add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	if (kstrtoul(buf, 0, &set))
198add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		return -EINVAL;
199add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
200add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	if (set != 1)
201add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		return count;
202add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
203add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	md = mmc_blk_get(dev_to_disk(dev));
204add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	card = md->queue.card;
205add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
206add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	mmc_claim_host(card->host);
207add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
208add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_WP,
209add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm				card->ext_csd.boot_ro_lock |
210add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm				EXT_CSD_BOOT_WP_B_PWR_WP_EN,
211add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm				card->ext_csd.part_time);
212add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	if (ret)
213add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		pr_err("%s: Locking boot partition ro until next power on failed: %d\n", md->disk->disk_name, ret);
214add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	else
215add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		card->ext_csd.boot_ro_lock |= EXT_CSD_BOOT_WP_B_PWR_WP_EN;
216add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
217add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	mmc_release_host(card->host);
218add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
219add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	if (!ret) {
220add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		pr_info("%s: Locking boot partition ro until next power on\n",
221add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm			md->disk->disk_name);
222add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		set_disk_ro(md->disk, 1);
223add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
224add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		list_for_each_entry(part_md, &md->part, part)
225add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm			if (part_md->area_type == MMC_BLK_DATA_AREA_BOOT) {
226add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm				pr_info("%s: Locking boot partition ro until next power on\n", part_md->disk->disk_name);
227add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm				set_disk_ro(part_md->disk, 1);
228add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm			}
229add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	}
230add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
231add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	mmc_blk_put(md);
232add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	return count;
233add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm}
234add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
235371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic ssize_t force_ro_show(struct device *dev, struct device_attribute *attr,
236371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin			     char *buf)
237371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{
238371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	int ret;
239371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
240371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
241371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	ret = snprintf(buf, PAGE_SIZE, "%d",
242371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		       get_disk_ro(dev_to_disk(dev)) ^
243371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		       md->read_only);
244371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	mmc_blk_put(md);
245371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	return ret;
246371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin}
247371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
248371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic ssize_t force_ro_store(struct device *dev, struct device_attribute *attr,
249371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin			      const char *buf, size_t count)
250371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{
251371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	int ret;
252371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	char *end;
253371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
254371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	unsigned long set = simple_strtoul(buf, &end, 0);
255371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	if (end == buf) {
256371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		ret = -EINVAL;
257371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		goto out;
258371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	}
259371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
260371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	set_disk_ro(dev_to_disk(dev), set || md->read_only);
261371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	ret = count;
262371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinout:
263371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	mmc_blk_put(md);
264371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	return ret;
265371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin}
266371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
267a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Virostatic int mmc_blk_open(struct block_device *bdev, fmode_t mode)
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
269a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Viro	struct mmc_blk_data *md = mmc_blk_get(bdev->bd_disk);
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret = -ENXIO;
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2722a48fc0ab24241755dc93bfd4f01d68efab47f5aArnd Bergmann	mutex_lock(&block_mutex);
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (md) {
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (md->usage == 2)
275a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Viro			check_disk_change(bdev);
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = 0;
277a00fc09029f02ca833cf90e5d5625f08c4ac4f51Pierre Ossman
278a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Viro		if ((mode & FMODE_WRITE) && md->read_only) {
27970bb08962ea9bd50797ae9f16b2493f5f7c65053Andrew Morton			mmc_blk_put(md);
280a00fc09029f02ca833cf90e5d5625f08c4ac4f51Pierre Ossman			ret = -EROFS;
28170bb08962ea9bd50797ae9f16b2493f5f7c65053Andrew Morton		}
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2832a48fc0ab24241755dc93bfd4f01d68efab47f5aArnd Bergmann	mutex_unlock(&block_mutex);
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
288a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Virostatic int mmc_blk_release(struct gendisk *disk, fmode_t mode)
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
290a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Viro	struct mmc_blk_data *md = disk->private_data;
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2922a48fc0ab24241755dc93bfd4f01d68efab47f5aArnd Bergmann	mutex_lock(&block_mutex);
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mmc_blk_put(md);
2942a48fc0ab24241755dc93bfd4f01d68efab47f5aArnd Bergmann	mutex_unlock(&block_mutex);
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
299a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwigmmc_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
301a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig	geo->cylinders = get_capacity(bdev->bd_disk) / (4 * 16);
302a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig	geo->heads = 4;
303a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig	geo->sectors = 16;
304a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig	return 0;
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
307cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtostruct mmc_blk_ioc_data {
308cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	struct mmc_ioc_cmd ic;
309cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	unsigned char *buf;
310cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	u64 buf_bytes;
311cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto};
312cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
313cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtostatic struct mmc_blk_ioc_data *mmc_blk_ioctl_copy_from_user(
314cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	struct mmc_ioc_cmd __user *user)
315cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto{
316cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	struct mmc_blk_ioc_data *idata;
317cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	int err;
318cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
319cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	idata = kzalloc(sizeof(*idata), GFP_KERNEL);
320cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (!idata) {
321cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		err = -ENOMEM;
322aea253ecffecd38b5ab97edd73fbe2842a7de371Vladimir Motyka		goto out;
323cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	}
324cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
325cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (copy_from_user(&idata->ic, user, sizeof(idata->ic))) {
326cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		err = -EFAULT;
327aea253ecffecd38b5ab97edd73fbe2842a7de371Vladimir Motyka		goto idata_err;
328cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	}
329cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
330cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	idata->buf_bytes = (u64) idata->ic.blksz * idata->ic.blocks;
331cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (idata->buf_bytes > MMC_IOC_MAX_BYTES) {
332cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		err = -EOVERFLOW;
333aea253ecffecd38b5ab97edd73fbe2842a7de371Vladimir Motyka		goto idata_err;
334cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	}
335cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
3364d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm	if (!idata->buf_bytes)
3374d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		return idata;
3384d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm
339cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	idata->buf = kzalloc(idata->buf_bytes, GFP_KERNEL);
340cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (!idata->buf) {
341cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		err = -ENOMEM;
342aea253ecffecd38b5ab97edd73fbe2842a7de371Vladimir Motyka		goto idata_err;
343cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	}
344cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
345cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (copy_from_user(idata->buf, (void __user *)(unsigned long)
346cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto					idata->ic.data_ptr, idata->buf_bytes)) {
347cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		err = -EFAULT;
348cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		goto copy_err;
349cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	}
350cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
351cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	return idata;
352cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
353cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtocopy_err:
354cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	kfree(idata->buf);
355aea253ecffecd38b5ab97edd73fbe2842a7de371Vladimir Motykaidata_err:
356cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	kfree(idata);
357aea253ecffecd38b5ab97edd73fbe2842a7de371Vladimir Motykaout:
358cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	return ERR_PTR(err);
359cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto}
360cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
361cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtostatic int mmc_blk_ioctl_cmd(struct block_device *bdev,
362cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	struct mmc_ioc_cmd __user *ic_ptr)
363cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto{
364cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	struct mmc_blk_ioc_data *idata;
365cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	struct mmc_blk_data *md;
366cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	struct mmc_card *card;
367cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	struct mmc_command cmd = {0};
368cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	struct mmc_data data = {0};
369ad5fd97288655b5628052c1fa906419417c86100Venkatraman S	struct mmc_request mrq = {NULL};
370cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	struct scatterlist sg;
371cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	int err;
372cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
373cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	/*
374cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	 * The caller must have CAP_SYS_RAWIO, and must be calling this on the
375cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	 * whole block device, not on a partition.  This prevents overspray
376cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	 * between sibling partitions.
377cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	 */
378cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if ((!capable(CAP_SYS_RAWIO)) || (bdev != bdev->bd_contains))
379cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		return -EPERM;
380cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
381cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	idata = mmc_blk_ioctl_copy_from_user(ic_ptr);
382cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (IS_ERR(idata))
383cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		return PTR_ERR(idata);
384cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
385cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	md = mmc_blk_get(bdev->bd_disk);
386cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (!md) {
387cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		err = -EINVAL;
388cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		goto cmd_done;
389cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	}
390cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
391cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	card = md->queue.card;
392cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (IS_ERR(card)) {
393cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		err = PTR_ERR(card);
394cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		goto cmd_done;
395cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	}
396cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
3974d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm	cmd.opcode = idata->ic.opcode;
3984d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm	cmd.arg = idata->ic.arg;
3994d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm	cmd.flags = idata->ic.flags;
4004d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm
4014d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm	if (idata->buf_bytes) {
4024d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		data.sg = &sg;
4034d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		data.sg_len = 1;
4044d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		data.blksz = idata->ic.blksz;
4054d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		data.blocks = idata->ic.blocks;
4064d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm
4074d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		sg_init_one(data.sg, idata->buf, idata->buf_bytes);
4084d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm
4094d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		if (idata->ic.write_flag)
4104d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm			data.flags = MMC_DATA_WRITE;
4114d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		else
4124d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm			data.flags = MMC_DATA_READ;
4134d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm
4144d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		/* data.flags must already be set before doing this. */
4154d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		mmc_set_data_timeout(&data, card);
4164d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm
4174d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		/* Allow overriding the timeout_ns for empirical tuning. */
4184d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		if (idata->ic.data_timeout_ns)
4194d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm			data.timeout_ns = idata->ic.data_timeout_ns;
4204d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm
4214d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		if ((cmd.flags & MMC_RSP_R1B) == MMC_RSP_R1B) {
4224d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm			/*
4234d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm			 * Pretend this is a data transfer and rely on the
4244d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm			 * host driver to compute timeout.  When all host
4254d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm			 * drivers support cmd.cmd_timeout for R1B, this
4264d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm			 * can be changed to:
4274d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm			 *
4284d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm			 *     mrq.data = NULL;
4294d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm			 *     cmd.cmd_timeout = idata->ic.cmd_timeout_ms;
4304d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm			 */
4314d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm			data.timeout_ns = idata->ic.cmd_timeout_ms * 1000000;
4324d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		}
4334d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm
4344d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		mrq.data = &data;
4354d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm	}
4364d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm
4374d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm	mrq.cmd = &cmd;
4384d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm
439cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	mmc_claim_host(card->host);
440cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
441cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (idata->ic.is_acmd) {
442cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		err = mmc_app_cmd(card->host, card);
443cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		if (err)
444cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto			goto cmd_rel_host;
445cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	}
446cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
447cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	mmc_wait_for_req(card->host, &mrq);
448cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
449cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (cmd.error) {
450cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		dev_err(mmc_dev(card->host), "%s: cmd error %d\n",
451cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto						__func__, cmd.error);
452cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		err = cmd.error;
453cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		goto cmd_rel_host;
454cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	}
455cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (data.error) {
456cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		dev_err(mmc_dev(card->host), "%s: data error %d\n",
457cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto						__func__, data.error);
458cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		err = data.error;
459cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		goto cmd_rel_host;
460cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	}
461cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
462cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	/*
463cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	 * According to the SD specs, some commands require a delay after
464cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	 * issuing the command.
465cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	 */
466cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (idata->ic.postsleep_min_us)
467cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		usleep_range(idata->ic.postsleep_min_us, idata->ic.postsleep_max_us);
468cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
469cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (copy_to_user(&(ic_ptr->response), cmd.resp, sizeof(cmd.resp))) {
470cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		err = -EFAULT;
471cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		goto cmd_rel_host;
472cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	}
473cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
474cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (!idata->ic.write_flag) {
475cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		if (copy_to_user((void __user *)(unsigned long) idata->ic.data_ptr,
476cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto						idata->buf, idata->buf_bytes)) {
477cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto			err = -EFAULT;
478cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto			goto cmd_rel_host;
479cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		}
480cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	}
481cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
482cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtocmd_rel_host:
483cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	mmc_release_host(card->host);
484cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
485cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtocmd_done:
486cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	mmc_blk_put(md);
487cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	kfree(idata->buf);
488cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	kfree(idata);
489cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	return err;
490cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto}
491cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
492cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtostatic int mmc_blk_ioctl(struct block_device *bdev, fmode_t mode,
493cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	unsigned int cmd, unsigned long arg)
494cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto{
495cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	int ret = -EINVAL;
496cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (cmd == MMC_IOC_CMD)
497cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		ret = mmc_blk_ioctl_cmd(bdev, (struct mmc_ioc_cmd __user *)arg);
498cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	return ret;
499cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto}
500cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
501cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto#ifdef CONFIG_COMPAT
502cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtostatic int mmc_blk_compat_ioctl(struct block_device *bdev, fmode_t mode,
503cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	unsigned int cmd, unsigned long arg)
504cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto{
505cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	return mmc_blk_ioctl(bdev, mode, cmd, (unsigned long) compat_ptr(arg));
506cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto}
507cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto#endif
508cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
50983d5cde47dedf01b6a4a4331882cbc0a7eea3c2eAlexey Dobriyanstatic const struct block_device_operations mmc_bdops = {
510a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Viro	.open			= mmc_blk_open,
511a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Viro	.release		= mmc_blk_release,
512a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig	.getgeo			= mmc_blk_getgeo,
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.owner			= THIS_MODULE,
514cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	.ioctl			= mmc_blk_ioctl,
515cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto#ifdef CONFIG_COMPAT
516cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	.compat_ioctl		= mmc_blk_compat_ioctl,
517cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto#endif
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
520371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic inline int mmc_blk_part_switch(struct mmc_card *card,
521371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin				      struct mmc_blk_data *md)
522371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{
523371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	int ret;
524371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	struct mmc_blk_data *main_md = mmc_get_drvdata(card);
5250d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter
526371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	if (main_md->part_curr == md->part_type)
527371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		return 0;
528371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
529371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	if (mmc_card_mmc(card)) {
5300d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter		u8 part_config = card->ext_csd.part_config;
5310d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter
5320d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter		part_config &= ~EXT_CSD_PART_CONFIG_ACC_MASK;
5330d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter		part_config |= md->part_type;
534371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
535371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
5360d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter				 EXT_CSD_PART_CONFIG, part_config,
537371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin				 card->ext_csd.part_time);
538371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		if (ret)
539371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin			return ret;
5400d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter
5410d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter		card->ext_csd.part_config = part_config;
54267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	}
543371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
544371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	main_md->part_curr = md->part_type;
545371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	return 0;
546371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin}
547371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
548ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossmanstatic u32 mmc_sd_num_wr_blocks(struct mmc_card *card)
549ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman{
550ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	int err;
551051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks	u32 result;
552051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks	__be32 *blocks;
553ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman
554ad5fd97288655b5628052c1fa906419417c86100Venkatraman S	struct mmc_request mrq = {NULL};
5551278dba167f01bb3c6626d16450d31129d041087Chris Ball	struct mmc_command cmd = {0};
556a61ad2b49bfce94dfddce828cd9222e4b9e7825bChris Ball	struct mmc_data data = {0};
557ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	unsigned int timeout_us;
558ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman
559ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	struct scatterlist sg;
560ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman
561ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	cmd.opcode = MMC_APP_CMD;
562ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	cmd.arg = card->rca << 16;
5637213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell	cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
564ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman
565ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	err = mmc_wait_for_cmd(card->host, &cmd, 0);
5667213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell	if (err)
5677213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell		return (u32)-1;
5687213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell	if (!mmc_host_is_spi(card->host) && !(cmd.resp[0] & R1_APP_CMD))
569ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman		return (u32)-1;
570ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman
571ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	memset(&cmd, 0, sizeof(struct mmc_command));
572ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman
573ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	cmd.opcode = SD_APP_SEND_NUM_WR_BLKS;
574ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	cmd.arg = 0;
5757213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell	cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
576ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman
577ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	data.timeout_ns = card->csd.tacc_ns * 100;
578ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	data.timeout_clks = card->csd.tacc_clks * 100;
579ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman
580ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	timeout_us = data.timeout_ns / 1000;
581ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	timeout_us += data.timeout_clks * 1000 /
582ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman		(card->host->ios.clock / 1000);
583ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman
584ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	if (timeout_us > 100000) {
585ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman		data.timeout_ns = 100000000;
586ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman		data.timeout_clks = 0;
587ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	}
588ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman
589ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	data.blksz = 4;
590ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	data.blocks = 1;
591ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	data.flags = MMC_DATA_READ;
592ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	data.sg = &sg;
593ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	data.sg_len = 1;
594ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman
595ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	mrq.cmd = &cmd;
596ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	mrq.data = &data;
597ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman
598051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks	blocks = kmalloc(4, GFP_KERNEL);
599051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks	if (!blocks)
600051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks		return (u32)-1;
601051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks
602051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks	sg_init_one(&sg, blocks, 4);
603ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman
604ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	mmc_wait_for_req(card->host, &mrq);
605ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman
606051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks	result = ntohl(*blocks);
607051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks	kfree(blocks);
608051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks
60917b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman	if (cmd.error || data.error)
610051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks		result = (u32)-1;
611ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman
612051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks	return result;
613ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman}
614ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman
615a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linuxstatic int send_stop(struct mmc_card *card, u32 *status)
616a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux{
617a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	struct mmc_command cmd = {0};
618a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	int err;
619a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
620a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	cmd.opcode = MMC_STOP_TRANSMISSION;
621a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
622a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	err = mmc_wait_for_cmd(card->host, &cmd, 5);
623a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	if (err == 0)
624a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		*status = cmd.resp[0];
625a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	return err;
626a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux}
627a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
6280a2d4048a22079d7e79d6654bbacbef57bd5728aRussell King - ARM Linuxstatic int get_card_status(struct mmc_card *card, u32 *status, int retries)
629504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter{
6301278dba167f01bb3c6626d16450d31129d041087Chris Ball	struct mmc_command cmd = {0};
631504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter	int err;
632504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter
633504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter	cmd.opcode = MMC_SEND_STATUS;
634504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter	if (!mmc_host_is_spi(card->host))
635504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter		cmd.arg = card->rca << 16;
636504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter	cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC;
6370a2d4048a22079d7e79d6654bbacbef57bd5728aRussell King - ARM Linux	err = mmc_wait_for_cmd(card->host, &cmd, retries);
6380a2d4048a22079d7e79d6654bbacbef57bd5728aRussell King - ARM Linux	if (err == 0)
6390a2d4048a22079d7e79d6654bbacbef57bd5728aRussell King - ARM Linux		*status = cmd.resp[0];
6400a2d4048a22079d7e79d6654bbacbef57bd5728aRussell King - ARM Linux	return err;
641504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter}
642504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter
643a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma#define ERR_NOMEDIUM	3
644a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux#define ERR_RETRY	2
645a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux#define ERR_ABORT	1
646a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux#define ERR_CONTINUE	0
647a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
648a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linuxstatic int mmc_blk_cmd_error(struct request *req, const char *name, int error,
649a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	bool status_valid, u32 status)
650a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux{
651a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	switch (error) {
652a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	case -EILSEQ:
653a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		/* response crc error, retry the r/w cmd */
654a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		pr_err("%s: %s sending %s command, card status %#x\n",
655a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux			req->rq_disk->disk_name, "response CRC error",
656a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux			name, status);
657a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		return ERR_RETRY;
658a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
659a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	case -ETIMEDOUT:
660a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		pr_err("%s: %s sending %s command, card status %#x\n",
661a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux			req->rq_disk->disk_name, "timed out", name, status);
662a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
663a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		/* If the status cmd initially failed, retry the r/w cmd */
664a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		if (!status_valid)
665a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux			return ERR_RETRY;
666a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
667a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		/*
668a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		 * If it was a r/w cmd crc error, or illegal command
669a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		 * (eg, issued in wrong state) then retry - we should
670a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		 * have corrected the state problem above.
671a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		 */
672a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		if (status & (R1_COM_CRC_ERROR | R1_ILLEGAL_COMMAND))
673a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux			return ERR_RETRY;
674a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
675a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		/* Otherwise abort the command */
676a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		return ERR_ABORT;
677a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
678a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	default:
679a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		/* We don't understand the error code the driver gave us */
680a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		pr_err("%s: unknown error %d sending read/write command, card status %#x\n",
681a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		       req->rq_disk->disk_name, error, status);
682a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		return ERR_ABORT;
683a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	}
684a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux}
685a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
686a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux/*
687a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * Initial r/w and stop cmd error recovery.
688a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * We don't know whether the card received the r/w cmd or not, so try to
689a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * restore things back to a sane state.  Essentially, we do this as follows:
690a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * - Obtain card status.  If the first attempt to obtain card status fails,
691a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux *   the status word will reflect the failed status cmd, not the failed
692a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux *   r/w cmd.  If we fail to obtain card status, it suggests we can no
693a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux *   longer communicate with the card.
694a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * - Check the card state.  If the card received the cmd but there was a
695a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux *   transient problem with the response, it might still be in a data transfer
696a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux *   mode.  Try to send it a stop command.  If this fails, we can't recover.
697a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * - If the r/w cmd failed due to a response CRC error, it was probably
698a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux *   transient, so retry the cmd.
699a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * - If the r/w cmd timed out, but we didn't get the r/w cmd status, retry.
700a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * - If the r/w cmd timed out, and the r/w cmd failed due to CRC error or
701a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux *   illegal cmd, retry.
702a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * Otherwise we don't understand what happened, so abort.
703a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux */
704a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linuxstatic int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req,
70567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	struct mmc_blk_request *brq, int *ecc_err)
706a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux{
707a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	bool prev_cmd_status_valid = true;
708a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	u32 status, stop_status = 0;
709a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	int err, retry;
710a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
711a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma	if (mmc_card_removed(card))
712a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma		return ERR_NOMEDIUM;
713a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma
714a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	/*
715a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	 * Try to get card status which indicates both the card state
716a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	 * and why there was no response.  If the first attempt fails,
717a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	 * we can't be sure the returned status is for the r/w command.
718a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	 */
719a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	for (retry = 2; retry >= 0; retry--) {
720a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		err = get_card_status(card, &status, 0);
721a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		if (!err)
722a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux			break;
723a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
724a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		prev_cmd_status_valid = false;
725a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		pr_err("%s: error %d sending status command, %sing\n",
726a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		       req->rq_disk->disk_name, err, retry ? "retry" : "abort");
727a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	}
728a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
729a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	/* We couldn't get a response from the card.  Give up. */
730a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma	if (err) {
731a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma		/* Check if the card is removed */
732a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma		if (mmc_detect_card_removed(card->host))
733a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma			return ERR_NOMEDIUM;
734a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		return ERR_ABORT;
735a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma	}
736a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
73767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	/* Flag ECC errors */
73867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	if ((status & R1_CARD_ECC_FAILED) ||
73967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	    (brq->stop.resp[0] & R1_CARD_ECC_FAILED) ||
74067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	    (brq->cmd.resp[0] & R1_CARD_ECC_FAILED))
74167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		*ecc_err = 1;
74267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter
743a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	/*
744a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	 * Check the current card state.  If it is in some data transfer
745a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	 * mode, tell it to stop (and hopefully transition back to TRAN.)
746a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	 */
747a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	if (R1_CURRENT_STATE(status) == R1_STATE_DATA ||
748a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	    R1_CURRENT_STATE(status) == R1_STATE_RCV) {
749a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		err = send_stop(card, &stop_status);
750a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		if (err)
751a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux			pr_err("%s: error %d sending stop command\n",
752a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux			       req->rq_disk->disk_name, err);
753a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
754a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		/*
755a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		 * If the stop cmd also timed out, the card is probably
756a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		 * not present, so abort.  Other errors are bad news too.
757a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		 */
758a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		if (err)
759a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux			return ERR_ABORT;
76067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		if (stop_status & R1_CARD_ECC_FAILED)
76167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			*ecc_err = 1;
762a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	}
763a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
764a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	/* Check for set block count errors */
765a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	if (brq->sbc.error)
766a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		return mmc_blk_cmd_error(req, "SET_BLOCK_COUNT", brq->sbc.error,
767a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux				prev_cmd_status_valid, status);
768a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
769a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	/* Check for r/w command errors */
770a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	if (brq->cmd.error)
771a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		return mmc_blk_cmd_error(req, "r/w cmd", brq->cmd.error,
772a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux				prev_cmd_status_valid, status);
773a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
77467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	/* Data errors */
77567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	if (!brq->stop.error)
77667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		return ERR_CONTINUE;
77767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter
778a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	/* Now for stop errors.  These aren't fatal to the transfer. */
779a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	pr_err("%s: error %d sending stop command, original cmd response %#x, card status %#x\n",
780a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	       req->rq_disk->disk_name, brq->stop.error,
781a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	       brq->cmd.resp[0], status);
782a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
783a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	/*
784a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	 * Subsitute in our own stop status as this will give the error
785a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	 * state which happened during the execution of the r/w command.
786a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	 */
787a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	if (stop_status) {
788a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		brq->stop.resp[0] = stop_status;
789a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		brq->stop.error = 0;
790a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	}
791a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	return ERR_CONTINUE;
792a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux}
793a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
79467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunterstatic int mmc_blk_reset(struct mmc_blk_data *md, struct mmc_host *host,
79567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			 int type)
79667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter{
79767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	int err;
79867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter
79967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	if (md->reset_done & type)
80067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		return -EEXIST;
80167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter
80267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	md->reset_done |= type;
80367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	err = mmc_hw_reset(host);
80467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	/* Ensure we switch back to the correct partition */
80567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	if (err != -EOPNOTSUPP) {
80667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		struct mmc_blk_data *main_md = mmc_get_drvdata(host->card);
80767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		int part_err;
80867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter
80967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		main_md->part_curr = main_md->part_type;
81067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		part_err = mmc_blk_part_switch(host->card, md);
81167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		if (part_err) {
81267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			/*
81367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			 * We have failed to get back into the correct
81467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			 * partition, so we need to abort the whole request.
81567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			 */
81667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			return -ENODEV;
81767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		}
81867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	}
81967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	return err;
82067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter}
82167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter
82267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunterstatic inline void mmc_blk_reset_success(struct mmc_blk_data *md, int type)
82367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter{
82467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	md->reset_done &= ~type;
82567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter}
82667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter
827bd788c9665fb7c543aac21317059375632343337Adrian Hunterstatic int mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req)
828bd788c9665fb7c543aac21317059375632343337Adrian Hunter{
829bd788c9665fb7c543aac21317059375632343337Adrian Hunter	struct mmc_blk_data *md = mq->data;
830bd788c9665fb7c543aac21317059375632343337Adrian Hunter	struct mmc_card *card = md->queue.card;
831bd788c9665fb7c543aac21317059375632343337Adrian Hunter	unsigned int from, nr, arg;
83267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	int err = 0, type = MMC_BLK_DISCARD;
833bd788c9665fb7c543aac21317059375632343337Adrian Hunter
834bd788c9665fb7c543aac21317059375632343337Adrian Hunter	if (!mmc_can_erase(card)) {
835bd788c9665fb7c543aac21317059375632343337Adrian Hunter		err = -EOPNOTSUPP;
836bd788c9665fb7c543aac21317059375632343337Adrian Hunter		goto out;
837bd788c9665fb7c543aac21317059375632343337Adrian Hunter	}
838bd788c9665fb7c543aac21317059375632343337Adrian Hunter
839bd788c9665fb7c543aac21317059375632343337Adrian Hunter	from = blk_rq_pos(req);
840bd788c9665fb7c543aac21317059375632343337Adrian Hunter	nr = blk_rq_sectors(req);
841bd788c9665fb7c543aac21317059375632343337Adrian Hunter
842b3bf915308ca2b50f3beec6cc824083870f0f4b5Kyungmin Park	if (mmc_can_discard(card))
843b3bf915308ca2b50f3beec6cc824083870f0f4b5Kyungmin Park		arg = MMC_DISCARD_ARG;
844b3bf915308ca2b50f3beec6cc824083870f0f4b5Kyungmin Park	else if (mmc_can_trim(card))
845bd788c9665fb7c543aac21317059375632343337Adrian Hunter		arg = MMC_TRIM_ARG;
846bd788c9665fb7c543aac21317059375632343337Adrian Hunter	else
847bd788c9665fb7c543aac21317059375632343337Adrian Hunter		arg = MMC_ERASE_ARG;
84867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunterretry:
8496a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin	if (card->quirks & MMC_QUIRK_INAND_CMD38) {
8506a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
8516a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin				 INAND_CMD38_ARG_EXT_CSD,
8526a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin				 arg == MMC_TRIM_ARG ?
8536a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin				 INAND_CMD38_ARG_TRIM :
8546a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin				 INAND_CMD38_ARG_ERASE,
8556a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin				 0);
8566a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin		if (err)
8576a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin			goto out;
8586a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin	}
859bd788c9665fb7c543aac21317059375632343337Adrian Hunter	err = mmc_erase(card, from, nr, arg);
860bd788c9665fb7c543aac21317059375632343337Adrian Hunterout:
86167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	if (err == -EIO && !mmc_blk_reset(md, card->host, type))
86267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		goto retry;
86367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	if (!err)
86467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		mmc_blk_reset_success(md, type);
865bd788c9665fb7c543aac21317059375632343337Adrian Hunter	spin_lock_irq(&md->lock);
866bd788c9665fb7c543aac21317059375632343337Adrian Hunter	__blk_end_request(req, err, blk_rq_bytes(req));
867bd788c9665fb7c543aac21317059375632343337Adrian Hunter	spin_unlock_irq(&md->lock);
868bd788c9665fb7c543aac21317059375632343337Adrian Hunter
869bd788c9665fb7c543aac21317059375632343337Adrian Hunter	return err ? 0 : 1;
870bd788c9665fb7c543aac21317059375632343337Adrian Hunter}
871bd788c9665fb7c543aac21317059375632343337Adrian Hunter
8724980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunterstatic int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq,
8734980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter				       struct request *req)
8744980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter{
8754980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter	struct mmc_blk_data *md = mq->data;
8764980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter	struct mmc_card *card = md->queue.card;
8774980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter	unsigned int from, nr, arg;
87867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	int err = 0, type = MMC_BLK_SECDISCARD;
8794980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter
880d9ddd62943ee07a75d0428ffcf52f1a747a28c39Kyungmin Park	if (!(mmc_can_secure_erase_trim(card) || mmc_can_sanitize(card))) {
8814980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter		err = -EOPNOTSUPP;
8824980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter		goto out;
8834980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter	}
8844980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter
885d9ddd62943ee07a75d0428ffcf52f1a747a28c39Kyungmin Park	/* The sanitize operation is supported at v4.5 only */
886d9ddd62943ee07a75d0428ffcf52f1a747a28c39Kyungmin Park	if (mmc_can_sanitize(card)) {
887d9ddd62943ee07a75d0428ffcf52f1a747a28c39Kyungmin Park		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
888d9ddd62943ee07a75d0428ffcf52f1a747a28c39Kyungmin Park				EXT_CSD_SANITIZE_START, 1, 0);
889d9ddd62943ee07a75d0428ffcf52f1a747a28c39Kyungmin Park		goto out;
890d9ddd62943ee07a75d0428ffcf52f1a747a28c39Kyungmin Park	}
891d9ddd62943ee07a75d0428ffcf52f1a747a28c39Kyungmin Park
8924980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter	from = blk_rq_pos(req);
8934980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter	nr = blk_rq_sectors(req);
8944980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter
8954980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter	if (mmc_can_trim(card) && !mmc_erase_group_aligned(card, from, nr))
8964980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter		arg = MMC_SECURE_TRIM1_ARG;
8974980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter	else
8984980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter		arg = MMC_SECURE_ERASE_ARG;
89967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunterretry:
9006a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin	if (card->quirks & MMC_QUIRK_INAND_CMD38) {
9016a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
9026a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin				 INAND_CMD38_ARG_EXT_CSD,
9036a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin				 arg == MMC_SECURE_TRIM1_ARG ?
9046a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin				 INAND_CMD38_ARG_SECTRIM1 :
9056a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin				 INAND_CMD38_ARG_SECERASE,
9066a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin				 0);
9076a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin		if (err)
9086a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin			goto out;
9096a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin	}
9104980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter	err = mmc_erase(card, from, nr, arg);
9116a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin	if (!err && arg == MMC_SECURE_TRIM1_ARG) {
9126a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin		if (card->quirks & MMC_QUIRK_INAND_CMD38) {
9136a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin			err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
9146a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin					 INAND_CMD38_ARG_EXT_CSD,
9156a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin					 INAND_CMD38_ARG_SECTRIM2,
9166a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin					 0);
9176a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin			if (err)
9186a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin				goto out;
9196a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin		}
9204980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter		err = mmc_erase(card, from, nr, MMC_SECURE_TRIM2_ARG);
9216a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin	}
9224980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunterout:
92367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	if (err == -EIO && !mmc_blk_reset(md, card->host, type))
92467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		goto retry;
92567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	if (!err)
92667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		mmc_blk_reset_success(md, type);
9274980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter	spin_lock_irq(&md->lock);
9284980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter	__blk_end_request(req, err, blk_rq_bytes(req));
9294980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter	spin_unlock_irq(&md->lock);
9304980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter
9314980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter	return err ? 0 : 1;
9324980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter}
9334980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter
934f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentinstatic int mmc_blk_issue_flush(struct mmc_queue *mq, struct request *req)
935f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin{
936f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin	struct mmc_blk_data *md = mq->data;
937881d1c25f765938a95def5afe39486ce39f9fc96Seungwon Jeon	struct mmc_card *card = md->queue.card;
938881d1c25f765938a95def5afe39486ce39f9fc96Seungwon Jeon	int ret = 0;
939881d1c25f765938a95def5afe39486ce39f9fc96Seungwon Jeon
940881d1c25f765938a95def5afe39486ce39f9fc96Seungwon Jeon	ret = mmc_flush_cache(card);
941881d1c25f765938a95def5afe39486ce39f9fc96Seungwon Jeon	if (ret)
942881d1c25f765938a95def5afe39486ce39f9fc96Seungwon Jeon		ret = -EIO;
943f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin
944f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin	spin_lock_irq(&md->lock);
945881d1c25f765938a95def5afe39486ce39f9fc96Seungwon Jeon	__blk_end_request_all(req, ret);
946f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin	spin_unlock_irq(&md->lock);
947f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin
948881d1c25f765938a95def5afe39486ce39f9fc96Seungwon Jeon	return ret ? 0 : 1;
949f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin}
950f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin
951f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin/*
952f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin * Reformat current write as a reliable write, supporting
953f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin * both legacy and the enhanced reliable write MMC cards.
954f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin * In each transfer we'll handle only as much as a single
955f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin * reliable write can handle, thus finish the request in
956f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin * partial completions.
957f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin */
958d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentinstatic inline void mmc_apply_rel_rw(struct mmc_blk_request *brq,
959d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin				    struct mmc_card *card,
960d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin				    struct request *req)
961f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin{
962f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin	if (!(card->ext_csd.rel_param & EXT_CSD_WR_REL_PARAM_EN)) {
963f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin		/* Legacy mode imposes restrictions on transfers. */
964f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin		if (!IS_ALIGNED(brq->cmd.arg, card->ext_csd.rel_sectors))
965f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin			brq->data.blocks = 1;
966f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin
967f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin		if (brq->data.blocks > card->ext_csd.rel_sectors)
968f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin			brq->data.blocks = card->ext_csd.rel_sectors;
969f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin		else if (brq->data.blocks < card->ext_csd.rel_sectors)
970f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin			brq->data.blocks = 1;
971f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin	}
972f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin}
973f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin
9744c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux#define CMD_ERRORS							\
9754c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux	(R1_OUT_OF_RANGE |	/* Command argument out of range */	\
9764c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux	 R1_ADDRESS_ERROR |	/* Misaligned address */		\
9774c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux	 R1_BLOCK_LEN_ERROR |	/* Transferred block length incorrect */\
9784c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux	 R1_WP_VIOLATION |	/* Tried to write to protected block */	\
9794c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux	 R1_CC_ERROR |		/* Card controller error */		\
9804c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux	 R1_ERROR)		/* General/unknown error */
9814c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux
982ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlinstatic int mmc_blk_err_check(struct mmc_card *card,
983ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin			     struct mmc_async_req *areq)
984d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin{
985ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin	struct mmc_queue_req *mq_mrq = container_of(areq, struct mmc_queue_req,
986ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin						    mmc_active);
987ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin	struct mmc_blk_request *brq = &mq_mrq->brq;
988ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin	struct request *req = mq_mrq->req;
98967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	int ecc_err = 0;
990d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin
991d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	/*
992d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 * sbc.error indicates a problem with the set block count
993d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 * command.  No data will have been transferred.
994d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 *
995d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 * cmd.error indicates a problem with the r/w command.  No
996d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 * data will have been transferred.
997d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 *
998d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 * stop.error indicates a problem with the stop command.  Data
999d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 * may have been transferred, or may still be transferring.
1000d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 */
100167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	if (brq->sbc.error || brq->cmd.error || brq->stop.error ||
100267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	    brq->data.error) {
100367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		switch (mmc_blk_cmd_recovery(card, req, brq, &ecc_err)) {
1004d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		case ERR_RETRY:
1005d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			return MMC_BLK_RETRY;
1006d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		case ERR_ABORT:
1007d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			return MMC_BLK_ABORT;
1008a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma		case ERR_NOMEDIUM:
1009a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma			return MMC_BLK_NOMEDIUM;
1010d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		case ERR_CONTINUE:
1011d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			break;
1012d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		}
1013d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	}
1014d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin
1015d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	/*
1016d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 * Check for errors relating to the execution of the
1017d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 * initial command - such as address errors.  No data
1018d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 * has been transferred.
1019d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 */
1020d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	if (brq->cmd.resp[0] & CMD_ERRORS) {
1021d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		pr_err("%s: r/w command failed, status = %#x\n",
1022d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		       req->rq_disk->disk_name, brq->cmd.resp[0]);
1023d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		return MMC_BLK_ABORT;
1024d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	}
1025d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin
1026d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	/*
1027d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 * Everything else is either success, or a data error of some
1028d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 * kind.  If it was a write, we may have transitioned to
1029d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 * program mode, which we have to wait for it to complete.
1030d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 */
1031d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) {
1032d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		u32 status;
1033d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		do {
1034d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			int err = get_card_status(card, &status, 5);
1035d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			if (err) {
1036a3c76eb9d4a1e68a69dd880cf0bcb8a52418b993Girish K S				pr_err("%s: error %d requesting status\n",
1037d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin				       req->rq_disk->disk_name, err);
1038d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin				return MMC_BLK_CMD_ERR;
1039d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			}
1040d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			/*
1041d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			 * Some cards mishandle the status bits,
1042d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			 * so make sure to check both the busy
1043d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			 * indication and the card state.
1044d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			 */
1045d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		} while (!(status & R1_READY_FOR_DATA) ||
1046d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			 (R1_CURRENT_STATE(status) == R1_STATE_PRG));
1047d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	}
1048d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin
1049d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	if (brq->data.error) {
1050d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		pr_err("%s: error %d transferring data, sector %u, nr %u, cmd response %#x, card status %#x\n",
1051d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		       req->rq_disk->disk_name, brq->data.error,
1052d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		       (unsigned)blk_rq_pos(req),
1053d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		       (unsigned)blk_rq_sectors(req),
1054d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		       brq->cmd.resp[0], brq->stop.resp[0]);
1055d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin
1056d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		if (rq_data_dir(req) == READ) {
105767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			if (ecc_err)
105867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter				return MMC_BLK_ECC_ERR;
1059d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			return MMC_BLK_DATA_ERR;
1060d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		} else {
1061d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			return MMC_BLK_CMD_ERR;
1062d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		}
1063d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	}
1064d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin
106567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	if (!brq->data.bytes_xfered)
106667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		return MMC_BLK_RETRY;
1067d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin
106867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	if (blk_rq_bytes(req) != brq->data.bytes_xfered)
106967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		return MMC_BLK_PARTIAL;
107067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter
107167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	return MMC_BLK_SUCCESS;
1072d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin}
1073d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin
107454d49d77628bed77e5491b8a2a1158a492843a19Per Forlinstatic void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
107554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin			       struct mmc_card *card,
107654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin			       int disable_multi,
107754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin			       struct mmc_queue *mq)
10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
107954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	u32 readcmd, writecmd;
108054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	struct mmc_blk_request *brq = &mqrq->brq;
108154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	struct request *req = mqrq->req;
10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mmc_blk_data *md = mq->data;
10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1084f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin	/*
1085f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin	 * Reliable writes are used to implement Forced Unit Access and
1086f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin	 * REQ_META accesses, and are supported only on MMCs.
108765299a3b788bd274bed92f9fa3232082c9f3ea70Christoph Hellwig	 *
108865299a3b788bd274bed92f9fa3232082c9f3ea70Christoph Hellwig	 * XXX: this really needs a good explanation of why REQ_META
108965299a3b788bd274bed92f9fa3232082c9f3ea70Christoph Hellwig	 * is treated special.
1090f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin	 */
1091f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin	bool do_rel_wr = ((req->cmd_flags & REQ_FUA) ||
1092f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin			  (req->cmd_flags & REQ_META)) &&
1093f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin		(rq_data_dir(req) == WRITE) &&
1094d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin		(md->flags & MMC_BLK_REL_WR);
1095f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin
109654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	memset(brq, 0, sizeof(struct mmc_blk_request));
109754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	brq->mrq.cmd = &brq->cmd;
109854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	brq->mrq.data = &brq->data;
10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
110054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	brq->cmd.arg = blk_rq_pos(req);
110154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	if (!mmc_card_blockaddr(card))
110254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		brq->cmd.arg <<= 9;
110354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	brq->cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
110454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	brq->data.blksz = 512;
110554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	brq->stop.opcode = MMC_STOP_TRANSMISSION;
110654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	brq->stop.arg = 0;
110754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	brq->stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
110854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	brq->data.blocks = blk_rq_sectors(req);
11096a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter
111054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	/*
111154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * The block layer doesn't support all sector count
111254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * restrictions, so we need to be prepared for too big
111354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * requests.
111454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 */
111554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	if (brq->data.blocks > card->host->max_blk_count)
111654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		brq->data.blocks = card->host->max_blk_count;
11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11182bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley	if (brq->data.blocks > 1) {
11192bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley		/*
11202bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley		 * After a read error, we redo the request one sector
11212bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley		 * at a time in order to accurately determine which
11222bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley		 * sectors can be read successfully.
11232bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley		 */
11242bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley		if (disable_multi)
11252bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley			brq->data.blocks = 1;
11262bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley
11272bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley		/* Some controllers can't do multiblock reads due to hw bugs */
11282bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley		if (card->host->caps2 & MMC_CAP2_NO_MULTI_READ &&
11292bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley		    rq_data_dir(req) == READ)
11302bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley			brq->data.blocks = 1;
11312bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley	}
1132d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin
113354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	if (brq->data.blocks > 1 || do_rel_wr) {
113454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		/* SPI multiblock writes terminate using a special
113554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		 * token, not a STOP_TRANSMISSION request.
1136d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin		 */
113754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		if (!mmc_host_is_spi(card->host) ||
113854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		    rq_data_dir(req) == READ)
113954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin			brq->mrq.stop = &brq->stop;
114054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		readcmd = MMC_READ_MULTIPLE_BLOCK;
114154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		writecmd = MMC_WRITE_MULTIPLE_BLOCK;
114254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	} else {
114354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		brq->mrq.stop = NULL;
114454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		readcmd = MMC_READ_SINGLE_BLOCK;
114554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		writecmd = MMC_WRITE_BLOCK;
114654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	}
114754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	if (rq_data_dir(req) == READ) {
114854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		brq->cmd.opcode = readcmd;
114954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		brq->data.flags |= MMC_DATA_READ;
115054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	} else {
115154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		brq->cmd.opcode = writecmd;
115254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		brq->data.flags |= MMC_DATA_WRITE;
115354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	}
1154d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin
115554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	if (do_rel_wr)
115654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		mmc_apply_rel_rw(brq, card, req);
1157f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin
115854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	/*
115954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * Pre-defined multi-block transfers are preferable to
116054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * open ended-ones (and necessary for reliable writes).
116154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * However, it is not sufficient to just send CMD23,
116254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * and avoid the final CMD12, as on an error condition
116354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * CMD12 (stop) needs to be sent anyway. This, coupled
116454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * with Auto-CMD23 enhancements provided by some
116554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * hosts, means that the complexity of dealing
116654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * with this is best left to the host. If CMD23 is
116754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * supported by card and host, we'll fill sbc in and let
116854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * the host deal with handling it correctly. This means
116954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * that for hosts that don't expose MMC_CAP_CMD23, no
117054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * change of behavior will be observed.
117154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 *
117254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * N.B: Some MMC cards experience perf degradation.
117354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * We'll avoid using CMD23-bounded multiblock writes for
117454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * these, while retaining features like reliable writes.
117554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 */
1176b146d26a61e0feab2f12a98ae83fd352830899c0Pierre Ossman
117754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	if ((md->flags & MMC_BLK_CMD23) &&
117854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	    mmc_op_multi(brq->cmd.opcode) &&
117954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	    (do_rel_wr || !(card->quirks & MMC_QUIRK_BLK_NO_CMD23))) {
118054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		brq->sbc.opcode = MMC_SET_BLOCK_COUNT;
118154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		brq->sbc.arg = brq->data.blocks |
118254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin			(do_rel_wr ? (1 << 31) : 0);
118354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		brq->sbc.flags = MMC_RSP_R1 | MMC_CMD_AC;
118454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		brq->mrq.sbc = &brq->sbc;
118554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	}
118698ccf14909ba02a41c5925b0b2c92aeeef23d3b9Pierre Ossman
118754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	mmc_set_data_timeout(&brq->data, card);
118854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin
118954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	brq->data.sg = mqrq->sg;
119054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	brq->data.sg_len = mmc_queue_map_sg(mq, mqrq);
119154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin
119254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	/*
119354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * Adjust the sg list so it is the same size as the
119454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * request.
119554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 */
119654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	if (brq->data.blocks != blk_rq_sectors(req)) {
119754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		int i, data_size = brq->data.blocks << 9;
119854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		struct scatterlist *sg;
119954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin
120054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		for_each_sg(brq->data.sg, sg, brq->data.sg_len, i) {
120154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin			data_size -= sg->length;
120254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin			if (data_size <= 0) {
120354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin				sg->length += data_size;
120454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin				i++;
120554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin				break;
12066a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter			}
12076a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter		}
120854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		brq->data.sg_len = i;
120954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	}
121054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin
1211ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin	mqrq->mmc_active.mrq = &brq->mrq;
1212ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin	mqrq->mmc_active.err_check = mmc_blk_err_check;
1213ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin
121454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	mmc_queue_bounce_pre(mqrq);
121554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin}
12166a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter
121767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunterstatic int mmc_blk_cmd_err(struct mmc_blk_data *md, struct mmc_card *card,
121867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			   struct mmc_blk_request *brq, struct request *req,
121967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			   int ret)
122067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter{
122167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	/*
122267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	 * If this is an SD card and we're writing, we can first
122367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	 * mark the known good sectors as ok.
122467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	 *
122567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	 * If the card is not SD, we can still ok written sectors
122667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	 * as reported by the controller (which might be less than
122767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	 * the real number of written sectors, but never more).
122867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	 */
122967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	if (mmc_card_sd(card)) {
123067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		u32 blocks;
123167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter
123267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		blocks = mmc_sd_num_wr_blocks(card);
123367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		if (blocks != (u32)-1) {
123467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			spin_lock_irq(&md->lock);
123567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			ret = __blk_end_request(req, 0, blocks << 9);
123667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			spin_unlock_irq(&md->lock);
123767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		}
123867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	} else {
123967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		spin_lock_irq(&md->lock);
124067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		ret = __blk_end_request(req, 0, brq->data.bytes_xfered);
124167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		spin_unlock_irq(&md->lock);
124267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	}
124367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	return ret;
124467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter}
124567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter
1246ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlinstatic int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
124754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin{
124854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	struct mmc_blk_data *md = mq->data;
124954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	struct mmc_card *card = md->queue.card;
125054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	struct mmc_blk_request *brq = &mq->mqrq_cur->brq;
125167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	int ret = 1, disable_multi = 0, retry = 0, type;
1252d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	enum mmc_blk_status status;
1253ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin	struct mmc_queue_req *mq_rq;
1254ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin	struct request *req;
1255ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin	struct mmc_async_req *areq;
12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1257ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin	if (!rqc && !mq->mqrq_prev->req)
1258ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		return 0;
125998ccf14909ba02a41c5925b0b2c92aeeef23d3b9Pierre Ossman
1260ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin	do {
1261ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		if (rqc) {
1262ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin			mmc_blk_rw_rq_prep(mq->mqrq_cur, card, 0, mq);
1263ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin			areq = &mq->mqrq_cur->mmc_active;
1264ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		} else
1265ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin			areq = NULL;
1266ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		areq = mmc_start_req(card->host, areq, (int *) &status);
1267ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		if (!areq)
1268ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin			return 0;
1269ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin
1270ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		mq_rq = container_of(areq, struct mmc_queue_req, mmc_active);
1271ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		brq = &mq_rq->brq;
1272ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		req = mq_rq->req;
127367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		type = rq_data_dir(req) == READ ? MMC_BLK_READ : MMC_BLK_WRITE;
1274ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		mmc_queue_bounce_post(mq_rq);
127598ccf14909ba02a41c5925b0b2c92aeeef23d3b9Pierre Ossman
1276d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		switch (status) {
1277d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		case MMC_BLK_SUCCESS:
1278d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		case MMC_BLK_PARTIAL:
1279d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			/*
1280d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			 * A block was successfully transferred.
1281d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			 */
128267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			mmc_blk_reset_success(md, type);
1283d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			spin_lock_irq(&md->lock);
1284d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			ret = __blk_end_request(req, 0,
1285d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin						brq->data.bytes_xfered);
1286d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			spin_unlock_irq(&md->lock);
128767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			/*
128867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			 * If the blk_end_request function returns non-zero even
128967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			 * though all data has been transferred and no errors
129067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			 * were returned by the host controller, it's a bug.
129167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			 */
1292ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin			if (status == MMC_BLK_SUCCESS && ret) {
1293a3c76eb9d4a1e68a69dd880cf0bcb8a52418b993Girish K S				pr_err("%s BUG rq_tot %d d_xfer %d\n",
1294ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin				       __func__, blk_rq_bytes(req),
1295ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin				       brq->data.bytes_xfered);
1296ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin				rqc = NULL;
1297ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin				goto cmd_abort;
1298ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin			}
1299d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			break;
1300d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		case MMC_BLK_CMD_ERR:
130167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			ret = mmc_blk_cmd_err(md, card, brq, req, ret);
130267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			if (!mmc_blk_reset(md, card->host, type))
130367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter				break;
130467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			goto cmd_abort;
1305d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		case MMC_BLK_RETRY:
1306d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			if (retry++ < 5)
1307a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux				break;
130867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			/* Fall through */
1309d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		case MMC_BLK_ABORT:
131067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			if (!mmc_blk_reset(md, card->host, type))
131167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter				break;
13124c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux			goto cmd_abort;
131367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		case MMC_BLK_DATA_ERR: {
131467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			int err;
131567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter
131667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			err = mmc_blk_reset(md, card->host, type);
131767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			if (!err)
131867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter				break;
131967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			if (err == -ENODEV)
132067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter				goto cmd_abort;
132167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			/* Fall through */
132267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		}
132367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		case MMC_BLK_ECC_ERR:
132467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			if (brq->data.blocks > 1) {
132567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter				/* Redo read one sector at a time */
132667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter				pr_warning("%s: retrying using single block read\n",
132767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter					   req->rq_disk->disk_name);
132867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter				disable_multi = 1;
132967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter				break;
133067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			}
1331d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			/*
1332d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			 * After an error, we redo I/O one sector at a
1333d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			 * time, so we only reach here after trying to
1334d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			 * read a single sector.
1335d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			 */
1336d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			spin_lock_irq(&md->lock);
1337d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			ret = __blk_end_request(req, -EIO,
1338d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin						brq->data.blksz);
1339d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			spin_unlock_irq(&md->lock);
1340ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin			if (!ret)
1341ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin				goto start_new_req;
1342d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			break;
1343a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma		case MMC_BLK_NOMEDIUM:
1344a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma			goto cmd_abort;
13454c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux		}
13464c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux
1347ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		if (ret) {
1348ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin			/*
134967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			 * In case of a incomplete request
1350ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin			 * prepare it again and resend.
1351ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin			 */
1352ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin			mmc_blk_rw_rq_prep(mq_rq, card, disable_multi, mq);
1353ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin			mmc_start_req(card->host, &mq_rq->mmc_active, NULL);
1354ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		}
13551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} while (ret);
13561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 1;
13581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1359a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux cmd_abort:
13601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irq(&md->lock);
1361a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma	if (mmc_card_removed(card))
1362a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma		req->cmd_flags |= REQ_QUIET;
1363fd539832c7d3a242269374dbcae2cd54da150930Kiyoshi Ueda	while (ret)
1364fd539832c7d3a242269374dbcae2cd54da150930Kiyoshi Ueda		ret = __blk_end_request(req, -EIO, blk_rq_cur_bytes(req));
13651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irq(&md->lock);
13661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1367ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin start_new_req:
1368ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin	if (rqc) {
1369ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		mmc_blk_rw_rq_prep(mq->mqrq_cur, card, 0, mq);
1370ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		mmc_start_req(card->host, &mq->mqrq_cur->mmc_active, NULL);
1371ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin	}
1372ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin
13731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
13741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1376bd788c9665fb7c543aac21317059375632343337Adrian Hunterstatic int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
1377bd788c9665fb7c543aac21317059375632343337Adrian Hunter{
13781a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin	int ret;
13791a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin	struct mmc_blk_data *md = mq->data;
13801a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin	struct mmc_card *card = md->queue.card;
13811a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin
1382ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin	if (req && !mq->mqrq_prev->req)
1383ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		/* claim host only for the first request */
1384ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		mmc_claim_host(card->host);
1385ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin
1386371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	ret = mmc_blk_part_switch(card, md);
1387371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	if (ret) {
13880d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter		if (req) {
13890d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter			spin_lock_irq(&md->lock);
13900d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter			__blk_end_request_all(req, -EIO);
13910d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter			spin_unlock_irq(&md->lock);
13920d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter		}
1393371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		ret = 0;
1394371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		goto out;
1395371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	}
13961a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin
1397ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin	if (req && req->cmd_flags & REQ_DISCARD) {
1398ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		/* complete ongoing async transfer before issuing discard */
1399ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		if (card->host->areq)
1400ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin			mmc_blk_issue_rw_rq(mq, NULL);
14014980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter		if (req->cmd_flags & REQ_SECURE)
14021a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin			ret = mmc_blk_issue_secdiscard_rq(mq, req);
14034980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter		else
14041a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin			ret = mmc_blk_issue_discard_rq(mq, req);
1405ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin	} else if (req && req->cmd_flags & REQ_FLUSH) {
1406393f9a08e2ee72e42379489a5781feaf9c406d5fJaehoon Chung		/* complete ongoing async transfer before issuing flush */
1407393f9a08e2ee72e42379489a5781feaf9c406d5fJaehoon Chung		if (card->host->areq)
1408393f9a08e2ee72e42379489a5781feaf9c406d5fJaehoon Chung			mmc_blk_issue_rw_rq(mq, NULL);
14091a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin		ret = mmc_blk_issue_flush(mq, req);
14104980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter	} else {
14111a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin		ret = mmc_blk_issue_rw_rq(mq, req);
14124980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter	}
14131a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin
1414371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinout:
1415ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin	if (!req)
1416ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		/* release host only when there are no more requests */
1417ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		mmc_release_host(card->host);
14181a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin	return ret;
1419bd788c9665fb7c543aac21317059375632343337Adrian Hunter}
14201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1421a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell Kingstatic inline int mmc_blk_readonly(struct mmc_card *card)
1422a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King{
1423a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	return mmc_card_readonly(card) ||
1424a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	       !(card->csd.cmdclass & CCC_BLOCK_WRITE);
1425a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King}
1426a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King
1427371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
1428371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin					      struct device *parent,
1429371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin					      sector_t size,
1430371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin					      bool default_ro,
1431add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm					      const char *subname,
1432add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm					      int area_type)
14331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mmc_blk_data *md;
14351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int devidx, ret;
14361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14375e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson	devidx = find_first_zero_bit(dev_use, max_devices);
14385e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson	if (devidx >= max_devices)
14391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return ERR_PTR(-ENOSPC);
14401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__set_bit(devidx, dev_use);
14411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1442dd00cc486ab1c17049a535413d1751ef3482141cYoann Padioleau	md = kzalloc(sizeof(struct mmc_blk_data), GFP_KERNEL);
1443a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	if (!md) {
1444a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King		ret = -ENOMEM;
1445a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King		goto out;
1446a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	}
14471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1448a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	/*
1449f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin	 * !subname implies we are creating main mmc_blk_data that will be
1450f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin	 * associated with mmc_card with mmc_set_drvdata. Due to device
1451f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin	 * partitions, devidx will not coincide with a per-physical card
1452f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin	 * index anymore so we keep track of a name index.
1453f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin	 */
1454f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin	if (!subname) {
1455f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin		md->name_idx = find_first_zero_bit(name_use, max_devices);
1456f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin		__set_bit(md->name_idx, name_use);
1457add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	} else
1458f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin		md->name_idx = ((struct mmc_blk_data *)
1459f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin				dev_to_disk(parent)->private_data)->name_idx;
1460f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin
1461add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	md->area_type = area_type;
1462add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
1463f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin	/*
1464a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	 * Set the read-only status based on the supported commands
1465a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	 * and the write protect switch.
1466a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	 */
1467a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	md->read_only = mmc_blk_readonly(card);
14681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14695e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson	md->disk = alloc_disk(perdev_minors);
1470a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	if (md->disk == NULL) {
1471a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King		ret = -ENOMEM;
1472a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King		goto err_kfree;
1473a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	}
14741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1475a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	spin_lock_init(&md->lock);
1476371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	INIT_LIST_HEAD(&md->part);
1477a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	md->usage = 1;
14781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1479d09408ade08a08a710a247fb52aa50101e73ebf7Adrian Hunter	ret = mmc_init_queue(&md->queue, card, &md->lock, subname);
1480a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	if (ret)
1481a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King		goto err_putdisk;
14821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1483a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	md->queue.issue_fn = mmc_blk_issue_rq;
1484a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	md->queue.data = md;
1485d2b18394259ef621fd2a6322aa9934198fd87a6aRussell King
1486fe6b4c8840c5e23fe9b8696450cee8f2e8cebffdPierre Ossman	md->disk->major	= MMC_BLOCK_MAJOR;
14875e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson	md->disk->first_minor = devidx * perdev_minors;
1488a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	md->disk->fops = &mmc_bdops;
1489a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	md->disk->private_data = md;
1490a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	md->disk->queue = md->queue.queue;
1491371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	md->disk->driverfs_dev = parent;
1492371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	set_disk_ro(md->disk, md->read_only || default_ro);
1493a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King
1494a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	/*
1495a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	 * As discussed on lkml, GENHD_FL_REMOVABLE should:
1496a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	 *
1497a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	 * - be set for removable media with permanent block devices
1498a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	 * - be unset for removable block devices with permanent media
1499a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	 *
1500a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	 * Since MMC block devices clearly fall under the second
1501a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	 * case, we do not set GENHD_FL_REMOVABLE.  Userspace
1502a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	 * should use the block device creation/destruction hotplug
1503a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	 * messages to tell when the card is present.
1504a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	 */
1505a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King
1506f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin	snprintf(md->disk->disk_name, sizeof(md->disk->disk_name),
1507f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin		 "mmcblk%d%s", md->name_idx, subname ? subname : "");
1508a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King
1509e1defc4ff0cf57aca6c5e3ff99fa503f5943c1f1Martin K. Petersen	blk_queue_logical_block_size(md->queue.queue, 512);
1510371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	set_capacity(md->disk, size);
1511d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin
1512f0d89972b01798cf9d245dfa1cacfa0ee78a3593Andrei Warkentin	if (mmc_host_cmd23(card->host)) {
1513f0d89972b01798cf9d245dfa1cacfa0ee78a3593Andrei Warkentin		if (mmc_card_mmc(card) ||
1514f0d89972b01798cf9d245dfa1cacfa0ee78a3593Andrei Warkentin		    (mmc_card_sd(card) &&
1515f0d89972b01798cf9d245dfa1cacfa0ee78a3593Andrei Warkentin		     card->scr.cmds & SD_SCR_CMD23_SUPPORT))
1516f0d89972b01798cf9d245dfa1cacfa0ee78a3593Andrei Warkentin			md->flags |= MMC_BLK_CMD23;
1517f0d89972b01798cf9d245dfa1cacfa0ee78a3593Andrei Warkentin	}
1518d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin
1519d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin	if (mmc_card_mmc(card) &&
1520d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin	    md->flags & MMC_BLK_CMD23 &&
1521d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin	    ((card->ext_csd.rel_param & EXT_CSD_WR_REL_PARAM_EN) ||
1522d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin	     card->ext_csd.rel_sectors)) {
1523d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin		md->flags |= MMC_BLK_REL_WR;
1524d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin		blk_queue_flush(md->queue.queue, REQ_FLUSH | REQ_FUA);
1525d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin	}
1526d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin
1527371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	return md;
1528371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
1529371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin err_putdisk:
1530371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	put_disk(md->disk);
1531371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin err_kfree:
1532371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	kfree(md);
1533371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin out:
1534371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	return ERR_PTR(ret);
1535371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin}
1536371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
1537371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
1538371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{
1539371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	sector_t size;
1540371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	struct mmc_blk_data *md;
1541a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King
154285a18ad93ec66888d85758630019b10a84257f3cPierre Ossman	if (!mmc_card_sd(card) && mmc_card_blockaddr(card)) {
154385a18ad93ec66888d85758630019b10a84257f3cPierre Ossman		/*
154485a18ad93ec66888d85758630019b10a84257f3cPierre Ossman		 * The EXT_CSD sector count is in number or 512 byte
154585a18ad93ec66888d85758630019b10a84257f3cPierre Ossman		 * sectors.
154685a18ad93ec66888d85758630019b10a84257f3cPierre Ossman		 */
1547371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		size = card->ext_csd.sectors;
154885a18ad93ec66888d85758630019b10a84257f3cPierre Ossman	} else {
154985a18ad93ec66888d85758630019b10a84257f3cPierre Ossman		/*
155085a18ad93ec66888d85758630019b10a84257f3cPierre Ossman		 * The CSD capacity field is in units of read_blkbits.
155185a18ad93ec66888d85758630019b10a84257f3cPierre Ossman		 * set_capacity takes units of 512 bytes.
155285a18ad93ec66888d85758630019b10a84257f3cPierre Ossman		 */
1553371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		size = card->csd.capacity << (card->csd.read_blkbits - 9);
155485a18ad93ec66888d85758630019b10a84257f3cPierre Ossman	}
1555371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
1556add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	md = mmc_blk_alloc_req(card, &card->dev, size, false, NULL,
1557add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm					MMC_BLK_DATA_AREA_MAIN);
15581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return md;
1559371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin}
1560a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King
1561371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic int mmc_blk_alloc_part(struct mmc_card *card,
1562371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin			      struct mmc_blk_data *md,
1563371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin			      unsigned int part_type,
1564371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin			      sector_t size,
1565371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin			      bool default_ro,
1566add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm			      const char *subname,
1567add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm			      int area_type)
1568371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{
1569371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	char cap_str[10];
1570371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	struct mmc_blk_data *part_md;
1571371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
1572371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	part_md = mmc_blk_alloc_req(card, disk_to_dev(md->disk), size, default_ro,
1573add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm				    subname, area_type);
1574371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	if (IS_ERR(part_md))
1575371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		return PTR_ERR(part_md);
1576371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	part_md->part_type = part_type;
1577371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	list_add(&part_md->part, &md->part);
1578371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
1579371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	string_get_size((u64)get_capacity(part_md->disk) << 9, STRING_UNITS_2,
1580371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin			cap_str, sizeof(cap_str));
1581a3c76eb9d4a1e68a69dd880cf0bcb8a52418b993Girish K S	pr_info("%s: %s %s partition %u %s\n",
1582371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	       part_md->disk->disk_name, mmc_card_id(card),
1583371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	       mmc_card_name(card), part_md->part_type, cap_str);
1584371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	return 0;
1585371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin}
1586371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
1587e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon/* MMC Physical partitions consist of two boot partitions and
1588e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon * up to four general purpose partitions.
1589e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon * For each partition enabled in EXT_CSD a block device will be allocatedi
1590e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon * to provide access to the partition.
1591e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon */
1592e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon
1593371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic int mmc_blk_alloc_parts(struct mmc_card *card, struct mmc_blk_data *md)
1594371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{
1595e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon	int idx, ret = 0;
1596371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
1597371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	if (!mmc_card_mmc(card))
1598371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		return 0;
1599371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
1600e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon	for (idx = 0; idx < card->nr_parts; idx++) {
1601e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon		if (card->part[idx].size) {
1602e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon			ret = mmc_blk_alloc_part(card, md,
1603e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon				card->part[idx].part_cfg,
1604e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon				card->part[idx].size >> 9,
1605e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon				card->part[idx].force_ro,
1606add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm				card->part[idx].name,
1607add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm				card->part[idx].area_type);
1608e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon			if (ret)
1609e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon				return ret;
1610e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon		}
1611371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	}
1612371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
1613371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	return ret;
16141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
16151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
16171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card)
16181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
16191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err;
16201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1621b855885e3b60cf6f9452848712a62517b94583ebPierre Ossman	mmc_claim_host(card->host);
16220f8d8ea64ec7c77ca5beb59534d386fe0235961aAdrian Hunter	err = mmc_set_blocklen(card, 512);
1623b855885e3b60cf6f9452848712a62517b94583ebPierre Ossman	mmc_release_host(card->host);
16241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (err) {
1626a3c76eb9d4a1e68a69dd880cf0bcb8a52418b993Girish K S		pr_err("%s: unable to set block size to 512: %d\n",
16270f8d8ea64ec7c77ca5beb59534d386fe0235961aAdrian Hunter			md->disk->disk_name, err);
16281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
16291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
16301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
16321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
16331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1634371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic void mmc_blk_remove_req(struct mmc_blk_data *md)
1635371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{
1636add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	struct mmc_card *card;
1637add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
1638371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	if (md) {
1639add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		card = md->queue.card;
1640371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		if (md->disk->flags & GENHD_FL_UP) {
1641371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin			device_remove_file(disk_to_dev(md->disk), &md->force_ro);
1642add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm			if ((md->area_type & MMC_BLK_DATA_AREA_BOOT) &&
1643add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm					card->ext_csd.boot_ro_lockable)
1644add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm				device_remove_file(disk_to_dev(md->disk),
1645add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm					&md->power_ro_lock);
1646371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
1647371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin			/* Stop new requests from getting into the queue */
1648371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin			del_gendisk(md->disk);
1649371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		}
1650371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
1651371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		/* Then flush out any already in there */
1652371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		mmc_cleanup_queue(&md->queue);
1653371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		mmc_blk_put(md);
1654371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	}
1655371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin}
1656371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
1657371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic void mmc_blk_remove_parts(struct mmc_card *card,
1658371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin				 struct mmc_blk_data *md)
1659371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{
1660371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	struct list_head *pos, *q;
1661371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	struct mmc_blk_data *part_md;
1662371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
1663f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin	__clear_bit(md->name_idx, name_use);
1664371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	list_for_each_safe(pos, q, &md->part) {
1665371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		part_md = list_entry(pos, struct mmc_blk_data, part);
1666371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		list_del(pos);
1667371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		mmc_blk_remove_req(part_md);
1668371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	}
1669371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin}
1670371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
1671371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic int mmc_add_disk(struct mmc_blk_data *md)
1672371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{
1673371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	int ret;
1674add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	struct mmc_card *card = md->queue.card;
1675371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
1676371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	add_disk(md->disk);
1677371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	md->force_ro.show = force_ro_show;
1678371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	md->force_ro.store = force_ro_store;
1679641c3187b9d53cfd4c23b0ce2ab18a13d5e775e5Rabin Vincent	sysfs_attr_init(&md->force_ro.attr);
1680371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	md->force_ro.attr.name = "force_ro";
1681371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	md->force_ro.attr.mode = S_IRUGO | S_IWUSR;
1682371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	ret = device_create_file(disk_to_dev(md->disk), &md->force_ro);
1683371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	if (ret)
1684add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		goto force_ro_fail;
1685add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
1686add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	if ((md->area_type & MMC_BLK_DATA_AREA_BOOT) &&
1687add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	     card->ext_csd.boot_ro_lockable) {
168888187398cc5fa6650f38b9dcd5464667f468888fAl Viro		umode_t mode;
1689add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
1690add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		if (card->ext_csd.boot_ro_lock & EXT_CSD_BOOT_WP_B_PWR_WP_DIS)
1691add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm			mode = S_IRUGO;
1692add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		else
1693add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm			mode = S_IRUGO | S_IWUSR;
1694add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
1695add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		md->power_ro_lock.show = power_ro_lock_show;
1696add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		md->power_ro_lock.store = power_ro_lock_store;
169700d9ac08757049f334803b3d4dd202a6b1687dabRabin Vincent		sysfs_attr_init(&md->power_ro_lock.attr);
1698add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		md->power_ro_lock.attr.mode = mode;
1699add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		md->power_ro_lock.attr.name =
1700add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm					"ro_lock_until_next_power_on";
1701add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		ret = device_create_file(disk_to_dev(md->disk),
1702add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm				&md->power_ro_lock);
1703add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		if (ret)
1704add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm			goto power_ro_lock_fail;
1705add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	}
1706add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	return ret;
1707add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
1708add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholmpower_ro_lock_fail:
1709add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	device_remove_file(disk_to_dev(md->disk), &md->force_ro);
1710add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholmforce_ro_fail:
1711add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	del_gendisk(md->disk);
1712371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
1713371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	return ret;
1714371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin}
1715371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
1716c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball#define CID_MANFID_SANDISK	0x2
1717c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball#define CID_MANFID_TOSHIBA	0x11
1718c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball#define CID_MANFID_MICRON	0x13
1719c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball
17206f60c22252af05df94352240f30f9fc84090d88dAndrei Warkentinstatic const struct mmc_fixup blk_fixups[] =
17216f60c22252af05df94352240f30f9fc84090d88dAndrei Warkentin{
1722c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball	MMC_FIXUP("SEM02G", CID_MANFID_SANDISK, 0x100, add_quirk,
1723c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball		  MMC_QUIRK_INAND_CMD38),
1724c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball	MMC_FIXUP("SEM04G", CID_MANFID_SANDISK, 0x100, add_quirk,
1725c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball		  MMC_QUIRK_INAND_CMD38),
1726c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball	MMC_FIXUP("SEM08G", CID_MANFID_SANDISK, 0x100, add_quirk,
1727c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball		  MMC_QUIRK_INAND_CMD38),
1728c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball	MMC_FIXUP("SEM16G", CID_MANFID_SANDISK, 0x100, add_quirk,
1729c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball		  MMC_QUIRK_INAND_CMD38),
1730c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball	MMC_FIXUP("SEM32G", CID_MANFID_SANDISK, 0x100, add_quirk,
1731c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball		  MMC_QUIRK_INAND_CMD38),
1732d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin
1733d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin	/*
1734d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin	 * Some MMC cards experience performance degradation with CMD23
1735d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin	 * instead of CMD12-bounded multiblock transfers. For now we'll
1736d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin	 * black list what's bad...
1737d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin	 * - Certain Toshiba cards.
1738d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin	 *
1739d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin	 * N.B. This doesn't affect SD cards.
1740d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin	 */
1741c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball	MMC_FIXUP("MMC08G", CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc,
1742d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin		  MMC_QUIRK_BLK_NO_CMD23),
1743c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball	MMC_FIXUP("MMC16G", CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc,
1744d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin		  MMC_QUIRK_BLK_NO_CMD23),
1745c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball	MMC_FIXUP("MMC32G", CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc,
1746d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin		  MMC_QUIRK_BLK_NO_CMD23),
17476de5fc9cf7de334912de4cfd2d06eb2d744d2afeStefan Nilsson XK
17486de5fc9cf7de334912de4cfd2d06eb2d744d2afeStefan Nilsson XK	/*
17496de5fc9cf7de334912de4cfd2d06eb2d744d2afeStefan Nilsson XK	 * Some Micron MMC cards needs longer data read timeout than
17506de5fc9cf7de334912de4cfd2d06eb2d744d2afeStefan Nilsson XK	 * indicated in CSD.
17516de5fc9cf7de334912de4cfd2d06eb2d744d2afeStefan Nilsson XK	 */
1752c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball	MMC_FIXUP(CID_NAME_ANY, CID_MANFID_MICRON, 0x200, add_quirk_mmc,
17536de5fc9cf7de334912de4cfd2d06eb2d744d2afeStefan Nilsson XK		  MMC_QUIRK_LONG_READ_TIME),
17546de5fc9cf7de334912de4cfd2d06eb2d744d2afeStefan Nilsson XK
17556f60c22252af05df94352240f30f9fc84090d88dAndrei Warkentin	END_FIXUP
17566f60c22252af05df94352240f30f9fc84090d88dAndrei Warkentin};
17576f60c22252af05df94352240f30f9fc84090d88dAndrei Warkentin
17581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mmc_blk_probe(struct mmc_card *card)
17591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1760371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	struct mmc_blk_data *md, *part_md;
17611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err;
1762a7bbb57333447d0cf950992653b6b079585f3531Pierre Ossman	char cap_str[10];
1763a7bbb57333447d0cf950992653b6b079585f3531Pierre Ossman
1764912490db699d83cb3d03570b63df7448677a3f56Pierre Ossman	/*
1765912490db699d83cb3d03570b63df7448677a3f56Pierre Ossman	 * Check that the card supports the command class(es) we need.
1766912490db699d83cb3d03570b63df7448677a3f56Pierre Ossman	 */
1767912490db699d83cb3d03570b63df7448677a3f56Pierre Ossman	if (!(card->csd.cmdclass & CCC_BLOCK_READ))
17681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENODEV;
17691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	md = mmc_blk_alloc(card);
17711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (IS_ERR(md))
17721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return PTR_ERR(md);
17731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err = mmc_blk_set_blksize(md, card);
17751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (err)
17761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
17771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1778444122fd58fdc83c96877a92b3f6288cafddb08dYi Li	string_get_size((u64)get_capacity(md->disk) << 9, STRING_UNITS_2,
1779a7bbb57333447d0cf950992653b6b079585f3531Pierre Ossman			cap_str, sizeof(cap_str));
1780a3c76eb9d4a1e68a69dd880cf0bcb8a52418b993Girish K S	pr_info("%s: %s %s %s %s\n",
17811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		md->disk->disk_name, mmc_card_id(card), mmc_card_name(card),
1782a7bbb57333447d0cf950992653b6b079585f3531Pierre Ossman		cap_str, md->read_only ? "(ro)" : "");
17831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1784371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	if (mmc_blk_alloc_parts(card, md))
1785371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		goto out;
1786371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
17871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mmc_set_drvdata(card, md);
17886f60c22252af05df94352240f30f9fc84090d88dAndrei Warkentin	mmc_fixup_device(card, blk_fixups);
17896f60c22252af05df94352240f30f9fc84090d88dAndrei Warkentin
1790371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	if (mmc_add_disk(md))
1791371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		goto out;
1792371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
1793371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	list_for_each_entry(part_md, &md->part, part) {
1794371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		if (mmc_add_disk(part_md))
1795371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin			goto out;
1796371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	}
17971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
17981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out:
1800371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	mmc_blk_remove_parts(card, md);
1801371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	mmc_blk_remove_req(md);
18021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
18031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
18041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mmc_blk_remove(struct mmc_card *card)
18061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
18071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mmc_blk_data *md = mmc_get_drvdata(card);
18081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1809371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	mmc_blk_remove_parts(card, md);
1810ddd6fa7e794e62af3ec3eb4ffdc78489885701f2Adrian Hunter	mmc_claim_host(card->host);
1811ddd6fa7e794e62af3ec3eb4ffdc78489885701f2Adrian Hunter	mmc_blk_part_switch(card, md);
1812ddd6fa7e794e62af3ec3eb4ffdc78489885701f2Adrian Hunter	mmc_release_host(card->host);
1813371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	mmc_blk_remove_req(md);
18141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mmc_set_drvdata(card, NULL);
18151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
18161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PM
18181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mmc_blk_suspend(struct mmc_card *card, pm_message_t state)
18191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1820371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	struct mmc_blk_data *part_md;
18211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mmc_blk_data *md = mmc_get_drvdata(card);
18221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (md) {
18241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mmc_queue_suspend(&md->queue);
1825371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		list_for_each_entry(part_md, &md->part, part) {
1826371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin			mmc_queue_suspend(&part_md->queue);
1827371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		}
18281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
18291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
18301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
18311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mmc_blk_resume(struct mmc_card *card)
18331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1834371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	struct mmc_blk_data *part_md;
18351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mmc_blk_data *md = mmc_get_drvdata(card);
18361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (md) {
18381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mmc_blk_set_blksize(md, card);
1839371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
1840371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		/*
1841371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		 * Resume involves the card going into idle state,
1842371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		 * so current partition is always the main one.
1843371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		 */
1844371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		md->part_curr = md->part_type;
18451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mmc_queue_resume(&md->queue);
1846371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		list_for_each_entry(part_md, &md->part, part) {
1847371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin			mmc_queue_resume(&part_md->queue);
1848371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		}
18491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
18501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
18511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
18521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
18531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	mmc_blk_suspend	NULL
18541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define mmc_blk_resume	NULL
18551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
18561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct mmc_driver mmc_driver = {
18581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.drv		= {
18591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.name	= "mmcblk",
18601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
18611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.probe		= mmc_blk_probe,
18621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.remove		= mmc_blk_remove,
18631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.suspend	= mmc_blk_suspend,
18641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.resume		= mmc_blk_resume,
18651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
18661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init mmc_blk_init(void)
18681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
18699d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita	int res;
18701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18715e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson	if (perdev_minors != CONFIG_MMC_BLOCK_MINORS)
18725e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson		pr_info("mmcblk: using %d minors per device\n", perdev_minors);
18735e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson
18745e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson	max_devices = 256 / perdev_minors;
18755e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson
1876fe6b4c8840c5e23fe9b8696450cee8f2e8cebffdPierre Ossman	res = register_blkdev(MMC_BLOCK_MAJOR, "mmc");
1877fe6b4c8840c5e23fe9b8696450cee8f2e8cebffdPierre Ossman	if (res)
18781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
18791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18809d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita	res = mmc_register_driver(&mmc_driver);
18819d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita	if (res)
18829d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita		goto out2;
18831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18849d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita	return 0;
18859d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita out2:
18869d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita	unregister_blkdev(MMC_BLOCK_MAJOR, "mmc");
18871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out:
18881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return res;
18891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
18901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit mmc_blk_exit(void)
18921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
18931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mmc_unregister_driver(&mmc_driver);
1894fe6b4c8840c5e23fe9b8696450cee8f2e8cebffdPierre Ossman	unregister_blkdev(MMC_BLOCK_MAJOR, "mmc");
18951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
18961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(mmc_blk_init);
18981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(mmc_blk_exit);
18991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
19011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("Multimedia Card (MMC) block device driver");
19021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1903