block.c revision c49433fb66935bd01930e37c7f47d38b6f8135fc
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Block driver for media (i.e., flash cards)
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright 2002 Hewlett-Packard Company
5979ce7208a679b8d012450610d5d5aa75aab3af9Pierre Ossman * Copyright 2005-2008 Pierre Ossman
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Use consistent with the GNU GPL is permitted,
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * provided that this copyright notice is
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * preserved in its entirety in all copies and derived works.
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * HEWLETT-PACKARD COMPANY MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FITNESS FOR ANY PARTICULAR PURPOSE.
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Many thanks to Alessandro Rubini and Jonathan Corbet!
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Author:  Andrew Christian
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *          28 May 2002
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/moduleparam.h>
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/fs.h>
265a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h>
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/hdreg.h>
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kdev_t.h>
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/blkdev.h>
31a621aaed690b9439141c555941b6af53873f6ff1Arjan van de Ven#include <linux/mutex.h>
32ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman#include <linux/scatterlist.h>
33a7bbb57333447d0cf950992653b6b079585f3531Pierre Ossman#include <linux/string_helpers.h>
34cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto#include <linux/delay.h>
35cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto#include <linux/capability.h>
36cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto#include <linux/compat.h>
37e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson#include <linux/pm_runtime.h>
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto#include <linux/mmc/ioctl.h>
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mmc/card.h>
41385e3227d4d83ab13d7767c4bb3593b0256bf246Pierre Ossman#include <linux/mmc/host.h>
42da7fbe58d2d347e95af699ddf04d885be6362bbePierre Ossman#include <linux/mmc/mmc.h>
43da7fbe58d2d347e95af699ddf04d885be6362bbePierre Ossman#include <linux/mmc/sd.h>
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
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
618fee476b219d1869762d9ef5c189a0c85e919a4dTrey Ramsay#define MMC_BLK_TIMEOUT_MS  (10 * 60 * 1000)        /* 10 minute timeout */
62775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez#define MMC_SANITIZE_REQ_TIMEOUT 240000
63775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez#define MMC_EXTRACT_INDEX_FROM_ARG(x) ((x & 0x00FF0000) >> 16)
646a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin
65ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon#define mmc_req_rel_wr(req)	(((req->cmd_flags & REQ_FUA) || \
66ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				  (req->cmd_flags & REQ_META)) && \
67ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				  (rq_data_dir(req) == WRITE))
68ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon#define PACKED_CMD_VER	0x01
69ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon#define PACKED_CMD_WR	0x02
70ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
715e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johanssonstatic DEFINE_MUTEX(block_mutex);
726b0b62853b2553be375033776902640320970846Andy Whitcroft
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
745e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson * The defaults come from config options but can be overriden by module
755e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson * or bootarg options.
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
775e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johanssonstatic int perdev_minors = CONFIG_MMC_BLOCK_MINORS;
781dff314451fa24d6b107aa05393d3169e56a7e0aDavid Woodhouse
795e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson/*
805e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson * We've only got one major, so number of mmcblk devices is
815e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson * limited to 256 / number of minors per device.
825e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson */
835e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johanssonstatic int max_devices;
845e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson
855e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson/* 256 minors, so at most 256 separate devices */
865e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johanssonstatic DECLARE_BITMAP(dev_use, 256);
87f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentinstatic DECLARE_BITMAP(name_use, 256);
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * There is one mmc_blk_data per slot.
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct mmc_blk_data {
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spinlock_t	lock;
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct gendisk	*disk;
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mmc_queue queue;
96371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	struct list_head part;
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
98d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin	unsigned int	flags;
99d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin#define MMC_BLK_CMD23	(1 << 0)	/* Can do SET_BLOCK_COUNT for multiblock */
100d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin#define MMC_BLK_REL_WR	(1 << 1)	/* MMC Reliable write support */
101ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon#define MMC_BLK_PACKED_CMD	(1 << 2)	/* MMC packed command support */
102d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int	usage;
104a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	unsigned int	read_only;
105371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	unsigned int	part_type;
106f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin	unsigned int	name_idx;
10767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	unsigned int	reset_done;
10867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter#define MMC_BLK_READ		BIT(0)
10967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter#define MMC_BLK_WRITE		BIT(1)
11067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter#define MMC_BLK_DISCARD		BIT(2)
11167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter#define MMC_BLK_SECDISCARD	BIT(3)
112371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
113371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	/*
114371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	 * Only set in main mmc_blk_data associated
115371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	 * with mmc_card with mmc_set_drvdata, and keeps
116371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	 * track of the current selected device partition.
117371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	 */
118371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	unsigned int	part_curr;
119371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	struct device_attribute force_ro;
120add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	struct device_attribute power_ro_lock;
121add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	int	area_type;
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
124a621aaed690b9439141c555941b6af53873f6ff1Arjan van de Venstatic DEFINE_MUTEX(open_lock);
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
126ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeonenum {
127ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	MMC_PACKED_NR_IDX = -1,
128ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	MMC_PACKED_NR_ZERO,
129ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	MMC_PACKED_NR_SINGLE,
130ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon};
131ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1325e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johanssonmodule_param(perdev_minors, int, 0444);
1335e71b7a64cb4c6cff75ca42b535d8227526ec592Olof JohanssonMODULE_PARM_DESC(perdev_minors, "Minors numbers to allocate per device");
1345e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson
1358d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardystatic inline int mmc_blk_part_switch(struct mmc_card *card,
1368d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy				      struct mmc_blk_data *md);
1378d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardystatic int get_card_status(struct mmc_card *card, u32 *status, int retries);
1388d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy
139ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeonstatic inline void mmc_blk_clear_packed(struct mmc_queue_req *mqrq)
140ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon{
141ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct mmc_packed *packed = mqrq->packed;
142ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
143ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	BUG_ON(!packed);
144ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
145ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	mqrq->cmd_type = MMC_PACKED_NONE;
146ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	packed->nr_entries = MMC_PACKED_NR_ZERO;
147ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	packed->idx_failure = MMC_PACKED_NR_IDX;
148ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	packed->retries = 0;
149ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	packed->blocks = 0;
150ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon}
151ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct mmc_blk_data *mmc_blk_get(struct gendisk *disk)
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mmc_blk_data *md;
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
156a621aaed690b9439141c555941b6af53873f6ff1Arjan van de Ven	mutex_lock(&open_lock);
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	md = disk->private_data;
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (md && md->usage == 0)
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		md = NULL;
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (md)
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		md->usage++;
162a621aaed690b9439141c555941b6af53873f6ff1Arjan van de Ven	mutex_unlock(&open_lock);
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return md;
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
167371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic inline int mmc_get_devidx(struct gendisk *disk)
168371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{
169371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	int devmaj = MAJOR(disk_devt(disk));
170371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	int devidx = MINOR(disk_devt(disk)) / perdev_minors;
171371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
172371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	if (!devmaj)
173371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		devidx = disk->first_minor / perdev_minors;
174371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	return devidx;
175371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin}
176371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mmc_blk_put(struct mmc_blk_data *md)
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
179a621aaed690b9439141c555941b6af53873f6ff1Arjan van de Ven	mutex_lock(&open_lock);
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	md->usage--;
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (md->usage == 0) {
182371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		int devidx = mmc_get_devidx(md->disk);
1835fa83ce284a4b7cd9dcfadd01500b0ed4ab9b740Adrian Hunter		blk_cleanup_queue(md->queue.queue);
1845fa83ce284a4b7cd9dcfadd01500b0ed4ab9b740Adrian Hunter
1851dff314451fa24d6b107aa05393d3169e56a7e0aDavid Woodhouse		__clear_bit(devidx, dev_use);
1861dff314451fa24d6b107aa05393d3169e56a7e0aDavid Woodhouse
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		put_disk(md->disk);
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kfree(md);
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
190a621aaed690b9439141c555941b6af53873f6ff1Arjan van de Ven	mutex_unlock(&open_lock);
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
193add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholmstatic ssize_t power_ro_lock_show(struct device *dev,
194add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		struct device_attribute *attr, char *buf)
195add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm{
196add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	int ret;
197add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
198add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	struct mmc_card *card = md->queue.card;
199add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	int locked = 0;
200add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
201add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	if (card->ext_csd.boot_ro_lock & EXT_CSD_BOOT_WP_B_PERM_WP_EN)
202add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		locked = 2;
203add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	else if (card->ext_csd.boot_ro_lock & EXT_CSD_BOOT_WP_B_PWR_WP_EN)
204add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		locked = 1;
205add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
206add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	ret = snprintf(buf, PAGE_SIZE, "%d\n", locked);
207add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
208add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	return ret;
209add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm}
210add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
211add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholmstatic ssize_t power_ro_lock_store(struct device *dev,
212add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		struct device_attribute *attr, const char *buf, size_t count)
213add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm{
214add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	int ret;
215add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	struct mmc_blk_data *md, *part_md;
216add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	struct mmc_card *card;
217add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	unsigned long set;
218add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
219add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	if (kstrtoul(buf, 0, &set))
220add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		return -EINVAL;
221add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
222add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	if (set != 1)
223add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		return count;
224add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
225add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	md = mmc_blk_get(dev_to_disk(dev));
226add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	card = md->queue.card;
227add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
228e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson	mmc_get_card(card);
229add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
230add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_WP,
231add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm				card->ext_csd.boot_ro_lock |
232add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm				EXT_CSD_BOOT_WP_B_PWR_WP_EN,
233add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm				card->ext_csd.part_time);
234add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	if (ret)
235add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		pr_err("%s: Locking boot partition ro until next power on failed: %d\n", md->disk->disk_name, ret);
236add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	else
237add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		card->ext_csd.boot_ro_lock |= EXT_CSD_BOOT_WP_B_PWR_WP_EN;
238add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
239e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson	mmc_put_card(card);
240add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
241add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	if (!ret) {
242add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		pr_info("%s: Locking boot partition ro until next power on\n",
243add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm			md->disk->disk_name);
244add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		set_disk_ro(md->disk, 1);
245add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
246add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		list_for_each_entry(part_md, &md->part, part)
247add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm			if (part_md->area_type == MMC_BLK_DATA_AREA_BOOT) {
248add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm				pr_info("%s: Locking boot partition ro until next power on\n", part_md->disk->disk_name);
249add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm				set_disk_ro(part_md->disk, 1);
250add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm			}
251add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	}
252add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
253add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	mmc_blk_put(md);
254add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	return count;
255add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm}
256add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
257371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic ssize_t force_ro_show(struct device *dev, struct device_attribute *attr,
258371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin			     char *buf)
259371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{
260371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	int ret;
261371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
262371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
263371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	ret = snprintf(buf, PAGE_SIZE, "%d",
264371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		       get_disk_ro(dev_to_disk(dev)) ^
265371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		       md->read_only);
266371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	mmc_blk_put(md);
267371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	return ret;
268371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin}
269371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
270371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic ssize_t force_ro_store(struct device *dev, struct device_attribute *attr,
271371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin			      const char *buf, size_t count)
272371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{
273371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	int ret;
274371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	char *end;
275371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
276371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	unsigned long set = simple_strtoul(buf, &end, 0);
277371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	if (end == buf) {
278371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		ret = -EINVAL;
279371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		goto out;
280371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	}
281371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
282371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	set_disk_ro(dev_to_disk(dev), set || md->read_only);
283371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	ret = count;
284371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinout:
285371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	mmc_blk_put(md);
286371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	return ret;
287371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin}
288371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
289a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Virostatic int mmc_blk_open(struct block_device *bdev, fmode_t mode)
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
291a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Viro	struct mmc_blk_data *md = mmc_blk_get(bdev->bd_disk);
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret = -ENXIO;
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2942a48fc0ab24241755dc93bfd4f01d68efab47f5aArnd Bergmann	mutex_lock(&block_mutex);
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (md) {
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (md->usage == 2)
297a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Viro			check_disk_change(bdev);
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = 0;
299a00fc09029f02ca833cf90e5d5625f08c4ac4f51Pierre Ossman
300a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Viro		if ((mode & FMODE_WRITE) && md->read_only) {
30170bb08962ea9bd50797ae9f16b2493f5f7c65053Andrew Morton			mmc_blk_put(md);
302a00fc09029f02ca833cf90e5d5625f08c4ac4f51Pierre Ossman			ret = -EROFS;
30370bb08962ea9bd50797ae9f16b2493f5f7c65053Andrew Morton		}
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3052a48fc0ab24241755dc93bfd4f01d68efab47f5aArnd Bergmann	mutex_unlock(&block_mutex);
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
310db2a144bedd58b3dcf19950c2f476c58c9f39d18Al Virostatic void mmc_blk_release(struct gendisk *disk, fmode_t mode)
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
312a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Viro	struct mmc_blk_data *md = disk->private_data;
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3142a48fc0ab24241755dc93bfd4f01d68efab47f5aArnd Bergmann	mutex_lock(&block_mutex);
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mmc_blk_put(md);
3162a48fc0ab24241755dc93bfd4f01d68efab47f5aArnd Bergmann	mutex_unlock(&block_mutex);
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
320a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwigmmc_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
322a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig	geo->cylinders = get_capacity(bdev->bd_disk) / (4 * 16);
323a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig	geo->heads = 4;
324a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig	geo->sectors = 16;
325a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig	return 0;
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
328cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtostruct mmc_blk_ioc_data {
329cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	struct mmc_ioc_cmd ic;
330cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	unsigned char *buf;
331cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	u64 buf_bytes;
332cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto};
333cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
334cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtostatic struct mmc_blk_ioc_data *mmc_blk_ioctl_copy_from_user(
335cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	struct mmc_ioc_cmd __user *user)
336cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto{
337cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	struct mmc_blk_ioc_data *idata;
338cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	int err;
339cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
340cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	idata = kzalloc(sizeof(*idata), GFP_KERNEL);
341cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (!idata) {
342cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		err = -ENOMEM;
343aea253ecffecd38b5ab97edd73fbe2842a7de371Vladimir Motyka		goto out;
344cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	}
345cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
346cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (copy_from_user(&idata->ic, user, sizeof(idata->ic))) {
347cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		err = -EFAULT;
348aea253ecffecd38b5ab97edd73fbe2842a7de371Vladimir Motyka		goto idata_err;
349cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	}
350cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
351cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	idata->buf_bytes = (u64) idata->ic.blksz * idata->ic.blocks;
352cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (idata->buf_bytes > MMC_IOC_MAX_BYTES) {
353cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		err = -EOVERFLOW;
354aea253ecffecd38b5ab97edd73fbe2842a7de371Vladimir Motyka		goto idata_err;
355cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	}
356cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
3574d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm	if (!idata->buf_bytes)
3584d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		return idata;
3594d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm
360cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	idata->buf = kzalloc(idata->buf_bytes, GFP_KERNEL);
361cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (!idata->buf) {
362cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		err = -ENOMEM;
363aea253ecffecd38b5ab97edd73fbe2842a7de371Vladimir Motyka		goto idata_err;
364cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	}
365cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
366cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (copy_from_user(idata->buf, (void __user *)(unsigned long)
367cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto					idata->ic.data_ptr, idata->buf_bytes)) {
368cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		err = -EFAULT;
369cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		goto copy_err;
370cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	}
371cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
372cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	return idata;
373cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
374cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtocopy_err:
375cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	kfree(idata->buf);
376aea253ecffecd38b5ab97edd73fbe2842a7de371Vladimir Motykaidata_err:
377cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	kfree(idata);
378aea253ecffecd38b5ab97edd73fbe2842a7de371Vladimir Motykaout:
379cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	return ERR_PTR(err);
380cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto}
381cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
3828d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardystatic int ioctl_rpmb_card_status_poll(struct mmc_card *card, u32 *status,
3838d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy				       u32 retries_max)
3848d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy{
3858d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy	int err;
3868d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy	u32 retry_count = 0;
3878d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy
3888d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy	if (!status || !retries_max)
3898d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy		return -EINVAL;
3908d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy
3918d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy	do {
3928d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy		err = get_card_status(card, status, 5);
3938d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy		if (err)
3948d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy			break;
3958d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy
3968d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy		if (!R1_STATUS(*status) &&
3978d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy				(R1_CURRENT_STATE(*status) != R1_STATE_PRG))
3988d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy			break; /* RPMB programming operation complete */
3998d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy
4008d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy		/*
4018d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy		 * Rechedule to give the MMC device a chance to continue
4028d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy		 * processing the previous command without being polled too
4038d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy		 * frequently.
4048d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy		 */
4058d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy		usleep_range(1000, 5000);
4068d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy	} while (++retry_count < retries_max);
4078d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy
4088d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy	if (retry_count == retries_max)
4098d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy		err = -EPERM;
4108d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy
4118d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy	return err;
4128d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy}
4138d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy
414775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erezstatic int ioctl_do_sanitize(struct mmc_card *card)
415775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez{
416775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez	int err;
417775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez
418a2d1086de6cc3ae2378d9db8b92712911c9e5fefUlf Hansson	if (!mmc_can_sanitize(card)) {
419775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez			pr_warn("%s: %s - SANITIZE is not supported\n",
420775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez				mmc_hostname(card->host), __func__);
421775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez			err = -EOPNOTSUPP;
422775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez			goto out;
423775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez	}
424775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez
425775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez	pr_debug("%s: %s - SANITIZE IN PROGRESS...\n",
426775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez		mmc_hostname(card->host), __func__);
427775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez
428775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez	err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
429775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez					EXT_CSD_SANITIZE_START, 1,
430775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez					MMC_SANITIZE_REQ_TIMEOUT);
431775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez
432775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez	if (err)
433775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez		pr_err("%s: %s - EXT_CSD_SANITIZE_START failed. err=%d\n",
434775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez		       mmc_hostname(card->host), __func__, err);
435775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez
436775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez	pr_debug("%s: %s - SANITIZE COMPLETED\n", mmc_hostname(card->host),
437775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez					     __func__);
438775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erezout:
439775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez	return err;
440775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez}
441775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez
442cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtostatic int mmc_blk_ioctl_cmd(struct block_device *bdev,
443cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	struct mmc_ioc_cmd __user *ic_ptr)
444cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto{
445cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	struct mmc_blk_ioc_data *idata;
446cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	struct mmc_blk_data *md;
447cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	struct mmc_card *card;
448cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	struct mmc_command cmd = {0};
449cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	struct mmc_data data = {0};
450ad5fd97288655b5628052c1fa906419417c86100Venkatraman S	struct mmc_request mrq = {NULL};
451cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	struct scatterlist sg;
452cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	int err;
4538d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy	int is_rpmb = false;
4548d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy	u32 status = 0;
455cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
456cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	/*
457cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	 * The caller must have CAP_SYS_RAWIO, and must be calling this on the
458cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	 * whole block device, not on a partition.  This prevents overspray
459cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	 * between sibling partitions.
460cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	 */
461cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if ((!capable(CAP_SYS_RAWIO)) || (bdev != bdev->bd_contains))
462cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		return -EPERM;
463cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
464cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	idata = mmc_blk_ioctl_copy_from_user(ic_ptr);
465cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (IS_ERR(idata))
466cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		return PTR_ERR(idata);
467cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
468cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	md = mmc_blk_get(bdev->bd_disk);
469cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (!md) {
470cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		err = -EINVAL;
4711c02f000e78347aa51822feb189fcb0d90273958Philippe De Swert		goto cmd_err;
472cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	}
473cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
4748d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy	if (md->area_type & MMC_BLK_DATA_AREA_RPMB)
4758d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy		is_rpmb = true;
4768d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy
477cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	card = md->queue.card;
478cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (IS_ERR(card)) {
479cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		err = PTR_ERR(card);
480cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		goto cmd_done;
481cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	}
482cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
4834d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm	cmd.opcode = idata->ic.opcode;
4844d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm	cmd.arg = idata->ic.arg;
4854d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm	cmd.flags = idata->ic.flags;
4864d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm
4874d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm	if (idata->buf_bytes) {
4884d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		data.sg = &sg;
4894d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		data.sg_len = 1;
4904d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		data.blksz = idata->ic.blksz;
4914d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		data.blocks = idata->ic.blocks;
4924d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm
4934d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		sg_init_one(data.sg, idata->buf, idata->buf_bytes);
4944d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm
4954d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		if (idata->ic.write_flag)
4964d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm			data.flags = MMC_DATA_WRITE;
4974d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		else
4984d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm			data.flags = MMC_DATA_READ;
4994d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm
5004d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		/* data.flags must already be set before doing this. */
5014d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		mmc_set_data_timeout(&data, card);
5024d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm
5034d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		/* Allow overriding the timeout_ns for empirical tuning. */
5044d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		if (idata->ic.data_timeout_ns)
5054d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm			data.timeout_ns = idata->ic.data_timeout_ns;
5064d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm
5074d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		if ((cmd.flags & MMC_RSP_R1B) == MMC_RSP_R1B) {
5084d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm			/*
5094d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm			 * Pretend this is a data transfer and rely on the
5104d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm			 * host driver to compute timeout.  When all host
5114d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm			 * drivers support cmd.cmd_timeout for R1B, this
5124d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm			 * can be changed to:
5134d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm			 *
5144d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm			 *     mrq.data = NULL;
5154d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm			 *     cmd.cmd_timeout = idata->ic.cmd_timeout_ms;
5164d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm			 */
5174d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm			data.timeout_ns = idata->ic.cmd_timeout_ms * 1000000;
5184d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		}
5194d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm
5204d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		mrq.data = &data;
5214d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm	}
5224d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm
5234d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm	mrq.cmd = &cmd;
5244d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm
525e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson	mmc_get_card(card);
526cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
5278d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy	err = mmc_blk_part_switch(card, md);
5288d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy	if (err)
5298d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy		goto cmd_rel_host;
5308d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy
531cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (idata->ic.is_acmd) {
532cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		err = mmc_app_cmd(card->host, card);
533cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		if (err)
534cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto			goto cmd_rel_host;
535cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	}
536cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
5378d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy	if (is_rpmb) {
5388d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy		err = mmc_set_blockcount(card, data.blocks,
5398d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy			idata->ic.write_flag & (1 << 31));
5408d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy		if (err)
5418d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy			goto cmd_rel_host;
5428d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy	}
5438d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy
544a82e484e2480583b17be6253b985fa6f582ad20dYaniv Gardi	if ((MMC_EXTRACT_INDEX_FROM_ARG(cmd.arg) == EXT_CSD_SANITIZE_START) &&
545a82e484e2480583b17be6253b985fa6f582ad20dYaniv Gardi	    (cmd.opcode == MMC_SWITCH)) {
546775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez		err = ioctl_do_sanitize(card);
547775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez
548775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez		if (err)
549775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez			pr_err("%s: ioctl_do_sanitize() failed. err = %d",
550775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez			       __func__, err);
551775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez
552775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez		goto cmd_rel_host;
553775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez	}
554775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez
555cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	mmc_wait_for_req(card->host, &mrq);
556cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
557cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (cmd.error) {
558cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		dev_err(mmc_dev(card->host), "%s: cmd error %d\n",
559cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto						__func__, cmd.error);
560cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		err = cmd.error;
561cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		goto cmd_rel_host;
562cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	}
563cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (data.error) {
564cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		dev_err(mmc_dev(card->host), "%s: data error %d\n",
565cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto						__func__, data.error);
566cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		err = data.error;
567cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		goto cmd_rel_host;
568cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	}
569cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
570cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	/*
571cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	 * According to the SD specs, some commands require a delay after
572cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	 * issuing the command.
573cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	 */
574cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (idata->ic.postsleep_min_us)
575cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		usleep_range(idata->ic.postsleep_min_us, idata->ic.postsleep_max_us);
576cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
577cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (copy_to_user(&(ic_ptr->response), cmd.resp, sizeof(cmd.resp))) {
578cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		err = -EFAULT;
579cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		goto cmd_rel_host;
580cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	}
581cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
582cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (!idata->ic.write_flag) {
583cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		if (copy_to_user((void __user *)(unsigned long) idata->ic.data_ptr,
584cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto						idata->buf, idata->buf_bytes)) {
585cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto			err = -EFAULT;
586cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto			goto cmd_rel_host;
587cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		}
588cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	}
589cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
5908d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy	if (is_rpmb) {
5918d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy		/*
5928d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy		 * Ensure RPMB command has completed by polling CMD13
5938d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy		 * "Send Status".
5948d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy		 */
5958d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy		err = ioctl_rpmb_card_status_poll(card, &status, 5);
5968d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy		if (err)
5978d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy			dev_err(mmc_dev(card->host),
5988d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy					"%s: Card Status=0x%08X, error %d\n",
5998d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy					__func__, status, err);
6008d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy	}
6018d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy
602cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtocmd_rel_host:
603e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson	mmc_put_card(card);
604cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
605cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtocmd_done:
606cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	mmc_blk_put(md);
6071c02f000e78347aa51822feb189fcb0d90273958Philippe De Swertcmd_err:
608cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	kfree(idata->buf);
609cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	kfree(idata);
610cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	return err;
611cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto}
612cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
613cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtostatic int mmc_blk_ioctl(struct block_device *bdev, fmode_t mode,
614cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	unsigned int cmd, unsigned long arg)
615cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto{
616cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	int ret = -EINVAL;
617cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (cmd == MMC_IOC_CMD)
618cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		ret = mmc_blk_ioctl_cmd(bdev, (struct mmc_ioc_cmd __user *)arg);
619cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	return ret;
620cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto}
621cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
622cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto#ifdef CONFIG_COMPAT
623cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtostatic int mmc_blk_compat_ioctl(struct block_device *bdev, fmode_t mode,
624cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	unsigned int cmd, unsigned long arg)
625cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto{
626cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	return mmc_blk_ioctl(bdev, mode, cmd, (unsigned long) compat_ptr(arg));
627cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto}
628cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto#endif
629cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
63083d5cde47dedf01b6a4a4331882cbc0a7eea3c2eAlexey Dobriyanstatic const struct block_device_operations mmc_bdops = {
631a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Viro	.open			= mmc_blk_open,
632a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Viro	.release		= mmc_blk_release,
633a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig	.getgeo			= mmc_blk_getgeo,
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.owner			= THIS_MODULE,
635cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	.ioctl			= mmc_blk_ioctl,
636cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto#ifdef CONFIG_COMPAT
637cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	.compat_ioctl		= mmc_blk_compat_ioctl,
638cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto#endif
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
641371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic inline int mmc_blk_part_switch(struct mmc_card *card,
642371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin				      struct mmc_blk_data *md)
643371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{
644371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	int ret;
645371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	struct mmc_blk_data *main_md = mmc_get_drvdata(card);
6460d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter
647371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	if (main_md->part_curr == md->part_type)
648371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		return 0;
649371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
650371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	if (mmc_card_mmc(card)) {
6510d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter		u8 part_config = card->ext_csd.part_config;
6520d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter
6530d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter		part_config &= ~EXT_CSD_PART_CONFIG_ACC_MASK;
6540d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter		part_config |= md->part_type;
655371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
656371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
6570d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter				 EXT_CSD_PART_CONFIG, part_config,
658371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin				 card->ext_csd.part_time);
659371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		if (ret)
660371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin			return ret;
6610d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter
6620d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter		card->ext_csd.part_config = part_config;
66367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	}
664371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
665371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	main_md->part_curr = md->part_type;
666371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	return 0;
667371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin}
668371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
669ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossmanstatic u32 mmc_sd_num_wr_blocks(struct mmc_card *card)
670ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman{
671ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	int err;
672051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks	u32 result;
673051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks	__be32 *blocks;
674ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman
675ad5fd97288655b5628052c1fa906419417c86100Venkatraman S	struct mmc_request mrq = {NULL};
6761278dba167f01bb3c6626d16450d31129d041087Chris Ball	struct mmc_command cmd = {0};
677a61ad2b49bfce94dfddce828cd9222e4b9e7825bChris Ball	struct mmc_data data = {0};
678ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman
679ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	struct scatterlist sg;
680ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman
681ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	cmd.opcode = MMC_APP_CMD;
682ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	cmd.arg = card->rca << 16;
6837213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell	cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
684ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman
685ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	err = mmc_wait_for_cmd(card->host, &cmd, 0);
6867213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell	if (err)
6877213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell		return (u32)-1;
6887213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell	if (!mmc_host_is_spi(card->host) && !(cmd.resp[0] & R1_APP_CMD))
689ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman		return (u32)-1;
690ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman
691ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	memset(&cmd, 0, sizeof(struct mmc_command));
692ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman
693ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	cmd.opcode = SD_APP_SEND_NUM_WR_BLKS;
694ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	cmd.arg = 0;
6957213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell	cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
696ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman
697ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	data.blksz = 4;
698ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	data.blocks = 1;
699ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	data.flags = MMC_DATA_READ;
700ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	data.sg = &sg;
701ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	data.sg_len = 1;
702d380443cd0271903bf9516bc04cead81676be034Subhash Jadavani	mmc_set_data_timeout(&data, card);
703ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman
704ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	mrq.cmd = &cmd;
705ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	mrq.data = &data;
706ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman
707051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks	blocks = kmalloc(4, GFP_KERNEL);
708051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks	if (!blocks)
709051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks		return (u32)-1;
710051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks
711051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks	sg_init_one(&sg, blocks, 4);
712ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman
713ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	mmc_wait_for_req(card->host, &mrq);
714ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman
715051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks	result = ntohl(*blocks);
716051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks	kfree(blocks);
717051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks
71817b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman	if (cmd.error || data.error)
719051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks		result = (u32)-1;
720ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman
721051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks	return result;
722ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman}
723ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman
724a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linuxstatic int send_stop(struct mmc_card *card, u32 *status)
725a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux{
726a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	struct mmc_command cmd = {0};
727a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	int err;
728a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
729a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	cmd.opcode = MMC_STOP_TRANSMISSION;
730a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
731a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	err = mmc_wait_for_cmd(card->host, &cmd, 5);
732a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	if (err == 0)
733a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		*status = cmd.resp[0];
734a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	return err;
735a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux}
736a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
7370a2d4048a22079d7e79d6654bbacbef57bd5728aRussell King - ARM Linuxstatic int get_card_status(struct mmc_card *card, u32 *status, int retries)
738504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter{
7391278dba167f01bb3c6626d16450d31129d041087Chris Ball	struct mmc_command cmd = {0};
740504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter	int err;
741504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter
742504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter	cmd.opcode = MMC_SEND_STATUS;
743504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter	if (!mmc_host_is_spi(card->host))
744504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter		cmd.arg = card->rca << 16;
745504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter	cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC;
7460a2d4048a22079d7e79d6654bbacbef57bd5728aRussell King - ARM Linux	err = mmc_wait_for_cmd(card->host, &cmd, retries);
7470a2d4048a22079d7e79d6654bbacbef57bd5728aRussell King - ARM Linux	if (err == 0)
7480a2d4048a22079d7e79d6654bbacbef57bd5728aRussell King - ARM Linux		*status = cmd.resp[0];
7490a2d4048a22079d7e79d6654bbacbef57bd5728aRussell King - ARM Linux	return err;
750504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter}
751504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter
752c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hanssonstatic int card_busy_detect(struct mmc_card *card, unsigned int timeout_ms,
753c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson		struct request *req, int *gen_err)
754c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson{
755c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson	unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
756c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson	int err = 0;
757c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson	u32 status;
758c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson
759c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson	do {
760c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson		err = get_card_status(card, &status, 5);
761c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson		if (err) {
762c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson			pr_err("%s: error %d requesting status\n",
763c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson			       req->rq_disk->disk_name, err);
764c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson			return err;
765c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson		}
766c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson
767c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson		if (status & R1_ERROR) {
768c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson			pr_err("%s: %s: error sending status cmd, status %#x\n",
769c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson				req->rq_disk->disk_name, __func__, status);
770c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson			*gen_err = 1;
771c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson		}
772c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson
773c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson		/*
774c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson		 * Timeout if the device never becomes ready for data and never
775c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson		 * leaves the program state.
776c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson		 */
777c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson		if (time_after(jiffies, timeout)) {
778c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson			pr_err("%s: Card stuck in programming state! %s %s\n",
779c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson				mmc_hostname(card->host),
780c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson				req->rq_disk->disk_name, __func__);
781c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson			return -ETIMEDOUT;
782c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson		}
783c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson
784c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson		/*
785c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson		 * Some cards mishandle the status bits,
786c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson		 * so make sure to check both the busy
787c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson		 * indication and the card state.
788c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson		 */
789c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson	} while (!(status & R1_READY_FOR_DATA) ||
790c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson		 (R1_CURRENT_STATE(status) == R1_STATE_PRG));
791c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson
792c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson	return err;
793c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson}
794c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson
795a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma#define ERR_NOMEDIUM	3
796a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux#define ERR_RETRY	2
797a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux#define ERR_ABORT	1
798a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux#define ERR_CONTINUE	0
799a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
800a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linuxstatic int mmc_blk_cmd_error(struct request *req, const char *name, int error,
801a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	bool status_valid, u32 status)
802a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux{
803a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	switch (error) {
804a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	case -EILSEQ:
805a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		/* response crc error, retry the r/w cmd */
806a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		pr_err("%s: %s sending %s command, card status %#x\n",
807a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux			req->rq_disk->disk_name, "response CRC error",
808a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux			name, status);
809a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		return ERR_RETRY;
810a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
811a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	case -ETIMEDOUT:
812a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		pr_err("%s: %s sending %s command, card status %#x\n",
813a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux			req->rq_disk->disk_name, "timed out", name, status);
814a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
815a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		/* If the status cmd initially failed, retry the r/w cmd */
816a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		if (!status_valid)
817a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux			return ERR_RETRY;
818a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
819a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		/*
820a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		 * If it was a r/w cmd crc error, or illegal command
821a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		 * (eg, issued in wrong state) then retry - we should
822a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		 * have corrected the state problem above.
823a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		 */
824a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		if (status & (R1_COM_CRC_ERROR | R1_ILLEGAL_COMMAND))
825a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux			return ERR_RETRY;
826a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
827a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		/* Otherwise abort the command */
828a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		return ERR_ABORT;
829a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
830a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	default:
831a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		/* We don't understand the error code the driver gave us */
832a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		pr_err("%s: unknown error %d sending read/write command, card status %#x\n",
833a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		       req->rq_disk->disk_name, error, status);
834a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		return ERR_ABORT;
835a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	}
836a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux}
837a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
838a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux/*
839a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * Initial r/w and stop cmd error recovery.
840a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * We don't know whether the card received the r/w cmd or not, so try to
841a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * restore things back to a sane state.  Essentially, we do this as follows:
842a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * - Obtain card status.  If the first attempt to obtain card status fails,
843a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux *   the status word will reflect the failed status cmd, not the failed
844a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux *   r/w cmd.  If we fail to obtain card status, it suggests we can no
845a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux *   longer communicate with the card.
846a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * - Check the card state.  If the card received the cmd but there was a
847a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux *   transient problem with the response, it might still be in a data transfer
848a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux *   mode.  Try to send it a stop command.  If this fails, we can't recover.
849a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * - If the r/w cmd failed due to a response CRC error, it was probably
850a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux *   transient, so retry the cmd.
851a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * - If the r/w cmd timed out, but we didn't get the r/w cmd status, retry.
852a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * - If the r/w cmd timed out, and the r/w cmd failed due to CRC error or
853a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux *   illegal cmd, retry.
854a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * Otherwise we don't understand what happened, so abort.
855a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux */
856a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linuxstatic int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req,
857c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake	struct mmc_blk_request *brq, int *ecc_err, int *gen_err)
858a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux{
859a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	bool prev_cmd_status_valid = true;
860a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	u32 status, stop_status = 0;
861a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	int err, retry;
862a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
863a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma	if (mmc_card_removed(card))
864a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma		return ERR_NOMEDIUM;
865a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma
866a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	/*
867a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	 * Try to get card status which indicates both the card state
868a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	 * and why there was no response.  If the first attempt fails,
869a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	 * we can't be sure the returned status is for the r/w command.
870a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	 */
871a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	for (retry = 2; retry >= 0; retry--) {
872a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		err = get_card_status(card, &status, 0);
873a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		if (!err)
874a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux			break;
875a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
876a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		prev_cmd_status_valid = false;
877a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		pr_err("%s: error %d sending status command, %sing\n",
878a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		       req->rq_disk->disk_name, err, retry ? "retry" : "abort");
879a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	}
880a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
881a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	/* We couldn't get a response from the card.  Give up. */
882a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma	if (err) {
883a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma		/* Check if the card is removed */
884a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma		if (mmc_detect_card_removed(card->host))
885a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma			return ERR_NOMEDIUM;
886a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		return ERR_ABORT;
887a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma	}
888a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
88967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	/* Flag ECC errors */
89067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	if ((status & R1_CARD_ECC_FAILED) ||
89167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	    (brq->stop.resp[0] & R1_CARD_ECC_FAILED) ||
89267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	    (brq->cmd.resp[0] & R1_CARD_ECC_FAILED))
89367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		*ecc_err = 1;
89467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter
895c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake	/* Flag General errors */
896c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake	if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ)
897c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake		if ((status & R1_ERROR) ||
898c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake			(brq->stop.resp[0] & R1_ERROR)) {
899c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake			pr_err("%s: %s: general error sending stop or status command, stop cmd response %#x, card status %#x\n",
900c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake			       req->rq_disk->disk_name, __func__,
901c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake			       brq->stop.resp[0], status);
902c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake			*gen_err = 1;
903c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake		}
904c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake
905a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	/*
906a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	 * Check the current card state.  If it is in some data transfer
907a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	 * mode, tell it to stop (and hopefully transition back to TRAN.)
908a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	 */
909a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	if (R1_CURRENT_STATE(status) == R1_STATE_DATA ||
910a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	    R1_CURRENT_STATE(status) == R1_STATE_RCV) {
911a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		err = send_stop(card, &stop_status);
912a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		if (err)
913a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux			pr_err("%s: error %d sending stop command\n",
914a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux			       req->rq_disk->disk_name, err);
915a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
916a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		/*
917a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		 * If the stop cmd also timed out, the card is probably
918a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		 * not present, so abort.  Other errors are bad news too.
919a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		 */
920a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		if (err)
921a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux			return ERR_ABORT;
92267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		if (stop_status & R1_CARD_ECC_FAILED)
92367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			*ecc_err = 1;
924c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake		if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ)
925c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake			if (stop_status & R1_ERROR) {
926c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake				pr_err("%s: %s: general error sending stop command, stop cmd response %#x\n",
927c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake				       req->rq_disk->disk_name, __func__,
928c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake				       stop_status);
929c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake				*gen_err = 1;
930c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake			}
931a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	}
932a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
933a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	/* Check for set block count errors */
934a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	if (brq->sbc.error)
935a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		return mmc_blk_cmd_error(req, "SET_BLOCK_COUNT", brq->sbc.error,
936a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux				prev_cmd_status_valid, status);
937a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
938a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	/* Check for r/w command errors */
939a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	if (brq->cmd.error)
940a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		return mmc_blk_cmd_error(req, "r/w cmd", brq->cmd.error,
941a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux				prev_cmd_status_valid, status);
942a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
94367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	/* Data errors */
94467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	if (!brq->stop.error)
94567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		return ERR_CONTINUE;
94667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter
947a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	/* Now for stop errors.  These aren't fatal to the transfer. */
948a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	pr_err("%s: error %d sending stop command, original cmd response %#x, card status %#x\n",
949a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	       req->rq_disk->disk_name, brq->stop.error,
950a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	       brq->cmd.resp[0], status);
951a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
952a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	/*
953a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	 * Subsitute in our own stop status as this will give the error
954a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	 * state which happened during the execution of the r/w command.
955a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	 */
956a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	if (stop_status) {
957a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		brq->stop.resp[0] = stop_status;
958a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		brq->stop.error = 0;
959a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	}
960a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	return ERR_CONTINUE;
961a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux}
962a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
96367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunterstatic int mmc_blk_reset(struct mmc_blk_data *md, struct mmc_host *host,
96467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			 int type)
96567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter{
96667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	int err;
96767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter
96867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	if (md->reset_done & type)
96967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		return -EEXIST;
97067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter
97167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	md->reset_done |= type;
97267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	err = mmc_hw_reset(host);
97367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	/* Ensure we switch back to the correct partition */
97467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	if (err != -EOPNOTSUPP) {
97567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		struct mmc_blk_data *main_md = mmc_get_drvdata(host->card);
97667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		int part_err;
97767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter
97867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		main_md->part_curr = main_md->part_type;
97967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		part_err = mmc_blk_part_switch(host->card, md);
98067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		if (part_err) {
98167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			/*
98267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			 * We have failed to get back into the correct
98367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			 * partition, so we need to abort the whole request.
98467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			 */
98567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			return -ENODEV;
98667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		}
98767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	}
98867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	return err;
98967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter}
99067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter
99167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunterstatic inline void mmc_blk_reset_success(struct mmc_blk_data *md, int type)
99267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter{
99367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	md->reset_done &= ~type;
99467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter}
99567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter
996bd788c9665fb7c543aac21317059375632343337Adrian Hunterstatic int mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req)
997bd788c9665fb7c543aac21317059375632343337Adrian Hunter{
998bd788c9665fb7c543aac21317059375632343337Adrian Hunter	struct mmc_blk_data *md = mq->data;
999bd788c9665fb7c543aac21317059375632343337Adrian Hunter	struct mmc_card *card = md->queue.card;
1000bd788c9665fb7c543aac21317059375632343337Adrian Hunter	unsigned int from, nr, arg;
100167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	int err = 0, type = MMC_BLK_DISCARD;
1002bd788c9665fb7c543aac21317059375632343337Adrian Hunter
1003bd788c9665fb7c543aac21317059375632343337Adrian Hunter	if (!mmc_can_erase(card)) {
1004bd788c9665fb7c543aac21317059375632343337Adrian Hunter		err = -EOPNOTSUPP;
1005bd788c9665fb7c543aac21317059375632343337Adrian Hunter		goto out;
1006bd788c9665fb7c543aac21317059375632343337Adrian Hunter	}
1007bd788c9665fb7c543aac21317059375632343337Adrian Hunter
1008bd788c9665fb7c543aac21317059375632343337Adrian Hunter	from = blk_rq_pos(req);
1009bd788c9665fb7c543aac21317059375632343337Adrian Hunter	nr = blk_rq_sectors(req);
1010bd788c9665fb7c543aac21317059375632343337Adrian Hunter
1011b3bf915308ca2b50f3beec6cc824083870f0f4b5Kyungmin Park	if (mmc_can_discard(card))
1012b3bf915308ca2b50f3beec6cc824083870f0f4b5Kyungmin Park		arg = MMC_DISCARD_ARG;
1013b3bf915308ca2b50f3beec6cc824083870f0f4b5Kyungmin Park	else if (mmc_can_trim(card))
1014bd788c9665fb7c543aac21317059375632343337Adrian Hunter		arg = MMC_TRIM_ARG;
1015bd788c9665fb7c543aac21317059375632343337Adrian Hunter	else
1016bd788c9665fb7c543aac21317059375632343337Adrian Hunter		arg = MMC_ERASE_ARG;
101767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunterretry:
10186a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin	if (card->quirks & MMC_QUIRK_INAND_CMD38) {
10196a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
10206a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin				 INAND_CMD38_ARG_EXT_CSD,
10216a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin				 arg == MMC_TRIM_ARG ?
10226a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin				 INAND_CMD38_ARG_TRIM :
10236a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin				 INAND_CMD38_ARG_ERASE,
10246a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin				 0);
10256a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin		if (err)
10266a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin			goto out;
10276a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin	}
1028bd788c9665fb7c543aac21317059375632343337Adrian Hunter	err = mmc_erase(card, from, nr, arg);
1029bd788c9665fb7c543aac21317059375632343337Adrian Hunterout:
103067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	if (err == -EIO && !mmc_blk_reset(md, card->host, type))
103167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		goto retry;
103267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	if (!err)
103367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		mmc_blk_reset_success(md, type);
1034ecf8b5d0a378a0f922ffca27bd0a9101f246fa11Subhash Jadavani	blk_end_request(req, err, blk_rq_bytes(req));
1035bd788c9665fb7c543aac21317059375632343337Adrian Hunter
1036bd788c9665fb7c543aac21317059375632343337Adrian Hunter	return err ? 0 : 1;
1037bd788c9665fb7c543aac21317059375632343337Adrian Hunter}
1038bd788c9665fb7c543aac21317059375632343337Adrian Hunter
10394980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunterstatic int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq,
10404980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter				       struct request *req)
10414980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter{
10424980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter	struct mmc_blk_data *md = mq->data;
10434980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter	struct mmc_card *card = md->queue.card;
1044775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez	unsigned int from, nr, arg;
104567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	int err = 0, type = MMC_BLK_SECDISCARD;
10464980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter
1047775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez	if (!(mmc_can_secure_erase_trim(card))) {
10484980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter		err = -EOPNOTSUPP;
10494980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter		goto out;
10504980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter	}
10514980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter
1052283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter	from = blk_rq_pos(req);
1053283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter	nr = blk_rq_sectors(req);
1054283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter
1055775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez	if (mmc_can_trim(card) && !mmc_erase_group_aligned(card, from, nr))
1056775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez		arg = MMC_SECURE_TRIM1_ARG;
1057775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez	else
1058775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez		arg = MMC_SECURE_ERASE_ARG;
1059d9ddd62943ee07a75d0428ffcf52f1a747a28c39Kyungmin Park
106067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunterretry:
10616a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin	if (card->quirks & MMC_QUIRK_INAND_CMD38) {
10626a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
10636a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin				 INAND_CMD38_ARG_EXT_CSD,
10646a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin				 arg == MMC_SECURE_TRIM1_ARG ?
10656a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin				 INAND_CMD38_ARG_SECTRIM1 :
10666a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin				 INAND_CMD38_ARG_SECERASE,
10676a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin				 0);
10686a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin		if (err)
1069283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter			goto out_retry;
10706a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin	}
1071283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter
10724980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter	err = mmc_erase(card, from, nr, arg);
1073283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter	if (err == -EIO)
1074283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter		goto out_retry;
1075283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter	if (err)
1076283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter		goto out;
1077283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter
1078283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter	if (arg == MMC_SECURE_TRIM1_ARG) {
10796a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin		if (card->quirks & MMC_QUIRK_INAND_CMD38) {
10806a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin			err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
10816a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin					 INAND_CMD38_ARG_EXT_CSD,
10826a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin					 INAND_CMD38_ARG_SECTRIM2,
10836a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin					 0);
10846a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin			if (err)
1085283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter				goto out_retry;
10866a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin		}
1087283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter
10884980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter		err = mmc_erase(card, from, nr, MMC_SECURE_TRIM2_ARG);
1089283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter		if (err == -EIO)
1090283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter			goto out_retry;
1091283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter		if (err)
1092283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter			goto out;
10936a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin	}
1094283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter
1095283028122db37621b124f079ca8eae5b64807ad4Adrian Hunterout_retry:
1096283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter	if (err && !mmc_blk_reset(md, card->host, type))
109767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		goto retry;
109867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	if (!err)
109967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		mmc_blk_reset_success(md, type);
1100283028122db37621b124f079ca8eae5b64807ad4Adrian Hunterout:
1101ecf8b5d0a378a0f922ffca27bd0a9101f246fa11Subhash Jadavani	blk_end_request(req, err, blk_rq_bytes(req));
11024980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter
11034980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter	return err ? 0 : 1;
11044980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter}
11054980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter
1106f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentinstatic int mmc_blk_issue_flush(struct mmc_queue *mq, struct request *req)
1107f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin{
1108f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin	struct mmc_blk_data *md = mq->data;
1109881d1c25f765938a95def5afe39486ce39f9fc96Seungwon Jeon	struct mmc_card *card = md->queue.card;
1110881d1c25f765938a95def5afe39486ce39f9fc96Seungwon Jeon	int ret = 0;
1111881d1c25f765938a95def5afe39486ce39f9fc96Seungwon Jeon
1112881d1c25f765938a95def5afe39486ce39f9fc96Seungwon Jeon	ret = mmc_flush_cache(card);
1113881d1c25f765938a95def5afe39486ce39f9fc96Seungwon Jeon	if (ret)
1114881d1c25f765938a95def5afe39486ce39f9fc96Seungwon Jeon		ret = -EIO;
1115f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin
1116ecf8b5d0a378a0f922ffca27bd0a9101f246fa11Subhash Jadavani	blk_end_request_all(req, ret);
1117f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin
1118881d1c25f765938a95def5afe39486ce39f9fc96Seungwon Jeon	return ret ? 0 : 1;
1119f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin}
1120f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin
1121f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin/*
1122f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin * Reformat current write as a reliable write, supporting
1123f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin * both legacy and the enhanced reliable write MMC cards.
1124f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin * In each transfer we'll handle only as much as a single
1125f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin * reliable write can handle, thus finish the request in
1126f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin * partial completions.
1127f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin */
1128d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentinstatic inline void mmc_apply_rel_rw(struct mmc_blk_request *brq,
1129d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin				    struct mmc_card *card,
1130d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin				    struct request *req)
1131f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin{
1132f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin	if (!(card->ext_csd.rel_param & EXT_CSD_WR_REL_PARAM_EN)) {
1133f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin		/* Legacy mode imposes restrictions on transfers. */
1134f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin		if (!IS_ALIGNED(brq->cmd.arg, card->ext_csd.rel_sectors))
1135f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin			brq->data.blocks = 1;
1136f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin
1137f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin		if (brq->data.blocks > card->ext_csd.rel_sectors)
1138f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin			brq->data.blocks = card->ext_csd.rel_sectors;
1139f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin		else if (brq->data.blocks < card->ext_csd.rel_sectors)
1140f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin			brq->data.blocks = 1;
1141f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin	}
1142f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin}
1143f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin
11444c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux#define CMD_ERRORS							\
11454c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux	(R1_OUT_OF_RANGE |	/* Command argument out of range */	\
11464c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux	 R1_ADDRESS_ERROR |	/* Misaligned address */		\
11474c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux	 R1_BLOCK_LEN_ERROR |	/* Transferred block length incorrect */\
11484c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux	 R1_WP_VIOLATION |	/* Tried to write to protected block */	\
11494c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux	 R1_CC_ERROR |		/* Card controller error */		\
11504c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux	 R1_ERROR)		/* General/unknown error */
11514c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux
1152ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlinstatic int mmc_blk_err_check(struct mmc_card *card,
1153ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin			     struct mmc_async_req *areq)
1154d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin{
1155ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin	struct mmc_queue_req *mq_mrq = container_of(areq, struct mmc_queue_req,
1156ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin						    mmc_active);
1157ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin	struct mmc_blk_request *brq = &mq_mrq->brq;
1158ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin	struct request *req = mq_mrq->req;
1159c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake	int ecc_err = 0, gen_err = 0;
1160d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin
1161d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	/*
1162d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 * sbc.error indicates a problem with the set block count
1163d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 * command.  No data will have been transferred.
1164d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 *
1165d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 * cmd.error indicates a problem with the r/w command.  No
1166d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 * data will have been transferred.
1167d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 *
1168d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 * stop.error indicates a problem with the stop command.  Data
1169d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 * may have been transferred, or may still be transferring.
1170d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 */
117167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	if (brq->sbc.error || brq->cmd.error || brq->stop.error ||
117267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	    brq->data.error) {
1173c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake		switch (mmc_blk_cmd_recovery(card, req, brq, &ecc_err, &gen_err)) {
1174d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		case ERR_RETRY:
1175d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			return MMC_BLK_RETRY;
1176d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		case ERR_ABORT:
1177d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			return MMC_BLK_ABORT;
1178a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma		case ERR_NOMEDIUM:
1179a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma			return MMC_BLK_NOMEDIUM;
1180d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		case ERR_CONTINUE:
1181d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			break;
1182d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		}
1183d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	}
1184d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin
1185d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	/*
1186d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 * Check for errors relating to the execution of the
1187d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 * initial command - such as address errors.  No data
1188d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 * has been transferred.
1189d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 */
1190d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	if (brq->cmd.resp[0] & CMD_ERRORS) {
1191d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		pr_err("%s: r/w command failed, status = %#x\n",
1192d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		       req->rq_disk->disk_name, brq->cmd.resp[0]);
1193d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		return MMC_BLK_ABORT;
1194d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	}
1195d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin
1196d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	/*
1197d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 * Everything else is either success, or a data error of some
1198d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 * kind.  If it was a write, we may have transitioned to
1199d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 * program mode, which we have to wait for it to complete.
1200d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 */
1201d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) {
1202c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson		int err;
12038fee476b219d1869762d9ef5c189a0c85e919a4dTrey Ramsay
1204c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake		/* Check stop command response */
1205c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake		if (brq->stop.resp[0] & R1_ERROR) {
1206c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake			pr_err("%s: %s: general error sending stop command, stop cmd response %#x\n",
1207c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake			       req->rq_disk->disk_name, __func__,
1208c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake			       brq->stop.resp[0]);
1209c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake			gen_err = 1;
1210c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake		}
1211c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake
1212c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson		err = card_busy_detect(card, MMC_BLK_TIMEOUT_MS, req, &gen_err);
1213c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson		if (err)
1214c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson			return MMC_BLK_CMD_ERR;
1215d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	}
1216d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin
1217c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake	/* if general error occurs, retry the write operation. */
1218c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake	if (gen_err) {
1219c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake		pr_warn("%s: retrying write for general error\n",
1220c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake				req->rq_disk->disk_name);
1221c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake		return MMC_BLK_RETRY;
1222c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake	}
1223c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake
1224d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	if (brq->data.error) {
1225d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		pr_err("%s: error %d transferring data, sector %u, nr %u, cmd response %#x, card status %#x\n",
1226d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		       req->rq_disk->disk_name, brq->data.error,
1227d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		       (unsigned)blk_rq_pos(req),
1228d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		       (unsigned)blk_rq_sectors(req),
1229d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		       brq->cmd.resp[0], brq->stop.resp[0]);
1230d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin
1231d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		if (rq_data_dir(req) == READ) {
123267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			if (ecc_err)
123367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter				return MMC_BLK_ECC_ERR;
1234d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			return MMC_BLK_DATA_ERR;
1235d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		} else {
1236d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			return MMC_BLK_CMD_ERR;
1237d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		}
1238d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	}
1239d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin
124067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	if (!brq->data.bytes_xfered)
124167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		return MMC_BLK_RETRY;
1242d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin
1243ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	if (mmc_packed_cmd(mq_mrq->cmd_type)) {
1244ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		if (unlikely(brq->data.blocks << 9 != brq->data.bytes_xfered))
1245ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			return MMC_BLK_PARTIAL;
1246ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		else
1247ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			return MMC_BLK_SUCCESS;
1248ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	}
1249ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
125067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	if (blk_rq_bytes(req) != brq->data.bytes_xfered)
125167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		return MMC_BLK_PARTIAL;
125267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter
125367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	return MMC_BLK_SUCCESS;
1254d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin}
1255d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin
1256ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeonstatic int mmc_blk_packed_err_check(struct mmc_card *card,
1257ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				    struct mmc_async_req *areq)
1258ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon{
1259ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct mmc_queue_req *mq_rq = container_of(areq, struct mmc_queue_req,
1260ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			mmc_active);
1261ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct request *req = mq_rq->req;
1262ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct mmc_packed *packed = mq_rq->packed;
1263ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	int err, check, status;
1264ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	u8 *ext_csd;
1265ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1266ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	BUG_ON(!packed);
1267ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1268ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	packed->retries--;
1269ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	check = mmc_blk_err_check(card, areq);
1270ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	err = get_card_status(card, &status, 0);
1271ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	if (err) {
1272ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		pr_err("%s: error %d sending status command\n",
1273ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		       req->rq_disk->disk_name, err);
1274ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		return MMC_BLK_ABORT;
1275ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	}
1276ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1277ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	if (status & R1_EXCEPTION_EVENT) {
1278ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		ext_csd = kzalloc(512, GFP_KERNEL);
1279ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		if (!ext_csd) {
1280ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			pr_err("%s: unable to allocate buffer for ext_csd\n",
1281ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			       req->rq_disk->disk_name);
1282ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			return -ENOMEM;
1283ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		}
1284ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1285ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		err = mmc_send_ext_csd(card, ext_csd);
1286ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		if (err) {
1287ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			pr_err("%s: error %d sending ext_csd\n",
1288ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			       req->rq_disk->disk_name, err);
1289ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			check = MMC_BLK_ABORT;
1290ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			goto free;
1291ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		}
1292ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1293ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		if ((ext_csd[EXT_CSD_EXP_EVENTS_STATUS] &
1294ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		     EXT_CSD_PACKED_FAILURE) &&
1295ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		    (ext_csd[EXT_CSD_PACKED_CMD_STATUS] &
1296ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		     EXT_CSD_PACKED_GENERIC_ERROR)) {
1297ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			if (ext_csd[EXT_CSD_PACKED_CMD_STATUS] &
1298ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			    EXT_CSD_PACKED_INDEXED_ERROR) {
1299ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				packed->idx_failure =
1300ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				  ext_csd[EXT_CSD_PACKED_FAILURE_INDEX] - 1;
1301ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				check = MMC_BLK_PARTIAL;
1302ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			}
1303ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			pr_err("%s: packed cmd failed, nr %u, sectors %u, "
1304ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			       "failure index: %d\n",
1305ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			       req->rq_disk->disk_name, packed->nr_entries,
1306ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			       packed->blocks, packed->idx_failure);
1307ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		}
1308ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeonfree:
1309ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		kfree(ext_csd);
1310ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	}
1311ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1312ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	return check;
1313ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon}
1314ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
131554d49d77628bed77e5491b8a2a1158a492843a19Per Forlinstatic void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
131654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin			       struct mmc_card *card,
131754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin			       int disable_multi,
131854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin			       struct mmc_queue *mq)
13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
132054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	u32 readcmd, writecmd;
132154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	struct mmc_blk_request *brq = &mqrq->brq;
132254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	struct request *req = mqrq->req;
13231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mmc_blk_data *md = mq->data;
13244265900e0be653f5b78baf2816857ef57cf1332fSaugata Das	bool do_data_tag;
13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1326f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin	/*
1327f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin	 * Reliable writes are used to implement Forced Unit Access and
1328f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin	 * REQ_META accesses, and are supported only on MMCs.
132965299a3b788bd274bed92f9fa3232082c9f3ea70Christoph Hellwig	 *
133065299a3b788bd274bed92f9fa3232082c9f3ea70Christoph Hellwig	 * XXX: this really needs a good explanation of why REQ_META
133165299a3b788bd274bed92f9fa3232082c9f3ea70Christoph Hellwig	 * is treated special.
1332f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin	 */
1333f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin	bool do_rel_wr = ((req->cmd_flags & REQ_FUA) ||
1334f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin			  (req->cmd_flags & REQ_META)) &&
1335f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin		(rq_data_dir(req) == WRITE) &&
1336d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin		(md->flags & MMC_BLK_REL_WR);
1337f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin
133854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	memset(brq, 0, sizeof(struct mmc_blk_request));
133954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	brq->mrq.cmd = &brq->cmd;
134054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	brq->mrq.data = &brq->data;
13411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
134254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	brq->cmd.arg = blk_rq_pos(req);
134354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	if (!mmc_card_blockaddr(card))
134454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		brq->cmd.arg <<= 9;
134554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	brq->cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
134654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	brq->data.blksz = 512;
134754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	brq->stop.opcode = MMC_STOP_TRANSMISSION;
134854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	brq->stop.arg = 0;
134954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	brq->data.blocks = blk_rq_sectors(req);
13506a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter
135154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	/*
135254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * The block layer doesn't support all sector count
135354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * restrictions, so we need to be prepared for too big
135454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * requests.
135554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 */
135654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	if (brq->data.blocks > card->host->max_blk_count)
135754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		brq->data.blocks = card->host->max_blk_count;
13581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13592bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley	if (brq->data.blocks > 1) {
13602bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley		/*
13612bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley		 * After a read error, we redo the request one sector
13622bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley		 * at a time in order to accurately determine which
13632bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley		 * sectors can be read successfully.
13642bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley		 */
13652bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley		if (disable_multi)
13662bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley			brq->data.blocks = 1;
13672bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley
13682bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley		/* Some controllers can't do multiblock reads due to hw bugs */
13692bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley		if (card->host->caps2 & MMC_CAP2_NO_MULTI_READ &&
13702bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley		    rq_data_dir(req) == READ)
13712bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley			brq->data.blocks = 1;
13722bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley	}
1373d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin
137454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	if (brq->data.blocks > 1 || do_rel_wr) {
137554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		/* SPI multiblock writes terminate using a special
137654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		 * token, not a STOP_TRANSMISSION request.
1377d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin		 */
137854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		if (!mmc_host_is_spi(card->host) ||
137954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		    rq_data_dir(req) == READ)
138054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin			brq->mrq.stop = &brq->stop;
138154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		readcmd = MMC_READ_MULTIPLE_BLOCK;
138254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		writecmd = MMC_WRITE_MULTIPLE_BLOCK;
138354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	} else {
138454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		brq->mrq.stop = NULL;
138554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		readcmd = MMC_READ_SINGLE_BLOCK;
138654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		writecmd = MMC_WRITE_BLOCK;
138754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	}
138854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	if (rq_data_dir(req) == READ) {
138954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		brq->cmd.opcode = readcmd;
139054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		brq->data.flags |= MMC_DATA_READ;
1391bcc3e1726d827c2d6f62f0e0e7bbc99eed7ad925Ulf Hansson		if (brq->mrq.stop)
1392bcc3e1726d827c2d6f62f0e0e7bbc99eed7ad925Ulf Hansson			brq->stop.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 |
1393bcc3e1726d827c2d6f62f0e0e7bbc99eed7ad925Ulf Hansson					MMC_CMD_AC;
139454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	} else {
139554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		brq->cmd.opcode = writecmd;
139654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		brq->data.flags |= MMC_DATA_WRITE;
1397bcc3e1726d827c2d6f62f0e0e7bbc99eed7ad925Ulf Hansson		if (brq->mrq.stop)
1398bcc3e1726d827c2d6f62f0e0e7bbc99eed7ad925Ulf Hansson			brq->stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B |
1399bcc3e1726d827c2d6f62f0e0e7bbc99eed7ad925Ulf Hansson					MMC_CMD_AC;
140054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	}
1401d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin
140254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	if (do_rel_wr)
140354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		mmc_apply_rel_rw(brq, card, req);
1404f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin
140554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	/*
14064265900e0be653f5b78baf2816857ef57cf1332fSaugata Das	 * Data tag is used only during writing meta data to speed
14074265900e0be653f5b78baf2816857ef57cf1332fSaugata Das	 * up write and any subsequent read of this meta data
14084265900e0be653f5b78baf2816857ef57cf1332fSaugata Das	 */
14094265900e0be653f5b78baf2816857ef57cf1332fSaugata Das	do_data_tag = (card->ext_csd.data_tag_unit_size) &&
14104265900e0be653f5b78baf2816857ef57cf1332fSaugata Das		(req->cmd_flags & REQ_META) &&
14114265900e0be653f5b78baf2816857ef57cf1332fSaugata Das		(rq_data_dir(req) == WRITE) &&
14124265900e0be653f5b78baf2816857ef57cf1332fSaugata Das		((brq->data.blocks * brq->data.blksz) >=
14134265900e0be653f5b78baf2816857ef57cf1332fSaugata Das		 card->ext_csd.data_tag_unit_size);
14144265900e0be653f5b78baf2816857ef57cf1332fSaugata Das
14154265900e0be653f5b78baf2816857ef57cf1332fSaugata Das	/*
141654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * Pre-defined multi-block transfers are preferable to
141754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * open ended-ones (and necessary for reliable writes).
141854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * However, it is not sufficient to just send CMD23,
141954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * and avoid the final CMD12, as on an error condition
142054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * CMD12 (stop) needs to be sent anyway. This, coupled
142154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * with Auto-CMD23 enhancements provided by some
142254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * hosts, means that the complexity of dealing
142354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * with this is best left to the host. If CMD23 is
142454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * supported by card and host, we'll fill sbc in and let
142554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * the host deal with handling it correctly. This means
142654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * that for hosts that don't expose MMC_CAP_CMD23, no
142754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * change of behavior will be observed.
142854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 *
142954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * N.B: Some MMC cards experience perf degradation.
143054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * We'll avoid using CMD23-bounded multiblock writes for
143154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * these, while retaining features like reliable writes.
143254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 */
14334265900e0be653f5b78baf2816857ef57cf1332fSaugata Das	if ((md->flags & MMC_BLK_CMD23) && mmc_op_multi(brq->cmd.opcode) &&
14344265900e0be653f5b78baf2816857ef57cf1332fSaugata Das	    (do_rel_wr || !(card->quirks & MMC_QUIRK_BLK_NO_CMD23) ||
14354265900e0be653f5b78baf2816857ef57cf1332fSaugata Das	     do_data_tag)) {
143654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		brq->sbc.opcode = MMC_SET_BLOCK_COUNT;
143754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		brq->sbc.arg = brq->data.blocks |
14384265900e0be653f5b78baf2816857ef57cf1332fSaugata Das			(do_rel_wr ? (1 << 31) : 0) |
14394265900e0be653f5b78baf2816857ef57cf1332fSaugata Das			(do_data_tag ? (1 << 29) : 0);
144054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		brq->sbc.flags = MMC_RSP_R1 | MMC_CMD_AC;
144154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		brq->mrq.sbc = &brq->sbc;
144254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	}
144398ccf14909ba02a41c5925b0b2c92aeeef23d3b9Pierre Ossman
144454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	mmc_set_data_timeout(&brq->data, card);
144554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin
144654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	brq->data.sg = mqrq->sg;
144754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	brq->data.sg_len = mmc_queue_map_sg(mq, mqrq);
144854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin
144954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	/*
145054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * Adjust the sg list so it is the same size as the
145154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * request.
145254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 */
145354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	if (brq->data.blocks != blk_rq_sectors(req)) {
145454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		int i, data_size = brq->data.blocks << 9;
145554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		struct scatterlist *sg;
145654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin
145754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		for_each_sg(brq->data.sg, sg, brq->data.sg_len, i) {
145854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin			data_size -= sg->length;
145954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin			if (data_size <= 0) {
146054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin				sg->length += data_size;
146154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin				i++;
146254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin				break;
14636a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter			}
14646a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter		}
146554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		brq->data.sg_len = i;
146654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	}
146754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin
1468ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin	mqrq->mmc_active.mrq = &brq->mrq;
1469ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin	mqrq->mmc_active.err_check = mmc_blk_err_check;
1470ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin
147154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	mmc_queue_bounce_pre(mqrq);
147254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin}
14736a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter
1474ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeonstatic inline u8 mmc_calc_packed_hdr_segs(struct request_queue *q,
1475ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon					  struct mmc_card *card)
1476ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon{
1477ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	unsigned int hdr_sz = mmc_large_sector(card) ? 4096 : 512;
1478ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	unsigned int max_seg_sz = queue_max_segment_size(q);
1479ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	unsigned int len, nr_segs = 0;
1480ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1481ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	do {
1482ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		len = min(hdr_sz, max_seg_sz);
1483ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		hdr_sz -= len;
1484ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		nr_segs++;
1485ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	} while (hdr_sz);
1486ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1487ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	return nr_segs;
1488ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon}
1489ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1490ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeonstatic u8 mmc_blk_prep_packed_list(struct mmc_queue *mq, struct request *req)
1491ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon{
1492ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct request_queue *q = mq->queue;
1493ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct mmc_card *card = mq->card;
1494ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct request *cur = req, *next = NULL;
1495ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct mmc_blk_data *md = mq->data;
1496ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct mmc_queue_req *mqrq = mq->mqrq_cur;
1497ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	bool en_rel_wr = card->ext_csd.rel_param & EXT_CSD_WR_REL_PARAM_EN;
1498ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	unsigned int req_sectors = 0, phys_segments = 0;
1499ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	unsigned int max_blk_count, max_phys_segs;
1500ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	bool put_back = true;
1501ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	u8 max_packed_rw = 0;
1502ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	u8 reqs = 0;
1503ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1504ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	if (!(md->flags & MMC_BLK_PACKED_CMD))
1505ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		goto no_packed;
1506ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1507ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	if ((rq_data_dir(cur) == WRITE) &&
1508ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	    mmc_host_packed_wr(card->host))
1509ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		max_packed_rw = card->ext_csd.max_packed_writes;
1510ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1511ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	if (max_packed_rw == 0)
1512ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		goto no_packed;
1513ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1514ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	if (mmc_req_rel_wr(cur) &&
1515ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	    (md->flags & MMC_BLK_REL_WR) && !en_rel_wr)
1516ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		goto no_packed;
1517ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1518ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	if (mmc_large_sector(card) &&
1519ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	    !IS_ALIGNED(blk_rq_sectors(cur), 8))
1520ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		goto no_packed;
1521ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1522ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	mmc_blk_clear_packed(mqrq);
1523ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1524ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	max_blk_count = min(card->host->max_blk_count,
1525ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			    card->host->max_req_size >> 9);
1526ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	if (unlikely(max_blk_count > 0xffff))
1527ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		max_blk_count = 0xffff;
1528ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1529ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	max_phys_segs = queue_max_segments(q);
1530ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	req_sectors += blk_rq_sectors(cur);
1531ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	phys_segments += cur->nr_phys_segments;
1532ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1533ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	if (rq_data_dir(cur) == WRITE) {
1534ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		req_sectors += mmc_large_sector(card) ? 8 : 1;
1535ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		phys_segments += mmc_calc_packed_hdr_segs(q, card);
1536ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	}
1537ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1538ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	do {
1539ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		if (reqs >= max_packed_rw - 1) {
1540ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			put_back = false;
1541ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			break;
1542ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		}
1543ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1544ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		spin_lock_irq(q->queue_lock);
1545ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		next = blk_fetch_request(q);
1546ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		spin_unlock_irq(q->queue_lock);
1547ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		if (!next) {
1548ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			put_back = false;
1549ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			break;
1550ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		}
1551ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1552ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		if (mmc_large_sector(card) &&
1553ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		    !IS_ALIGNED(blk_rq_sectors(next), 8))
1554ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			break;
1555ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1556ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		if (next->cmd_flags & REQ_DISCARD ||
1557ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		    next->cmd_flags & REQ_FLUSH)
1558ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			break;
1559ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1560ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		if (rq_data_dir(cur) != rq_data_dir(next))
1561ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			break;
1562ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1563ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		if (mmc_req_rel_wr(next) &&
1564ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		    (md->flags & MMC_BLK_REL_WR) && !en_rel_wr)
1565ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			break;
1566ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1567ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		req_sectors += blk_rq_sectors(next);
1568ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		if (req_sectors > max_blk_count)
1569ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			break;
1570ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1571ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		phys_segments +=  next->nr_phys_segments;
1572ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		if (phys_segments > max_phys_segs)
1573ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			break;
1574ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1575ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		list_add_tail(&next->queuelist, &mqrq->packed->list);
1576ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		cur = next;
1577ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		reqs++;
1578ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	} while (1);
1579ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1580ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	if (put_back) {
1581ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		spin_lock_irq(q->queue_lock);
1582ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		blk_requeue_request(q, next);
1583ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		spin_unlock_irq(q->queue_lock);
1584ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	}
1585ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1586ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	if (reqs > 0) {
1587ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		list_add(&req->queuelist, &mqrq->packed->list);
1588ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		mqrq->packed->nr_entries = ++reqs;
1589ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		mqrq->packed->retries = reqs;
1590ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		return reqs;
1591ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	}
1592ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1593ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeonno_packed:
1594ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	mqrq->cmd_type = MMC_PACKED_NONE;
1595ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	return 0;
1596ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon}
1597ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1598ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeonstatic void mmc_blk_packed_hdr_wrq_prep(struct mmc_queue_req *mqrq,
1599ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon					struct mmc_card *card,
1600ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon					struct mmc_queue *mq)
1601ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon{
1602ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct mmc_blk_request *brq = &mqrq->brq;
1603ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct request *req = mqrq->req;
1604ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct request *prq;
1605ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct mmc_blk_data *md = mq->data;
1606ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct mmc_packed *packed = mqrq->packed;
1607ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	bool do_rel_wr, do_data_tag;
1608ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	u32 *packed_cmd_hdr;
1609ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	u8 hdr_blocks;
1610ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	u8 i = 1;
1611ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1612ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	BUG_ON(!packed);
1613ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1614ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	mqrq->cmd_type = MMC_PACKED_WRITE;
1615ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	packed->blocks = 0;
1616ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	packed->idx_failure = MMC_PACKED_NR_IDX;
1617ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1618ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	packed_cmd_hdr = packed->cmd_hdr;
1619ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	memset(packed_cmd_hdr, 0, sizeof(packed->cmd_hdr));
1620ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	packed_cmd_hdr[0] = (packed->nr_entries << 16) |
1621ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		(PACKED_CMD_WR << 8) | PACKED_CMD_VER;
1622ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	hdr_blocks = mmc_large_sector(card) ? 8 : 1;
1623ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1624ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	/*
1625ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	 * Argument for each entry of packed group
1626ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	 */
1627ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	list_for_each_entry(prq, &packed->list, queuelist) {
1628ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		do_rel_wr = mmc_req_rel_wr(prq) && (md->flags & MMC_BLK_REL_WR);
1629ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		do_data_tag = (card->ext_csd.data_tag_unit_size) &&
1630ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			(prq->cmd_flags & REQ_META) &&
1631ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			(rq_data_dir(prq) == WRITE) &&
1632ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			((brq->data.blocks * brq->data.blksz) >=
1633ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			 card->ext_csd.data_tag_unit_size);
1634ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		/* Argument of CMD23 */
1635ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		packed_cmd_hdr[(i * 2)] =
1636ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			(do_rel_wr ? MMC_CMD23_ARG_REL_WR : 0) |
1637ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			(do_data_tag ? MMC_CMD23_ARG_TAG_REQ : 0) |
1638ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			blk_rq_sectors(prq);
1639ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		/* Argument of CMD18 or CMD25 */
1640ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		packed_cmd_hdr[((i * 2)) + 1] =
1641ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			mmc_card_blockaddr(card) ?
1642ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			blk_rq_pos(prq) : blk_rq_pos(prq) << 9;
1643ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		packed->blocks += blk_rq_sectors(prq);
1644ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		i++;
1645ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	}
1646ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1647ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	memset(brq, 0, sizeof(struct mmc_blk_request));
1648ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	brq->mrq.cmd = &brq->cmd;
1649ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	brq->mrq.data = &brq->data;
1650ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	brq->mrq.sbc = &brq->sbc;
1651ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	brq->mrq.stop = &brq->stop;
1652ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1653ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	brq->sbc.opcode = MMC_SET_BLOCK_COUNT;
1654ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	brq->sbc.arg = MMC_CMD23_ARG_PACKED | (packed->blocks + hdr_blocks);
1655ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	brq->sbc.flags = MMC_RSP_R1 | MMC_CMD_AC;
1656ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1657ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	brq->cmd.opcode = MMC_WRITE_MULTIPLE_BLOCK;
1658ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	brq->cmd.arg = blk_rq_pos(req);
1659ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	if (!mmc_card_blockaddr(card))
1660ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		brq->cmd.arg <<= 9;
1661ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	brq->cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
1662ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1663ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	brq->data.blksz = 512;
1664ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	brq->data.blocks = packed->blocks + hdr_blocks;
1665ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	brq->data.flags |= MMC_DATA_WRITE;
1666ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1667ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	brq->stop.opcode = MMC_STOP_TRANSMISSION;
1668ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	brq->stop.arg = 0;
1669ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	brq->stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
1670ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1671ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	mmc_set_data_timeout(&brq->data, card);
1672ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1673ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	brq->data.sg = mqrq->sg;
1674ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	brq->data.sg_len = mmc_queue_map_sg(mq, mqrq);
1675ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1676ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	mqrq->mmc_active.mrq = &brq->mrq;
1677ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	mqrq->mmc_active.err_check = mmc_blk_packed_err_check;
1678ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1679ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	mmc_queue_bounce_pre(mqrq);
1680ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon}
1681ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
168267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunterstatic int mmc_blk_cmd_err(struct mmc_blk_data *md, struct mmc_card *card,
168367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			   struct mmc_blk_request *brq, struct request *req,
168467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			   int ret)
168567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter{
1686ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct mmc_queue_req *mq_rq;
1687ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	mq_rq = container_of(brq, struct mmc_queue_req, brq);
1688ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
168967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	/*
169067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	 * If this is an SD card and we're writing, we can first
169167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	 * mark the known good sectors as ok.
169267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	 *
169367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	 * If the card is not SD, we can still ok written sectors
169467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	 * as reported by the controller (which might be less than
169567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	 * the real number of written sectors, but never more).
169667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	 */
169767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	if (mmc_card_sd(card)) {
169867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		u32 blocks;
169967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter
170067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		blocks = mmc_sd_num_wr_blocks(card);
170167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		if (blocks != (u32)-1) {
1702ecf8b5d0a378a0f922ffca27bd0a9101f246fa11Subhash Jadavani			ret = blk_end_request(req, 0, blocks << 9);
170367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		}
170467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	} else {
1705ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		if (!mmc_packed_cmd(mq_rq->cmd_type))
1706ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			ret = blk_end_request(req, 0, brq->data.bytes_xfered);
170767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	}
170867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	return ret;
170967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter}
171067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter
1711ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeonstatic int mmc_blk_end_packed_req(struct mmc_queue_req *mq_rq)
1712ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon{
1713ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct request *prq;
1714ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct mmc_packed *packed = mq_rq->packed;
1715ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	int idx = packed->idx_failure, i = 0;
1716ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	int ret = 0;
1717ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1718ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	BUG_ON(!packed);
1719ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1720ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	while (!list_empty(&packed->list)) {
1721ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		prq = list_entry_rq(packed->list.next);
1722ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		if (idx == i) {
1723ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			/* retry from error index */
1724ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			packed->nr_entries -= idx;
1725ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			mq_rq->req = prq;
1726ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			ret = 1;
1727ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1728ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			if (packed->nr_entries == MMC_PACKED_NR_SINGLE) {
1729ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				list_del_init(&prq->queuelist);
1730ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				mmc_blk_clear_packed(mq_rq);
1731ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			}
1732ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			return ret;
1733ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		}
1734ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		list_del_init(&prq->queuelist);
1735ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		blk_end_request(prq, 0, blk_rq_bytes(prq));
1736ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		i++;
1737ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	}
1738ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1739ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	mmc_blk_clear_packed(mq_rq);
1740ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	return ret;
1741ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon}
1742ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1743ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeonstatic void mmc_blk_abort_packed_req(struct mmc_queue_req *mq_rq)
1744ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon{
1745ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct request *prq;
1746ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct mmc_packed *packed = mq_rq->packed;
1747ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1748ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	BUG_ON(!packed);
1749ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1750ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	while (!list_empty(&packed->list)) {
1751ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		prq = list_entry_rq(packed->list.next);
1752ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		list_del_init(&prq->queuelist);
1753ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		blk_end_request(prq, -EIO, blk_rq_bytes(prq));
1754ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	}
1755ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1756ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	mmc_blk_clear_packed(mq_rq);
1757ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon}
1758ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1759ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeonstatic void mmc_blk_revert_packed_req(struct mmc_queue *mq,
1760ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				      struct mmc_queue_req *mq_rq)
1761ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon{
1762ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct request *prq;
1763ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct request_queue *q = mq->queue;
1764ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct mmc_packed *packed = mq_rq->packed;
1765ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1766ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	BUG_ON(!packed);
1767ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1768ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	while (!list_empty(&packed->list)) {
1769ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		prq = list_entry_rq(packed->list.prev);
1770ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		if (prq->queuelist.prev != &packed->list) {
1771ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			list_del_init(&prq->queuelist);
1772ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			spin_lock_irq(q->queue_lock);
1773ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			blk_requeue_request(mq->queue, prq);
1774ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			spin_unlock_irq(q->queue_lock);
1775ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		} else {
1776ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			list_del_init(&prq->queuelist);
1777ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		}
1778ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	}
1779ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1780ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	mmc_blk_clear_packed(mq_rq);
1781ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon}
1782ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1783ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlinstatic int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
178454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin{
178554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	struct mmc_blk_data *md = mq->data;
178654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	struct mmc_card *card = md->queue.card;
178754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	struct mmc_blk_request *brq = &mq->mqrq_cur->brq;
178867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	int ret = 1, disable_multi = 0, retry = 0, type;
1789d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	enum mmc_blk_status status;
1790ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin	struct mmc_queue_req *mq_rq;
1791a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das	struct request *req = rqc;
1792ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin	struct mmc_async_req *areq;
1793ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	const u8 packed_nr = 2;
1794ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	u8 reqs = 0;
17951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1796ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin	if (!rqc && !mq->mqrq_prev->req)
1797ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		return 0;
179898ccf14909ba02a41c5925b0b2c92aeeef23d3b9Pierre Ossman
1799ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	if (rqc)
1800ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		reqs = mmc_blk_prep_packed_list(mq, rqc);
1801ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1802ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin	do {
1803ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		if (rqc) {
1804a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das			/*
1805a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das			 * When 4KB native sector is enabled, only 8 blocks
1806a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das			 * multiple read or write is allowed
1807a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das			 */
1808a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das			if ((brq->data.blocks & 0x07) &&
1809a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das			    (card->ext_csd.data_sector_size == 4096)) {
1810a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das				pr_err("%s: Transfer size is not 4KB sector size aligned\n",
1811a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das					req->rq_disk->disk_name);
1812ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				mq_rq = mq->mqrq_cur;
1813a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das				goto cmd_abort;
1814a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das			}
1815ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1816ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			if (reqs >= packed_nr)
1817ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				mmc_blk_packed_hdr_wrq_prep(mq->mqrq_cur,
1818ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon							    card, mq);
1819ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			else
1820ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				mmc_blk_rw_rq_prep(mq->mqrq_cur, card, 0, mq);
1821ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin			areq = &mq->mqrq_cur->mmc_active;
1822ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		} else
1823ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin			areq = NULL;
1824ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		areq = mmc_start_req(card->host, areq, (int *) &status);
18252220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman		if (!areq) {
18262220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman			if (status == MMC_BLK_NEW_REQUEST)
18272220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman				mq->flags |= MMC_QUEUE_NEW_REQUEST;
1828ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin			return 0;
18292220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman		}
1830ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin
1831ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		mq_rq = container_of(areq, struct mmc_queue_req, mmc_active);
1832ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		brq = &mq_rq->brq;
1833ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		req = mq_rq->req;
183467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		type = rq_data_dir(req) == READ ? MMC_BLK_READ : MMC_BLK_WRITE;
1835ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		mmc_queue_bounce_post(mq_rq);
183698ccf14909ba02a41c5925b0b2c92aeeef23d3b9Pierre Ossman
1837d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		switch (status) {
1838d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		case MMC_BLK_SUCCESS:
1839d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		case MMC_BLK_PARTIAL:
1840d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			/*
1841d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			 * A block was successfully transferred.
1842d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			 */
184367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			mmc_blk_reset_success(md, type);
1844ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1845ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			if (mmc_packed_cmd(mq_rq->cmd_type)) {
1846ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				ret = mmc_blk_end_packed_req(mq_rq);
1847ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				break;
1848ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			} else {
1849ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				ret = blk_end_request(req, 0,
1850d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin						brq->data.bytes_xfered);
1851ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			}
1852ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
185367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			/*
185467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			 * If the blk_end_request function returns non-zero even
185567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			 * though all data has been transferred and no errors
185667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			 * were returned by the host controller, it's a bug.
185767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			 */
1858ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin			if (status == MMC_BLK_SUCCESS && ret) {
1859a3c76eb9d4a1e68a69dd880cf0bcb8a52418b993Girish K S				pr_err("%s BUG rq_tot %d d_xfer %d\n",
1860ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin				       __func__, blk_rq_bytes(req),
1861ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin				       brq->data.bytes_xfered);
1862ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin				rqc = NULL;
1863ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin				goto cmd_abort;
1864ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin			}
1865d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			break;
1866d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		case MMC_BLK_CMD_ERR:
186767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			ret = mmc_blk_cmd_err(md, card, brq, req, ret);
186867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			if (!mmc_blk_reset(md, card->host, type))
186967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter				break;
187067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			goto cmd_abort;
1871d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		case MMC_BLK_RETRY:
1872d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			if (retry++ < 5)
1873a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux				break;
187467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			/* Fall through */
1875d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		case MMC_BLK_ABORT:
187667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			if (!mmc_blk_reset(md, card->host, type))
187767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter				break;
18784c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux			goto cmd_abort;
187967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		case MMC_BLK_DATA_ERR: {
188067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			int err;
188167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter
188267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			err = mmc_blk_reset(md, card->host, type);
188367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			if (!err)
188467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter				break;
1885ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			if (err == -ENODEV ||
1886ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				mmc_packed_cmd(mq_rq->cmd_type))
188767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter				goto cmd_abort;
188867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			/* Fall through */
188967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		}
189067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		case MMC_BLK_ECC_ERR:
189167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			if (brq->data.blocks > 1) {
189267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter				/* Redo read one sector at a time */
189367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter				pr_warning("%s: retrying using single block read\n",
189467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter					   req->rq_disk->disk_name);
189567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter				disable_multi = 1;
189667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter				break;
189767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			}
1898d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			/*
1899d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			 * After an error, we redo I/O one sector at a
1900d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			 * time, so we only reach here after trying to
1901d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			 * read a single sector.
1902d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			 */
1903ecf8b5d0a378a0f922ffca27bd0a9101f246fa11Subhash Jadavani			ret = blk_end_request(req, -EIO,
1904d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin						brq->data.blksz);
1905ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin			if (!ret)
1906ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin				goto start_new_req;
1907d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			break;
1908a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma		case MMC_BLK_NOMEDIUM:
1909a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma			goto cmd_abort;
19102220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman		default:
19112220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman			pr_err("%s: Unhandled return value (%d)",
19122220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman					req->rq_disk->disk_name, status);
19132220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman			goto cmd_abort;
19144c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux		}
19154c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux
1916ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		if (ret) {
1917ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			if (mmc_packed_cmd(mq_rq->cmd_type)) {
1918ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				if (!mq_rq->packed->retries)
1919ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon					goto cmd_abort;
1920ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				mmc_blk_packed_hdr_wrq_prep(mq_rq, card, mq);
1921ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				mmc_start_req(card->host,
1922ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon					      &mq_rq->mmc_active, NULL);
1923ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			} else {
1924ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1925ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				/*
1926ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				 * In case of a incomplete request
1927ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				 * prepare it again and resend.
1928ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				 */
1929ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				mmc_blk_rw_rq_prep(mq_rq, card,
1930ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon						disable_multi, mq);
1931ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				mmc_start_req(card->host,
1932ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon						&mq_rq->mmc_active, NULL);
1933ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			}
1934ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		}
19351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} while (ret);
19361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 1;
19381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1939a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux cmd_abort:
1940ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	if (mmc_packed_cmd(mq_rq->cmd_type)) {
1941ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		mmc_blk_abort_packed_req(mq_rq);
1942ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	} else {
1943ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		if (mmc_card_removed(card))
1944ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			req->cmd_flags |= REQ_QUIET;
1945ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		while (ret)
1946ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			ret = blk_end_request(req, -EIO,
1947ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon					blk_rq_cur_bytes(req));
1948ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	}
19491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1950ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin start_new_req:
1951ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin	if (rqc) {
19527a81902fa52f2b6f5037e167f74ebb5a41cfc7d1Seungwon Jeon		if (mmc_card_removed(card)) {
19537a81902fa52f2b6f5037e167f74ebb5a41cfc7d1Seungwon Jeon			rqc->cmd_flags |= REQ_QUIET;
19547a81902fa52f2b6f5037e167f74ebb5a41cfc7d1Seungwon Jeon			blk_end_request_all(rqc, -EIO);
19557a81902fa52f2b6f5037e167f74ebb5a41cfc7d1Seungwon Jeon		} else {
1956ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			/*
1957ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			 * If current request is packed, it needs to put back.
1958ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			 */
1959ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			if (mmc_packed_cmd(mq->mqrq_cur->cmd_type))
1960ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				mmc_blk_revert_packed_req(mq, mq->mqrq_cur);
1961ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
19627a81902fa52f2b6f5037e167f74ebb5a41cfc7d1Seungwon Jeon			mmc_blk_rw_rq_prep(mq->mqrq_cur, card, 0, mq);
19637a81902fa52f2b6f5037e167f74ebb5a41cfc7d1Seungwon Jeon			mmc_start_req(card->host,
19647a81902fa52f2b6f5037e167f74ebb5a41cfc7d1Seungwon Jeon				      &mq->mqrq_cur->mmc_active, NULL);
19657a81902fa52f2b6f5037e167f74ebb5a41cfc7d1Seungwon Jeon		}
1966ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin	}
1967ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin
19681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
19691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
19701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1971bd788c9665fb7c543aac21317059375632343337Adrian Hunterstatic int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
1972bd788c9665fb7c543aac21317059375632343337Adrian Hunter{
19731a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin	int ret;
19741a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin	struct mmc_blk_data *md = mq->data;
19751a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin	struct mmc_card *card = md->queue.card;
19762220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman	struct mmc_host *host = card->host;
19772220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman	unsigned long flags;
1978f662ae48ae67dfd42739e65750274fe8de46240aRay Jui	unsigned int cmd_flags = req ? req->cmd_flags : 0;
19791a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin
1980ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin	if (req && !mq->mqrq_prev->req)
1981ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		/* claim host only for the first request */
1982e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson		mmc_get_card(card);
1983ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin
1984371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	ret = mmc_blk_part_switch(card, md);
1985371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	if (ret) {
19860d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter		if (req) {
1987ecf8b5d0a378a0f922ffca27bd0a9101f246fa11Subhash Jadavani			blk_end_request_all(req, -EIO);
19880d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter		}
1989371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		ret = 0;
1990371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		goto out;
1991371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	}
19921a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin
19932220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman	mq->flags &= ~MMC_QUEUE_NEW_REQUEST;
1994f662ae48ae67dfd42739e65750274fe8de46240aRay Jui	if (cmd_flags & REQ_DISCARD) {
1995ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		/* complete ongoing async transfer before issuing discard */
1996ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		if (card->host->areq)
1997ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin			mmc_blk_issue_rw_rq(mq, NULL);
19983550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen		if (req->cmd_flags & REQ_SECURE &&
19993550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen			!(card->quirks & MMC_QUIRK_SEC_ERASE_TRIM_BROKEN))
20001a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin			ret = mmc_blk_issue_secdiscard_rq(mq, req);
20014980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter		else
20021a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin			ret = mmc_blk_issue_discard_rq(mq, req);
2003f662ae48ae67dfd42739e65750274fe8de46240aRay Jui	} else if (cmd_flags & REQ_FLUSH) {
2004393f9a08e2ee72e42379489a5781feaf9c406d5fJaehoon Chung		/* complete ongoing async transfer before issuing flush */
2005393f9a08e2ee72e42379489a5781feaf9c406d5fJaehoon Chung		if (card->host->areq)
2006393f9a08e2ee72e42379489a5781feaf9c406d5fJaehoon Chung			mmc_blk_issue_rw_rq(mq, NULL);
20071a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin		ret = mmc_blk_issue_flush(mq, req);
20084980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter	} else {
20092220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman		if (!req && host->areq) {
20102220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman			spin_lock_irqsave(&host->context_info.lock, flags);
20112220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman			host->context_info.is_waiting_last_req = true;
20122220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman			spin_unlock_irqrestore(&host->context_info.lock, flags);
20132220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman		}
20141a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin		ret = mmc_blk_issue_rw_rq(mq, req);
20154980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter	}
20161a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin
2017371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinout:
2018ef3a69c7a40d5350adeaed7f0f4b4dcf6362dbbdSeungwon Jeon	if ((!req && !(mq->flags & MMC_QUEUE_NEW_REQUEST)) ||
2019f662ae48ae67dfd42739e65750274fe8de46240aRay Jui	     (cmd_flags & MMC_REQ_SPECIAL_MASK))
2020ef3a69c7a40d5350adeaed7f0f4b4dcf6362dbbdSeungwon Jeon		/*
2021ef3a69c7a40d5350adeaed7f0f4b4dcf6362dbbdSeungwon Jeon		 * Release host when there are no more requests
2022ef3a69c7a40d5350adeaed7f0f4b4dcf6362dbbdSeungwon Jeon		 * and after special request(discard, flush) is done.
2023ef3a69c7a40d5350adeaed7f0f4b4dcf6362dbbdSeungwon Jeon		 * In case sepecial request, there is no reentry to
2024ef3a69c7a40d5350adeaed7f0f4b4dcf6362dbbdSeungwon Jeon		 * the 'mmc_blk_issue_rq' with 'mqrq_prev->req'.
2025ef3a69c7a40d5350adeaed7f0f4b4dcf6362dbbdSeungwon Jeon		 */
2026e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson		mmc_put_card(card);
20271a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin	return ret;
2028bd788c9665fb7c543aac21317059375632343337Adrian Hunter}
20291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2030a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell Kingstatic inline int mmc_blk_readonly(struct mmc_card *card)
2031a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King{
2032a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	return mmc_card_readonly(card) ||
2033a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	       !(card->csd.cmdclass & CCC_BLOCK_WRITE);
2034a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King}
2035a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King
2036371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
2037371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin					      struct device *parent,
2038371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin					      sector_t size,
2039371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin					      bool default_ro,
2040add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm					      const char *subname,
2041add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm					      int area_type)
20421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
20431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mmc_blk_data *md;
20441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int devidx, ret;
20451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20465e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson	devidx = find_first_zero_bit(dev_use, max_devices);
20475e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson	if (devidx >= max_devices)
20481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return ERR_PTR(-ENOSPC);
20491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__set_bit(devidx, dev_use);
20501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2051dd00cc486ab1c17049a535413d1751ef3482141cYoann Padioleau	md = kzalloc(sizeof(struct mmc_blk_data), GFP_KERNEL);
2052a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	if (!md) {
2053a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King		ret = -ENOMEM;
2054a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King		goto out;
2055a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	}
20561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2057a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	/*
2058f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin	 * !subname implies we are creating main mmc_blk_data that will be
2059f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin	 * associated with mmc_card with mmc_set_drvdata. Due to device
2060f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin	 * partitions, devidx will not coincide with a per-physical card
2061f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin	 * index anymore so we keep track of a name index.
2062f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin	 */
2063f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin	if (!subname) {
2064f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin		md->name_idx = find_first_zero_bit(name_use, max_devices);
2065f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin		__set_bit(md->name_idx, name_use);
2066add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	} else
2067f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin		md->name_idx = ((struct mmc_blk_data *)
2068f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin				dev_to_disk(parent)->private_data)->name_idx;
2069f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin
2070add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	md->area_type = area_type;
2071add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
2072f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin	/*
2073a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	 * Set the read-only status based on the supported commands
2074a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	 * and the write protect switch.
2075a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	 */
2076a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	md->read_only = mmc_blk_readonly(card);
20771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20785e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson	md->disk = alloc_disk(perdev_minors);
2079a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	if (md->disk == NULL) {
2080a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King		ret = -ENOMEM;
2081a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King		goto err_kfree;
2082a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	}
20831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2084a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	spin_lock_init(&md->lock);
2085371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	INIT_LIST_HEAD(&md->part);
2086a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	md->usage = 1;
20871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2088d09408ade08a08a710a247fb52aa50101e73ebf7Adrian Hunter	ret = mmc_init_queue(&md->queue, card, &md->lock, subname);
2089a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	if (ret)
2090a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King		goto err_putdisk;
20911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2092a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	md->queue.issue_fn = mmc_blk_issue_rq;
2093a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	md->queue.data = md;
2094d2b18394259ef621fd2a6322aa9934198fd87a6aRussell King
2095fe6b4c8840c5e23fe9b8696450cee8f2e8cebffdPierre Ossman	md->disk->major	= MMC_BLOCK_MAJOR;
20965e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson	md->disk->first_minor = devidx * perdev_minors;
2097a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	md->disk->fops = &mmc_bdops;
2098a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	md->disk->private_data = md;
2099a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	md->disk->queue = md->queue.queue;
2100371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	md->disk->driverfs_dev = parent;
2101371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	set_disk_ro(md->disk, md->read_only || default_ro);
210253d8f97462b0bbb51150f4d6bc2fd45336a008b9Loic Pallardy	if (area_type & MMC_BLK_DATA_AREA_RPMB)
210353d8f97462b0bbb51150f4d6bc2fd45336a008b9Loic Pallardy		md->disk->flags |= GENHD_FL_NO_PART_SCAN;
2104a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King
2105a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	/*
2106a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	 * As discussed on lkml, GENHD_FL_REMOVABLE should:
2107a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	 *
2108a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	 * - be set for removable media with permanent block devices
2109a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	 * - be unset for removable block devices with permanent media
2110a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	 *
2111a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	 * Since MMC block devices clearly fall under the second
2112a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	 * case, we do not set GENHD_FL_REMOVABLE.  Userspace
2113a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	 * should use the block device creation/destruction hotplug
2114a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	 * messages to tell when the card is present.
2115a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	 */
2116a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King
2117f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin	snprintf(md->disk->disk_name, sizeof(md->disk->disk_name),
2118f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin		 "mmcblk%d%s", md->name_idx, subname ? subname : "");
2119a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King
2120a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das	if (mmc_card_mmc(card))
2121a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das		blk_queue_logical_block_size(md->queue.queue,
2122a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das					     card->ext_csd.data_sector_size);
2123a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das	else
2124a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das		blk_queue_logical_block_size(md->queue.queue, 512);
2125a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das
2126371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	set_capacity(md->disk, size);
2127d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin
2128f0d89972b01798cf9d245dfa1cacfa0ee78a3593Andrei Warkentin	if (mmc_host_cmd23(card->host)) {
2129f0d89972b01798cf9d245dfa1cacfa0ee78a3593Andrei Warkentin		if (mmc_card_mmc(card) ||
2130f0d89972b01798cf9d245dfa1cacfa0ee78a3593Andrei Warkentin		    (mmc_card_sd(card) &&
2131f0d89972b01798cf9d245dfa1cacfa0ee78a3593Andrei Warkentin		     card->scr.cmds & SD_SCR_CMD23_SUPPORT))
2132f0d89972b01798cf9d245dfa1cacfa0ee78a3593Andrei Warkentin			md->flags |= MMC_BLK_CMD23;
2133f0d89972b01798cf9d245dfa1cacfa0ee78a3593Andrei Warkentin	}
2134d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin
2135d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin	if (mmc_card_mmc(card) &&
2136d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin	    md->flags & MMC_BLK_CMD23 &&
2137d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin	    ((card->ext_csd.rel_param & EXT_CSD_WR_REL_PARAM_EN) ||
2138d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin	     card->ext_csd.rel_sectors)) {
2139d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin		md->flags |= MMC_BLK_REL_WR;
2140d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin		blk_queue_flush(md->queue.queue, REQ_FLUSH | REQ_FUA);
2141d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin	}
2142d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin
2143ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	if (mmc_card_mmc(card) &&
2144ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	    (area_type == MMC_BLK_DATA_AREA_MAIN) &&
2145ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	    (md->flags & MMC_BLK_CMD23) &&
2146ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	    card->ext_csd.packed_event_en) {
2147ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		if (!mmc_packed_init(&md->queue, card))
2148ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			md->flags |= MMC_BLK_PACKED_CMD;
2149ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	}
2150ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
2151371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	return md;
2152371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
2153371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin err_putdisk:
2154371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	put_disk(md->disk);
2155371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin err_kfree:
2156371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	kfree(md);
2157371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin out:
2158371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	return ERR_PTR(ret);
2159371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin}
2160371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
2161371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
2162371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{
2163371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	sector_t size;
2164371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	struct mmc_blk_data *md;
2165a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King
216685a18ad93ec66888d85758630019b10a84257f3cPierre Ossman	if (!mmc_card_sd(card) && mmc_card_blockaddr(card)) {
216785a18ad93ec66888d85758630019b10a84257f3cPierre Ossman		/*
216885a18ad93ec66888d85758630019b10a84257f3cPierre Ossman		 * The EXT_CSD sector count is in number or 512 byte
216985a18ad93ec66888d85758630019b10a84257f3cPierre Ossman		 * sectors.
217085a18ad93ec66888d85758630019b10a84257f3cPierre Ossman		 */
2171371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		size = card->ext_csd.sectors;
217285a18ad93ec66888d85758630019b10a84257f3cPierre Ossman	} else {
217385a18ad93ec66888d85758630019b10a84257f3cPierre Ossman		/*
217485a18ad93ec66888d85758630019b10a84257f3cPierre Ossman		 * The CSD capacity field is in units of read_blkbits.
217585a18ad93ec66888d85758630019b10a84257f3cPierre Ossman		 * set_capacity takes units of 512 bytes.
217685a18ad93ec66888d85758630019b10a84257f3cPierre Ossman		 */
2177371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		size = card->csd.capacity << (card->csd.read_blkbits - 9);
217885a18ad93ec66888d85758630019b10a84257f3cPierre Ossman	}
2179371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
2180add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	md = mmc_blk_alloc_req(card, &card->dev, size, false, NULL,
2181add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm					MMC_BLK_DATA_AREA_MAIN);
21821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return md;
2183371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin}
2184a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King
2185371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic int mmc_blk_alloc_part(struct mmc_card *card,
2186371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin			      struct mmc_blk_data *md,
2187371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin			      unsigned int part_type,
2188371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin			      sector_t size,
2189371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin			      bool default_ro,
2190add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm			      const char *subname,
2191add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm			      int area_type)
2192371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{
2193371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	char cap_str[10];
2194371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	struct mmc_blk_data *part_md;
2195371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
2196371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	part_md = mmc_blk_alloc_req(card, disk_to_dev(md->disk), size, default_ro,
2197add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm				    subname, area_type);
2198371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	if (IS_ERR(part_md))
2199371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		return PTR_ERR(part_md);
2200371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	part_md->part_type = part_type;
2201371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	list_add(&part_md->part, &md->part);
2202371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
2203371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	string_get_size((u64)get_capacity(part_md->disk) << 9, STRING_UNITS_2,
2204371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin			cap_str, sizeof(cap_str));
2205a3c76eb9d4a1e68a69dd880cf0bcb8a52418b993Girish K S	pr_info("%s: %s %s partition %u %s\n",
2206371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	       part_md->disk->disk_name, mmc_card_id(card),
2207371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	       mmc_card_name(card), part_md->part_type, cap_str);
2208371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	return 0;
2209371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin}
2210371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
2211e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon/* MMC Physical partitions consist of two boot partitions and
2212e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon * up to four general purpose partitions.
2213e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon * For each partition enabled in EXT_CSD a block device will be allocatedi
2214e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon * to provide access to the partition.
2215e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon */
2216e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon
2217371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic int mmc_blk_alloc_parts(struct mmc_card *card, struct mmc_blk_data *md)
2218371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{
2219e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon	int idx, ret = 0;
2220371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
2221371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	if (!mmc_card_mmc(card))
2222371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		return 0;
2223371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
2224e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon	for (idx = 0; idx < card->nr_parts; idx++) {
2225e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon		if (card->part[idx].size) {
2226e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon			ret = mmc_blk_alloc_part(card, md,
2227e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon				card->part[idx].part_cfg,
2228e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon				card->part[idx].size >> 9,
2229e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon				card->part[idx].force_ro,
2230add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm				card->part[idx].name,
2231add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm				card->part[idx].area_type);
2232e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon			if (ret)
2233e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon				return ret;
2234e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon		}
2235371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	}
2236371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
2237371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	return ret;
22381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
22391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2240371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic void mmc_blk_remove_req(struct mmc_blk_data *md)
2241371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{
2242add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	struct mmc_card *card;
2243add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
2244371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	if (md) {
2245fdfa20c1631210d0ca218689204682ea80e170e3Paul Taysom		/*
2246fdfa20c1631210d0ca218689204682ea80e170e3Paul Taysom		 * Flush remaining requests and free queues. It
2247fdfa20c1631210d0ca218689204682ea80e170e3Paul Taysom		 * is freeing the queue that stops new requests
2248fdfa20c1631210d0ca218689204682ea80e170e3Paul Taysom		 * from being accepted.
2249fdfa20c1631210d0ca218689204682ea80e170e3Paul Taysom		 */
22508efb83a2f8518a6ffcc074177f8d659c5165ef37Franck Jullien		card = md->queue.card;
2251fdfa20c1631210d0ca218689204682ea80e170e3Paul Taysom		mmc_cleanup_queue(&md->queue);
2252fdfa20c1631210d0ca218689204682ea80e170e3Paul Taysom		if (md->flags & MMC_BLK_PACKED_CMD)
2253fdfa20c1631210d0ca218689204682ea80e170e3Paul Taysom			mmc_packed_clean(&md->queue);
2254371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		if (md->disk->flags & GENHD_FL_UP) {
2255371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin			device_remove_file(disk_to_dev(md->disk), &md->force_ro);
2256add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm			if ((md->area_type & MMC_BLK_DATA_AREA_BOOT) &&
2257add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm					card->ext_csd.boot_ro_lockable)
2258add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm				device_remove_file(disk_to_dev(md->disk),
2259add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm					&md->power_ro_lock);
2260371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
2261371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin			del_gendisk(md->disk);
2262371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		}
2263371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		mmc_blk_put(md);
2264371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	}
2265371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin}
2266371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
2267371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic void mmc_blk_remove_parts(struct mmc_card *card,
2268371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin				 struct mmc_blk_data *md)
2269371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{
2270371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	struct list_head *pos, *q;
2271371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	struct mmc_blk_data *part_md;
2272371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
2273f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin	__clear_bit(md->name_idx, name_use);
2274371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	list_for_each_safe(pos, q, &md->part) {
2275371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		part_md = list_entry(pos, struct mmc_blk_data, part);
2276371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		list_del(pos);
2277371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		mmc_blk_remove_req(part_md);
2278371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	}
2279371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin}
2280371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
2281371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic int mmc_add_disk(struct mmc_blk_data *md)
2282371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{
2283371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	int ret;
2284add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	struct mmc_card *card = md->queue.card;
2285371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
2286371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	add_disk(md->disk);
2287371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	md->force_ro.show = force_ro_show;
2288371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	md->force_ro.store = force_ro_store;
2289641c3187b9d53cfd4c23b0ce2ab18a13d5e775e5Rabin Vincent	sysfs_attr_init(&md->force_ro.attr);
2290371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	md->force_ro.attr.name = "force_ro";
2291371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	md->force_ro.attr.mode = S_IRUGO | S_IWUSR;
2292371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	ret = device_create_file(disk_to_dev(md->disk), &md->force_ro);
2293371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	if (ret)
2294add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		goto force_ro_fail;
2295add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
2296add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	if ((md->area_type & MMC_BLK_DATA_AREA_BOOT) &&
2297add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	     card->ext_csd.boot_ro_lockable) {
229888187398cc5fa6650f38b9dcd5464667f468888fAl Viro		umode_t mode;
2299add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
2300add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		if (card->ext_csd.boot_ro_lock & EXT_CSD_BOOT_WP_B_PWR_WP_DIS)
2301add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm			mode = S_IRUGO;
2302add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		else
2303add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm			mode = S_IRUGO | S_IWUSR;
2304add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
2305add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		md->power_ro_lock.show = power_ro_lock_show;
2306add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		md->power_ro_lock.store = power_ro_lock_store;
230700d9ac08757049f334803b3d4dd202a6b1687dabRabin Vincent		sysfs_attr_init(&md->power_ro_lock.attr);
2308add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		md->power_ro_lock.attr.mode = mode;
2309add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		md->power_ro_lock.attr.name =
2310add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm					"ro_lock_until_next_power_on";
2311add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		ret = device_create_file(disk_to_dev(md->disk),
2312add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm				&md->power_ro_lock);
2313add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		if (ret)
2314add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm			goto power_ro_lock_fail;
2315add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	}
2316add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	return ret;
2317add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
2318add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholmpower_ro_lock_fail:
2319add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	device_remove_file(disk_to_dev(md->disk), &md->force_ro);
2320add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholmforce_ro_fail:
2321add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	del_gendisk(md->disk);
2322371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
2323371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	return ret;
2324371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin}
2325371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
2326c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball#define CID_MANFID_SANDISK	0x2
2327c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball#define CID_MANFID_TOSHIBA	0x11
2328c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball#define CID_MANFID_MICRON	0x13
23293550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen#define CID_MANFID_SAMSUNG	0x15
2330c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball
23316f60c22252af05df94352240f30f9fc84090d88dAndrei Warkentinstatic const struct mmc_fixup blk_fixups[] =
23326f60c22252af05df94352240f30f9fc84090d88dAndrei Warkentin{
2333c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball	MMC_FIXUP("SEM02G", CID_MANFID_SANDISK, 0x100, add_quirk,
2334c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball		  MMC_QUIRK_INAND_CMD38),
2335c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball	MMC_FIXUP("SEM04G", CID_MANFID_SANDISK, 0x100, add_quirk,
2336c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball		  MMC_QUIRK_INAND_CMD38),
2337c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball	MMC_FIXUP("SEM08G", CID_MANFID_SANDISK, 0x100, add_quirk,
2338c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball		  MMC_QUIRK_INAND_CMD38),
2339c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball	MMC_FIXUP("SEM16G", CID_MANFID_SANDISK, 0x100, add_quirk,
2340c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball		  MMC_QUIRK_INAND_CMD38),
2341c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball	MMC_FIXUP("SEM32G", CID_MANFID_SANDISK, 0x100, add_quirk,
2342c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball		  MMC_QUIRK_INAND_CMD38),
2343d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin
2344d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin	/*
2345d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin	 * Some MMC cards experience performance degradation with CMD23
2346d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin	 * instead of CMD12-bounded multiblock transfers. For now we'll
2347d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin	 * black list what's bad...
2348d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin	 * - Certain Toshiba cards.
2349d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin	 *
2350d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin	 * N.B. This doesn't affect SD cards.
2351d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin	 */
2352c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball	MMC_FIXUP("MMC08G", CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc,
2353d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin		  MMC_QUIRK_BLK_NO_CMD23),
2354c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball	MMC_FIXUP("MMC16G", CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc,
2355d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin		  MMC_QUIRK_BLK_NO_CMD23),
2356c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball	MMC_FIXUP("MMC32G", CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc,
2357d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin		  MMC_QUIRK_BLK_NO_CMD23),
23586de5fc9cf7de334912de4cfd2d06eb2d744d2afeStefan Nilsson XK
23596de5fc9cf7de334912de4cfd2d06eb2d744d2afeStefan Nilsson XK	/*
23606de5fc9cf7de334912de4cfd2d06eb2d744d2afeStefan Nilsson XK	 * Some Micron MMC cards needs longer data read timeout than
23616de5fc9cf7de334912de4cfd2d06eb2d744d2afeStefan Nilsson XK	 * indicated in CSD.
23626de5fc9cf7de334912de4cfd2d06eb2d744d2afeStefan Nilsson XK	 */
2363c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball	MMC_FIXUP(CID_NAME_ANY, CID_MANFID_MICRON, 0x200, add_quirk_mmc,
23646de5fc9cf7de334912de4cfd2d06eb2d744d2afeStefan Nilsson XK		  MMC_QUIRK_LONG_READ_TIME),
23656de5fc9cf7de334912de4cfd2d06eb2d744d2afeStefan Nilsson XK
23663550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen	/*
23673550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen	 * On these Samsung MoviNAND parts, performing secure erase or
23683550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen	 * secure trim can result in unrecoverable corruption due to a
23693550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen	 * firmware bug.
23703550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen	 */
23713550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen	MMC_FIXUP("M8G2FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
23723550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen		  MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
23733550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen	MMC_FIXUP("MAG4FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
23743550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen		  MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
23753550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen	MMC_FIXUP("MBG8FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
23763550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen		  MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
23773550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen	MMC_FIXUP("MCGAFA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
23783550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen		  MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
23793550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen	MMC_FIXUP("VAL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
23803550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen		  MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
23813550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen	MMC_FIXUP("VYL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
23823550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen		  MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
23833550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen	MMC_FIXUP("KYL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
23843550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen		  MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
23853550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen	MMC_FIXUP("VZL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
23863550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen		  MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
23873550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen
23886f60c22252af05df94352240f30f9fc84090d88dAndrei Warkentin	END_FIXUP
23896f60c22252af05df94352240f30f9fc84090d88dAndrei Warkentin};
23906f60c22252af05df94352240f30f9fc84090d88dAndrei Warkentin
23911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mmc_blk_probe(struct mmc_card *card)
23921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2393371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	struct mmc_blk_data *md, *part_md;
2394a7bbb57333447d0cf950992653b6b079585f3531Pierre Ossman	char cap_str[10];
2395a7bbb57333447d0cf950992653b6b079585f3531Pierre Ossman
2396912490db699d83cb3d03570b63df7448677a3f56Pierre Ossman	/*
2397912490db699d83cb3d03570b63df7448677a3f56Pierre Ossman	 * Check that the card supports the command class(es) we need.
2398912490db699d83cb3d03570b63df7448677a3f56Pierre Ossman	 */
2399912490db699d83cb3d03570b63df7448677a3f56Pierre Ossman	if (!(card->csd.cmdclass & CCC_BLOCK_READ))
24001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENODEV;
24011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	md = mmc_blk_alloc(card);
24031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (IS_ERR(md))
24041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return PTR_ERR(md);
24051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2406444122fd58fdc83c96877a92b3f6288cafddb08dYi Li	string_get_size((u64)get_capacity(md->disk) << 9, STRING_UNITS_2,
2407a7bbb57333447d0cf950992653b6b079585f3531Pierre Ossman			cap_str, sizeof(cap_str));
2408a3c76eb9d4a1e68a69dd880cf0bcb8a52418b993Girish K S	pr_info("%s: %s %s %s %s\n",
24091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		md->disk->disk_name, mmc_card_id(card), mmc_card_name(card),
2410a7bbb57333447d0cf950992653b6b079585f3531Pierre Ossman		cap_str, md->read_only ? "(ro)" : "");
24111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2412371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	if (mmc_blk_alloc_parts(card, md))
2413371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		goto out;
2414371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
24151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mmc_set_drvdata(card, md);
24166f60c22252af05df94352240f30f9fc84090d88dAndrei Warkentin	mmc_fixup_device(card, blk_fixups);
24176f60c22252af05df94352240f30f9fc84090d88dAndrei Warkentin
2418371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	if (mmc_add_disk(md))
2419371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		goto out;
2420371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
2421371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	list_for_each_entry(part_md, &md->part, part) {
2422371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		if (mmc_add_disk(part_md))
2423371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin			goto out;
2424371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	}
2425e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson
2426e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson	pm_runtime_set_autosuspend_delay(&card->dev, 3000);
2427e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson	pm_runtime_use_autosuspend(&card->dev);
2428e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson
2429e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson	/*
2430e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson	 * Don't enable runtime PM for SD-combo cards here. Leave that
2431e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson	 * decision to be taken during the SDIO init sequence instead.
2432e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson	 */
2433e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson	if (card->type != MMC_TYPE_SD_COMBO) {
2434e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson		pm_runtime_set_active(&card->dev);
2435e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson		pm_runtime_enable(&card->dev);
2436e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson	}
2437e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson
24381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
24391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out:
2441371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	mmc_blk_remove_parts(card, md);
2442371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	mmc_blk_remove_req(md);
24435865f2876baa5c68fd0d50029dd220ce19f3d2afUlf Hansson	return 0;
24441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
24451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mmc_blk_remove(struct mmc_card *card)
24471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
24481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mmc_blk_data *md = mmc_get_drvdata(card);
24491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2450371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	mmc_blk_remove_parts(card, md);
2451e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson	pm_runtime_get_sync(&card->dev);
2452ddd6fa7e794e62af3ec3eb4ffdc78489885701f2Adrian Hunter	mmc_claim_host(card->host);
2453ddd6fa7e794e62af3ec3eb4ffdc78489885701f2Adrian Hunter	mmc_blk_part_switch(card, md);
2454ddd6fa7e794e62af3ec3eb4ffdc78489885701f2Adrian Hunter	mmc_release_host(card->host);
2455e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson	if (card->type != MMC_TYPE_SD_COMBO)
2456e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson		pm_runtime_disable(&card->dev);
2457e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson	pm_runtime_put_noidle(&card->dev);
2458371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	mmc_blk_remove_req(md);
24591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mmc_set_drvdata(card, NULL);
24601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
24611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24627628774851751e55362ec7d9d57c9334e656a655Ulf Hanssonstatic int _mmc_blk_suspend(struct mmc_card *card)
24631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2464371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	struct mmc_blk_data *part_md;
24651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mmc_blk_data *md = mmc_get_drvdata(card);
24661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (md) {
24681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mmc_queue_suspend(&md->queue);
2469371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		list_for_each_entry(part_md, &md->part, part) {
2470371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin			mmc_queue_suspend(&part_md->queue);
2471371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		}
24721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
24731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
24741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
24751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24767628774851751e55362ec7d9d57c9334e656a655Ulf Hanssonstatic void mmc_blk_shutdown(struct mmc_card *card)
24777628774851751e55362ec7d9d57c9334e656a655Ulf Hansson{
24787628774851751e55362ec7d9d57c9334e656a655Ulf Hansson	_mmc_blk_suspend(card);
24797628774851751e55362ec7d9d57c9334e656a655Ulf Hansson}
24807628774851751e55362ec7d9d57c9334e656a655Ulf Hansson
24817628774851751e55362ec7d9d57c9334e656a655Ulf Hansson#ifdef CONFIG_PM
24827628774851751e55362ec7d9d57c9334e656a655Ulf Hanssonstatic int mmc_blk_suspend(struct mmc_card *card)
24837628774851751e55362ec7d9d57c9334e656a655Ulf Hansson{
24847628774851751e55362ec7d9d57c9334e656a655Ulf Hansson	return _mmc_blk_suspend(card);
24857628774851751e55362ec7d9d57c9334e656a655Ulf Hansson}
24867628774851751e55362ec7d9d57c9334e656a655Ulf Hansson
24871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mmc_blk_resume(struct mmc_card *card)
24881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2489371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	struct mmc_blk_data *part_md;
24901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mmc_blk_data *md = mmc_get_drvdata(card);
24911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (md) {
2493371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		/*
2494371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		 * Resume involves the card going into idle state,
2495371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		 * so current partition is always the main one.
2496371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		 */
2497371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		md->part_curr = md->part_type;
24981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mmc_queue_resume(&md->queue);
2499371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		list_for_each_entry(part_md, &md->part, part) {
2500371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin			mmc_queue_resume(&part_md->queue);
2501371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		}
25021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
25031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
25041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
25051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
25061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	mmc_blk_suspend	NULL
25071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define mmc_blk_resume	NULL
25081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
25091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct mmc_driver mmc_driver = {
25111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.drv		= {
25121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.name	= "mmcblk",
25131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
25141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.probe		= mmc_blk_probe,
25151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.remove		= mmc_blk_remove,
25161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.suspend	= mmc_blk_suspend,
25171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.resume		= mmc_blk_resume,
25187628774851751e55362ec7d9d57c9334e656a655Ulf Hansson	.shutdown	= mmc_blk_shutdown,
25191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
25201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init mmc_blk_init(void)
25221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
25239d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita	int res;
25241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25255e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson	if (perdev_minors != CONFIG_MMC_BLOCK_MINORS)
25265e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson		pr_info("mmcblk: using %d minors per device\n", perdev_minors);
25275e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson
25285e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson	max_devices = 256 / perdev_minors;
25295e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson
2530fe6b4c8840c5e23fe9b8696450cee8f2e8cebffdPierre Ossman	res = register_blkdev(MMC_BLOCK_MAJOR, "mmc");
2531fe6b4c8840c5e23fe9b8696450cee8f2e8cebffdPierre Ossman	if (res)
25321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
25331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25349d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita	res = mmc_register_driver(&mmc_driver);
25359d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita	if (res)
25369d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita		goto out2;
25371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25389d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita	return 0;
25399d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita out2:
25409d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita	unregister_blkdev(MMC_BLOCK_MAJOR, "mmc");
25411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out:
25421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return res;
25431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
25441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit mmc_blk_exit(void)
25461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
25471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mmc_unregister_driver(&mmc_driver);
2548fe6b4c8840c5e23fe9b8696450cee8f2e8cebffdPierre Ossman	unregister_blkdev(MMC_BLOCK_MAJOR, "mmc");
25491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
25501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(mmc_blk_init);
25521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(mmc_blk_exit);
25531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
25551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("Multimedia Card (MMC) block device driver");
25561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2557