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